2017-07-24 184 views
0

幾年前,我寫了一些代碼,它突出顯示了Google地圖上用寬度輸入的用戶的路徑。用戶確定突出顯示的路徑以米爲單位的寬度,以便他們可以看到他們覆蓋的地面(如草坪施肥等)。我計算了一個點的距離,並使用Google Maps computeOffset來確定多邊形的角點。接下來,我使用路徑中的方位信息繪製下一個多邊形。谷歌地圖使用多邊形模擬多段線

LatLng corner1 = SphericalUtil.computeOffset(point2, widthInMeters/2, bears + 90); 
LatLng corner2 = SphericalUtil.computeOffset(point2, widthInMeters/2, bears - 90); 
LatLng corner3 = SphericalUtil.computeOffset(corner2, distance, bears); 
LatLng corner4 = SphericalUtil.computeOffset(corner1, distance, bears); 

return new PolygonOptions().add(corner1, corner2, corner3, corner4); 

我這樣做是因爲當時Google Maps SDK沒有改變多段線寬度的方法來顯示導航路徑的寬度。 (農場實現這麼多英尺寬。)今天的折線功能在不同的縮放級別具有恆定的寬度。

Polygon mapping example at 50 feet wide

的問題是,你可以看到承載的信息是,特別是如果它被動搖周圍的設備非常不可靠。創建的路徑會產生間隙,並且多邊形不會像粗多線那樣平滑連接。

有沒有人看到有任何新的API可以突出顯示某個寬度的路徑或可調折線(球面距離佔)?我想過使用更小的多邊形,但是這是非常耗費資源的。

回答

1

怎麼樣在你的原始路徑上創建一個複雜的多邊形,使用你已經創建的每個視角的角點?

我編輯了答案,但我沒有完整的代碼來創建4個角。

您計算在左側距離/ 2 90°和,同爲右點一個點,那麼你與所有放入系統點的多邊形(從第一次離開自始至終離開他們最後右右一)

我已經嘗試過了,看起來並沒有那麼糟糕......只是當原始路徑的角度大於90°並且最後一點未畫出時出現一些問題。

enter image description here

