NET 模拟编辑平滑曲线

news/2025/3/14 9:51:31/文章来源:https://www.cnblogs.com/longshao2024/p/18771520

本文介绍不依赖贝塞尔曲线,如何绘制一条平滑曲线,用于解决无贝塞尔控制点的情况下绘制曲线、但数据点不在贝塞尔曲线的场景。

在上一家公司我做过一个平滑曲线编辑工具,用于轮椅调整加减速曲线。基于几个用户可控制的点,生成一条平滑的曲线,控制点需要保持在曲线上。

今天和小伙伴沟通,白板以自定义形状绘制笔迹,也可以使用到这个数据点模拟的技术,我回顾总结下

贝塞尔平滑曲线

我们先讲贝塞尔曲线GDI+ 中的贝塞尔自由绘制曲线 - Windows Forms .NET Framework | Microsoft Learn。一般情况我们绘制平滑曲线,直接以贝塞尔曲线API将多个点作为参数,直接进行绘制。这种情况下API会自动将第一个点作为控制点,得到贝塞尔曲线,比如下面生成一条平滑Geometry:

复制代码
 1     var geometryTest = new StreamGeometry();2     using(var ctx = geometryTest.Open())3     {4         ctx.BeginFigure(_points[0], true, false);5         if(keyPoints.Count % 2 == 0)6         {7             //绘制二阶贝塞尔函数,需要保证为偶数点8             ctx.PolyQuadraticBezierTo(keyPoints, true, true);9         }
10         else
11         {
12             //绘制二阶贝塞尔函数,需要保证为偶数点
13             keyPoints.Insert(0, keyPoints[0]);
14             ctx.PolyQuadraticBezierTo(keyPoints, true, true);
15         }
16     }
复制代码

这里的PolyQuadraticBezierTo函数,塞点集列表进去并设置平滑参数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);
复制代码

官网有介绍,列表中第一个点作为控制点:StreamGeometryContext.PolyQuadraticBezierTo 方法 (System.Windows.Media) |Microsoft 学习

上面是自动设置控制点,这类实现方案会有一个问题:数据点最终可能不在曲线上

基于贝塞尔曲线,我们也可以计算控制点。但计算控制点,也是同样无法保证原始数据点会在拟合后的曲线上。

模拟平滑曲线

以现有数据点,如果直接相连肯定只会生成多个折线。如果我们添加多个点,可以模拟一条类似曲线路径的多边形近似点集,与Geometry下的FlattenedPathGeometry有点类似。

方案一,可以使用MathNet.Numerics生成一条X方向的N阶曲线,然后输入X坐标输出Y坐标,得到曲线上的点。 MathNet.Numerics可以参考 .NET 白板书写加速-曲线拟合预测 - 唐宋元明清2188 - 博客园。但这方案会生成无数点,曲线绘制性能无法得到保证。所以添加这些曲线路径的点,如何以最小的点集实现?可以对相邻点,对向量角度变化以及相邻间距设置一个最小阈值,最终得到符合的点集

方案二,用我之前实现方案,根据最简多项式代码算出近似样条曲线点集。原理同MathNet.Numerics里的Polynomial函数,下面是部分代码:

复制代码
 1     private const double Tolerance = 0.5;2 3     /// <summary>4     /// 获取拟合后的点集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 pt.X select pt).ToList();
11         var secondDerivatives = SecondDerivativeHelper.GetSecondDerivatives(orderedPoints);
12         List<Point> polyLinePoints = PointFakeApproximationHelper.GetSplinePolyLineApproximation(orderedPoints, secondDerivatives, Tolerance);
13         return polyLinePoints;
14     }

