5

Google지도에서 이미지를 배치하기위한 사용자 인터페이스를 개발 중입니다. 나는 다음과 같이 시작했다 : http://overlay-tiler.googlecode.com/svn/trunk/upload.html 이것은 내가 원하는 것에 거의 가깝다.Google지도에서 회전/크기 조정/변환을 사용하여 이미지 위치 지정

하지만 3 개의 접촉점 대신 회전 도구, 크기 조정 도구 및 변환 도구 (나중에 있음)가 필요합니다.

은 내가 회전 도구를 추가하려고하지만 예상대로 작동하지 않습니다 :

내가 (이미지의 중심을) 회전을 제어하는 ​​왼쪽 하단 모서리에 점을 넣어. 마우스로 컨트롤 점을 드래그하면 3 점을 계산합니다.

내 코드는 선점 개체를 기반으로하지만 난으로 onMouseMove 기능 변경 :

overlaytiler.Rotater.prototype.rotateDot_ = function(dot, theta, origin) { 
    dot.x = ((dot.x - origin.x) * Math.cos(theta) - (dot.y - origin.y) * Math.sin(theta)) + origin.x; 
    dot.y = ((dot.x - origin.x) * Math.sin(theta) + (dot.y - origin.y) * Math.cos(theta)) + origin.y; 
    dot.render(); 
}; 

overlaytiler.Rotater.prototype.onMouseMove_ = function(e) { 
    var dots = this.controlDots_; 
    var center = overlaytiler.Rotater.prototype.getCenter_(dots); 

    // Diagonal length 
    var r = Math.sqrt(Math.pow(this.x - center.x, 2) + Math.pow(this.y - center.y, 2)); 
    var old = { 
    x: this.x, 
    y: this.y 
    }; 

    // Real position 
    var newPos = { 
    x: this.x + e.clientX - this.cx, 
    y: this.y + e.clientY - this.cy 
    } 

    var newR = Math.sqrt(Math.pow(newPos.x - center.x, 2) + Math.pow(newPos.y - center.y, 2)); 
    var theta = - Math.acos((2 * r * r - (Math.pow(newPos.x - old.x, 2) + Math.pow(newPos.y - old.y, 2)))/(2 * r * r)); 

    // Fixed distance position 
    this.x = (newPos.x - center.x) * (r/newR) + center.x; 
    this.y = (newPos.y - center.y) * (r/newR) + center.y; 

    dots[1].x = center.x + (center.x - this.x); 
    dots[1].y = center.y + (center.y - this.y); 
    dots[1].render(); 

    overlaytiler.Rotater.prototype.rotateDot_(dots[2], theta, center); 
    overlaytiler.Rotater.prototype.rotateDot_(dots[0], theta, center); 

    // Render 
    this.render(); 

    this.cx = e.clientX; 
    this.cy = e.clientY; 
}; 

불행하게도 정밀도와 각도 기호에 문제가있는 것입니다. 이미지가 매우 왜곡되고 회전이 한 방향으로 만지지되는 몇 회전 후

http://jsbin.com/iQEbIzo/4/

.

어떻게하면 왜곡없이 큰 정밀도를 얻을 수 있을지 궁금합니다.

내 접근 방식이 유용하지 않을 수도 있습니다. (오른쪽 좌표로 모서리를 이동하려고 시도합니다.) 캔버스로 이미지를 회전하려했지만 시도가 실패했습니다.

편집 : 전체 작업 버전 : http://jsbin.com/iQEbIzo/7/

답변

2

회전 한 방향으로 만

이 두 벡터 사이의 각도를 계산하는 방법에 기인 지원됩니다. 마우스가 점의 오른쪽에 있든 상관없이 항상 동일한 벡터를 제공합니다. german math board에 해결책을 찾았습니다 (불행히도 Google의 캐시를 사용하지 않고 사이트에 액세스 할 수 없습니다 : cached version). 이 예에서 각도 α는 양쪽 두 번째 하나에 -α 기대와 동일한하지에 있는지

Two vectors

참고. 벡터 a가 항상 벡터 b의 "같은면"에 있는지 알아 보려면이 공식을 사용할 수 있습니다.

ax*by - ay*bx 

이것은 양수 또는 음수입니다. 당신은 단순히 각도의 부호를 α * -1으로 변경할 수 있습니다.

코드 일부가 수정되었습니다. 당신이 알고 싶은 경우에

overlaytiler.Rotater.prototype.rotateDot_ = function(dot, theta, origin) { 
    // translate to origin 
    dot.x -= origin.x ; 
    dot.y -= origin.y ; 

    // perform rotation 
    newPos = { 
     x: dot.x*Math.cos(theta) - dot.y*Math.sin(theta), 
     y: dot.x*Math.sin(theta) + dot.y*Math.cos(theta) 
    } ; 
    dot.x = newPos.x ; 
    dot.y = newPos.y ; 

    // translate back to center 
    dot.x += origin.x ; 
    dot.y += origin.y ; 

    dot.render(); 
}; 

, 나는이 점을 회전하는 방법을 this sitethis one에 참조하시기 바랍니다.당신은 내가 벡터 계산을위한 몇 가지 기능을 쓴 것을 볼 수 있습니다

