Math 如何计算SVG路径的内角之和?
例如,下面这样的路径:Math 如何计算SVG路径的内角之和?,math,svg,Math,Svg,例如,下面这样的路径: <path d="M 35 50 L 35 35 L 90 90 z" fill="goldenrod"/> 如果轮廓是闭合的(z命令),并且是简单多边形,则s是 其中n是顶点数 这里有3个顶点,因此SA=180 (它也适用于凹多边形,但不适用于自相交多边形(它们“不简单”)MBo的答案很好,但如果您想显式计算角度,可以使用点积。对于两个向量A=(Ax,Ay),B=(Bx,By)点积由A.B=Ax*Bx+Ay*By给出。如果A的长度是| A |=sqrt(
<path d="M 35 50 L 35 35 L 90 90 z" fill="goldenrod"/>
如果轮廓是闭合的(z命令),并且是简单多边形,则s是
其中n是顶点数
这里有3个顶点,因此SA=180
(它也适用于凹多边形,但不适用于自相交多边形(它们“不简单”)MBo的答案很好,但如果您想显式计算角度,可以使用点积。对于两个向量
A=(Ax,Ay),B=(Bx,By)
点积由A.B=Ax*Bx+Ay*By
给出。如果A的长度是| A |=sqrt(Ax*Ax+Ay*Ay)
,则向量之间的角度具有关系A。B=| A | B | cos(角度)
。所以这个角度是由
acos( A . B / ( |A| |B| )
假设svg代码中的元素具有显式id
<svg id="picture" version="1.1"
xmlns="http://www.w3.org/2000/svg"
width="400" height="300">
<path id="poly" d="M 35 50 L 35 35 L 90 90 z" fill="goldenrod"/>
</svg>
这很有趣,我甚至没有想到自交的。是否有一种简单的方法来检查路径是否自交?对于少量线段(几十条),检查所有线段相交(二次复杂度)更简单,对于成百上千条线段,最好使用扫描线算法(O(nlogn))谢谢,除了看角度之外,我还试图找到一种更简单的方法来检查多边形是否凹/凸。您有什么建议吗?是的,您可以按顺序计算相邻边的叉积,并检查它们的符号。对于凸多边形,所有叉积符号都相同(或正,或负,取决于行走方向)
<svg id="picture" version="1.1"
xmlns="http://www.w3.org/2000/svg"
width="400" height="300">
<path id="poly" d="M 35 50 L 35 35 L 90 90 z" fill="goldenrod"/>
</svg>
poly = document.getElementById("poly"); // get the svg element
// get the parts of the d attribute and split on space.
parts = poly.getAttribute("d").split(/\s+/);
x=[],y=[]; // Arrays to hold x,y coords
j=0;
// loop through parts of svg, extract x,y coords
for(i=0;i<parts.length-1;i+=3) {
x[j]=parts[i+1];
y[j]=parts[i+2];
++j;
}
sum=0; // variable to hold the sum
for(var i=0;i<x.length;++i) { // loop through each vertex
prev = i >0 ? i-1 : x.length-1; // get previous index
next = (i+1) % x.length; // get next index
Ax = x[next] - x[i]; Ay = y[next] - y[i]; // vector A
Bx = x[prev] - x[i]; By = y[prev] - y[i]; // Vector B
dot = Ax * Bx + Ay * By; // dot product
lenA = Math.sqrt(Ax*Ax + Ay*Ay); // Length of A
lenB = Math.sqrt(Bx*Bx + By*By); // Or use Math.hypot
angle = Math.acos( dot / (lenA * lenB)); // find angle using
sum+=angle; // find sum
}
// print the sum (using degrees)
console.log(180 * sum / Math.PI);
cross = Ax * By - Ay * Bx;
if(cross > 0)
sum+=angle;
else
sum += Math.PI*2 - angle;