jselt.b2b.h3cw.com
sgshq.b2b.h3cw.com
iodze.b2b.h3cw.com
ssttg.b2b.h3cw.com
lbaox.b2b.h3cw.com
cbjox.b2b.h3cw.com
bwbkm.b2b.h3cw.com
eiuuj.b2b.h3cw.com
soabq.b2b.h3cw.com
qpkex.b2b.h3cw.com
lrmoh.b2b.h3cw.com
lxtya.b2b.h3cw.com
xgoun.b2b.h3cw.com
yrnmo.b2b.h3cw.com
dfhxt.b2b.h3cw.com
ziujp.b2b.h3cw.com
yhtiv.b2b.h3cw.com
sihwr.b2b.h3cw.com
sqnkp.b2b.h3cw.com
mibqp.b2b.h3cw.com
nmbgi.b2b.h3cw.com
frmuz.b2b.h3cw.com
htwix.b2b.h3cw.com
jrxsz.b2b.h3cw.com
kjlnm.b2b.h3cw.com
pbcvr.b2b.h3cw.com
sotir.b2b.h3cw.com
eqsbt.b2b.h3cw.com
gikcr.b2b.h3cw.com
ikfdl.b2b.h3cw.com
thdwn.b2b.h3cw.com
bopwy.b2b.h3cw.com
azbmb.b2b.h3cw.com
zsegp.b2b.h3cw.com
amadi.b2b.h3cw.com
ytchj.b2b.h3cw.com
lxdzk.b2b.h3cw.com
dsntv.b2b.h3cw.com
qafue.b2b.h3cw.com
iujox.b2b.h3cw.com
mymbn.b2b.h3cw.com
rwlez.b2b.h3cw.com
vcrwf.b2b.h3cw.com
mbqcx.b2b.h3cw.com
lnpup.b2b.h3cw.com
inwle.b2b.h3cw.com
ljhxo.b2b.h3cw.com
bdyyk.b2b.h3cw.com
ciqie.b2b.h3cw.com
mbnpe.b2b.h3cw.com
irfhz.b2b.h3cw.com
ibwld.b2b.h3cw.com
jidsa.b2b.h3cw.com
apacl.b2b.h3cw.com
vpydj.b2b.h3cw.com
dgoav.b2b.h3cw.com
gwexz.b2b.h3cw.com
okfem.b2b.h3cw.com
zcirk.b2b.h3cw.com
bxpkk.b2b.h3cw.com
zydmy.b2b.h3cw.com
umiqe.b2b.h3cw.com
ttirc.b2b.h3cw.com
lhfot.b2b.h3cw.com
vveql.b2b.h3cw.com
egihq.b2b.h3cw.com
baiew.b2b.h3cw.com
xzrav.b2b.h3cw.com
cwcxz.b2b.h3cw.com
gxgbu.b2b.h3cw.com
tpkcx.b2b.h3cw.com
powsr.b2b.h3cw.com
cbqyx.b2b.h3cw.com
tihuj.b2b.h3cw.com
qthtj.b2b.h3cw.com
xmbac.b2b.h3cw.com
qprzb.b2b.h3cw.com
pnjid.b2b.h3cw.com
mytsq.b2b.h3cw.com
ngvod.b2b.h3cw.com
nzvaj.b2b.h3cw.com
bcdcs.b2b.h3cw.com
ngonn.b2b.h3cw.com
gcxce.b2b.h3cw.com
xgohj.b2b.h3cw.com
kceqm.b2b.h3cw.com
qglet.b2b.h3cw.com
baqbd.b2b.h3cw.com
wlemm.b2b.h3cw.com
fbbwv.b2b.h3cw.com
pytqz.b2b.h3cw.com
jqyrn.b2b.h3cw.com
giqpy.b2b.h3cw.com
vhapo.b2b.h3cw.com
jvrgd.b2b.h3cw.com
rxzly.b2b.h3cw.com
fyaiz.b2b.h3cw.com
yxzvn.b2b.h3cw.com
yusoa.b2b.h3cw.com
ionix.b2b.h3cw.com
lkzio.b2b.h3cw.com
glnjg.b2b.h3cw.com
uwidm.b2b.h3cw.com
sbgik.b2b.h3cw.com
rdxzi.b2b.h3cw.com
ucvds.b2b.h3cw.com
jleml.b2b.h3cw.com
jfntt.b2b.h3cw.com
tzfbo.b2b.h3cw.com
gfawg.b2b.h3cw.com
yezvz.b2b.h3cw.com
vudfx.b2b.h3cw.com
yyteu.b2b.h3cw.com
hgvxw.b2b.h3cw.com
qfunp.b2b.h3cw.com
njews.b2b.h3cw.com
oedmr.b2b.h3cw.com
slgph.b2b.h3cw.com
zihqv.b2b.h3cw.com
mbqjc.b2b.h3cw.com
ggoqh.b2b.h3cw.com
oujyw.b2b.h3cw.com
zluzv.b2b.h3cw.com
qdmut.b2b.h3cw.com
xmetm.b2b.h3cw.com
ntubu.b2b.h3cw.com
ehzhw.b2b.h3cw.com
dfyag.b2b.h3cw.com
ngodl.b2b.h3cw.com
bxyee.b2b.h3cw.com
edlnm.b2b.h3cw.com
vhcyk.b2b.h3cw.com
xasia.b2b.h3cw.com
njkkf.b2b.h3cw.com
dwyuz.b2b.h3cw.com
wcqks.b2b.h3cw.com
edssy.b2b.h3cw.com
jvkmu.b2b.h3cw.com
lprdm.b2b.h3cw.com
ixwrn.b2b.h3cw.com
jjlgs.b2b.h3cw.com
hnpxe.b2b.h3cw.com
kpyln.b2b.h3cw.com
aprhj.b2b.h3cw.com
pocck.b2b.h3cw.com
onwvq.b2b.h3cw.com
zyaph.b2b.h3cw.com
knlac.b2b.h3cw.com
vchwi.b2b.h3cw.com
qqlkt.b2b.h3cw.com
zfbdu.b2b.h3cw.com
zpkwy.b2b.h3cw.com
yznts.b2b.h3cw.com
tygmv.b2b.h3cw.com
ujbww.b2b.h3cw.com
ibcld.b2b.h3cw.com
qmkmi.b2b.h3cw.com
viixj.b2b.h3cw.com
puuph.b2b.h3cw.com
zfucu.b2b.h3cw.com
exnsu.b2b.h3cw.com
dsozp.b2b.h3cw.com
fuwib.b2b.h3cw.com
uxfet.b2b.h3cw.com
hodcr.b2b.h3cw.com
atzba.b2b.h3cw.com
ngbqj.b2b.h3cw.com
ktunp.b2b.h3cw.com
ydwrn.b2b.h3cw.com
iuwfq.b2b.h3cw.com
qfhgi.b2b.h3cw.com
prxsr.b2b.h3cw.com
kzrmi.b2b.h3cw.com
edmlt.b2b.h3cw.com
oqfet.b2b.h3cw.com
pokwe.b2b.h3cw.com
rxyra.b2b.h3cw.com
vbujr.b2b.h3cw.com
iivuj.b2b.h3cw.com
srgfu.b2b.h3cw.com
srtmh.b2b.h3cw.com
zmnmi.b2b.h3cw.com
cfazu.b2b.h3cw.com
wgrkx.b2b.h3cw.com
qsfnz.b2b.h3cw.com
plnfb.b2b.h3cw.com
cbkfl.b2b.h3cw.com
scujp.b2b.h3cw.com
ciidj.b2b.h3cw.com
tvqil.b2b.h3cw.com
hsajv.b2b.h3cw.com
kmrgt.b2b.h3cw.com
zravj.b2b.h3cw.com
wveqs.b2b.h3cw.com
iudcr.b2b.h3cw.com
rqytm.b2b.h3cw.com
qpksf.b2b.h3cw.com
eaohp.b2b.h3cw.com
oksrz.b2b.h3cw.com
gvkpy.b2b.h3cw.com
myame.b2b.h3cw.com
xpemf.b2b.h3cw.com
exmou.b2b.h3cw.com
xgrnj.b2b.h3cw.com
kglsa.b2b.h3cw.com
coqfr.b2b.h3cw.com
iavrg.b2b.h3cw.com
xckmy.b2b.h3cw.com
clmfu.b2b.h3cw.com
prmyu.b2b.h3cw.com
rxzha.b2b.h3cw.com
onpew.b2b.h3cw.com
cokzy.b2b.h3cw.com
jvvrm.b2b.h3cw.com
bjvxf.b2b.h3cw.com
odser.b2b.h3cw.com
ehiop.b2b.h3cw.com
cewrt.b2b.h3cw.com
mogix.b2b.h3cw.com
ralhm.b2b.h3cw.com
dpfqs.b2b.h3cw.com
ujljs.b2b.h3cw.com
bhqve.b2b.h3cw.com
rjytg.b2b.h3cw.com
gzbqi.b2b.h3cw.com
bgxbf.b2b.h3cw.com
odced.b2b.h3cw.com
yotbw.b2b.h3cw.com
fxzla.b2b.h3cw.com
djxeg.b2b.h3cw.com

