[英]Intersection of 2 SVG Paths
我需要檢查兩個 SVG Path 元素是否相交。 檢查邊界框與.getBBox()
交集太不准確了。 我目前正在做的是用.getTotalLength()
迭代兩條路徑,然后檢查兩個點.getPointAtLength()
是否相等。
下面是一個片段,但正如您所看到的,這非常慢並且會阻止瀏覽器選項卡。 必須有一種更有效的方法來檢查兩條路徑之間的交叉點。
var path1 = document.getElementById("p1"); var path2 = document.getElementById("p2"); var time = document.getElementById("time"); var btn = document.getElementById("start"); btn.addEventListener("click", getIntersection); function getIntersection() { var start = Date.now(); for (var i = 0; i < path1.getTotalLength(); i++) { for (var j = 0; j < path2.getTotalLength(); j++) { var point1 = path1.getPointAtLength(i); var point2 = path2.getPointAtLength(j); if (pointIntersect(point1, point2)) { var end = Date.now(); time.innerHTML = (end - start) / 1000 + "s"; return; } } } } function pointIntersect(p1, p2) { p1.x = Math.round(p1.x); p1.y = Math.round(p1.y); p2.x = Math.round(p2.x); p2.y = Math.round(p2.y); return p1.x === p2.x && p1.y === p2.y; }
svg { fill: none; stroke: black; } #start { border: 1px solid; display: inline-block; position: absolute; }
<div id="start">Start </div> <svg xmlns="http://www.w3.org/2000/svg"> <path d="M 50 10 c 120 120 120 120 120 20 z" id="p1"></path> <path d="M 150 10 c 120 120 120 120 120 20 z" id="p2"></path> </svg> <div id="time"></div>
您可以使用現有的庫來執行此操作: https : //github.com/signavio/svg-intersections
它以數學方式而不是迭代方式計算交點,因此性能不應因路徑很長而降低。
我不確定,但如果您可以從路徑中提取向量和曲線,則有可能從數學上解決這個問題。 但是,您可以通過緩存一條路徑中的點並減少對getTotalLength
和getPointAtLength
的調用次數來優化您的函數。
function getIntersection() {
var start = Date.now(),
path1Length = path1.getTotalLength(),
path2Length = path2.getTotalLength(),
path2Points = [];
for (var j = 0; j < path2Length; j++) {
path2Points.push(path2.getPointAtLength(j));
}
for (var i = 0; i < path1Length; i++) {
var point1 = path1.getPointAtLength(i);
for (var j = 0; j < path2Points.length; j++) {
if (pointIntersect(point1, path2Points[j])) {
var end = Date.now();
time.innerHTML = (end - start) / 1000 + "s";
return;
}
}
}
}
這可以在大約 0.07 秒而不是 4-5 秒內計算示例路徑。
時間 0.027s
function getIntersection2() {
function Intersect(p1, p2) {
return p1.z!==p2.z && p1.x === p2.x && p1.y === p2.y;
}
var paths = [path1,path2];
var start = Date.now(),
pathLength = [path1.getTotalLength(),path2.getTotalLength()],
pathPoints = [],
inters = [];
for (var i = 0; i < 2; i++) {
for (var j = 0; j < pathLength[i]; j++) {
var p = paths[i].getPointAtLength(j);
p.z=i;
p.x=Math.round(p.x);
p.y=Math.round(p.y);
pathPoints.push(p);
}
}
pathPoints.sort((a,b)=>a.x!=b.x?a.x-b.x:a.y!=b.y?a.y-b.y:0)
// todos os pontos
.forEach((a,i,m)=>i&&Intersect(m[i-1],a)?inters.push([a.x,a.y]):0)
// somente o primeiro
//.some((a,i,m)=>i&&Intersect(m[i-1],a)?inters.push([a.x,a.y]):0);
result.innerHTML = inters;
var end = Date.now();
time.innerHTML = (end - start) / 1000 + "s";
return;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.