2013-05-13 20 views
6

Poiché nella richiesta di ricezione esiste una limitazione a 2048 caratteri, non è possibile generare un'immagine con Google Maps statiche che contiene un poligono con un numero elevato di punti poligono.Mappe statiche: disegno di poligoni con molti punti. (Limitazione 2048 caratteri)

Specialmente se si tenta di disegnare molti poligoni complessi su una mappa. Se usi l'API di Google Maps, non avrai problemi: funziona molto bene! Ma voglio avere un'immagine (jpg o png) ...

Quindi, c'è la possibilità di creare un'immagine dall'API di Google Maps? O un modo per "ingannare" il limite di 2048 caratteri?

Grazie!

+0

Fare riferimento all'url seguente, questo aiuterà molto https://developers.google.com/maps/documentation/staticmaps/?hl=fr#EncodedPolylines – user3364541

risposta

6

Non c'è modo di "ingannare" il limite di caratteri, ma è possibile semplificare la polilinea per portare la stringa polilinea codificata al di sotto del limite di caratteri. Questo può o non può risultare in un poligono di fedeltà adeguata alle tue esigenze.

Un ulteriore avvertimento è che (per quanto ne so io, l'API di mappe statiche consente di disegnare sulla mappa una sola polilinea codificata (questo può sembrare un poligono, se lo si chiude o lo si riempie) , ma è ancora una polilinea, non un poligono).

Un'opzione per semplificare la polilinea è l'algoritmo Douglas Peucker. Di seguito è riportata un'implementazione che estende l'oggetto google.maps.Polyline con un metodo simplify.

Questo si basa sull'avere caricato l'API JS di Google Maps, che potrebbe non essere utile se si utilizzano le mappe statiche, ma il codice riportato di seguito potrebbe facilmente essere riscritto.

google.maps.Polyline.prototype.simplify = function(tolerance) { 

    var points = this.getPath().getArray(); // An array of google.maps.LatLng objects 
    var keep = []; // The simplified array of points 

    // Check there is something to simplify. 
    if (points.length <= 2) { 
     return points; 
    } 

    function distanceToSegment(p, v, w) { 

     function distanceSquared(v, w) { 
      return Math.pow((v.x - w.x),2) + Math.pow((v.y - w.y),2) 
     } 
     function distanceToSegmentSquared(p, v, w) { 

      var l2 = distanceSquared(v, w); 
      if (l2 === 0) return distanceSquared(p, v); 

      var t = ((p.x - v.x) * (w.x - v.x) + (p.y - v.y) * (w.y - v.y))/l2; 
      if (t < 0) return distanceSquared(p, v); 
      if (t > 1) return distanceSquared(p, w); 
      return distanceSquared(p, { x: v.x + t * (w.x - v.x), y: v.y + t * (w.y - v.y) }); 
     } 

     // Lat/Lng to x/y 
     function ll2xy(p){ 
      return {x:p.lat(),y:p.lng()}; 
     } 

     return Math.sqrt(distanceToSegmentSquared(ll2xy(p), ll2xy(v), ll2xy(w))); 
    } 

    function dp(points, tolerance) { 

     // If the segment is too small, just keep the first point. 
     // We push the final point on at the very end. 
     if (points.length <= 2) { 
      return [points[0]]; 
     } 

     var keep = [], // An array of points to keep 
      v = points[0], // Starting point that defines a segment 
      w = points[points.length-1], // Ending point that defines a segment 
      maxDistance = 0, // Distance of farthest point 
      maxIndex = 0; // Index of said point 

     // Loop over every intermediate point to find point greatest distance from segment 
     for (var i = 1, ii = points.length - 2; i <= ii; i++) { 
      var distance = distanceToSegment(points[i], points[0], points[points.length-1]); 
      if(distance > maxDistance) { 
       maxDistance = distance; 
       maxIndex = i; 
      } 
     } 

     // check if the max distance is greater than our tollerance allows 
     if (maxDistance >= tolerance) { 

      // Recursivly call dp() on first half of points 
      keep = keep.concat(dp(points.slice(0, maxIndex + 1), tolerance)); 

      // Then on second half 
      keep = keep.concat(dp(points.slice(maxIndex, points.length), tolerance)); 

     } else { 
      // Discarding intermediate point, keep the first 
      keep = [points[0]]; 
     } 
     return keep; 
    }; 

    // Push the final point on 
    keep = dp(points, tolerance); 
    keep.push(points[points.length-1]); 
    return keep; 

}; 

Ciò è stato messo insieme con l'aiuto di un paio di esempi (here e here).

Ora è possibile prendere la polilinea originale e alimentarla attraverso questa funzione con tolleranza crescente fino a quando la polilinea codificata risultante scende al di sotto del limite di lunghezza dell'URL (che dipenderà dagli altri parametri che si passano a Mappe statiche).

Qualcosa del genere dovrebbe funzionare:

var line = new google.maps.Polyline({path: path}); 
var encoded = google.maps.geometry.encoding.encodePath(line.getPath()); 
var tol = 0.0001; 
while (encoded.length > 1800) { 
    path = line.simplify(tol); 
    line = new google.maps.Polyline({path: path}); 
    encoded = google.maps.geometry.encoding.encodePath(path); 
    tol += .005; 
} 
+0

Grazie - Dovrei provare la prossima volta. In realtà ho deciso di ottenere l'immagine statica di Google e di disegnare un poligono pieno con PHP. È possibile grazie a una funzione lineare e funziona correttamente. –

+0

Questa risposta è sorprendente. Grazie mille. –