2011-11-15 3 views
3

패키지 여행을위한 일종의 일정 매퍼에서 일하고 있으며, 지금까지 내가 한 일에 정말 만족합니다. 방향을 api 사용자 정의 렌더러 구현, 그래서 운전 방향을 걸릴 수 내 자신의 폴리 라인 경로를 따라 간격 Google의 끔찍한되지 않습니다 방향 화살표 완료. 나는 정확하게 수학 전문가는 아니며, 나는 다른 길과 평행 한 길을 만들 수있는 방법을 찾아 내려고 노력하고 있습니다. 예를 들어 여정은 도시 1에서 도시 2로 이동 한 다음 도시 1로 돌아갑니다.Google지도 api 병렬 경로 라인

도시 1의 폴리 라인으로 다시 이동하여 경로를 반영하지만 이동할 수 있습니다. 이상적으로, 나는 경로를 만들 때, 다른 경로에서 교차점을 확인하고, 발견 된 경우 해당 점에서만 경로를 오프셋하는 것이 좋습니다. 예를 들어 짧은 시간 동안 만 다른 경로를 만나는 경우와 같이 다른 경로와 교차하는 경우에만 경로를 병렬 처리 할 수 ​​있으므로 더 나은 구현이됩니다. http://wtp2.appspot.com/ParallelLines.htm

업데이트 : 어떻게 든이 v3에서 작업을 진행하는이 오래된 V2 스크립트를 변환하기 위해 관리하지만 일부 발생하고있어

나는

이 링크는 여기에 법안 채드윅에서 API2이 코드를 발견 문제 ...

원래의 포인트 수가 두 배 이상이고 경로를 따라 가면서 실제로 무작위로 던지는 것입니다. 여기에 스크린 샷 : I 변환

Google maps screenshot

클래스는 여기에 있습니다 :이 점에 노력하고 있습니다

function BDCCParallelLines(points, color, weight, opacity, opts, gapPx) { 

    console.log('Pllel COnstructor Initialized'); 
    this.gapPx = gapPx; 
    this.points = points; 
    this.color = color; 
    this.weight = weight; 
    this.opacity = opacity; 
    this.opts = opts; 
    this.line1 = null; 
    this.line2 = null; 
    this.lstnZoom = null; 
} 


BDCCParallelLines.prototype = new google.maps.OverlayView(); 



BDCCParallelLines.prototype.onAdd = function() { 
console.log('Pllel Initialized'); 
this.prj = map.getProjection(); 

var self = this; 
    this.lstnZoom = google.maps.event.addListener(map, "zoom_changed", function() { 
self.recalc(); 
    }); 
    this.recalc();//first draw 
} 


BDCCParallelLines.prototype.onRemove = function() { 

    if(this.line2) 
     this.line2.setMap(null); 
    if(this.line1) 
     this.line1.setMap(null); 
    if(this.lstnZoom != null) 
     google.maps.event.removeListener(this.lstnZoom); 

} 

BDCCParallelLines.prototype.copy = function() { 
    return new BDCCParallelLines(this.points,this.color,this.weight,this.opacity,this.opts,this.gapPx); 
} 

BDCCParallelLines.prototype.draw = function(force) { 
    return; //do nothing 
} 




    /** 
* @param {google.maps.Map} map 
* @param {google.maps.LatLng} latlng 
* @param {int} z 
* @return {google.maps.Point} 
*/ 
BDCCParallelLines.prototype.latLngToPoint = function(latlng, z){ 
var normalizedPoint = map.getProjection().fromLatLngToPoint(latlng); // returns x,y normalized to 0~255 
var scale = Math.pow(2, z); 
var pixelCoordinate = new google.maps.Point(normalizedPoint.x * scale, normalizedPoint.y * scale); 
return pixelCoordinate; 
}; 
/** 
* @param {google.maps.Map} map 
* @param {google.maps.Point} point 
* @param {int} z 
* @return {google.maps.LatLng} 
*/ 
BDCCParallelLines.prototype.pointToLatlng = function(point, z){ 
var scale = Math.pow(2, z); 
var normalizedPoint = new google.maps.Point(point.x/scale, point.y/scale); 
var latlng = map.getProjection().fromPointToLatLng(normalizedPoint); 
return latlng; 
}; 


