2016-09-16 71 views
0

距離畫在畫布上

<html> 
 
<body style="margin:10px;"> 
 
<canvas id="myCanvas" width="500" height="500" style="border:1px solid #d3d3d3;"> 
 
</canvas> 
 
    
 
</body> 
 
    
 
<script language="javascript" type="text/javascript"> 
 

 

 

 
     var canvas = document.getElementById('myCanvas'); 
 
     var context = canvas.getContext('2d'); 
 

 
     var centerX = 400; 
 
     var centerY = 400; 
 
     var radius = .5; 
 

 
     context.beginPath(400,400); 
 
     context.arc(centerX, centerY, radius, 0, 2 * Math.PI, false); 
 
     context.fillStyle = 'blue'; 
 
     context.fill(); 
 
     context.lineWidth = 1; 
 
     context.strokeStyle = '#003300'; 
 
     context.stroke(); 
 

 

 

 
     context.beginPath(); 
 
     context.moveTo(50, 250); 
 
     context.bezierCurveTo(50, 250, 50, 250, 50, 250); 
 
     context.bezierCurveTo(90, 210, 90, 210, 90, 210); 
 
     context.bezierCurveTo(130, 90, 130, 90, 130, 90); 
 
     context.bezierCurveTo(260, 240, 260, 240, 260, 240); 
 
     context.bezierCurveTo(255, 400, 255, 400, 255, 400); 
 

 
     context.closePath(); 
 
     context.lineWidth = 1; 
 
     context.strokeStyle = 'green'; 
 
     context.stroke(); 
 
    
 
</script> 
 
\t 
 
\t 
 
\t 
 
\t 
 
</html>

第一次張貼在這裏,但這個網站已經幫助了我很多與其他灰色地帶我有!

我想確定從畫布上的點到形狀邊緣的距離。形狀將是不規則的,例如,如果它的三角形我不認爲如果距離公式超出三角形的邊緣,它將不起作用。

我有點沮喪,因爲這可能是我的項目的垮臺。任何開放的想法,將不勝感激!

謝謝

編輯:這裏就是我說的,在這個例子中,我想知道這是多少像素從共同ORD 400,400對象的最近點的例子。但對於我的項目,無論這個點在哪裏,我都希望能夠測量到物體的最近點。

我知道這是很多要問,但我想我會給它一個鏡頭!

感謝您提前回復!

+1