var debug = false ; 
 

 
    jQuery(document).ready(function(){ 
 

 
     var infos = [] ; 
 
     var polyLeft = [] ; 
 
     var polyRight = [] ; 
 
     var strokeOpacity = 0 ; 
 
     var widthInMeters = 20 ; 
 
     if (debug) strokeOpacity = 0.6 ; 
 

 
     // Create a map object and specify the DOM element for display. 
 
     var map = new google.maps.Map(document.getElementById('map'), { 
 
      center: {lat: 37.772, lng: -122.214}, 
 
      scrollwheel: false, 
 
      zoom: 2 
 
     }); 
 
     
 
     var path = [{"lat":45.878521,"lng":3.694520},{"lat":45.879269,"lng":3.693960},{"lat":45.880539,"lng":3.694340},{"lat":45.882172,"lng":3.694080},{"lat":45.883900,"lng":3.692780},{"lat":45.884430,"lng":3.692930},{"lat":45.885101,"lng":3.692600},{"lat":45.885490,"lng":3.692590},{"lat":45.887169,"lng":3.692070},{"lat":45.887421,"lng":3.691580},{"lat":45.888000,"lng":3.690050},{"lat":45.888889,"lng":3.689280},{"lat":45.889408,"lng":3.688710},{"lat":45.890331,"lng":3.688690},{"lat":45.890461,"lng":3.688480},{"lat":45.890511,"lng":3.687520},{"lat":45.891251,"lng":3.687020},{"lat":45.891769,"lng":3.686900},{"lat":45.894039,"lng":3.687510},{"lat":45.896568,"lng":3.688810},{"lat":45.897430,"lng":3.689040},{"lat":45.898140,"lng":3.688630},{"lat":45.898769,"lng":3.687980},{"lat":45.899719,"lng":3.687290},{"lat":45.900040,"lng":3.687170},{"lat":45.900101,"lng":3.686700},{"lat":45.900570,"lng":3.685970},{"lat":45.901321,"lng":3.685550},{"lat":45.902061,"lng":3.685050},{"lat":45.903030,"lng":3.683950},{"lat":45.903412,"lng":3.683880},{"lat":45.903938,"lng":3.683920},{"lat":45.905102,"lng":3.683280},{"lat":45.906361,"lng":3.682710},{"lat":45.906681,"lng":3.682380},{"lat":45.907082,"lng":3.682250},{"lat":45.907970,"lng":3.682800},{"lat":45.908772,"lng":3.682820},{"lat":45.909149,"lng":3.683270},{"lat":45.909370,"lng":3.684730},{"lat":45.909679,"lng":3.685440},{"lat":45.910191,"lng":3.685902},{"lat":45.910381,"lng":3.686270},{"lat":45.911282,"lng":3.686700},{"lat":45.912209,"lng":3.687900},{"lat":45.912281,"lng":3.688140},{"lat":45.912128,"lng":3.688280},{"lat":45.911942,"lng":3.689290},{"lat":45.911709,"lng":3.690250},{"lat":45.911339,"lng":3.691200},{"lat":45.911491,"lng":3.693050},{"lat":45.912109,"lng":3.695400},{"lat":45.913391,"lng":3.698570},{"lat":45.913940,"lng":3.700200},{"lat":45.914688,"lng":3.701790},{"lat":45.915218,"lng":3.702120},{"lat":45.916248,"lng":3.703170},{"lat":45.916889,"lng":3.703440},{"lat":45.917122,"lng":3.703860},{"lat":45.917210,"lng":3.704280},{"lat":45.917770,"lng":3.704750},{"lat":45.918739,"lng":3.704860},{"lat":45.919571,"lng":3.704730},{"lat":45.919861,"lng":3.704920},{"lat":45.920139,"lng":3.706380},{"lat":45.920460,"lng":3.706880},{"lat":45.920818,"lng":3.708750},{"lat":45.921249,"lng":3.709650},{"lat":45.921680,"lng":3.711240},{"lat":45.921822,"lng":3.712880},{"lat":45.921860,"lng":3.715220},{"lat":45.921951,"lng":3.715510},{"lat":45.922371,"lng":3.715930},{"lat":45.922691,"lng":3.718220},{"lat":45.922958,"lng":3.719330},{"lat":45.923012,"lng":3.720330},{"lat":45.922821,"lng":3.721420},{"lat":45.923988,"lng":3.718530},{"lat":45.924110,"lng":3.717490},{"lat":45.924030,"lng":3.716700},{"lat":45.924389,"lng":3.715310},{"lat":45.924671,"lng":3.714956},{"lat":45.925072,"lng":3.714200},{"lat":45.925621,"lng":3.711630},{"lat":45.926830,"lng":3.709340},{"lat":45.927231,"lng":3.709070},{"lat":45.928013,"lng":3.708873},{"lat":45.929050,"lng":3.708430},{"lat":45.929790,"lng":3.707750},{"lat":45.930168,"lng":3.707290},{"lat":45.930759,"lng":3.707410},{"lat":45.931370,"lng":3.707620},{"lat":45.931900,"lng":3.707470},{"lat":45.932739,"lng":3.706920},{"lat":45.933529,"lng":3.705940},{"lat":45.934410,"lng":3.703300},{"lat":45.934662,"lng":3.701430},{"lat":45.934841,"lng":3.699650},{"lat":45.934700,"lng":3.698620},{"lat":45.934841,"lng":3.697930},{"lat":45.935371,"lng":3.696900},{"lat":45.935741,"lng":3.696590},{"lat":45.936520,"lng":3.695530},{"lat":45.936661,"lng":3.695120},{"lat":45.936729,"lng":3.694160},{"lat":45.936600,"lng":3.693150},{"lat":45.936710,"lng":3.692080},{"lat":45.936699,"lng":3.691320},{"lat":45.936989,"lng":3.690560},{"lat":45.938160,"lng":3.689220},{"lat":45.939362,"lng":3.688750},{"lat":45.940102,"lng":3.688380},{"lat":45.940521,"lng":3.687900},{"lat":45.940731,"lng":3.687590},{"lat":45.940990,"lng":3.686870},{"lat":45.941479,"lng":3.686270},{"lat":45.941959,"lng":3.685800},{"lat":45.942169,"lng":3.685150},{"lat":45.942520,"lng":3.684640},{"lat":45.942829,"lng":3.683400},{"lat":45.943020,"lng":3.682970},{"lat":45.943199,"lng":3.682250},{"lat":45.943600,"lng":3.681720},{"lat":45.944160,"lng":3.681310},{"lat":45.944771,"lng":3.681170},{"lat":45.945690,"lng":3.681750},{"lat":45.946121,"lng":3.681730},{"lat":45.946960,"lng":3.681180},{"lat":45.947201,"lng":3.681140},{"lat":45.948021,"lng":3.681520},{"lat":45.949181,"lng":3.682410},{"lat":45.949741,"lng":3.683030},{"lat":45.949959,"lng":3.683370},{"lat":45.950809,"lng":3.684230},{"lat":45.951229,"lng":3.684470},{"lat":45.952309,"lng":3.685560},{"lat":45.953129,"lng":3.685960},{"lat":45.953758,"lng":3.686160},{"lat":45.954319,"lng":3.685820},{"lat":45.955429,"lng":3.685740},{"lat":45.956108,"lng":3.685940},{"lat":45.956200,"lng":3.686010},{"lat":45.956619,"lng":3.686740},{"lat":45.956860,"lng":3.687270},{"lat":45.956921,"lng":3.687740},{"lat":45.957260,"lng":3.688530},{"lat":45.957809,"lng":3.689250},{"lat":45.958401,"lng":3.689540},{"lat":45.958851,"lng":3.689660},{"lat":45.959599,"lng":3.690140},{"lat":45.959789,"lng":3.690520},{"lat":45.960258,"lng":3.690750},{"lat":45.960571,"lng":3.691020},{"lat":45.961521,"lng":3.692110},{"lat":45.961761,"lng":3.692530}]; 
 

 
     var bounds = new google.maps.LatLngBounds() ; 
 
     map.fitBounds(bounds) ; 
 

 
     for (var i in path) 
 
      bounds.extend(path[i]) ; 
 

 
     var poly = new google.maps.Polyline({ 
 
      path: path, 
 
      strokeColor: '#FF0000', 
 
      strokeOpacity: 1.0, 
 
      strokeWeight: 2 
 
     }) 
 
     poly.setMap(map) ; 
 
     
 
     for (var k in path) 
 
     { 
 
      var currentLatLng = new google.maps.LatLng(path[k]) ; 
 
      var lastLatLng = null ; 
 
      var nextLatLng = null ; 
 
      var headingRight, headingLeft ; 
 
      var cas = 0 ; 
 

 
      if (typeof path[parseInt(k)-1] != 'undefined') lastLatLng = new google.maps.LatLng(path[parseInt(k)-1]) ; 
 
      if (typeof path[parseInt(k)+1] != 'undefined') nextLatLng = new google.maps.LatLng(path[parseInt(k)+1]) ; 
 

 
      var etat = 'lastLatLng='+lastLatLng + '<br />' + 
 
         'currentLatLng='+currentLatLng+'<br />' + 
 
         'nextLaLng='+nextLatLng+'<br />' ; 
 

 
      if (lastLatLng === null && nextLatLng !== null) 
 
      { 
 
       for (var i = 0 ; i <= 180 ; i += 10) 
 
       { 
 
       var heading = parseFloat(google.maps.geometry.spherical.computeHeading(currentLatLng,nextLatLng)) + 90 + i ; 
 
       addPoint(heading,currentLatLng,false) ; 
 
       } 
 
      } 
 

 
      if (lastLatLng !== null) 
 
      { 
 
       headingRight = parseFloat(google.maps.geometry.spherical.computeHeading(currentLatLng,lastLatLng)) - 90 ; 
 
       addPoint(headingRight,currentLatLng) ; 
 
      } 
 

 
      if (lastLatLng !== null && nextLatLng !== null) 
 
      { 
 
       cas = 'intermediaires' ; 
 
       var headingBefore = google.maps.geometry.spherical.computeHeading(currentLatLng,lastLatLng) ; 
 
       var headingAfter = google.maps.geometry.spherical.computeHeading(currentLatLng,nextLatLng) ; 
 
       headingBefore += 360 ; headingBefore = headingBefore % 360 ; 
 
       headingAfter += 360 ; headingAfter = headingAfter % 360 ; 
 
       
 
       headingRight = parseFloat((headingBefore + headingAfter)/2) ; 
 
       if (headingAfter > headingBefore) headingRight += 180 ; 
 
       headingRight += 360 ; 
 
       
 
       headingRight = headingRight % 360 ; 
 

 
       addPoint(headingRight,currentLatLng) ; 
 
      } 
 

 
      if (nextLatLng !== null) 
 
      { 
 
       headingRight = parseFloat(google.maps.geometry.spherical.computeHeading(currentLatLng,nextLatLng)) + 90 ; 
 
       addPoint(headingRight,currentLatLng) ; 
 
      } 
 

 
      if (lastLatLng !== null && nextLatLng === null) 
 
      { 
 
       for (var i = 0 ; i <= 180 ; i += 10) 
 
       { 
 
       var heading = parseFloat(google.maps.geometry.spherical.computeHeading(currentLatLng,lastLatLng)) - 90 - i ; 
 
       addPoint(heading,currentLatLng,false) ; 
 
       } 
 
      } 
 

 
      
 
      if (debug) 
 
      { 
 
       var content = etat+'<hr />'+ 
 
       'k='+k+'<br />'+ 
 
       'cas='+cas+'<br />'+ 
 
       'currentLatLng='+currentLatLng+'<br />'+ 
 
       'path[k]='+path[k]['lat']+','+path[k]['lng']+' <br /> '+ 
 
       'headingBefore='+headingBefore+'<br />'+ 
 
       'headingAfter='+headingAfter+'<br />'+ 
 
       'headingRight='+headingRight+'<br />'+ 
 
       'headingLeft='+headingLeft+'<br />' ; 
 
       /* 
 
       'pointLeft='+pointLeft.lat()+','+pointLeft.lng()+'<br />'+ 
 
       'pointLeft='+pointRight.lat()+','+pointRight.lng() ; 
 
       */ 
 

 
       var marker = new google.maps.Marker({ 
 
       position: path[k], 
 
       map: map, 
 
       title: 'Uluru (Ayers Rock)' 
 
       }); 
 
       var infowindow = new google.maps.InfoWindow() ; 
 
       
 
       google.maps.event.addListener(marker,'click', (function(marker,content,infowindow){ 
 
       return function() { 
 
        closeInfos(); 
 
        infowindow.setContent(content); 
 
        infowindow.open(map,marker); 
 
        
 
        infos[0]=infowindow; 
 
        
 
        }; 
 
       })(marker,content,infowindow)); 
 
      } 
 
      
 
     } 
 
     
 
     /* 
 
     console.log(path) ; 
 
     console.log(polyTop) ; 
 
     console.log(polyBottom) ; 
 
     */ 
 
     // At this point, polyTop and polyBottom should contain a pass parrallel as your initial path, but from widthInMeter/2 on left of the orig. path for polyFrom and widthInMeter/2 on right for polyBottom. 
 
     
 
     // It's a start, but if we want to draw a complex polygon, we need only one path of coordinates. 
 
     // What we need to do know is "mix" the 2 pathes into one, reversing bottomPath so the path created will go from first element of polyTop, to last element of polyTop, then last element of polyBottom and finish on last element of polyBottom. It should result in a sort a huge polygon making a "tour" around your original path. 
 
     
 
     new google.maps.Polyline({ 
 
      path: polyLeft, 
 
      geodesic: true, 
 
      strokeColor: '#00FF00', 
 
      strokeOpacity: strokeOpacity, 
 
      strokeWeight: 2 
 
     }).setMap(map) ; 
 

 
     new google.maps.Polyline({ 
 
      path: polyRight, 
 
      geodesic: true, 
 
      strokeColor: '#0000FF', 
 
      strokeOpacity: strokeOpacity, 
 
      strokeWeight: 2 
 
     }).setMap(map) ; 
 

 
     polyRight.reverse() ; 
 
     var polys = polyLeft.concat(polyRight) ; 
 
     
 
     var complexPoly = new google.maps.Polygon({ 
 
      paths: polys, 
 
      strokeOpacity: 0, 
 
      strokeWeight: 0, 
 
      fillColor: '#FF0000', 
 
      fillOpacity: 0.35, 
 
     }); 
 
     complexPoly.setMap(map); 
 
     
 
     function closeInfos(){ 
 
      
 
      if(infos.length > 0){ 
 
      
 
       /* detach the info-window from the marker ... undocumented in the API docs */ 
 
       infos[0].set("marker", null); 
 
      
 
       /* and close it */ 
 
       infos[0].close(); 
 
      
 
       /* blank the array */ 
 
       infos.length = 0; 
 
      } 
 
     } 
 

 
     function addPoint(hRight,currentLatLng,both=true) 
 
     { 
 
      hLeft = hRight + 180 ; 
 
      if (hLeft > 360) hLeft -= 360 ; 
 
      if (hRight > 360) hRight -= 360 ; 
 

 
      var pointRight = google.maps.geometry.spherical.computeOffset(currentLatLng,widthInMeters/2,hRight) ; 
 
      var pointLeft = google.maps.geometry.spherical.computeOffset(currentLatLng,widthInMeters/2,hLeft) ; 
 

 
      if (! isNaN(pointLeft.lat()) && ! isNaN(pointRight.lat())) 
 
      { 
 
       if (both) polyLeft.push({'lat':pointLeft.lat(),'lng':pointLeft.lng()}) ; 
 
       polyRight.push({'lat':pointRight.lat(),'lng':pointRight.lng()}) ;  
 
      } 
 
     } 
 

 
    }) ;
#map { 
 

 
    width:400px ; 
 
    height:200px ; 
 
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
 
<script src="https://maps.googleapis.com/maps/api/js?libraries=geometry"></script> 
 
    <div id="map"></div>

+0

謝謝,但strokeWeight,用於不必在爲米任意連接寬度。如果用戶的路徑寬度爲75米,則無法將其轉換爲正確的衝程重量或寬度。多段線需要精確地輸入寬度。這是一個類似的問題:https://stackoverflow.com/questions/17651293/draw-google-polyline-with-line-width-set-in-meters但唯一的答案是Android API或iOS上沒有JavaScript API Google SDK。無論如何,進行像素轉換在不同設備上聽起來都有風險。 – johnsonjp34

+0

是的,它顯然與strokeWeight不一致。我已經編輯了我的答案,並在解決方案開始時創建了一個圍繞您的路徑的多邊形:您可以看看它嗎? –

+0

這是一個非常好的主意。我可以繪製平行的多段線,並將線條的寬度變薄,以便不會對其造成太大影響。接下來,我將重點介紹線條之間的區域。謝謝!我想我可以製作一個大的多邊形來填充中心。不要關閉底部和頂部,以便始終顯示一個大的多邊形。 – johnsonjp34