我正在进行这个基于浏览器的实验,我给了N个特定的圆圈(让我们说它们中有一个独特的图片)并且需要将它们放在一起,尽可能留下它们之间的空间。它不必排成一个圆圈,但它们应该“聚集”在一起。
圆圈尺寸可自定义,用户可以通过拖动javascript滑块来更改尺寸,更改某些圆圈的尺寸(例如,在滑块的10%中,圆圈4的半径为20px,圆圈2 10px,圆圈5保持不变等等)。正如您可能已经猜到的那样,我将尝试在移动滑块时平滑地“转换”调整大小 - 重新定位。
到目前为止我尝试过的方法:不是手动尝试定位它们,而是尝试使用物理引擎 -
这个想法:
对于此任务,我使用了“box2Dweb”。我把一个引力拉到了屏幕的中心,然而,它花了很长时间才将球放在中心并且它们漂浮在周围。然后我在中间放了一小块静态球,这样他们就可以击中它然后停下来。它看起来像这样:
结果好一点,但圈子在静止之前仍然移动了一段时间。即使在玩了诸如球摩擦和不同引力之类的变量之后,整个事物只是漂浮在周围并且感觉非常“摇摆不定”,而我希望球只在我拖动时间滑块(当它们改变尺寸时)移动。另外,box2d不允许更改对象的大小,我不得不破解我的解决方法。
所以,box2d的方法让我意识到,留下一个物理引擎来处理这个问题并不是最好的解决方案。或许我必须包括一些我没有想到的其他力量。我在StackOverflow上找到了this similar question。然而,非常重要的区别在于它只是“同时”生成了一些非特定的圆圈,并且不允许额外的特定球尺寸和位置操纵。
我现在真的被困住了,有没有人有任何想法如何处理这个问题?
更新:已经快一年了,我完全忘记了这个帖子。我最终做的是坚持物理模型并在几乎空闲的条件下重置力/停止。结果可以在这里看到http://stateofwealth.net/ 你看到的三角形都在那些圆圈内。剩余的线路通过“delaunay三角测量算法”连接
答案 0 :(得分:5)
我记得看到一个d3.js演示,与您所描述的非常相似。它由Mike Bostock自己撰写:http://bl.ocks.org/mbostock/1747543
它使用四叉树进行快速碰撞检测并使用基于力的图形,它们都是d3.js实用程序。
在tick
函数中,您应该能够添加.attr("r", function(d) { return d.radius; })
,以便在更改nodes
数据时更新每个滴答的半径。对于初学者来说,你可以将它设置为随机返回,而圆圈应该像疯了一样抖动。
答案 1 :(得分:1)
(不是评论,因为它不合适)
我给你留下了深刻的印象,你带来了Box2D以帮助解决繁重的问题,但不幸的是,它可能不太适合你的要求,因为当你模拟刚性时,Box2D处于最佳状态物体及其碰撞动力学。
我认为如果你真的考虑到你需要什么,那根本就不是一个严格的身体动力学问题。你实际上不需要box2d的复杂性,因为你的所有几何都包含球体(我保证你比任意凸多边形更容易建模,这就是IMO Box2D的复杂性产生的原因),就像你提到的那样,Box2D不能平滑地改变几何参数并没有帮助,因为它会使浏览器陷入不必要的几何分配和解除分配,并且无法应用任何类型的平滑动画。
你可能正在寻找的是一种算法或方法,用于演化一组坐标的位置(每个坐标的半径也可能发生变化),以便它们保持半径分开,并最小化它们到中心的距离位置。如果这必须是平滑的,那么您不能每次都应用最小的解决方案,因为您可能会“扭曲”,因为最佳配置可能会在滑块移动的特定点处发生显着变化。我只想说你要做很多调整,但实际上并没有比Box2D内部必须应对的更可怕。
您的圈子不重叠有多重要?我认为你应该做一个简单的迭代“求解器”,首先尝试将圆圈带到目标(屏幕中心?),然后尝试根据半径将它们分开。
我相信如果你试图为你想要的运动提出一个简化的数学模型,那么比试图让Box2D更好。 Box2D很神奇,但它擅长擅长什么。
答案 2 :(得分:0)
至少对我而言,最简单的解决方案似乎是首先在群集中设置圈子。因此,首先设置中心的最大圆圈,将第二个圆圈放在第一个圆圈旁边。对于第三个,您可以将它放在第一个圆圈旁边,然后沿边缘移动它直到它碰到第二个圆圈。
所有其他圆圈可以采用相同的方法:将它放在任意圆圈旁边,然后沿边缘移动直到它接触,但不与另一个圆相交。请注意,这不会使它成为最有效的群集,但它可以工作。之后,当你展开圈子1时,你将所有相邻的圆圈向外移动,并将它们移动以重新聚类。