Draw circle's arc on google maps

后端 未结 1 1240
长情又很酷
长情又很酷 2020-12-05 09:02

The idea is to draw an arc centered on a specific point, using angles. Note: Not the chord, nor the sector, nor the area between the chord and the arc.

Memento: http

相关标签:
1条回答
  • 2020-12-05 09:33

    This is the code I use in this example:

    function drawArc(center, initialBearing, finalBearing, radius) { 
      var d2r = Math.PI / 180;   // degrees to radians 
      var r2d = 180 / Math.PI;   // radians to degrees 
    
      var points = 32; 
    
      // find the raidus in lat/lon 
      var rlat = (radius / EarthRadiusMeters) * r2d; 
      var rlng = rlat / Math.cos(center.lat() * d2r); 
    
      var extp = new Array();
    
      if (initialBearing > finalBearing) finalBearing += 360;
      var deltaBearing = finalBearing - initialBearing;
      deltaBearing = deltaBearing/points;
      for (var i=0; (i < points+1); i++) 
      { 
        extp.push(center.DestinationPoint(initialBearing + i*deltaBearing, radius)); 
        bounds.extend(extp[extp.length-1]);
      } 
      return extp;
    }
    

    Used like this, where startPoint it the start of the arc, endPoint is the end of the arc and centerPoint is the center, but you can specify center, angles and radius.

    var arcPts = drawArc(centerPoint, centerPoint.Bearing(startPoint), centerPoint.Bearing(endPoint), centerPoint.distanceFrom(startPoint));
    
    
    var piePoly = new google.maps.Polygon({
                 paths: [arcPts],
                 strokeColor: "#00FF00",
                 strokeOpacity: 0.5,
                 strokeWeight: 2,
                 fillColor: "#FF0000",
                 fillOpacity: 0.35,
                 map: map
     });
    

    Ancillary functions, may no longer be necessary if you include the geometry library

    var EarthRadiusMeters = 6378137.0; // meters
    /* Based the on the Latitude/longitude spherical geodesy formulae & scripts
       at http://www.movable-type.co.uk/scripts/latlong.html
       (c) Chris Veness 2002-2010
    */ 
    google.maps.LatLng.prototype.DestinationPoint = function (brng, dist) {
    var R = EarthRadiusMeters; // earth's mean radius in meters
    var brng = brng.toRad();
    var lat1 = this.lat().toRad(), lon1 = this.lng().toRad();
    var lat2 = Math.asin( Math.sin(lat1)*Math.cos(dist/R) + 
                          Math.cos(lat1)*Math.sin(dist/R)*Math.cos(brng) );
    var lon2 = lon1 + Math.atan2(Math.sin(brng)*Math.sin(dist/R)*Math.cos(lat1), 
                                 Math.cos(dist/R)-Math.sin(lat1)*Math.sin(lat2));
    
    return new google.maps.LatLng(lat2.toDeg(), lon2.toDeg());
    }
    
    // === A function which returns the bearing between two LatLng in radians ===
    // === If v1 is null, it returns the bearing between the first and last vertex ===
    // === If v1 is present but v2 is null, returns the bearing from v1 to the next vertex ===
    // === If either vertex is out of range, returns void ===
    google.maps.LatLng.prototype.Bearing = function(otherLatLng) {
      var from = this;
      var to = otherLatLng;
      if (from.equals(to)) {
        return 0;
      }
      var lat1 = from.latRadians();
      var lon1 = from.lngRadians();
      var lat2 = to.latRadians();
      var lon2 = to.lngRadians();
      var angle = - Math.atan2( Math.sin( lon1 - lon2 ) * Math.cos( lat2 ), Math.cos( lat1 ) * Math.sin( lat2 ) - Math.sin( lat1 ) * Math.cos( lat2 ) * Math.cos( lon1 - lon2 ) );
      if ( angle < 0.0 ) angle  += Math.PI * 2.0;
      if ( angle > Math.PI ) angle -= Math.PI * 2.0; 
      return parseFloat(angle.toDeg());
    }
    
    
    /**
     * Extend the Number object to convert degrees to radians
     *
     * @return {Number} Bearing in radians
     * @ignore
     */ 
    Number.prototype.toRad = function () {
      return this * Math.PI / 180;
    };
    
    /**
     * Extend the Number object to convert radians to degrees
     *
     * @return {Number} Bearing in degrees
     * @ignore
     */ 
    Number.prototype.toDeg = function () {
      return this * 180 / Math.PI;
    };
    
    /**
     * Normalize a heading in degrees to between 0 and +360
     *
     * @return {Number} Return 
     * @ignore
     */ 
    Number.prototype.toBrng = function () {
      return (this.toDeg() + 360) % 360;
    };
    

    code snippet (using geometry library):

    var EarthRadiusMeters = 6378137.0; // meters
    /* Based the on the Latitude/longitude spherical geodesy formulae & scripts
       at http://www.movable-type.co.uk/scripts/latlong.html
       (c) Chris Veness 2002-2010
    */
    google.maps.LatLng.prototype.DestinationPoint = function(brng, dist) {
      var R = EarthRadiusMeters; // earth's mean radius in meters
      var brng = brng.toRad();
      var lat1 = this.lat().toRad(),
        lon1 = this.lng().toRad();
      var lat2 = Math.asin(Math.sin(lat1) * Math.cos(dist / R) +
        Math.cos(lat1) * Math.sin(dist / R) * Math.cos(brng));
      var lon2 = lon1 + Math.atan2(Math.sin(brng) * Math.sin(dist / R) * Math.cos(lat1),
        Math.cos(dist / R) - Math.sin(lat1) * Math.sin(lat2));
    
      return new google.maps.LatLng(lat2.toDeg(), lon2.toDeg());
    }
    
    /**
     * Extend the Number object to convert degrees to radians
     *
     * @return {Number} Bearing in radians
     * @ignore
     */
    Number.prototype.toRad = function() {
      return this * Math.PI / 180;
    };
    
    /**
     * Extend the Number object to convert radians to degrees
     *
     * @return {Number} Bearing in degrees
     * @ignore
     */
    Number.prototype.toDeg = function() {
      return this * 180 / Math.PI;
    };
    
    var infowindow = new google.maps.InfoWindow({
      size: new google.maps.Size(150, 50)
    });
    
    function createMarker(latlng, html) {
      var contentString = html;
      var marker = new google.maps.Marker({
        position: latlng,
        map: map,
        zIndex: Math.round(latlng.lat() * -100000) << 5
      });
      bounds.extend(latlng);
      google.maps.event.addListener(marker, 'click', function() {
        infowindow.setContent(contentString);
        infowindow.open(map, marker);
      });
    }
    
    function drawArc(center, initialBearing, finalBearing, radius) {
      var d2r = Math.PI / 180; // degrees to radians 
      var r2d = 180 / Math.PI; // radians to degrees 
    
      var points = 32;
    
      // find the raidus in lat/lon 
      var rlat = (radius / EarthRadiusMeters) * r2d;
      var rlng = rlat / Math.cos(center.lat() * d2r);
    
      var extp = new Array();
    
      if (initialBearing > finalBearing) finalBearing += 360;
      var deltaBearing = finalBearing - initialBearing;
      deltaBearing = deltaBearing / points;
      for (var i = 0;
        (i < points + 1); i++) {
        extp.push(center.DestinationPoint(initialBearing + i * deltaBearing, radius));
        bounds.extend(extp[extp.length - 1]);
      }
      return extp;
    }
    
    function drawCircle(point, radius) {
      var d2r = Math.PI / 180; // degrees to radians 
      var r2d = 180 / Math.PI; // radians to degrees 
      var EarthRadiusMeters = 6378137.0; // meters
      var earthsradius = 3963; // 3963 is the radius of the earth in miles
    
      var points = 32;
    
      // find the raidus in lat/lon 
      var rlat = (radius / EarthRadiusMeters) * r2d;
      var rlng = rlat / Math.cos(point.lat() * d2r);
    
    
      var extp = new Array();
      for (var i = 0; i < points + 1; i++) // one extra here makes sure we connect the 
      {
        var theta = Math.PI * (i / (points / 2));
        ey = point.lng() + (rlng * Math.cos(theta)); // center a + radius x * cos(theta) 
        ex = point.lat() + (rlat * Math.sin(theta)); // center b + radius y * sin(theta) 
        extp.push(new google.maps.LatLng(ex, ey));
        bounds.extend(extp[extp.length - 1]);
      }
      // alert(extp.length);
      return extp;
    }
    
    var map = null;
    var bounds = null;
    
    function initialize() {
      var myOptions = {
        zoom: 10,
        center: new google.maps.LatLng(-33.9, 151.2),
        mapTypeControl: true,
        mapTypeControlOptions: {
          style: google.maps.MapTypeControlStyle.DROPDOWN_MENU
        },
        navigationControl: true,
        mapTypeId: google.maps.MapTypeId.ROADMAP
      }
      map = new google.maps.Map(document.getElementById("map_canvas"),
        myOptions);
    
      bounds = new google.maps.LatLngBounds();
    
      google.maps.event.addListener(map, 'click', function() {
        infowindow.close();
      });
    
      var startPoint = new google.maps.LatLng(48.610335003092956, -1.6123447775299600);
      var endPoint = new google.maps.LatLng(48.596190206866830, -1.5551704322317228);
      var centerPoint = new google.maps.LatLng(48.565630000000006, -1.6050300000000002);
      createMarker(startPoint, "start: " + startPoint.toUrlValue(6) + "<br>distance to center: " + (google.maps.geometry.spherical.computeDistanceBetween(centerPoint, startPoint) / 1000).toFixed(3) + " km<br>Bearing: " + google.maps.geometry.spherical.computeHeading(centerPoint, startPoint) + "<br><a href='javascript:map.setCenter(new google.maps.LatLng(" + startPoint.toUrlValue(6) + "));map.setZoom(20);'>zoom in</a> - <a href='javascript:map.fitBounds(bounds);'>zoom out</a>");
      createMarker(endPoint, "end: " + endPoint.toUrlValue(6) + "<br>distance to center: " + (google.maps.geometry.spherical.computeDistanceBetween(centerPoint, endPoint) / 1000).toFixed(3) + " km<br>Bearing: " + google.maps.geometry.spherical.computeHeading(centerPoint, endPoint) + "<br><a href='javascript:map.setCenter(new google.maps.LatLng(" + endPoint.toUrlValue(6) + "));map.setZoom(20);'>zoom in</a> - <a href='javascript:map.fitBounds(bounds);'>zoom out</a>");
      createMarker(centerPoint, "center: " + centerPoint.toUrlValue(6));
    
      var arcPts = drawArc(centerPoint, google.maps.geometry.spherical.computeHeading(centerPoint, startPoint), google.maps.geometry.spherical.computeHeading(centerPoint, endPoint), google.maps.geometry.spherical.computeDistanceBetween(centerPoint, startPoint));
      // add the start and end lines
      arcPts.push(centerPoint);
      bounds.extend(centerPoint);
      arcPts.push(startPoint);
    
      var piePoly = new google.maps.Polygon({
        paths: [arcPts],
        strokeColor: "#00FF00",
        strokeOpacity: 0.5,
        strokeWeight: 2,
        fillColor: "#FF0000",
        fillOpacity: 0.35,
        map: map
      });
    
      map.fitBounds(bounds);
    }
    google.maps.event.addDomListener(window, 'load', initialize);
    html,
    body,
    #map_canvas {
      height: 100%;
      width: 100%;
      margin: 0;
      padding: 0;
    }
    <script type="text/javascript" src="http://maps.google.com/maps/api/js?key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk&libraries=geometry"></script>
    <div id="map_canvas"></div>

    0 讨论(0)
提交回复
热议问题