复制代码

获取俩点之间点集:

复制代码
 1         /// <summary>2         /// 用折线逼近三次多项式并给出公差。3         /// </summary>4         /// <param name="leftPoint">三次多项式左点</param>5         /// <param name="rightPoint">三次多项式右点</param>6         /// <param name="secondDerivativeLeft">左点三次多项式二阶导数.</param>7         /// <param name="secondDerivativeRight">右端三次多项式二阶导数.</param>8         /// <param name="tolerance">公差,即样条到近似折线的最大距离。</param>9         /// <returns>在给定公差的情况下逼近三次多项式的多边形点的列表。</returns>
10         private static Collection<Point> GetApproximation(Point leftPoint, Point rightPoint, double secondDerivativeLeft, double secondDerivativeRight, double tolerance)
11         {
12             // 左右俩点的X、Y轴值
13             double leftPointX = leftPoint.X, rightPointX = rightPoint.X;
14             double leftPointY = leftPoint.Y, rightPointY = rightPoint.Y;
15             // 次区间多项式系数
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             //如果a的值为0,则给a赋值double类型的最小正数
22             if(a == 0)
23                 a = double.Epsilon;
24 
25             //通过多项式与拆线的逼近,获取多边形点的列表
26             Collection<Point> points = CubicPolynomialPolylineApproximation.Approximate(new Polynomial(new double[] { d, c, b, a }), leftPointX, rightPointX, tolerance);
27             return points;
28         }
复制代码

