我有一个可以绘制的svg路径。使用d3js
我使用d3.geom.hull(...)
计算路径周围的凸包。现在我有一些svg对象,如节点(svg:circle),我想知道节点是否在船体内。我怎么能意识到这一点?这是我的svg视图中的图片:
修改 我的目标是船体中的节点元素(在路径内),而不仅仅是在路径的边缘。
答案 0 :(得分:1)
这是一种简单的方法:
计算你的船体几何,找回d3.geom.hull给你的坐标数组。
将新点添加到原始数据数组,并在此数组上再次计算d3.geom.hull。
将步骤1返回的点数组与步骤2返回的点数组进行比较,以查看计算出的船体是否已更改。如果有,那么该点在凸包外面。如果没有变化,则它在凸包内。
如果你有一个非常大的数据集,这可能是性能密集型的。
以下是一些简单的代码来演示:
// Some Random points
var coords = d3.range(50).map(function() {return [Math.random(),Math.random()]})
yourHull = d3.geom.hull(coords)
// Random new point
newCoord = [Math.random(),Math.random()]
coords.push(newCoord)
newHull = d3.geom.hull(coords)
//The easy case to spot
if (newHull.length != yourHull.length) {
console.log("Outside")
}
//If the array lengths are the same, the point values may have changed
else {
var outside = false;
for (var x = 0; x < yourHull.length;x++) {
for (var y = 0; y < 2;y++) {
if (yourHull[x][y] != newHull[x][y]) {
outside = true;
break;
}
}
}
if (outside) {
console.log("outside")
}
else {
console.log("on the hull")
}
}
答案 1 :(得分:1)
最快的方法是让浏览器完成所有实际工作。特别是,使用方法document.getElementFromPoint()
让渲染引擎确定重叠。
这个想法很简单 - 添加你对后面船体感兴趣的点,然后检查上面的方法是否给你点或船体。代码看起来像这样。
function isInside(point) {
var c = svg.insert("circle", "path.hull")
.attr("r", 1)
.attr("cx", point[0])
.attr("cy", point[1]);
var bounds = c.node().getBoundingClientRect();
var atPoint = document.elementFromPoint(bounds.left, bounds.top);
var inside = atPoint == c.node() ? false : true;
c.remove();
return inside;
}
唯一稍微棘手的一点是将点的相对坐标转换为绝对坐标 - 上面的代码假定SVG是页面本身的顶级元素或者不是由包含元素转换的。如果不是这种情况,请根据需要调整代码。
与其他答案相比,最大优势是运行时不依赖于船体的大小(如定义它的点数)。它只取决于您要检查的点数。
完整演示here。