将贝塞尔曲线分成两半相等 [英] Divide bezier curve into two equal halves
问题描述
我有2点之间的bezier曲线。我想将所有曲线切成两个相等的一半。
我的一个想法是,如果我可以控制't'值,我将通过t = [0,0.5]和t = [0.5,1]绘制2条曲线,但我不知道如何。以下是我的代码。我不介意任何其他想法或建议
I have the bezier curves between 2 points. I'd like to cut all curves into two equal half. One of my idea is if I can control 't' value I'll draw 2 curves by t = [0,0.5] and t = [0.5,1] but I don't know how. Below is my code. I won't mind any other idea or suggestion
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>D3 test</title>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script>
var Over = function(){
d3.select(this)
.style("stroke-opacity", 0.25);
}
var Out = function(){
d3.select(this)
.transition().duration(200)
.style("stroke-opacity", 0);
}
function curve(n,x1,y1,x2,y2){
var xr = (x1+x2)/2,
yr = (y1+y2)/2,
euDist = Math.sqrt(Math.pow(x2-x1,2)+Math.pow(y2-y1,2)),
x3 = -y1+xr+yr, x4 = -y2+xr+yr,
y3 = x1+yr-xr, y4 = x2+yr-xr,
ctrl , curveDescription;
svg.append('path')
.attr("stroke", 'blue')
.attr('fill','none')
.style("stroke-opacity",0.25)
.attr('d', 'M'+x3+','+y3+'L'+x4+','+y4)
.attr('stroke-width',strokeWidth);
for(var j=0;j<=n;j++){
ctrl = [(x4-x3)*j/n+x3 , (y4-y3)*j/n+y3] ,
curveDescription=
'M' +x1+',' +y1+
'Q' +ctrl[0]+','+ctrl[1]+','
+x2+',' +y2;
svg.append('path')
.attr("stroke", 'blue')
.attr('fill','none')
.style("stroke-opacity",0.25)
.attr('d', curveDescription)
.attr('stroke-width',strokeWidth);
svg.append('path')
.attr("stroke", 'blue')
.attr('fill','none')
.style("stroke-opacity",0)
.on("mouseover", Over)
.on("mouseout", Out)
.attr('d', curveDescription)
.attr('stroke-width',strokeWidth*25);
}
}
</script>
</head>
<body>
<script>
var w = 1268 , h = 680 , strokeWidth = 2;
var svg = d3.select("body")
.append("svg")
.attr("width", w)
.attr("height", h)
curve(5, 100,100, 400,500);
</script>
</body>
</html>
推荐答案
将贝塞尔曲线分成两条曲线非常简单。查看De Casteljau的算法。 https://en.wikipedia.org/wiki/De_Casteljau%27s_algorithm
Splitting a bezier into two curves is fairly simple. Look up De Casteljau's Algorithm. https://en.wikipedia.org/wiki/De_Casteljau%27s_algorithm
更新
De Casteljau比看起来更简单。对于非mathermeticians而言,WP文章可能更清楚。所以我会更简单地解释一下。
De Casteljau is simpler than it looks. That WP article could be clearer for non-mathermeticians. So I'll explain more simply.
想象一下你有一个由A,B,C和A点定义的bezier。 D.其中A和D是终点,B和C是控制点。
Imagine you have a bezier defined by the points A,B,C & D. Where A and D are the endpoints and B and C are the control points.
所以,你想要在't'点找到曲线的值沿着曲线(其中t在0..1范围内。你可以通过几何形状这样做:
So, say you wanted to find the value of the curve at point 't' along the curve (where t is in the range 0..1. You can do it this way by geometry:
- 找到E点沿着直线AB在't'处。
- 沿直线BC找到't'处的点F.
-
找到沿着直线CD在't'处的点G.
- Find the point E that is at 't' along the straight line AB.
- Find the point F that is at 't' along the straight line BC.
Find the point G that is at 't' along the straight line CD.
找到直线上't'处的点H.线EF。
Find the point H that is at 't' along the straight line EF.
找到沿直线FG位于't'的点J.
Find the point J that is at 't' along the straight line FG.
最后,沿着直线HJ找到位于't'的点K.
Finally, find the point K that is at 't' along the straight line HJ.
K也等于bezier上的't'点。这是De Casteljau的算法。
K is also equal to the point that is 't' along the bezier. This is De Casteljau's Algorithm.
但是有用的是,它也给了我们两个的控制点如果是,那将导致的beziers e曲线在点K处分开。两条贝塞尔曲线为:A,E,H,K和K,J,G,D。
But usefully, it also gives us the control points of the two beziers that would result if the curve was split at point K. The two bezier curves are: A,E,H,K and K,J,G,D.
在您的情况下t = 0.5,所以找到两条曲线只是一系列加法和除以2。
In your case t=0.5, so finding the two curves is just a sequence of additions and divides-by-2.
E = (A+B)/2
F = (B+C)/2
G = (C+D)/2
H = (E+F)/2
J = (F+G)/2
K = (H+J)/2
显然每个这些计算必须针对x和y进行。
Obviously each of these calculations has to be done for x and y.
希望这会有所帮助。
这篇关于将贝塞尔曲线分成两半相等的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!