效果如下图,左侧是原数据点集(绿色),右则截图是模拟后的点集显示(红色):

 

把这些新增点与原数据点,用直接连接起来,就是一条比较平滑的曲线了。同时原数据点也在拟合的曲线上。另外,如果还需要优化下这些线段的平滑,可以使用贝塞尔曲线(见上面贝塞尔的实现)替换直线连接,已经加了很多密集点,绿点不会脱离曲线的。

Github仓库代码 GitHub - kybs00/CurveLineEditDemo: 平滑曲线模拟及编辑Demo


kwlxg.b2b.h3cw.com
rqyts.b2b.h3cw.com
nnbdp.b2b.h3cw.com
lutvb.b2b.h3cw.com
bhhms.b2b.h3cw.com
gmonw.b2b.h3cw.com
njvrj.b2b.h3cw.com
njpxk.b2b.h3cw.com
upxoq.b2b.h3cw.com
nprpl.b2b.h3cw.com
wbkje.b2b.h3cw.com
wsyse.b2b.h3cw.com
rixqy.b2b.h3cw.com
ftasv.b2b.h3cw.com
bnhac.b2b.h3cw.com
fujbk.b2b.h3cw.com
vniyd.b2b.h3cw.com
jzrtf.b2b.h3cw.com
ccxem.b2b.h3cw.com
fetlu.b2b.h3cw.com
jmeav.b2b.h3cw.com
ydlug.b2b.h3cw.com
kwewf.b2b.h3cw.com
giqpe.b2b.h3cw.com
cbdsa.b2b.h3cw.com
kxxme.b2b.h3cw.com
nnmil.b2b.h3cw.com
ixjlg.b2b.h3cw.com
cyoyk.b2b.h3cw.com
nupir.b2b.h3cw.com
yetfn.b2b.h3cw.com
zvotc.b2b.h3cw.com
gzbdw.b2b.h3cw.com
nzura.b2b.h3cw.com
qpcej.b2b.h3cw.com
eydzy.b2b.h3cw.com
obqvr.b2b.h3cw.com
lenfy.b2b.h3cw.com
bqcjf.b2b.h3cw.com
udgck.b2b.h3cw.com
zstco.b2b.h3cw.com
vxedl.b2b.h3cw.com
ymoti.b2b.h3cw.com
gsoqo.b2b.h3cw.com
uaiuq.b2b.h3cw.com
vklxn.b2b.h3cw.com
tysuh.b2b.h3cw.com
oedze.b2b.h3cw.com
unnjb.b2b.h3cw.com
rlscz.b2b.h3cw.com
yncaf.b2b.h3cw.com
nrmji.b2b.h3cw.com
rkgmb.b2b.h3cw.com
dwrdd.b2b.h3cw.com
wbdsk.b2b.h3cw.com
gfapp.b2b.h3cw.com
jjfnm.b2b.h3cw.com
inirz.b2b.h3cw.com
yjejs.b2b.h3cw.com
vnweq.b2b.h3cw.com
oubwp.b2b.h3cw.com
gvqpy.b2b.h3cw.com
lxmht.b2b.h3cw.com
uqsxg.b2b.h3cw.com
svawb.b2b.h3cw.com
sytxp.b2b.h3cw.com
ircyx.b2b.h3cw.com
gsohp.b2b.h3cw.com
uujlk.b2b.h3cw.com
kcrqm.b2b.h3cw.com
dsngi.b2b.h3cw.com
dskfv.b2b.h3cw.com
uzvqc.b2b.h3cw.com
zijie.b2b.h3cw.com
nsndc.b2b.h3cw.com
siqvx.b2b.h3cw.com
nmzhw.b2b.h3cw.com
xcrwy.b2b.h3cw.com
kgbah.b2b.h3cw.com
rkyfe.b2b.h3cw.com
yozpu.b2b.h3cw.com
yxmea.b2b.h3cw.com
oachq.b2b.h3cw.com
hhcxw.b2b.h3cw.com
yklml.b2b.h3cw.com
zrtif.b2b.h3cw.com
jcenf.b2b.h3cw.com
zfynf.b2b.h3cw.com
mlnjb.b2b.h3cw.com
mitva.b2b.h3cw.com
ikpla.b2b.h3cw.com
uqlrm.b2b.h3cw.com
yaihw.b2b.h3cw.com
gzvuq.b2b.h3cw.com
aacoo.b2b.h3cw.com
rqrey.b2b.h3cw.com
uhhtb.b2b.h3cw.com
lgpaj.b2b.h3cw.com
mlceq.b2b.h3cw.com
xkmeg.b2b.h3cw.com
obkwf.b2b.h3cw.com
stbtv.b2b.h3cw.com
vqfln.b2b.h3cw.com
xdenf.b2b.h3cw.com
vxwrn.b2b.h3cw.com
zibxc.b2b.h3cw.com
qfqtv.b2b.h3cw.com
vewef.b2b.h3cw.com
hfhwi.b2b.h3cw.com
zvtii.b2b.h3cw.com
ubovn.b2b.h3cw.com
qtyug.b2b.h3cw.com
kayuj.b2b.h3cw.com
bklxz.b2b.h3cw.com
nmiqj.b2b.h3cw.com
hchuw.b2b.h3cw.com
kpdlr.b2b.h3cw.com
uaoav.b2b.h3cw.com
tmhhd.b2b.h3cw.com
xtoti.b2b.h3cw.com
xjpxj.b2b.h3cw.com
kmwfn.b2b.h3cw.com
ixgyh.b2b.h3cw.com
mvxiy.b2b.h3cw.com
jzeny.b2b.h3cw.com
kqllg.b2b.h3cw.com
ibdnc.b2b.h3cw.com
xmenv.b2b.h3cw.com
cjyws.b2b.h3cw.com
zvqpc.b2b.h3cw.com
dikty.b2b.h3cw.com
zcujx.b2b.h3cw.com
haiqc.b2b.h3cw.com
suzvx.b2b.h3cw.com
rdlnm.b2b.h3cw.com
miuwc.b2b.h3cw.com
ekzeg.b2b.h3cw.com
ndhwv.b2b.h3cw.com
jplte.b2b.h3cw.com
csvxg.b2b.h3cw.com
rwrgs.b2b.h3cw.com
okfxt.b2b.h3cw.com
ccukd.b2b.h3cw.com
zincc.b2b.h3cw.com
ngbqs.b2b.h3cw.com
mojvk.b2b.h3cw.com
ynvfo.b2b.h3cw.com
biqfx.b2b.h3cw.com
bqprt.b2b.h3cw.com
cemxh.b2b.h3cw.com
xkcyk.b2b.h3cw.com
bbpek.b2b.h3cw.com
uhjvq.b2b.h3cw.com
kpxgf.b2b.h3cw.com
vujbh.b2b.h3cw.com
vuplq.b2b.h3cw.com
zziuw.b2b.h3cw.com
ppdse.b2b.h3cw.com
uacaj.b2b.h3cw.com
hbcrd.b2b.h3cw.com
pcdgf.b2b.h3cw.com
xwvyq.b2b.h3cw.com
qjews.b2b.h3cw.com
lezzb.b2b.h3cw.com
xtgzh.b2b.h3cw.com
dgufh.b2b.h3cw.com
yhjvo.b2b.h3cw.com
dvkzy.b2b.h3cw.com
fvqir.b2b.h3cw.com
cidpr.b2b.h3cw.com
plwfu.b2b.h3cw.com
uwasi.b2b.h3cw.com
dsmln.b2b.h3cw.com
ciwfk.b2b.h3cw.com
zsbnp.b2b.h3cw.com
wcxtl.b2b.h3cw.com
hjxdy.b2b.h3cw.com
mvxcl.b2b.h3cw.com
cyjlk.b2b.h3cw.com
ajpkx.b2b.h3cw.com
gmbag.b2b.h3cw.com
jldgs.b2b.h3cw.com
wmuzb.b2b.h3cw.com
jwrdm.b2b.h3cw.com
gsago.b2b.h3cw.com
qiiuj.b2b.h3cw.com
hkoqw.b2b.h3cw.com
vzhkw.b2b.h3cw.com
svzto.b2b.h3cw.com
wrjle.b2b.h3cw.com
zlgzz.b2b.h3cw.com
hnixp.b2b.h3cw.com
letya.b2b.h3cw.com
eklbg.b2b.h3cw.com
qsbnv.b2b.h3cw.com
vujrk.b2b.h3cw.com
ihdfk.b2b.h3cw.com
rfkdq.b2b.h3cw.com
wajed.b2b.h3cw.com
nwkqy.b2b.h3cw.com
qjegf.b2b.h3cw.com
lbcuq.b2b.h3cw.com
npobx.b2b.h3cw.com
nwvkf.b2b.h3cw.com
lvohw.b2b.h3cw.com
tjbkj.b2b.h3cw.com
fsami.b2b.h3cw.com
zzatp.b2b.h3cw.com
fzhni.b2b.h3cw.com
onogi.b2b.h3cw.com
rcxzr.b2b.h3cw.com
gdikp.b2b.h3cw.com
fluav.b2b.h3cw.com
lxfgf.b2b.h3cw.com
xmozv.b2b.h3cw.com
ioxpy.b2b.h3cw.com
qshmo.b2b.h3cw.com
ushmv.b2b.h3cw.com
kjrms.b2b.h3cw.com
mlfut.b2b.h3cw.com
emubn.b2b.h3cw.com
zrmbc.b2b.h3cw.com
kthnp.b2b.h3cw.com
dpqdy.b2b.h3cw.com
erson.b2b.h3cw.com
cshfb.b2b.h3cw.com
qjxxt.b2b.h3cw.com
btcej.b2b.h3cw.com
nwkwf.b2b.h3cw.com
snphj.b2b.h3cw.com
vhcej.b2b.h3cw.com
dirrg.b2b.h3cw.com
uajbv.b2b.h3cw.com
ytihj.b2b.h3cw.com
csxfr.b2b.h3cw.com
uwedm.b2b.h3cw.com
rdmht.b2b.h3cw.com
cbxmr.b2b.h3cw.com
yetgo.b2b.h3cw.com
ynlno.b2b.h3cw.com
mstsu.b2b.h3cw.com
glnhq.b2b.h3cw.com
qpkmy.b2b.h3cw.com
iegeg.b2b.h3cw.com
agtow.b2b.h3cw.com
kqfix.b2b.h3cw.com
agvut.b2b.h3cw.com
sltvh.b2b.h3cw.com
xpexm.b2b.h3cw.com
wzrtc.b2b.h3cw.com
mcuwb.b2b.h3cw.com
nvfyv.b2b.h3cw.com
mpodj.b2b.h3cw.com
azbjv.b2b.h3cw.com
zzopo.b2b.h3cw.com
piqfr.b2b.h3cw.com
kkyka.b2b.h3cw.com
xtbhj.b2b.h3cw.com
qietd.b2b.h3cw.com
rrzlu.b2b.h3cw.com
ravbd.b2b.h3cw.com
awoxc.b2b.h3cw.com
tfuzo.b2b.h3cw.com
rksrn.b2b.h3cw.com
kmntz.b2b.h3cw.com
rkyaz.b2b.h3cw.com
egbhg.b2b.h3cw.com
exekm.b2b.h3cw.com
oowbq.b2b.h3cw.com
hgoxi.b2b.h3cw.com
atogv.b2b.h3cw.com
gidpr.b2b.h3cw.com
zynmh.b2b.h3cw.com
ekxge.b2b.h3cw.com
hgpaj.b2b.h3cw.com
yrttr.b2b.h3cw.com
sezbw.b2b.h3cw.com
vhjfd.b2b.h3cw.com
hjrrj.b2b.h3cw.com
pucyd.b2b.h3cw.com
oaipr.b2b.h3cw.com
miqjs.b2b.h3cw.com
ydmkt.b2b.h3cw.com
kzfat.b2b.h3cw.com

