svg arc,如何确定给定开始和结束的扫掠和大弧标志&;通过点
在svg中,我想构建一个函数,返回path-d属性中“arc元素”的所有参数。给定起点、终点和过孔点。(非直线上的3个点符合圆上的定义)。我只对圆弧感兴趣(rx==ry) 我可以很容易地计算出圆心和半径。但是我正在与这两个标志作斗争,是否有一个清晰的定义,如何通过比较这三个点的拓扑来设置这些标志?彼此之间的角度或距离如何?)svg arc,如何确定给定开始和结束的扫掠和大弧标志&;通过点,svg,geometry,geometric-arc,Svg,Geometry,Geometric Arc,在svg中,我想构建一个函数,返回path-d属性中“arc元素”的所有参数。给定起点、终点和过孔点。(非直线上的3个点符合圆上的定义)。我只对圆弧感兴趣(rx==ry) 我可以很容易地计算出圆心和半径。但是我正在与这两个标志作斗争,是否有一个清晰的定义,如何通过比较这三个点的拓扑来设置这些标志?彼此之间的角度或距离如何?) 我知道标志的含义,最小弧与最大弧,顺时针与逆时针方向的扫掠标志。我最近对svg圆弧做了一些工作,并使用以下内容获得了圆弧扫掠和d值。这可能会有帮助 //---x1,y1 a
我知道标志的含义,最小弧与最大弧,顺时针与逆时针方向的扫掠标志。我最近对svg圆弧做了一些工作,并使用以下内容获得了圆弧扫掠和d值。这可能会有帮助
//---x1,y1 and x2,y2 are the two end points---
function polarToCartesian(centerX, centerY,radius, angleInDegrees)
{
var angleInRadians = (angleInDegrees) * Math.PI / 180.0;
return {
x: centerX + (radius * Math.cos(angleInRadians)),
y: centerY + (radius * Math.sin(angleInRadians))
};
}
var startAngle = 180/Math.PI*Math.atan2(y1-cy, x1-cx);
var endAngle = 180/Math.PI*Math.atan2(y2-cy, x2-cx);
StartPnt = polarToCartesian(cx, cy, radius, startAngle);
EndPnt = polarToCartesian(cx, cy, radius, endAngle);
ArcSweep = endAngle - startAngle <= 180 ? "0" : "1";
var d = [
"M", StartPnt.x, StartPnt.y,
"A", radius, radius, 0, ArcSweep, 0, EndPnt.x, EndPnt.y
].join(" ");
/--x1、y1和x2、y2是两个端点---
函数极笛卡尔坐标(centerX、centerY、半径、angleInDegrees)
{
var angleInRadians=(angleInDegrees)*Math.PI/180.0;
返回{
x:centerX+(半径*数学坐标(角半径)),
y:中心y+(半径*数学正弦(角度半径))
};
}
var startAngle=180/数学π*数学atan2(y1 cy,x1 cx);
变量端角=180/数学PI*数学atan2(y2 cy,x2 cx);
StartPnt=极笛卡尔坐标(cx,cy,半径,startAngle);
EndPnt=极笛卡尔坐标(cx,cy,半径,端角);
ArcSweep=endAngle-startAngle是的,您可以通过查看由该圆弧的起点(S)、过孔(V)和终点(E)点形成的角度来确定svg路径圆弧段的大圆弧和扫掠标志
对于大圆弧标志:
- 如果|&角度;SVE |>π/2然后标志=0
- 如果|&角度;SVE |<π/2然后标志=1
- 您正在确定以V为中心的角度是锐角还是钝角
- 如果这个角度是“尖的”(即锐角),那么你将绕着圆走很长一段路
对于扫描标志:
- If&angle;ESV>0,然后标志=0
- If&angle;ESV<0然后标志=1
- 您正在确定V点位于S-to-E线的哪一侧
- 当你从S向E看的时候,如果V在右边,那么你将逆时针绕着圆圈移动
注意以下几点:
- 形成角度的点的顺序很重要:对于大弧标志和扫掠标志,分别为S-V-E和E-S-V
- 所有角度必须介于-π和π之间,即介于-180°和180°之间
- 绝对值用于确定大圆弧标志,而不是扫描标志
此答案底部的演示代码演示了这些计算。直接回答OP问题的唯一重要代码是前两行:
const lgArcFl = (S,V,E) => Math.abs(angle(S,V,E)) > pi/2 ? 0 : 1;
const sweepFl = (S,V,E) => angle(E,S,V) > 0 ? 0 : 1;
要使用演示,请单击“运行代码片段”按钮,然后单击矩形上的3x,以按该顺序定位起点(S)、通过点(V)和终点(E)。演示将计算半径,然后使用两个标志的各种组合绘制所有4条可能的圆弧,即0,0
、0,1
、1,0
和1,1
。大弧线和小弧线分别为蓝色和红色,顺时针和逆时针弧线分别为实心和虚线。一个正确的弧将以黄色突出显示。绘制圆弧后,您可以重新单击3次以重复,等等。请注意,在同一位置单击两次或在直线上单击3次不会产生任何圆弧,这在几何上是预期的
请注意,在我第一次发布这个答案(2016年11月5日)时,该演示在Chrome、Opera和Safari中运行,但在Firefox中不起作用。(我没有检查Explorer或Edge,也没有检查任何移动浏览器。)我怀疑这可能是因为我使用了ES6/ES2015代码。但是,在代码编辑器中单击“Use BabelJS/ES2015”按钮会使代码无法使用,原因我不明白。因此,如果您在使演示程序正常工作时遇到问题,可以尝试其他浏览器
constlgarcfl=(S,V,E)=>Math.abs(角度(S,V,E))>pi/2?0 : 1;
常数扫掠FL=(S,V,E)=>角度(E,S,V)=>0?0 : 1;
常数角=([a,b],[c,d],[e,f])=>(数学atan2(f-d,e-c)-数学atan2(b-d,a-c)+3*pi)%(2*pi)-pi;
const qs=sel=>document.querySelector(sel),pi=Math.pi,pts=[];
常数半径=([a,b],[c,d],[e,f])=>{
常数g=c-a,h=2*(c-e)/g,i=d-b,j=c*c+d*d,k=j-a*a-b*b,l=(j-e*e-f*f-h*k/2)/(2*(d-f)-h*i);
返回数学模型(a+(i*l-k/2)/g,b-l);
};
常量mkArc=(arc[sx,sy],[ex,ey],r,lg,sw)=>arc.setAttribute('d',
`M${sx}${sy}A${r}${r}${0${lg}${sw}${ex}${ey}`);
const calcArcs=(S,V,E)=>{
常数args=[S,E,半径(S,V,E)];
[0,0],[0,1],[1,0],[1,1]].forEach([lg,sw])=>mkArc(qs(`arc${lg}${sw}'),…args,lg,sw));
mkArc(qs(`arc'),…args,lgArcFl(S,V,E),sweepFl(S,V,E));
};
设ptNum=0;
qs('svg')。addEventListener('click',evt=>{
常数x=evt.x-10,y=evt.y-10;
pts[ptNum]=[x,y];
setAttribute('transform','translate(${x},${y})`);
如果(ptNum++==2){
钙质(…pts);
ptNum=0;
}
});代码>
文本{
字体系列:信使;
字号:18px;
填充:黑色;
中风:无;
转换:转换(-5px,5px);
}
#arc00,#arc01{
笔画:红色;
}
#弧10,#弧11{
笔画:蓝色;
}
#arc00,#arc10{
笔画宽度:4;
笔划数组:5,5;
}
#arc01,#arc11{
笔画宽度:2;
}
直肠{
填充:无;
笔画:黑色;
高度:200px;
宽度:600px;
}
s
v
E
这是不正确的。SVG弧是“一个radx rady xrot deg largearc扫描端点x endy”。您所称的ArcSweep实际上是largeArc标志,如果角度大于PI,则为“1”。扫描标志确定是顺时针还是逆时针绘制,并具有反射效果