How to simplify cubic bezier curve?

放肆的年华 提交于 2019-12-08 02:53:49

问题


I have a Cubic Bezier curve comprises of a number of segments (left image). It has some rough curvature and I need to make it smoother like the right image. This problem is somewhat like "noise reduction", how do I achieve this?

There's similar thread here, but the input is a set of point and fitting a bezier curve on it using least square, but in my problem the input is already cubic bezier.

On image above I don't draw the segments and control points but I hope you get the idea.


回答1:


Do you want to keep the same number of segments? Do you need to keep continuity between Bezier segments? Are you trying to hit a certain number of segments, or just keep things within a certain tolerance of the original curve?

For now I'll assume that you want to reduce the number of Bezier segments, any you need to keep G1 continuity between the segments, and you're trying to smooth within a tolerance (just guessing from your image).

For the top-level algorithm, you go through every adjacent pair of curves, and try to combine them. Repeat this until combining two adjacent curves would fall outside of your tolerance.

How do you combine two adjacent Bezier curves? Let's assume that they are curves P and Q, and since they're both cubic they have 4 CVs each, P0, P1, P2, P3 and Q0, Q1, Q2, Q3. We'll also assume that P3 == Q0. Also, we'll say that the output curve is R, composed of R0, R1, R2, R3.

One other very important step - you need to assign t values for each Bezier curve segment within the larger curve that you're simplifying. So, segment 0 would go from 0..1, segment 1 goes from 1..2, segment 2 goes from 2..3, etc.

If you want to maintain P's continuity with its neighbor, and Q's continuity with its neighbor, you can't move P0 or Q3, and the tangent vectors formed by (P1-P0) and (Q2-Q3) must stay in the same direction.. they can only be scaled.

Since you only have 4 CVs in R, those two scale factors are the only degree of freedom that you have. We'll call them kp and kq.

R0=P0
R1=P0+kp*(P1-P0)
R2=Q3+kq*(Q2-Q3)
R3=Q3

If the knot length of the two curves are equal, than kp = 2 and kq = 2.




回答2:


I looked into doing this a while ago:

Some suggestions:

Iteratively Remove Knots

By remove you can either

  • Collapse segments to form a new knot at a location on the segment.
  • Remove the knot, then measure the error caused by the removal.

After removal you will need to re-calculate the handle lengths for the remaining knots on either side, then measure the error that the removal causes (the cost of removal). See FitCurve.c for an example of least-square tangent length calculation.

To 'cost' of each removal can be put into a min-heap, then you can pop the lowest cost elements from the top of the heap, (re-evaluating adjacent the cost after removal for adjacent knots).

Heres some C code that does just this.

Re-Evaluate the Curve

You could evaluate the curve into a simple polygon, then run a curve fitting algorithm on the resulting points with a lower error threshold.

Adding this option since its significantly less trouble once you already have curve-fitting functionality.

This probably won't give quite as good results, however it may be good enough for your purposes.

Since you can use an existing curve fitting library, (own open-source library linked here).



来源:https://stackoverflow.com/questions/21571434/how-to-simplify-cubic-bezier-curve

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!