Location>code7788 >text

NET Simulate & Edit Smooth Curves

Popularity:507 ℃/2024-12-13 01:28:27

This article describes how to draw a smooth curve without relying on the Bezier curve, used to solve the case of no Bezier control points to draw the curve, but the data points are not in the Bezier curve scenario.

At my last company I made a smooth curve editing tool for wheelchair tuning acceleration and deceleration curves. A smooth curve was generated based on a few user controllable points, the control points needed to stay on the curve.

Today, I communicated with my partner that whiteboards drawing handwriting in custom shapes can also be used for this data point simulation technique, which I reviewed and summarized as follows

Bessel smoothing curve

Let's start with the Bezier curveFreehand Bezier Curves in GDI+ - Windows Forms .The following are some examples of smooth curves that we can use to draw smooth curves. In general we draw smooth curves, directly to the Bezier curve API will be multiple points as parameters, directly to draw. In this case the API will automatically use the first point as a control point to get the Bezier curve, such as the following to generate a smooth Geometry:

 1     var geometryTest = new StreamGeometry();
 2     using(var ctx = ())
 3     {
 4         (_points[0], true, false);
 5         if( % 2 == 0)
 6         {
 7             //Plotting second-order Bessel functions needs to be guaranteed to be an even number of points
 8             (keyPoints, true, true);
 9         }
10         else
11         {
12             //Plotting second-order Bessel functions needs to be guaranteed to be an even number of points
13             (0, keyPoints[0]);
14             (keyPoints, true, true);
15         }
16     }

Here's the PolyQuadraticBezierTo function, stuffing the point set list in and setting the smoothing parameter isSmoothJoin=true

1     public abstract void PolyQuadraticBezierTo(
2       IList<Point> points,
3       bool isStroked,
4       bool isSmoothJoin);
5 
6     public abstract void PolyBezierTo(IList<Point> points, bool isStroked, bool isSmoothJoin);

It is described on the official website, and the first point in the list is used as the control point: Methods () | Microsoft Learning

Above is the automatic setting of control points, and this type of implementation has a problem: the data points may end up not being on the curve

Based on the Bessel curve, we can also calculate control points. But calculating the control points is the same way that there is no guarantee that the original data points will be on the fitted curve.

Simulation of smoothing curves

With the existing data points, if we connect them directly we will definitely only generate multiple fold lines. If we add multiple points, we can simulate a polygonal approximation of the set of points similar to a curved path, somewhat similar to FlattenedPathGeometry under Geometry.

Option 1, you can use to generate an N-order curve in the X-direction, and then input the X coordinates to output the Y coordinates to get the points on the curve. You can refer toNET Whiteboard Writing Acceleration - Curve Fitting Prediction - TangSongYuanMingQing2188 - Blogspot. But this scheme generates countless points and curve drawing performance cannot be guaranteed. So how to add the points of these curve paths, and how to realize it with a minimum point set? You can set a minimum threshold for the neighboring points, for the vector angle change and for the neighbor spacing, and finally get a conforming point set

Option 2, use my previous implementation to compute the approximate spline curve point set based on the minimal polynomial code. The principle is the same as the Polynomial function in the same article, here is some of the code:

 1     private const double Tolerance = 0.5;
 2 
 3     /// <summary>
 4     /// Get the fitted point set
 5     /// </summary>
 6     /// <param name="points"></param>
 7     /// <returns></returns>
 8     public static List<Point> GetFittingLinePoints(List<Point> points)
 9     {
10         var orderedPoints = (from pt in points orderby  select pt).ToList();
11         var secondDerivatives = (orderedPoints);
12         List<Point> polyLinePoints = (orderedPoints, secondDerivatives, Tolerance);
13         return polyLinePoints;
14     }

Get the set of points between two points:

 1         /// <summary>
 2         /// Approximate the cubic polynomial with a fold and give the tolerance.
 3         /// </summary>
 4         /// <param name="leftPoint">left point of a cubic polynomial</param>
 5         /// <param name="rightPoint">Cubic polynomial right point</param>
 6         /// <param name="secondDerivativeLeft">Second-order derivatives of left-point cubic polynomials.</param>
 7         /// <param name="secondDerivativeRight">Second-order derivatives of right-terminal cubic polynomials.</param>
 8         /// <param name="tolerance">Tolerance, the maximum distance from the spline to the approximate fold.</param>
 9         /// <returns>A list of polygonal points that approximate a cubic polynomial with a given tolerance.</returns>
10         private static Collection<Point> GetApproximation(Point leftPoint, Point rightPoint, double secondDerivativeLeft, double secondDerivativeRight, double tolerance)
11         {
12             // X and Y axis values of the left and right points
13             double leftPointX = , rightPointX = ;
14             double leftPointY = , rightPointY = ;
15             // Subinterval polynomial coefficients
16             double a = (secondDerivativeRight - secondDerivativeLeft) / (6 * (rightPointX - leftPointX));
17             double b = (secondDerivativeLeft - 6 * a * leftPointX) / 2;
18             double c = (rightPointY - rightPointX * rightPointX * (a * rightPointX + b) - leftPointY + leftPointX * leftPointX * (a * leftPointX + b)) / (rightPointX - leftPointX);
19             double d = leftPointY - leftPointX * (leftPointX * (a * leftPointX + b) + c);
20 
21             //If the value of a is 0, assign a to the smallest positive number of type double
22             if(a == 0)
23                 a = double.Epsilon;
24 
25             //Getting a list of polygon points by approximating polynomials with split lines
26             Collection<Point> points = (new Polynomial(new double[] { d, c, b, a }), leftPointX, rightPointX, tolerance);
27             return points;
28         }

The effect is shown below, with the original data point set (green) on the left, and the simulated point set displayed (red) in the screenshot on the right:

 

Connecting these added points with the original data points, using a direct connection, is a smoother curve. The original data points are also on the fitted curve. Alternatively, if you still need to optimize the smoothing of these line segments, you can use a Bezier curve to replace the straight line connection, which has been added with a lot of dense points, and the green dots won't be off the curve.

Github repository codeGitHub - kybs00/CurveLineEditDemo: Smooth Curve Simulation and Editing Demo

Edit Smooth Curve

Above we have completed the point set simulation of a smooth curve, which is connected to a curve. In some business scenarios, it is necessary to use the points on the curve as the control operation points and move the points to edit the curve.

Setting multiple operating points on a curve. How to set points on a curve at a desired position can be seen in theNET Points on a Curve - Get Nearest Point - TangSongYuanMingQing2188 - Blogspot. When clicking, just get the point of the curve closest to the clicked position

After selecting the point, the operation control point moves. The curve changes according to the position of the operation point and regenerates a new curve. The curve editing effect is shown below:

Re-generate the curve of this part of the code is not difficult, the core code is the above smoothing curve simulation. Just look at the warehouse code above

 

Reference Article:

Freehand Bezier Curves in GDI+ - Windows Forms .

Bezier curve inverse control point_How to inverse the control point of Bezier curve-CSDN Blog