BDCCParallelLines.prototype.recalc = function() { 

var distallowance; 
console.log('recalc called'); 
    var zoom = map.getZoom(); 
    distallowance = 1.6; 
    if(zoom > 6){ 
     distallowance = 1.3; 
     if(zoom > 9){ 
      distallowance = .7; 
      if(zoom > 13){ 
       distallowance = .2; 
       if(zoom > 15){ 
       distallowance = .0001; 
       } 
       } 

      }  
     } 
     console.log('Zoom Level: ' + zoom); 
     console.log('Allowance = ' + distallowance); 


    var pts1 = new Array();//left side of center 

    //shift the pts array away from the centre-line by half the gap + half the line width 
    var o = (this.gapPx + this.weight)/2; 

    var p2l,p2r; 

    for (var i=1; i<this.points.length; i++){ 

     var p1lm1; 
     var p1rm1; 
     var p2lm1; 
     var p2rm1; 
     var thetam1; 

     var p1 = this.latLngToPoint(this.points[i-1], zoom) 
     var p2 = this.latLngToPoint(this.points[i], zoom) 
     var theta = Math.atan2(p1.x-p2.x,p1.y-p2.y); 
     theta = theta + (Math.PI/2); 


     var dl = Math.sqrt(((p1.x-p2.x)*(p1.x-p2.x))+((p1.y-p2.y)*(p1.y-p2.y))); 

     if(theta > Math.PI) 
      theta -= Math.PI*2; 
     var dx = Math.round(o * Math.sin(theta)); 
     var dy = Math.round(o * Math.cos(theta)); 

     var p1l = new google.maps.Point(p1.x+dx,p1.y+dy); 
     var p1r = new google.maps.Point(p1.x-dx,p1.y-dy); 
     p2l = new google.maps.Point(p2.x+dx,p2.y+dy); 
     p2r = new google.maps.Point(p2.x-dx,p2.y-dy); 

     if(i==1){ //first point 
     pts1.push(this.pointToLatlng(p1l,zoom)); 
     } 
     else{ // mid this.points 

    if(distbetweentwo(this.points[i-1], this.points[i]) > distallowance){ 

     if(theta == thetam1){ 
      // adjacent segments in a straight line 
     pts1.push(this.pointToLatlng(p1l,zoom)); 
     } 
     else{ 
      var pli = this.intersect(p1lm1,p2lm1,p1l,p2l); 
      var pri = this.intersect(p1rm1,p2rm1,p1r,p2r); 

      var dlxi = (pli.x-p1.x); 
      var dlyi = (pli.y-p1.y); 
      var drxi = (pri.x-p1.x); 
      var dryi = (pri.y-p1.y); 
     var di = Math.sqrt((drxi*drxi)+(dryi*dryi)); 
      var s = o/di; 

      var dTheta = theta - thetam1; 
      if(dTheta < (Math.PI*2)) 
       dTheta += Math.PI*2; 
      if(dTheta > (Math.PI*2)) 
       dTheta -= Math.PI*2; 

      if(dTheta < Math.PI){ 
       //intersect point on outside bend 
      pts1.push(this.pointToLatlng(p2lm1,zoom)); 
      pts1.push(this.pointToLatlng(new google.maps.Point(p1.x+(s*dlxi),p1.y+(s*dlyi)),zoom)); 
      pts1.push(this.pointToLatlng(p1l,zoom)); 


      } 
     else if (di < dl){ 

     pts1.push(this.pointToLatlng(pli,zoom)); 

     } 
      else{ 

       pts1.push(this.pointToLatlng(p2lm1,zoom)); 
       pts1.push(this.pointToLatlng(p1l,zoom)); 

     } 



     } 

    } 
    else{ 
    //console.log(distbetweentwo(this.points[i-1], this.points[i])); 
    } 
    } 




     p1lm1 = p1l; 
     p1rm1 = p1r; 
     p2lm1 = p2l; 
     p2rm1 = p2r; 
     thetam1 = theta; 

     //end loop 
    } 

    pts1.push(this.pointToLatlng(p2l,zoom));//final point 

    // console.log(pts1); 

    if(this.line1) 
    this.line1.setMap(null); 
     this.line1 = new google.maps.Polyline({ 
     strokeColor: this.color, 
     strokeOpacity: this.opacity, 
     strokeWeight: this.weight, 
     map: map, 
     path: pts1 }); 


    this.line1.setMap(map); 


} 