overlaytiler.Rotater.prototype.onMouseMove_ = function(e) {             
    var dots = this.controlDots_;                   
    var center = overlaytiler.Rotater.prototype.getCenter_(dots);           

    // get the location of the canvas relative to the screen                           
    var rect = new Array() ; 
    rect[0] = dots[0].canvas_.getBoundingClientRect() ; 
    rect[1] = dots[1].canvas_.getBoundingClientRect() ; 
    rect[2] = dots[2].canvas_.getBoundingClientRect() ; 

    // calculate the relative center of the image 
    var relCenter = { 
     x: (rect[0].left + rect[2].left)/2, 
     y: (rect[0].top + rect[2].top)/2 
    } ; 

    // calculate a vector from the center to the bottom left of the image 
    dotCorner = { 
     x: rect[1].left - (rect[1].left - relCenter.x) * 2 - relCenter.x, 
     y: rect[1].top - (rect[1].top - relCenter.y) * 2 - relCenter.y 
    } ;                         

    // calculate a vector from the center to the mouse position            
    mousePos = {                        
      x: e.clientX - relCenter.x,                   
      y: e.clientY - relCenter.y                    
    } ;                          

    // calculate the angle between the two vector               
    theta = calculateAngle(dotCorner, mousePos) ;               

    // is the mouse-vector left of the dot-vector -> refer to the german math board               
    if(dotCorner.y*mousePos.x - dotCorner.x*mousePos.y > 0) {            
      theta *= -1 ;                      
    }                          

    // calculate new position of the dots and render them             
    overlaytiler.Rotater.prototype.rotateDot_(dots[2], theta, center);          
    overlaytiler.Rotater.prototype.rotateDot_(dots[1], theta, center);          
    overlaytiler.Rotater.prototype.rotateDot_(dots[0], theta, center);          

    // Render                        
    this.render();                       

    this.cx = e.clientX;                      
    this.cy = e.clientY;                      
}; 

은 (단지 코드를 읽기 쉽게 만들기 위해) :

function calculateScalarProduct(v1,v2) 
{ 
    return (v1.x * v2.x + v1.y * v2.y) ; 
} 

function calculateLength(v1) 
{ 
    return (Math.sqrt(v1.x*v1.x + v1.y*v1.y)) ; 
} 

function calculateAngle(v1, v2) 
{ 
    return (Math.acos(calculateScalarProduct(v1,v2)/(calculateLength(v1)*calculateLength(v2)))) ; 
} 

이 내 작업 솔루션입니다. 당신이 무언가를 이해하지 못한다면 나는 대답을 더 포괄적으로 만들 수 있습니다.

근무 예 :

JSBin 와우,이 힘든 일이었다.

+0

축하! 작동하는 것처럼 보입니다. 각도와 회전 기능에 문제가 있다고 생각합니다. – luxcem

+0

@BenR 기꺼이 도와 드릴 수 있습니다. 나는 주된 문제가 내 생각에 무엇인지 지적하기 위해 더 많은 발언과 그래픽을 추가했다. – efux

+0

가끔 스크립트가 멈추고 이미지가 원래 위치로 돌아가고 점을 이동할 수 없습니다 ... 콘솔에 오류가 없습니다. – luxcem

2

여기 내 버전입니다. @efux와 @Ben 응답은 훨씬 더 완벽하고 잘 설계되어 있지만 확대/축소 할 때지도의 크기가 조정되지 않습니다. 오버레이는 기존지도 위에 "두 번째지도"또는 사진을 넣는 데 사용되므로이 작업을 수행해야 할 가능성이 매우 높습니다. http://jsfiddle.net/adelriosantiago/3tzzwmsx/4/

드로잉을 수행하는 코드는 다음과 같습니다 : 확인을 위해

DebugOverlay.prototype.draw = function() { 
       var overlayProjection = this.getProjection(); 
       var sw = overlayProjection.fromLatLngToDivPixel(this.bounds_.getSouthWest()); 
       var ne = overlayProjection.fromLatLngToDivPixel(this.bounds_.getNorthEast()); 
    var div = this.div_; 
    div.style.left = sw.x + 'px'; 
    div.style.top = ne.y + 'px'; 
    div.style.width = (ne.x - sw.x) + 'px'; 
    div.style.height = (sw.y - ne.y) + 'px'; 
    div.style.transform = 'rotate(' + rot + 'deg)'; 
}; 

필요한 경우이 코드 efux와 벤 코드에 구현 될 수 있지만, 내가하지 않은 다음

는 JSFiddle입니다 아직 시도했다.

주 박스 마커의 위치를 ​​갱신하지 않는 경우 회전 마커 이동 ...

+0

JSFiddle에 뭔가 빠져 있습니다. 나는'point1 (NaN, NaN)'과'point2 (NaN, NaN)'을 계속 볼 수 있지만 콘솔에는 아무런 에러도 없다. 출력에서 회색 사각형 이미지를 볼 수는 없지만 회전 기회는 절대 신경 쓰지 않아야합니다. 내가 잘못 했니? – zipzit

+0

@zipzit JSFiddle을 수정했습니다. Google지도에서 .k 및 .D 값 대신 lat() 및 lng()를 사용하고있는 것으로 보입니다. – adelriosantiago

+0

우와. 굉장해. 그래서 .. 나는 방금 [this] (http://stackoverflow.com/questions/37802325/how-can-i-rotate-an-overlay-image-on-google-maps) 질문을 스택에 올렸다. 그 일을하지 말았어야합니까? 아야. 나는 당신의 JS 바이올린을 좋아한다! – zipzit