Trabajando con Google Maps

Standard

Ubicar puntos dentro de una figura irregular con Google Maps

Hola a todos, ¿qué tal? , ¿cuántas veces nos hemos topado con problemas que nos quitan horas e incluso hasta un día completo en resolver?, supongo que muchas y en algunas ocasiones es muy estresante, este fué mi caso cuando implementé Google Maps en una aplicación Web usando figuras irregulares para dibujar en el mapa y querer manipular nuestra figura para que haga cierta acción. Y es aquí donde mi aventura y reto a la vez con Google Maps empieza.

Primero si no tienes idea de como agregar la opción de dibujar en nuestro mapa (así como yo no la tenia) solo debes agregar un drawingManager el cual nos proporcionará esta herramienta, para esto agrega el siguiente código:

var drawingManager = new google.maps.drawing.DrawingManager({
   drawingMode: google.maps.drawing.OverlayType.MARKER,
   drawingControl: true,
   drawingControlOptions: {
     position: google.maps.ControlPosition.TOP_CENTER,
     drawingModes: [
       google.maps.drawing.OverlayType.MARKER,
       google.maps.drawing.OverlayType.CIRCLE,
       google.maps.drawing.OverlayType.POLYGON,
       google.maps.drawing.OverlayType.POLYLINE,
       google.maps.drawing.OverlayType.RECTANGLE
      ]
    },
    markerOptions: {},
    circleOptions: {
    fillColor: '#ffff00',
    fillOpacity: 1,
    strokeWeight: 5,
    clickable: false,
    editable: true,
    zIndex: 1
    }
});
drawingManager.setMap(map);

/*donde map representa nuestro mapa en la aplicación.Esta código nos agrega   ra la opción de poder dibujar en nuestro mapa.*/ 

Esto nos producirá un resultado como el siguiente:

unoEL PROBLEMA:

Ubicar cuantos de nuestros puntos ubicados en el mapa que están dentro del área seleccionada, tomando en cuenta que esta área es de forma irregular. (Y vaya que si es un verdadero problema)

Después de eso, agregamos nuestros markers (para más información te recomiendo consultar la API de Google Maps “https://developers.google.com/maps/“)

Una vez hecho este pequeño paréntesis retomemos a nuestro problema inicial.

Tomamos como ejemplo la siguiente imagen para situar nuestro problema.

dos

 

En este caso tenemos el mapa situando las ubicaciones compuestas con una Latitud y una Longitud.

LA PREGUNTA:

¿Cómo ubicar los puntos dentro de una figura irregular?

Dibujamos nuestra figura en el mapa.

tres

LA SOLUCIÓN:

1: Crearemos una función llamada Contains, complementándolo en la clase Polígono, utilizando el algoritmo de “Ray-casting”, el cual determinará si un par de coordenadas (Logitud y Latitud) y está dentro de la figura trazada.
       
       google.maps.Polygon.prototype.Contains = function (point) {
               var crossings = 0,
               path = this.getPath();

               // for each edge
              for (var i = 0; i < path.getLength(); i++) { 
                    var a = path.getAt(i), 
                    j = i + 1; 
                    if (j >= path.getLength()) {
                             j = 0;
                    }
                    var b = path.getAt(j);
                    if (rayCrossesSegment(point, a, b)) {
                         crossings++;
                    }
              }

             // odd number of crossings?
             return (crossings % 2 == 1);

            function rayCrossesSegment(point, a, b) {
                 var px = point.lng(),
                     py = point.lat(),
                     ax = a.lng(),
                     ay = a.lat(),
                     bx = b.lng(),
                     by = b.lat();
                     if (ay > by) {
                         ax = b.lng();
                         ay = b.lat();
                         bx = a.lng();
                         by = a.lat();
                     }
                 // alter longitude to cater for 180 degree crossings
                    if (px < 0) {
                          px += 360
                    };
                    if (ax < 0) {
                         ax += 360
                    };
                   if (bx < 0) { 
                        bx += 360 
                   }; 
                   if (py == ay || py == by) 
                         py += 0.00000001; 
                   if ((py > by || py < ay) || (px > Math.max(ax, bx))) 
                       return false;
                   if (px < Math.min(ax, bx)) 
                            return true; 
                 var red = (ax != bx) ? ((by - ay) / (bx - ax)) : Infinity;                 var blue = (ax != px) ? ((py - ay) / (px - ax)) :Infinity;                 return (blue >= red);
             }
};

2: Ya que tenemos nuestra función Contains, debemos obtener las coordenadas de los puntos los cuales componen nuestra figura, en este caso de inicio y fin. Para esto en nuestro código agregaremos la siguiente función dentro de nuestro javascript la cual agregará un listener a nuestro drawingManager para identificar cuando terminemos de dibujar. Esta función retornará en un Callback una variable llamada “line” la cual contiene un arreglo con nuestras coordenadas de inicio y fin de cada una de nuestras lineas.

//Datos de nuestros puntos situados en el mapa 
var point1 = new google.maps.LatLng(24.799588, -107.390800);
var point2 = new google.maps.LatLng(24.833788, -107.393868);
var arrayOfPoints = {point1, point2};
google.maps.event.addListener(drawingManager, 'polylinecomplete', function(line) {

    //Obtenemos las coordenadas del polígono
    var arrayCoordinates = line.getPath().getArray( );
    var arrayGetCoordinates = new Array( );

     for (var i = 0; i < arrayCoordinates.length; i++) {

         /*Obtenemos por cada iteración un par de coordenadas el cual 
          convertimos a String similar a este: [-107.54466, 45.00007]*/

         var actualItem = arrayCoordinates[i].toString();
         var index = actualItem.indexOf(',');
         var lati = actualItem.substring(1,index);
         var lngi = actualItem.substring(index+2,actualItem.length-1);
         //Agregamos nuestra coordenadas al arreglo de coordenadas
         arrayGetcCoordinates.push({lat: parseFloat(lati) ,                                                       lng: parseFloat(lngi)});

};
//Creamos un nuevo polígono en Google Maps
var polygon = new google.maps.Polygon({path:arrayofPolygon});

//Ahora procederemos a recorrer nuestro arreglo de coordenadas
var inside = 0;
for (var i = 0; i < arrayOfPoints.length; i++) {
//Preguntamos si nuestro polygon contiene el arreglo de puntos
       if(polygon.Contains(arrayOfPoints[i])){
           inside = inside+1;
       }
   }
}

Al terminar este código en la variable inside estará el numero de puntos que se encuentran dentro del área seleccionada. O bien, si quieres hacer algo con los puntos que tienes, puedes manipularlo de la forma que tu lo requieras.cuatro
Bueno hasta aquí el blog de hoy. Espero les haya gustado y les sirva para resolver su problema (y no volverse loco y estresarse un buen rato como yo lo hice). Si tienes más dudas acerca de la implementación de este código en tu aplicación, no dudes en contactarme.

Nicolás Villegas
Practicante de HunabSys R&D
Estudiante de Ing. en Sistemas Computacionales

Leave a Reply

Your email address will not be published. Required fields are marked *