BDCCParallelLines.prototype.intersect = function(p0,p1,p2,p3) 
{ 
// this function computes the intersection of the sent lines p0-p1 and p2-p3 
// and returns the intersection point, 

var a1,b1,c1, // constants of linear equations 
    a2,b2,c2, 
    det_inv, // the inverse of the determinant of the coefficient matrix 
    m1,m2; // the slopes of each line 

var x0 = p0.x; 
var y0 = p0.y; 
var x1 = p1.x; 
var y1 = p1.y; 
var x2 = p2.x; 
var y2 = p2.y; 
var x3 = p3.x; 
var y3 = p3.y; 

// compute slopes, note the cludge for infinity, however, this will 
// be close enough 

if ((x1-x0)!=0) 
    m1 = (y1-y0)/(x1-x0); 
else 
    m1 = 1e+10; // close enough to infinity 

if ((x3-x2)!=0) 
    m2 = (y3-y2)/(x3-x2); 
else 
    m2 = 1e+10; // close enough to infinity 

// compute constants 

a1 = m1; 
a2 = m2; 

b1 = -1; 
b2 = -1; 

c1 = (y0-m1*x0); 
c2 = (y2-m2*x2); 

// compute the inverse of the determinate 

det_inv = 1/(a1*b2 - a2*b1); 

// use Kramers rule to compute xi and yi 

var xi=((b1*c2 - b2*c1)*det_inv); 
var yi=((a2*c1 - a1*c2)*det_inv); 

return new google.maps.Point(Math.round(xi),Math.round(yi)); 

} 

... 그것은 원래의 구현뿐만 아니라 노력하고 있습니다. 전체 경로는 확대/축소 기준으로 다시 계산되며 더 높은 확대/축소 수준에서는 매우 짧은 경로 (이상한 각도)를 건너 뛰는 기능을 해킹했습니다. 확대하면 경로가 더 가깝습니다.

꽤 집약적 인 것처럼 재 계산되지 않는 고정 된 거리 오프셋을 가지고 있습니다 ...이 위업, rhino3d, autocad, 일러스트 레이터를 수행하는 많은 프로그램이 있습니다 ... Google지도 자체의 길 찾기에 도움이 될 것 같아요. , 왕복 여행과 원래 여행을 구별 할 수 있도록 경로의 오프셋.

Google지도가 아닌 경우에도 JS에서 이와 비슷한 작업을 한 사람은 누구나 볼 수 있습니다. 링크 내가 조사하고 있습니다 : 일반적으로

http://processingjs.nihongoresources.com/bezierinfo/

http://www.groupsrv.com/computers/about21532.html

+0

문제를 해결 했습니까? 감사합니다 – SERG

답변

4

오프셋 경로입니다 꽤 까다로운 사업입니다은. 이 논문 (과학 논문의 경고)은 '전문적인'오프셋 알고리즘을 위해 취해진 조치에 대한 좋은 설명을 제공합니다.

http://cgcad.thss.tsinghua.edu.cn/~yongjh/papers/CiI2007V58N03P0240.pdf

+0

와우 .... 그래, 그건 내 머리 위로 방법입니다, 나는 대학에 머물러 야한다고 생각합니다! 음 .. 나는 지금 당장 가지고있는 것들로 놀아나 겠지만 정보에 감사드립니다. – Ben

0

당신은 데모로 공상으로 아무것도 원하는 것 같지 않습니다. 내가 모은 것에서는 동일한 폴리 라인을 원한다. 일부 픽셀은 오른쪽으로 이동하고 일부는 맨 위로 이동하여 겹치지 않도록한다.

게시 한 코드에는 latLngToPoint 기능과 pointToLatLng 기능이 있습니다.Google에서 얻은 길 찾기는 LatLng이므로 점으로 변환하고 x 및 y 속성을 늘리면 다시 LatLng로 변환하고 폴리 라인을 그릴 수 있습니다.

원본 줄에 정확히 일치하는 줄이 있어야합니다. 그러나 데모에서 보는 것처럼 화려하지는 않습니다. 이후 아무런 포인트가 추가되지 않습니다 부드러운 라인.

+0

음 - 당신은 그 소리를 진짜 간단하게 만들었지 만, 나는 단지 x와 y를 덧붙일 수는 없습니다. 나는 이미 청구서 채드윅의 데모의 전체 기반 인 포인트 변환 기능을 사용하고있다. x, y 점에 임의의 숫자를 단순히 덧붙이면 겹치는 선으로 끝나고 실제로 경로를 따라 가지 않습니다. 실제로 각 점 쌍의 폴리 라인을 계산 한 다음 그 폴리선의 (아크 탄젠트?)를 계산하여 어느 방향으로 옵셋해야하는지 확인해야합니다. 그리고 이것은 조금만 상쇄하는 경우에 효과적입니다. 그러나 다음과 같은 커브가있을 때 : \ _/: – Ben

+0

그리고 거리가 약간 벗어난다면 모든 로직이 깨집니다. 커브의 정확한 복사본을 만들지 않기 때문에 ... 거리에서 오프셋 할 때 스케일링과 비슷합니다. – Ben

+0

아마도 교차점과 같이 선의 방향이 바뀌면 감지 할 수 있습니다. 다음 그림이 그 예입니다. http://img855.imageshack.us/img855/4063/crossover.png – Halcyon