检测不规则形状

时间:2013-07-21 12:36:50

标签: javascript html5-canvas quadtree

从这个问题Detecting mouse coordinates with precision开始,我在过去的几天里学到了很多东西。以下是我选择的关于此主题的最佳学习资源:

  1. http://gamedev.tutsplus.com/tutorials/implementation/quick-tip-use-quadtrees-to-detect-likely-collisions-in-2d-space/
  2. http://www.gamedev.net/page/resources/_/technical/graphics-programming-and-theory/quadtrees-r1303
  3. http://jsfiddle.net/2dchA/2/
  4. (3)中的代码在JSFiddle中工作,但在我的测试环境(VS2012)中在此部分中断:

    var myTree = new Quadtree({
      x: 0,
      y: 0,
      width: 400,
      height: 300
    });
    

    在IE中未定义消息Quadtree。 FF& Chrome只是对其进行光泽处理并显示空白页面。我无法理清。 问题1:有人可以提供帮助吗?

    我的主要问题: 我有一个地区(像地图一样的地块),大约有1500个地块用html5绘制,而不是jpg或png图像。要完成它需要很多代码,但渲染效果很好,所以我保持这种方式。我打算让鼠标悬停事件告诉我当鼠标停止时我站在哪个包裹上。正如您在上一个问题中所看到的那样,我以前的尝试并不令人印象深刻。基于我一直在做的学习,并且由于Ken J的回答/评论,我想采用这种新的方法将我的画布分成15个四元组,每个对象100个。但是,在我以错误的方式进行另一次疯狂潜水之前,我想要一些指导。

    问题2:我应该在创建时将其切片,还是应该在鼠标位于某个区域时切片,即跟踪鼠标?后者听起来对我来说更好,但我认为我可以做一些建议,如果可能的话,一些开始代码。四叉树概念对我来说是全新的。感谢。

3 个答案:

答案 0 :(得分:1)

对问题1无能为力。

你应该尽可能早地构建树,因为目标是在用户点击某个地方后让页面尽快响应。

只要用户与2d区域交互,就保留树。更新四叉树不应该太难,所以即使该区域改变内容,您也应该能够重用现有树(只需更新它)。

答案 1 :(得分:1)

鉴于您的绘图区域是众所周知的,我认为QuadTree在空间散列函数方面没有任何优势。此函数将为您提供(x,y)点之外的整数。

var blocWidth   = 20;
var blocHeight  = 20;
var blocsPerLine = ( 0 | ( worldWidth / blocWidth) ) + 1 ; 
function hashPoint(x,y) {
   return ( 0 | (x/blocWidth)) + blocsPerLine*(0|(y/blocHeight));
}

构建完成后,在阵列中散列所有地块:

parcelHash = [];

function addHash(i,p) {
   if (!parcelHash[i]) { parcelHash[i]=[ p ]; return; }
   if (parcelHash[i].indexOf(p) != -1 ) return;
   parcelHash[i].push(p);
}

function hashParcel (p) {
     var thisHash = hashPoint(p.x,p.y); // upper left
     addHash( thisHash, p);
     thisHash = hashPoint(p.x+width, p.y); // upper right
     addHash(thisHash, p);
     thisHash = hashPoint(p.x, p.y+p.height); // lower left
     addHash(thisHash, p);
     thisHash = hashPoint(p.x+width, p.y+p.height); // lower right
     addHash(thisHash, p);         
};

for (var i=0; i<allParcels.length; i++) { hashParcel(allParcels[i]) };

现在,如果您有鼠标位置,则可以检索中的所有宗地 相同的块:

  function getParcels(x,y) {  
       var thisHash = hashPoint(x,y); 
       return parcelHash[thisHash]; 
    }

答案 2 :(得分:0)

除了别人说的话之外,我会给你一些提示。

...有一个鼠标悬停事件告诉我我正站在哪个包裹上......

从您的其他消息中我得出结论,包裹将具有不规则的形状。 Quadtrees通常使用矩形,因此您必须围绕宗地的形状计算边界矩形并在四叉树中插入该矩形。然后当你想确定鼠标是否在一个包裹上时,你将查询四叉树,它将为你提供一组可能在鼠标下的包裹,但你必须这样做更准确地检查你自己是否确实。

...当鼠标停止时。

从其他问题我看到你试图检测鼠标何时“停止”。也许你应该这样看待它:鼠标光标永远不会移动,它是从前一个点到另一个点在屏幕周围传送。它总是停止,永不停止。这可能看起来有点哲学,但它会让你的代码更简单。你绝对应该能够在没有任何setTimeout检查的情况下实现你的目标。

...将我的画布分成15个四个100个对象。
...我应该在创建时将其切片,还是应该在鼠标位于某个区域时进行切片

当你从中插入或删除项目时,你不会(也不能)进行切片,四叉树实现会自动执行(这是它的目的)(请注意,移动项目实际上是删除然后重新插入它)。

我没有研究你正在使用的四叉树的实现,但是这里有两个MX-CIF四叉树实现,以防一个不适合你:

问题1中的问题可能是因为jsfiddle(http)页面正在尝试访问位于https上的quadtree.js