形狀是否都是多邊形 - 由線段組成?當你說「距離」時,你的意思是指形狀還是別的什麼?如果對兩者都是肯定的,你可以測試多邊形的每一條線段並[找到距離該點最小的距離](http:// stackoverflow。COM /問題/ 29021887 /拖拽點-沿着矢量與 - 小鼠/ 29023665#29023665)。 – markE

+0

邊緣x,y座標將根據所使用的多邊形和畫布方法而變化....您可以發佈代碼示例嗎? – KpTheConstructor

+0

據我所知(在所有誠實中有點生鏽),因爲Canvas使用光柵(像素)繪圖,所以一旦你畫出一個形狀就會被遺忘,當然,你可以比較每個像素的顏色,但這將是昂貴的。最好的方法是跟蹤你畫到畫布上的每一個形狀,並與這些形狀進行比較,至於數學背後的真正取決於你的使用情況 –

回答

2

這個問題的範圍對於我來說寫很多解決方案。我將概述如何添加一些限制。

形狀是一組弧形,線條,曲線(立方體和二次方)以及矩形,它們可以連接也可以不連接。距離將是定義每個形狀的線上最近的點,並且不包括線寬。形狀都在相同的規模和方向。

最好的方法是使用MarkE指出的距離線功能(在他的評論「find the least distance from the point」中)並將所有路徑對象轉換爲線。如何細分每條曲線將決定位置的準確度,直線不需要細分。但假設你只是在一個像素之後(鼠標分辨率),那麼代碼就不會做太多的處理。

您可以將行定義爲點集。由於您可能有未加入的路徑,所以這些點集將位於二維數組中。

var lines = []; 
var currentLine = null; 
function startLine(){ 
    if(currentLine.length > 0){ 
     currentLine = []; // new array 
     lines.push(cuurentLine); // push onto the line array 
    } 
} 
function moveToPoint(x,y){ 
    startLine(); 
    addPoint(x,y); 
} 
function addPoint(x,y){ 
    currentLine.push(x:x,y:y); 
} 
function closePath(){ 
    currentLine.push(currentLine[0]); 
} 

然後你就可以匹配調用上述功能

所有渲染調用一個最簡單的一組線

ctx.beginPath(); 
ctx.moveTo(x,y); // to save me time x and y are points of some coordinate. 
ctx.lineTo(x,y); 
ctx.lineTo(x,y); 
ctx.lineTo(x,y); 
ctx.closePath(); 

應與

startLine(); // you really only need moveToPoint 
moveToPoint(x,y); 
addPoint(x,y); 
addPoint(x,y); 
addPoint(x,y); 
closePath(); 
匹配

您的陣列應該看起來像

// p represents a point {x :x,y: y} 
lines [[p,p,p,p,p]]; // An array inside lines with 5 points. The last point is 
        // back to the start 

如果添加另一個路徑

ctx.moveTo(x,y); // to save me time x and y are points of some coordinate. 
ctx.lineTo(x,y); 
ctx.lineTo(x,y); 
ctx.lineTo(x,y); 
// note I did not close path 

你必須

moveToPoint(x,y); 
addPoint(x,y); 
addPoint(x,y); 
addPoint(x,y); 

與之相匹配的陣列現在看起來像

// p represents a point {x :x,y: y} 
lines [[p,p,p,p,p],[p,p,p,p]]; // not second path is not closed and has one less point 

,幷包含兩個路徑。

然後,您可以檢查使用線功能(在回答的頂部鏈接)找到最接近的形狀,你有你只需要調用該函數,你必須形狀

function findclosestPoint(px,py){ // the point px,py 
    var minDist = Infinity; 
    var pf = {x:0,y:0}; // the closest point 
    for(i = 0; i < lines.length; i+=1){ 
     for(j = 0; j < lines[i].length-1; j+=1){ 
      var p = lines[i][j]; 
      var p1 = lines[i][j+1]; 
      // get closet point 
      var cp = getClosestPointOnLine({x0 : p.x, y0 : p.y, x1 : p1.x, y1 : p1.y},px,py); 
      // then get the distance. 
      var x = cp.x - px; 
      var y = cp.y - py; 
      x *= x; 
      y *= y; 
      var dist = Math.sqrt(x + y); 

      // is it the closest? 
      if(dist < minDist){ 
       minDist = dist; // yes remember this distance 
       pf.x = cp.x; 
       pf.y = cp.y; 
      } 
     } 
    } 
    return {dist : minDist, point : pf}; 
}   

的點解決方案。

var closest = findclosestPoint(400,400); 
console.log(closest.point) ;// >> {x:?,y:?} 
console.log(closest.dist) ;// >> ? in pixels 

爲了讓它適用於弧線,創建一個將弧線分割成更小的線段的功能。貝塞爾曲線和三次曲線相同。相隔2至3個像素的間隔點應該足夠多。在StackOverflow中有很多用於查找弧和貝塞爾點的示例。

對於矩形作爲一個例子

ctx.rect(x,y,w,h); 

創建一個函數來添加定義矩形的線條。

function addRect(x,y,w,h) 
    addPoint(x,y) // rects start at top left 
    addPoint(x+w,y) 
    addPoint(x+w,y+h) 
    addPoint(x,y+h) 
    addPoint(x,y) 
} 

請記住,fillrect和strokeRect以moveTo開頭,因此如果需要添加moveToPoint函數調用。

對弧和貝塞爾曲線做同樣的操作。

這就是它的全部。

如果你打算有不同的比例和旋轉,你將不得不添加這些轉換時,你將點添加到線陣列。

如果您希望包含線寬,您將不得不爲每條線的邊緣創建線條。對貝塞爾來說,這可能會很棘手,但是對於每個在堆棧中的子問題都有解決方案。從基礎開始,提煉直至達到目標。

+0

非常感謝! – Mick