/* Editor vetorial de limites para a interface google maps Utilizado em i3geo/metaestat/editorlimites.php Utiliza a API do Google Maps e pacotes/wicket/wicket.js (que cria o objeto Wkt com funcoes para processamento de Wkt) Licenca: GPL2 i3Geo Interface Integrada de Ferramentas de Geoprocessamento para Internet Direitos Autorais Reservados (c) 2006 Ministério do Meio Ambiente Brasil Desenvolvedor: Edmar Moretti edmar.moretti@gmail.com Esse programa utiliza parcialmente os codigos da aplicacao calculadora de carbono desenvolvido pelo IPAM - Instituto de Pesquisa Ambiental da Amazonia Este programa e software livre; voce pode redistribui-lo e/ou modifica-lo sob os termos da Licenca Publica Geral GNU conforme publicada pela Free Software Foundation; Este programa e distribuido na expectativa de que seja util, porem, SEM NENHUMA GARANTIA; nem mesmo a garantia implicita de COMERCIABILIDADE OU ADEQUACAO A UMA FINALIDADE ESPECIFICA. Consulte a Licenca Publica Geral do GNU para mais detalhes. Voce deve ter recebido uma copia da Licenca Publica Geral do GNU junto com este programa; se nao, escreva para a Free Software Foundation, Inc., no endereco 59 Temple Street, Suite 330, Boston, MA 02111-1307 USA. */ if(typeof(i3GEO) === 'undefined'){ var i3GEO = {}; } /* Classe: i3GEO.editorGM Funções de edição vetorial utilizadas pelo editor de regiões do sistema METAESTAT */ i3GEO.editorGM = { iconePonto: function(sel){ if(sel){ return i3GEO.configura.locaplic+"/imagens/google/symbol_middot_y.png"; } else{ return i3GEO.configura.locaplic+"/imagens/google/symbol_middot.png"; } }, /** * Objeto DOM com a imagem de aguarde existente no cabecalho da janela * */ aguarde: "", /** * Guarda o Id do DIV que recebera o conteudo HTML do editor */ iddiv: "", /** * Objeto criado com new google.maps.drawing.DrawingManager */ drawingManager: "", selectedShape: null, /** * guarda o mapeamento entre o codigo da regiao e o codigo do layer adicionado ao mapa */ regioestemas:{}, /** * Guarda o mapeamento entre o codigo da regiao e o codigo do layer adicionado ao mapa */ temasregioes:{}, /** * Guarda os dados descritivos sobre cada regiao obtidos na formacao no combo de escolha de regioes */ descregioes:[], /** * Inicia o editor * * Cria o objeto da API do Google Maps com new google.maps.drawing.DrawingManager * A janela flutuante que recebera os componentes do editor ja deve estar aberta (veja editorlimites.php) * Executa i3GEO.editorGM.html * * @param Id do DIV que recebera o conteudo HTML do editor */ inicia: function(iddiv){ var i,n,ics; //mensagem i3GEO.janela.tempoMsg("Atenção: apenas tabelas no esquema i3geo_metaestat podem ser editadas."); i3GEO.editorGM.iddiv = iddiv; $i(iddiv).innerHTML = i3GEO.editorGM.html(); ics = $i(iddiv).getElementsByTagName("button"); n = ics.length; i3GEO.barraDeBotoes.ativaBotoes(); i3GEO.editorGM.comboRegiaoEditavel(); for(i=0;i' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + '
'; //combo para escolher a regiao return ins; }, /** * Atualiza a ferramenta quando a janela flutuante tem seu foco ativado */ ativaFoco: function(){ i3GEO.util.mudaCursor(i3GEO.configura.cursores,"crosshair",i3GEO.Interface.IDMAPA,i3GEO.configura.locaplic); i3GEO.barraDeBotoes.ativaIcone("pan"); i3GEO.editorGM.mudaicone(); i3GEO.Interface.googlemaps.recalcPar(); }, /** * Marca uma figura como selecionada * @param objeto shape que sera marcado */ setSelection: function(shape){ if(shape.setEditable){ shape.setEditable(!shape.editable); } else{ shape.editable = true; shape.setIcon({url: i3GEO.editorGM.iconePonto(true)}); } }, /** * Marca todas as figuras como nao selecionadas * As figuras existentes no mapa sao mantidas na variavel i3GEO.desenho.googlemaps.shapes */ clearSelection: function(){ var i, n = i3GEO.desenho.googlemaps.shapes.length; for(i=0;i 0){ if(naoconfirma === false){ var x = window.confirm("Remove as figuras selecionadas?"); } else{ x = true; } if(x){ for(i=0;i"+dados[i].nome_tipo_regiao+""; i3GEO.editorGM.descregioes["a_"+dados[i].codigo_tipo_regiao] = dados[i]; } } ins += ""; if(onde){ onde.innerHTML = ins; } return ins; }; i3GEO.php.listaTipoRegiao(temp,codigo_tipo_regiao); }, /** * Funcao ativada no evento onchange do combo criado com comboRegiaoEditavel * Executa i3GEO.php.mapfileTipoRegiao */ comboRegiaoEditavelOnchange: function(combo){ if(combo.value === ""){ return; } i3GEO.editorGM.editarAtributos.desativa(); var temp = function(retorno){ if(i3GEO.arvoreDeCamadas.pegaTema(retorno.layer) == ""){ i3GEO.php.adtema(i3GEO.atualiza,retorno.mapfile); //guarda o codigo e relaciona com a regiao i3GEO.editorGM.regioestemas["a"+$i("i3geoCartoRegioesEditaveis").value] = retorno.layer; i3GEO.editorGM.temasregioes[retorno.layer] = $i("i3geoCartoRegioesEditaveis").value; } }; i3GEO.php.mapfileTipoRegiao(temp,combo.value); }, /** * Altera as bordas dos icones e desativa eventos * Desativa todos os botoes e ativa o indicado * @param objeto DOM que representa o botao que sera focado */ mudaicone: function(botao){ var c = $i(i3GEO.editorGM.iddiv), ci = c.getElementsByTagName("img"), n = ci.length, i; for(i=0;i 0){ i3GEO.editorGM.deleteSelectedShape(true); } pol = new google.maps.Marker({ position: new google.maps.LatLng(obj.getPosition().ob,obj.getPosition().pb), map: i3GeoMap, icon: { url: i3GEO.editorGM.iconePonto(false) }, clickable: true, zIndex: 1, draggable: true, tema: tema, colunaid: colunaid, valorid: valorid, colunanome: colunanome, valornome: valornome, editable: false }); google.maps.event.addListener(pol, 'click', function() { i3GEO.editorGM.setSelection(pol); }); i3GEO.desenho.googlemaps.shapes.push(pol); return; } }, /** * Salva um poligono no banco de dados */ salvaLimite: { /** * Inicia a ferramenta definindo as funcoes dos botoes * Executa i3GEO.editorGM.salvaLimite.criaJanelaFlutuante */ inicia: function(){ if(i3GEO.login.verificaCookieLogin() === false){ i3GEO.janela.tempoMsg("Você precisa fazer login para usar essa opção"); return; } var s = i3GEO.editorGM.selectedShapes(), n = s.length, janela = YAHOO.i3GEO.janela.manager.find("salvaLimite"); if(janela){ janela.destroy(); } if(n == 1){ s = s[0]; i3GEO.editorGM.salvaLimite.criaJanelaFlutuante(i3GEO.editorGM.salvaLimite.html( s.colunaid, s.valorid, s.colunanome, s.valornome )); new YAHOO.widget.Button( "i3GEOFmetaestati3GEO.editorGMBotao1", {onclick:{fn: function(){ i3GEO.editorGM.salvaLimite.gravaDados(true); }}} ); new YAHOO.widget.Button( "i3GEOFmetaestati3GEO.editorGMBotao2", {onclick:{fn: function(){ i3GEO.editorGM.salvaLimite.gravaDados(false); }}} ); new YAHOO.widget.Button( "i3GEOFmetaestati3GEO.editorGMBotao3", {onclick:{fn: function(){ i3GEO.editorGM.salvaLimite.excluiPoligono(); }}} ); } else{ i3GEO.janela.tempoMsg("Selecione uma figura"); } }, /** * Monta o HTML para o formulario que permite salvar os dados */ html:function(colunaIdElemento,valorIdElemento,colunaNomeElemento,valorNomeElemento){ var ins = '' + '

Se o valor do código for vazio, será criado um novo elemento. Caso contrário, os valores atualmente registrados serão atualizados.

' + '

Edite os atributos:

' + '' + '' + '' + '' + '

Código:

' + '

' + '

Nome:

' + '

' + '

Escolha a operação desejada:

' + '' + ' ' + '

'; return ins; }, /** * Cria a janela flutuante para receber os componentes da ferramenta * @param html com o conteudo da ferramenta */ criaJanelaFlutuante: function(html){ var titulo,cabecalho,minimiza,janela; cabecalho = function(){}; minimiza = function(){ i3GEO.janela.minimiza("salvaLimite"); }; titulo = "Salva limite   "; janela = i3GEO.janela.cria( "300px", "265px", "", "", "", titulo, "salvaLimite", true, "hd", cabecalho, minimiza ); $i("salvaLimite_corpo").style.backgroundColor = "white"; $i("salvaLimite_corpo").innerHTML = html; YAHOO.util.Event.addListener(janela[0].close, "click", i3GEO.editorGM.mudaicone); }, /** * Aplica a operacao de salvar os dados no banco para o shape selecionado * Executa admin/php/metaestat.php?funcao=mantemDadosRegiao * @param boolean indica se as coordenadas serao salvas tambem */ gravaDados: function(comwkt){ if(i3GEO.login.verificaCookieLogin() === false){ i3GEO.janela.tempoMsg("Você precisa fazer login para usar essa opção"); return; } if(!window.confirm("Grava mesmo os dados?")){ return; } var p,codigo_tipo_regiao = $i("i3geoCartoRegioesEditaveis").value, identificadornovo = $i("inputIdentificadorNovoElemento").value, identificador = $i("inputIdentificadorElemento").value, nome = $i("inputNomeNovoElemento").value, wkt = "", temp = function(retorno){ i3GEO.editorGM.deleteSelectedShape(true); var janela = YAHOO.i3GEO.janela.manager.find("salvaLimite"); if(janela){ janela.destroy(); } i3GEO.Interface.redesenha(); }; if(comwkt === true){ wkt = i3GEO.editorGM.toWKT(i3GEO.editorGM.selectedShapes()[0]); } else{ if(identificadornovo === identificador && $i("inputNomeElemento").value === nome){ i3GEO.janela.tempoMsg("Valores iguais ao original"); return; } } p = i3GEO.configura.locaplic+"/admin/php/metaestat.php?funcao=mantemDadosRegiao&tipo="; cpJSON.call(p,"foo",temp,"&codigo_tipo_regiao="+codigo_tipo_regiao+"&identificadornovo="+identificadornovo+"&identificador="+identificador+"&nome="+nome+"&wkt="+wkt); }, /** * Exclui um registro do banco de dados * Executa admin/php/metaestat.php?funcao=mantemDadosRegiao&tipo=excluir */ excluiPoligono: function(){ if(i3GEO.login.verificaCookieLogin() === false){ i3GEO.janela.tempoMsg("Você precisa fazer login para usar essa opção"); return; } if(!window.confirm("Exclui mesmo o poligono?")){ return; } var codigo_tipo_regiao = $i("i3geoCartoRegioesEditaveis").value, identificador = $i("inputIdentificadorElemento").value, temp = function(retorno){ i3GEO.editorGM.deleteSelectedShape(true); var janela = YAHOO.i3GEO.janela.manager.find("salvaLimite"); if(janela){ janela.destroy(); } i3GEO.Interface.redesenha(); }, p = i3GEO.configura.locaplic+"/admin/php/metaestat.php?funcao=mantemDadosRegiao&tipo=excluir"; cpJSON.call(p,"foo",temp,"&codigo_tipo_regiao="+codigo_tipo_regiao+"&identificador="+identificador); } }, /** *Funcoes que controlam o processo de edicao de atributos de um shape */ editarAtributos: { aliascolunas: "", //guarda os nomes das colunas e seus aliases para permitir a criacao de novos registros x: "", y: "", /** * Ativa a ferramenta * Define os eventos de onclick para abrir formulario quando o usuario clica no mapa * Para cada regiao sao obtidas todas as variaveis cadastradas * Executa i3GEO.editorGM.editarAtributos.criaJanelaFlutuante * Executa i3GEO.editorGM.editarAtributos.comboVariaveis(); */ ativa: function(botao){ if($i("i3geoCartoRegioesEditaveis").value == ""){ i3GEO.janela.tempoMsg("Escolha uma regiao"); return; } i3GEO.editorGM.mudaicone(botao); if(i3GEO.eventos.MOUSECLIQUE.toString().search("i3GEO.editorGM.editarAtributos.captura()") < 0) {i3GEO.eventos.MOUSECLIQUE.push("i3GEO.editorGM.editarAtributos.captura()");} var janela = YAHOO.i3GEO.janela.manager.find("editaAtributos"); if(janela){ $i("editarAtributosForm").innerHTML = ""; } else{ i3GEO.editorGM.editarAtributos.criaJanelaFlutuante(i3GEO.editorGM.editarAtributos.html()); i3GEO.editorGM.editarAtributos.comboVariaveis(); } }, /** * Fecha a janela de edicao */ desativa: function(){ var janela = YAHOO.i3GEO.janela.manager.find("editaAtributos"); if(janela){ janela.destroy(); } }, criaJanelaFlutuante: function(html){ var janela,titulo,cabecalho,minimiza; cabecalho = function(){}; minimiza = function(){ i3GEO.janela.minimiza("editaAtributos"); }; titulo = "Atributos   "; janela = i3GEO.janela.cria( "250px", "265px", "", "", "", titulo, "editaAtributos", false, "hd", cabecalho, minimiza ); $i("editaAtributos_corpo").style.backgroundColor = "white"; $i("editaAtributos_corpo").innerHTML = html; i3GEO.janela.tempoMsg("Após escolher a medida da variável, clique no mapa para escolher o limite geográfico."); YAHOO.util.Event.addListener(janela[0].close, "click", i3GEO.editorGM.mudaicone); }, /** * Fornece o HTML com os objetos que receberao os componentes da ferramenta * @return html */ html: function(){ var ins = '' + '

' + '

' + '

' + '

' + ''; return ins; }, /** * Monta um combo para escolha de uma variavel que sera editada * Executa i3GEO.php.listaVariavel */ comboVariaveis: function(){ var temp = function(dados){ var i,n = dados.length, ins = ''; ins += '

Escolha uma variável para editar

'; ins += ""; $i("editarAtributosVariaveis").innerHTML = ins; }; i3GEO.php.listaVariavel(temp,"i3geo_metaestat"); }, /** * Monta um combo com as medidas de uma variavel * Executa i3GEO.php.listaMedidaVariavel * @param objeto DOM do tipo select que contem a lista de variaveis */ comboMedidasVariavel: function(comboMedidas){ var temp = function(dados){ var i,n = dados.length, ins = ''; ins += '

Escolha uma medida da variável para editar

'; ins += ""; $i("editarAtributosMedidasVariavel").innerHTML = ins; }; if(comboMedidas.value !== ""){ i3GEO.php.listaMedidaVariavel(comboMedidas.value,temp); } }, /** * Captura os atributos de um elemento do mapa * Executa i3GEO.editorGM.editarAtributos.pegaDados(); */ captura: function(){ if(!YAHOO.i3GEO.janela.manager.find("editaAtributos")){ i3GEO.editorGM.mudaicone(botao); return; } i3GEO.editorGM.editarAtributos.x = objposicaocursor.ddx; i3GEO.editorGM.editarAtributos.y = objposicaocursor.ddy; i3GEO.editorGM.editarAtributos.pegaDados(); }, /** * Obtem os dados de um elemento de uma regiao * Monta o formulario para edicao * Executa admin/php/metaestat.php?funcao=listaAtributosMedidaVariavelXY */ pegaDados: function(){ var p = i3GEO.configura.locaplic+"/admin/php/metaestat.php?funcao=listaAtributosMedidaVariavelXY", codigo_tipo_regiao = $i("i3geoCartoRegioesEditaveis").value, id_medida_variavel = $i("editarAtributosComboMedidas").value, temp = function(retorno){ var atr = retorno.atributos, i = 0, n = atr.dados.length, j = 0, idunico = "", nj = atr.aliascolunas.length, ins = "" + '

Limite geográfico escolhido:

' + '

Nome: ' + retorno.regiao.nomeregiao + '

' + '

Código: ' + retorno.regiao.identificador_regiao + '

' + '' + '

Atributos:

' + '' + ' '; $i("editarAtributosRegiao").innerHTML = ins; ins = ""; //registros for(i=0;iexcluir

"; //colunas for(j=0;j' + '

'; } } } $i("editarAtributosForm").innerHTML = ins; new YAHOO.widget.Button( "editarAtributosAdicionar", {onclick:{fn: function(){ var novoel = document.createElement("div"), ins = "

"; for(j=0;j' + '

'; } } ins + "
"; novoel.innerHTML = ins; $i("editarAtributosForm").appendChild(novoel); }}} ); new YAHOO.widget.Button( "editarAtributosSalvar", {onclick:{fn: function(){ i3GEO.editorGM.editarAtributos.salva(); }}} ); }; cpJSON.call(p,"foo",temp,"&codigo_tipo_regiao="+codigo_tipo_regiao+"&id_medida_variavel="+id_medida_variavel+"&x="+i3GEO.editorGM.editarAtributos.x+"&y="+i3GEO.editorGM.editarAtributos.y); }, //TODO redesenhar as camadas que sofrerem alteracoes em funcao do salvar ou excluir /** * Exclui o valor de uma medida de variavel para o componente de uma regiao */ excluir: function(id){ if(i3GEO.login.verificaCookieLogin() === false){ i3GEO.janela.tempoMsg("Você precisa fazer login para usar essa opção"); return; } var p = i3GEO.configura.locaplic+"/admin/php/metaestat.php?funcao=excluiAtributosMedidaVariavel", codigo_tipo_regiao = $i("i3geoCartoRegioesEditaveis").value, id_medida_variavel = $i("editarAtributosComboMedidas").value, identificador_regiao = $i("editarAtributosidentificador_regiao").value, temp = function(retorno){ i3GEO.editorGM.editarAtributos.pegaDados(); i3GEO.janela.fechaAguarde("aguardeSalvaAtributos"); }; i3GEO.janela.AGUARDEMODAL = true; i3GEO.janela.abreAguarde("aguardeSalvaAtributos","Salvando..."); i3GEO.janela.AGUARDEMODAL = false; cpJSON.call(p,"foo",temp,"&codigo_tipo_regiao="+codigo_tipo_regiao+"&identificador_regiao="+identificador_regiao+"&id_medida_variavel="+id_medida_variavel+"&id="+id); }, /** * Salva os valores digitados */ salva: function(){ if(i3GEO.login.verificaCookieLogin() === false){ i3GEO.janela.tempoMsg("Você precisa fazer login para usar essa opção"); return; } var container = $i("editarAtributosForm"), divsT = container.getElementsByTagName("div"), n = divsT.length, i = 0, dv = "", inputs = "", codigo_tipo_regiao = $i("i3geoCartoRegioesEditaveis").value, id_medida_variavel = $i("editarAtributosComboMedidas").value, identificador_regiao = $i("editarAtributosidentificador_regiao").value, nj, j, colunas = [], colunasT = [], valores = [], valoresT = [], idsunicosT = [], p = i3GEO.configura.locaplic+"/admin/php/metaestat.php?funcao=salvaAtributosMedidaVariavel", re = new RegExp("idunico_", "g"),//prefixo usado para marcar o id dos elementos input que contem os valores que se quer obter temp = function(retorno){ i3GEO.editorGM.editarAtributos.pegaDados(); i3GEO.editorGM.atualizaCamadasMetaestat(); i3GEO.janela.fechaAguarde("aguardeSalvaAtributos"); }; if(codigo_tipo_regiao == ""){ i3GEO.janela.tempoMsg("Problemas com o codigo da regiao"); return; } if(id_medida_variavel == ""){ i3GEO.janela.tempoMsg("Escolha uma medida"); return; } if(identificador_regiao == ""){ i3GEO.janela.tempoMsg("Problemas com o identificador da regiao"); return; } for(i=0;i" + "Clique no mapa para traçar um polígono novo. Cada clique corresponde a um vértice do polígono. Para encerrar o traçado utilize um duplo clique. Após traçar um novo polígono pode-se selecioná-lo novamente e editar os vértices, se for necessário, ou mesmo apagar o polígono por completo. O novo polígono só será salvo por meio da opção específica para isso." + "" + "Utilize essa opção para capturar os vértices de um polígono existente. O resultado da captura é uma figura que pode ser editada, ou seja, os vértices podem ser modificados de posição ou mesmo removidos. Após editar, salve o novo polígono." + "" + "Após ativar essa opção clique no mapa sobre uma figura existente (que tenha sido capturada ou digtalizada). A figura passará então para o estado de 'selecionada' podendo ser utilizada por outras ferramentas de edição." + "" + "Remove da tela a figura que estiver selecionada. Essa operação não apaga o polígono do banco de dados, apenas remove do modo de edição." + "" + "Salva no banco de dados a figura que estiver selecionada. Essa opção altera apenas os atributos do limite geográfico, não afetando os valores armazenados em cada medida de variável." + "" + "Abre um formulário que permite alterar os valores de uma medida de variável relacionada a uma determinada região. Após abrir o formulário, clique no mapa sobre a região desejada, mas escolha a medida da variável primeiro. Os valores já existentes poderão então ser alterados ou podem ser adicionados novos." + ""; $i("editaAtributosAjuda_corpo").innerHTML = html; } }; //copia do original de pacotes/wicket /*global Wkt, google, document, window, console*/ google.maps.Marker.prototype.type = 'marker'; google.maps.Polyline.prototype.type = 'polyline'; google.maps.Polygon.prototype.type = 'polygon'; google.maps.Rectangle.prototype.type = 'rectangle'; google.maps.Circle.prototype.type = 'circle'; /** * An object of framework-dependent construction methods used to generate * objects belonging to the various geometry classes of the framework. */ Wkt.Wkt.prototype.construct = { /** * Creates the framework's equivalent point geometry object. * @param config {Object} An optional properties hash the object should use * @param component {Object} An optional component to build from * @return {google.maps.Marker} */ 'point': function (config, component) { var c = component || this.components; config = config || {}; config.position = new google.maps.LatLng(c[0].y, c[0].x); return new google.maps.Marker(config); }, /** * Creates the framework's equivalent multipoint geometry object. * @param config {Object} An optional properties hash the object should use * @return {Array} Array containing multiple google.maps.Marker */ 'multipoint': function (config) { var i, c, arr; c = this.components; config = config || {}; arr = []; for (i = 0; i < c.length; i += 1) { arr.push(this.construct.point(config, c[i])); } return arr; }, /** * Creates the framework's equivalent multipoint geometry object. * @param config {Object} An optional properties hash the object should use * @param component {Object} An optional component to build from * @return {google.maps.Polyline} */ 'linestring': function (config, component) { var i, c; c = component || this.components; config = config || { editable: false }; config.path = []; for (i = 0; i < c.length; i += 1) { config.path.push(new google.maps.LatLng(c[i].y, c[i].x)); } return new google.maps.Polyline(config); }, /** * Creates the framework's equivalent multilinestring geometry object. * @param config {Object} An optional properties hash the object should use * @return {Array} Array containing multiple google.maps.Polyline instances */ 'multilinestring': function (config) { var i, c, arr; c = this.components; config = config || { editable: false }; config.path = []; arr = []; for (i = 0; i < c.length; i += 1) { arr.push(this.construct.linestring(config, c[i])); } return arr; }, /** * Creates the framework's equivalent polygon geometry object. * @param config {Object} An optional properties hash the object should use * @return {google.maps.Polygon} */ 'polygon': function (config) { var j, k, c, rings, verts; c = this.components; config = config || { editable: false // Editable geometry off by default }; config.paths = []; rings = []; for (j = 0; j < c.length; j += 1) { // For each ring... verts = []; for (k = 0; k < c[j].length; k += 1) { // For each vertex... verts.push(new google.maps.LatLng(c[j][k].y, c[j][k].x)); } // eo for each vertex if (j !== 0) { // Reverse the order of coordinates in inner rings if (config.reverseInnerPolygons == null || config.reverseInnerPolygons) { verts.reverse(); } } rings.push(verts); } // eo for each ring config.paths = config.paths.concat(rings); if (this.isRectangle) { console.log('Rectangles are not yet supported; set the isRectangle property to false (default).'); } else { return new google.maps.Polygon(config); } }, /** * Creates the framework's equivalent multipolygon geometry object. * @param config {Object} An optional properties hash the object should use * @return {Array} Array containing multiple google.maps.Polygon */ 'multipolygon': function (config) { var i, j, k, c, rings, verts; c = this.components; config = config || { editable: false // Editable geometry off by default }; config.paths = []; // Must ensure this property is available for (i = 0; i < c.length; i += 1) { // For each polygon... rings = []; for (j = 0; j < c[i].length; j += 1) { // For each ring... verts = []; for (k = 0; k < c[i][j].length; k += 1) { // For each vertex... verts.push(new google.maps.LatLng(c[i][j][k].y, c[i][j][k].x)); } // eo for each vertex /* // This is apparently not needed in multipolygon cases if (j !== 0) { // Reverse the order of coordinates in inner rings verts.reverse(); } */ rings.push(verts); } // eo for each ring config.paths = config.paths.concat(rings); } // eo for each polygon return new google.maps.Polygon(config); } }; /** * A framework-dependent deconstruction method used to generate internal * geometric representations from instances of framework geometry. This method * uses object detection to attempt to classify members of framework geometry * classes into the standard WKT types. * @param obj {Object} An instance of one of the framework's geometry classes * @return {Object} A hash of the 'type' and 'components' thus derived */ Wkt.Wkt.prototype.deconstruct = function (obj) { var i, j, verts, rings, tmp; // google.maps.Marker ////////////////////////////////////////////////////// if (obj.getPosition && typeof obj.getPosition === 'function') { // Only Markers, among all overlays, have the getPosition property return { type: 'point', components: [{ x: obj.getPosition().lng(), y: obj.getPosition().lat() }] }; // google.maps.Polyline //////////////////////////////////////////////////// } else if (obj.getPath && !obj.getPaths) { // Polylines have a single path (getPath) not paths (getPaths) verts = []; for (i = 0; i < obj.getPath().length; i += 1) { tmp = obj.getPath().getAt(i); verts.push({ x: tmp.lng(), y: tmp.lat() }); } return { type: 'linestring', components: verts }; // google.maps.Polygon ///////////////////////////////////////////////////// } else if (obj.getPaths) { // Polygon is the only class with the getPaths property // TODO Polygons with holes cannot be distinguished from multipolygons rings = []; for (i = 0; i < obj.getPaths().length; i += 1) { // For each polygon (ring)... tmp = obj.getPaths().getAt(i); verts = []; for (j = 0; j < obj.getPaths().getAt(i).length; j += 1) { // For each vertex... verts.push({ x: tmp.getAt(j).lng(), y: tmp.getAt(j).lat() }); } verts.push({ // Add the first coordinate again for closure x: tmp.getAt(0).lng(), y: tmp.getAt(0).lat() }); // Since we can't distinguish between single polygons with holes // and multipolygons, we always create multipolygons if (obj.getPaths().length > 1) { verts = [verts]; // Wrap multipolygons once more (collection) } rings.push(verts); } return { type: 'polygon', components: rings }; // google.maps.Rectangle /////////////////////////////////////////////////// } else if (obj.getBounds && !obj.getRadius) { // Rectangle is only overlay class with getBounds property and not getRadius property tmp = obj.getBounds(); return { type: 'polygon', isRectangle: true, components: [ [ { // NW corner x: tmp.getSouthWest().lng(), y: tmp.getNorthEast().lat() }, { // NE corner x: tmp.getNorthEast().lng(), y: tmp.getNorthEast().lat() }, { // SE corner x: tmp.getNorthEast().lng(), y: tmp.getSouthWest().lat() }, { // SW corner x: tmp.getSouthWest().lng(), y: tmp.getSouthWest().lat() }, { // NW corner (again, for closure) x: tmp.getSouthWest().lng(), y: tmp.getNorthEast().lat() } ] ] }; // google.maps.Circle ////////////////////////////////////////////////////// } else if (obj.getBounds && obj.getRadius) { // Circle is the only overlay class with both the getBounds and getRadius properties console.log('Deconstruction of google.maps.Circle objects is not yet supported'); } else { console.log('The passed object does not have any recognizable properties.'); } }; /** * A framework-dependent flag, set for each Wkt.Wkt() instance, that indicates * whether or not a closed polygon geometry should be interpreted as a rectangle. */ Wkt.Wkt.prototype.isRectangle = false;