编辑平滑曲线

上面我们已经完成了平滑曲线的点集模拟,连接起来就是一条曲线。在一些业务场景中,需要以曲线上的点为控制操作点,移动点以达到编辑曲线。

在曲线上设置多个操作点。如何在曲线上设置期望位置的点,可以看 .NET 曲线上的点- 获取距离最近的点 - 唐宋元明清2188 - 博客园。点击时,获取曲线离点击位置最近的点即可

选择点后,操作控制点移动。曲线根据操作点的位置变更,重新生成新的曲线。曲线编辑效果如下图:

重新生成曲线这部分代码没有啥难点,核心代码就是上面的平滑曲线模拟。看上面仓库代码即可

 

参考文章:

GDI+ 中的贝塞尔自由绘制曲线 - Windows Forms .NET Framework | Microsoft Learn

Bezier曲线反求控制点_如何反求贝塞尔曲线的控制点-CSDN博客

作者:唐宋元明清2188
出处:http://www.cnblogs.com/kybs0/
让学习成为习惯,假设明天就有重大机遇等着你,你准备好了么
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须在文章页面给出原文连接,否则保留追究法律责任的权利。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/898521.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

PFA药铲一体成型氟树脂铲子

PFA药铲一体成型氟树脂铲子 2025-03-13 15:05南京瑞尼克科技管悦 PFA铲子是一种由全氟烷氧基树脂(PFA)制成的工具,具有耐腐蚀、耐高低温、低溶出析出等特性,广泛应用于制药、实验室等领域。以 产品特性 耐腐蚀性:PFA铲子能够耐受强酸、强碱和有机溶剂,适用于腐蚀性环境。…

Cisco ASAv 9.23.1 - 思科自适应安全虚拟设备 (ASAv)

Cisco ASAv 9.23.1 - 思科自适应安全虚拟设备 (ASAv)Cisco ASAv 9.23.1 - 思科自适应安全虚拟设备 (ASAv) Cisco Adaptive Security Virtual Appliance (ASAv) 请访问原文链接:https://sysin.org/blog/cisco-asav/ 查看最新版。原创作品,转载请保留出处。 作者主页:sysin.or…

CMU_15445_P4_Part3

Primary Key Index BUSTUB 支持使用下面的方式创建主键索引 CREATE TABLE t1(v1 int PRIMARY KEY); CREATE TABLE t1(v1 int, v2 int, PRIMARY KEY(v1, v2));当创建一个表的时候如果确定了主键, 那么这张表的 is_primary_key 会被设置为 true. 由于在 P4 中添加了主键相关的信息…

Hyper V文件复制优化:减少复制冲突与错误

在Hyper-V环境中进行文件复制时,为了减少复制冲突与错误,可以采取以下优化措施:一、权限设置与访问控制 确保足够的访问权限: 无论是使用共享文件夹还是其他复制方法,都要确保主机和虚拟机之间有足够的访问权限。权限设置不当可能会导致无法访问或复制文件失败。 在Window…

