简体   繁体   English

如何在WPF中仅绘制Bezier曲线的一部分?

[英]How can I draw only a subsection of a Bezier curve in WPF?

I have a requirement to draw small curved arrows. 我需要绘制小的弯曲箭头。 I can work out the angle of the arrowhead OK, and I was going to use Beziers to define the path segments. 我可以计算出箭头的角度,然后使用Beziers定义路径段。 However, what I would really like to do is to calculate an invisible curved path between start and end, and only stroke the path from a small distance after the start and just before the end. 但是,我真正想做的是计算起点和终点之间的一条不可见的弯曲路径,并且仅在起点之后和终点之前的一小段距离内绘制路径。

This would leave a suitable gap between any objects at the start and end points. 这将在起点和终点之间的任何对象之间留下适当的间隙。 Any suggestions? 有什么建议么?

I think I may have hit upon a possible solution, after a lot of head scratching. 我想我可能已经想过可能的解决方案,但要花很多时间挠头。 Say you have a Bezier curve ABCD, where B & C are the control points and A & D the start and end points. 假设您有一个贝塞尔曲线ABCD,其中B和C是控制点,而A&D是起点和终点。 And you want to start and end a standoff distance X from A and D: 您想开始和结束与A和D的对峙距离X:

  1. Generate the Initial Bezier 生成初始贝塞尔曲线

  2. Call GetFlattenedPathGeometry to convert it into a series of small segments 调用GetFlattenedPathGeometry将其转换为一系列小段

  3. Sum up to get the length of the Bezier and divide into X to get the fraction length F from beginning and end 求和以得到贝塞尔曲线的长度,然后除以X以得到从起点到终点的分数长度F

  4. Call PathGeometry.GetPointAtFractionLength on the original Bezier, passing in F and 1-F. 在原始Bezier上调用PathGeometry.GetPointAtFractionLength ,传入F和1-F。 This will yield a start/end point and a tangent vector for each end of the shortened Bezier 这将为缩短的贝塞尔曲线的每个末端产生一个起点/终点和一个切向量

  5. Add the start/end point to the tangent vector to get the corresponding control point 将起点/终点添加到切向量,以获得相应的控制点

  6. Generate a new Bezier using these points, which should stand off the original start and end points by X 使用这些点生成一个新的Bezier,该距离应与原始起点和终点相差X

See any problem with this approach? 看到这种方法有什么问题吗?

Arrows generally don't have insanely messed up curves, they have pretty smooth curves, with the t values near the ends behaving as pure cubics (since the Bezier function is dominated by (1-t)³ at the start coordinate, and by t³ at the end coordinate), so near the end points you can "guestimate" the "t" value you need to plug in to get a coordinate near the need by using the cube root: 箭头通常没有疯狂地弄乱曲线,它们具有相当平滑的曲线,其末端附近的t值表现为纯立方(因为Bezier函数在起始坐标处以(1-t)³为主,而在t³处在终点坐标处),因此在终点附近,您可以使用立方体根“推测”您需要插入的“ t”值以获取接近需要的坐标:

// let's say we want "10% away from the end"
desiredDistance = 0.9;

// then the guestimate for the "t" value is simply the cube root of 0.9
probablyT = Math.pow(desiredDistance, 1/3);

// and the point we want to cut at is at that "t" value
cutPoint = get(probablyT, pts);

// and we can split up the curve into two segments at that "t" value
curves = split(probablyT, pts);

// and then keep the segment we need for the arrow
arrowcurve = curves[0];

See http://jsbin.com/dovodibaze/edit?js,output for how well this approximates distances near the end point (and how this clearly only works near the end point you're guessing for =) 参见http://jsbin.com/dovodibaze/edit?js ,有关此输出如何近似逼近端点的距离(以及该输出如何明显仅在您猜测为=的端点附近起作用)的输出,

With that probablyT value you can split your original curve, draw the "first" curve that you get from that split (covering the original t=0 to t=near-the-end segment) and then draw your arrow head at the original end point. 使用该probablyT值,您可以分割原始曲线,绘制从该分割中获得的“第一条”曲线(覆盖原始t = 0到t = near-the-end线段),然后在原始端绘制箭头点。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM