2013-09-30 24 views
0

我嘗試用coffeescript重寫這段代碼,來自http://jsfromhell.com/math/is-point-in-poly。它檢測一個點是否在一個多邊形中,並且工作得很好,但我不確定一個優雅的咖啡文本翻譯會是什麼樣的?如何重寫從javascript到coffeescript的更復雜的循環?

function isPointInPoly(poly, pt){ 
    for(var c = false, i = -1, l = poly.length, j = l - 1; ++i < l; j = i) 
    ((poly[i].y <= pt.y && pt.y < poly[j].y) || (poly[j].y <= pt.y && pt.y < poly[i].y)) 
    && (pt.x < (poly[j].x - poly[i].x) * (pt.y - poly[i].y)/(poly[j].y - poly[i].y) + poly[i].x) 
    && (c = !c); 
return c; 
} 
+4

您是否試圖首先獲得優雅的JavaScript版本? – Bergi

+0

http://js2coffee.org/ – Mathletics

+0

謝謝你的js2coffee.org,這是一個很好的。因爲我的問題被授予-1,所以我可能沒有清楚地問清我的主要問題是什麼:在聲明中用重寫來重寫for循環的適當方法是什麼? js2coffee建議的while循環是要走的路嗎? –

回答

4

正如比較(雙關語意)的一個點,這裏是這個算法我幾年前寫的部分的版本PolyGonzo(我在Google競選地圖中使用的一個快速多邊形繪圖庫)。這是從原來的,它處理多面體,通常用於地理工作,而不是單一的多邊形。

我爲速度寫了這段代碼 - 它應該比舊版瀏覽器的問題代碼快得多,而且在新瀏覽器中速度要快一些。 (我暫時還沒有對它進行基準測試,但是我認爲現在瀏覽器在優化JavaScript方面已經有了很大的改觀)。

例如,它避免了jsfromhell中使用的所有重複的數組和屬性取消引用例。我認爲讀起來也容易一點。當然算法本身仍然有點複雜!

function pointInPoly(poly, point) { 
    var inside = false, 
     x = point.x, y = point.y, 
     n = poly.length, 
     vertex = poly[ n - 1 ], 
     x1 = vertex.x, y1 = vertex.y; 

    for(var i = 0; i < n; ++i) { 
     vertex = poly[i]; 
     var x2 = vertex.x, y2 = vertex.y; 

     if((y1 < y) != (y2 < y)) 
      if(x1 + (y - y1)/(y2 - y1) * (x2 - x1) < x) 
       inside = ! inside; 

     x1 = x2, y1 = y2; 
    } 

    return inside; 
} 

我真的不喜歡js2coffee.org爲該代碼生成的翻譯。特別是,在循環嵌套if語句變成一個長期的一行:

inside = not inside if x1 + (y - y1)/(y2 - y1) * (x2 - x1) < x unless (y1 < y) is (y2 < y) 

但它很容易使用爲出發點,把它變成一個更好的CoffeeScript的版本:

pointInPoly = (poly, point) -> 
    inside = false 
    x = point.x 
    y = point.y 

    vertex = poly[ poly.length - 1 ] 
    x1 = vertex.x 
    y1 = vertex.y 

    for vertex in poly 
     x2 = vertex.x 
     y2 = vertex.y 
     if (y1 < y) != (y2 < y) 
      if x1 + (y - y1)/(y2 - y1) * (x2 - x1) < x 
       inside = not inside 
     x1 = x2 
     y1 = y2 

    inside 

這是比其他版本更多的代碼行,但它的優化速度比簡潔更多。

+1

它也更清晰。取決於快捷鍵'||'和'&&'使得代碼非常不透明。 – hpaulj

1

我與

isPointInPoly = (poly, pt) -> 
    c = false 
    j = poly.length - 1 
    for b, i in poly 
    a = poly[j] 
    if ((a.y <= pt.y && pt.y < b.y) || (b.y <= pt.y && pt.y < a.y)) && (pt.x < (b.x - a.x) * (pt.y - a.y)/(b.y - a.y) + a.x) 
     c = not c 
    j = i 
    c 

demo compilation)去

+0

@ muistooshort:但是當*有*沒有其他循環在那個函數中......你是對的,沒有保證,也不應該使用它們。 – Bergi