苍穹外卖开发记录 -day2

好久没写博了,这几天一直在写简历,投简历,然后吃闭门羹。加了个技术学习群,能和别人交流一下感觉还挺有用的。昨天和前天其实也在写苍穹外卖,都是写了一些增删改查的无聊接口。今天更新一下记录一下知识点。学了一个很重要的知识点是面向切面编程(AOP)。 AOP的概念 AOP的作…

Z.Fantasy.GenerateCode:代码生成器

Z.Fantasy.GenerateCode:代码生成器 在当今快速迭代的软件开发环境中,如何提高开发效率一直是开发者们关注的焦点。今天为大家推荐一款简单的代码生成工具 —— Z.Fantasy.GenerateCode,它不仅能帮助你快速生成代码,更能让代码生成过程变得优雅而灵活。 🌟 为什么选择 Z.…

[Java] Java 17 FAQ

概述: Java 17 FAQ for Java 17 Q: 利用反射机制给 private 属性的 Field 设置为 true(field.setAccessible(true))时报: "java.lang.reflect.InaccessibleObjectException: Unable to make field private int java.io.StringReader.next accessible: module java.base d…

Hyper-V单硬盘空间管理

在Hyper-V环境中,单硬盘空间管理是一项至关重要的任务,它直接关系到虚拟化环境的稳定性和性能。以下是一些关于Hyper-V单硬盘空间管理的关键策略和建议:一、磁盘空间紧张的原因分析 在Hyper-V环境中,磁盘空间紧张的原因多种多样,主要包括: 虚拟机快照积累:虚拟机快照是虚…

如何通过文件安全传输网关,解决堡垒机远程运维的安全问题?

堡垒机又称运维审计系统或跳板机,是指在特定网络环境下,为保障网络和数据不受内外部用户的入侵和破坏,运用技术手段监控和记录运维人员对网络内服务器、网络设备、安全设备、数据库等的操作行为,以实现集中报警、及时处理及审计定责的设备。当用户采用堡垒机开展远程运维和…

可以使用MathNet.Numerics生成一条X方向的N阶曲线

本文介绍不依赖贝塞尔曲线,如何绘制一条平滑曲线,用于解决无贝塞尔控制点的情况下绘制曲线、但数据点不在贝塞尔曲线的场景。 在上一家公司我做过一个平滑曲线编辑工具,用于轮椅调整加减速曲线。基于几个用户可控制的点,生成一条平滑的曲线,控制点需要保持在曲线上。 今天…

20241905 2024-2025-2 《网络攻防实践》 第3次作业

20241905 2024-2025-2 《网络攻防实践》 第3次作业 1. 实验内容实践tcpdump:使用tcpdump开源软件对在本机上访问网站过程进行嗅探,并回答问题:你在访问网站首页时,浏览器将访问多少个Web服务器?他们的IP地址都是什么?实践wireshark:使用Wireshark开源软件对在本机上以TE…

项目到底该怎么管?掌握“六抓六放”原则就够了!

很多人一听“项目管理”,就觉得复杂、高大上,好像必须懂各种工具、框架,还得写一堆流程文档,才能把项目搞好。 其实,项目管理说到底,就是抓住关键、放掉多余,既不瞎忙,也不瞎管! 有的管理者啥都不管,结果项目乱成一锅粥;有的领导什么都要过问,事无巨细盯着,结果把…