微软公司宣布不再支持你正在使用的 IE浏览器,这会严重影响浏览网页,请使用微软最新的Edge浏览器
您好, 登录| 注册|

wpf中在Canvas上绘制过三点的弧线(后台实现)

  • 2022-01-23 15:22
  • 米修儿

    LV.0
  • 1763

    浏览

  • 5

    回复

  • 1

    获赞

  • 项目中需要绘制一个圆弧,找了很久也没有找到最优的方案,最后只能算是能用,所以暂时记录一下,有更好的方案了来补充。

    先来说说画弧的原理和数学公式

    1.   三点绘制圆

       已知三点为(x1,y1)、(x2,y2),(x3,y3),求三点形成的圆的坐标,可以设求得的圆的原点为(X,Y),半径为R,这样可以得到方程组:

     (x1-X)²-(y1-Y)²=R²      (1)式 (x2-X)²-(y2-Y)²=R²     (2)式 (x3-X)²-(y3-Y)²=R²     (3)式

    由上述方程组可以得到:

     2(x1-x2)X +2(y1-y2)Y= x12-x22+y12-y22        (5)式

     2(x1-x3)X +2(y1-y3)Y= x12-x32+y12-y32        (6)式

    此时,设:

       A= x1-x2

          B = y1-y2

       C= x1-x3

       D = y1-y3

    E= (x12-x22+y12-y22)/2

       F= (x12-x32+y12-y32)/2

    得到方程组:

    AX+BY = E

    CX+DY = F

    求解,得到

    X= -DE-BF)/ (BC-AD)

    Y = -(AF-CE)/ (BC-AD)

    经过计算,得到了圆心的坐标位置,也就得到了圆的半径计算公式

    R = sqrt((x1-X)(x1-X)+(y1-Y) (y1-Y));

    2.   在圆上确定三点的角度

      根据四个象限的坐标,选定cos作为角度的值,并利用sin值扩展到360度全象限,利用三个点的位置关系确定弧度为顺时针还是逆时针绘制弧线,其中某点(x0, y0):

    Sin = (y0-Y)/R

    Cos=  (x0-X)/R

    3.   绘制弧线

    在C#中,可以利用DrawArc()绘制弧线,其中最重要的要注意角度,绘制时角度要沿顺时针旋转,角度0度位于X轴的正方向上,在绘制弧度时,确定三个点的位置关系十分重要。

    4.C#程序源码

            void DrawArcFromThreePoint(Graphics mImgGraph, int x1, int y1, int x2, int y2, int x3, int y3)
            {
                double a = x1 - x2;
                double b = y1 - y2;
                double c = x1 - x3;
                double d = y1 - y3;
                double e = ((x1 * x1 - x2 * x2) + (y1 * y1 - y2 * y2)) / 2.0;
                double f = ((x1 * x1 - x3 * x3) + (y1 * y1 - y3 * y3)) / 2.0;
                double det = b * c - a * d;
    
                if (Math.Abs(det) >0.001)
                {
                    //x0,y0为计算得到的原点
                    double x0 = -(d * e - b * f) / det;
                    double y0 = -(a * f - c * e) / det;
    
                    SolidBrush OriginBrush = newSolidBrush(Color.Blue);
                    mImgGraph.FillEllipse(OriginBrush, (int)(x0-3), (int)(y0-3), 6, 6);
                    double radius = Math.Sqrt((x1 - x0)*(x1 - x0)+(y1 - y0)*(y1 - y0));
    
                    double angle1;
                    double angle2;
                    double angle3;
    
                    double sinValue1;
                    double cosValue1;
                    double sinValue2;
                    double cosValue2;
                    double sinValue3;
                    double cosValue3;
    
                    sinValue1 = (y1 - y0) / radius;
                    cosValue1 = (x1 - x0) / radius;
    
                    if (cosValue1 >= 0.99999) cosValue1 = 0.99999;
                    if (cosValue1 <= -0.99999) cosValue1 = -0.99999;
    
                    angle1 = Math.Acos(cosValue1);
                    angle1 = angle1 / 3.14 * 180;
    
                    if (sinValue1 < -0.05) angle1 = 360 - angle1;
    
                    sinValue2 = (y2 - y0) / radius;
                    cosValue2 = (x2 - x0) / radius;
    
                    if (cosValue2 >= 0.99999) cosValue2 = 0.99999;
                    if (cosValue2 <= -0.99999) cosValue2 = -0.99999;
    
                    angle2 = Math.Acos(cosValue2);
                    angle2 = angle2 / 3.14 * 180;
    
                    if (sinValue2 < -0.05) angle2 = 360 - angle2;
    
                    sinValue3 = (y3 - y0) / radius;
                    cosValue3 = (x3 - x0) / radius;
    
                    if (cosValue3 >= 0.99999) cosValue3 = 0.99999;
                    if (cosValue3 <= -0.99999) cosValue3 = -0.99999;
    
                    angle3 = Math.Acos(cosValue3);
                    angle3 = angle3 / 3.14 * 180;
    
                    if (sinValue3 < -0.05) angle3 = 360-angle3;
    
                    Pen CurvePen = newPen(m_CurveColor);
                    Pen CurvePen1 = newPen(Color.Green);
    
                    bool PosDown = false;
                    double Delta13;
                    if (angle1 < angle3)
                    {
                        Delta13 = angle3 - angle1;
                    }
                    else Delta13 = angle3 - angle1 + 360;
    
                    double Delta12;
                    if (angle1 < angle2)
                    {
                        Delta12 = angle2 - angle1;
                    }
                    else Delta12 = angle2 - angle1 + 360;
    
                    if (Delta13 > Delta12) PosDown = true;
                    else PosDown = false;
                    if (PosDown)
                    {
                        if (angle3 > angle1) mImgGraph.DrawArc(CurvePen, (int)(x0 - radius), (int)(y0 - radius), (int)(2 * radius), (int)(2 * radius), (int)(angle1), (int)(angle3 - angle1));
                        else mImgGraph.DrawArc(CurvePen, (int)(x0 - radius), (int)(y0 - radius), (int)(2 * radius), (int)(2 * radius), (int)(angle1), (int)(angle3 - angle1 + 360));
                    }
                    else
                    {
                        if (angle1 > angle3) mImgGraph.DrawArc(CurvePen, (int)(x0 - radius), (int)(y0 - radius), (int)(2 * radius), (int)(2 * radius), (int)(angle3), (int)(angle1 - angle3));
                        else mImgGraph.DrawArc(CurvePen, (int)(x0 - radius), (int)(y0 - radius), (int)(2 * radius), (int)(2 * radius), (int)(angle3), (int)(angle1 - angle3 + 360));
                    }
                }
            }

    最后通过画路径,最后在canvas中添加改路径

    这样就可以在canvas上完美的画出过三点的弧线了

    同是电子工程师,请一定不要吝啬你的赞!

    1人已赞

    编辑 举报

    LV.1

    4258670

    2512461

    23

    821817

    说说你的看法

  • LV.

    @

    编辑

    删除

    举报

    #该内容仅管理员可见#

    #回复内容已被删除#

    #该内容正在审核#

    回复:

    取消
    发送
  • 现在还没有回复呢,说说你的想法

    现在还没有回复呢,说说你的想法

    全部回复(5)

  • 米修儿

    LV.1

    2022-03-09 09:10

    @

    在canvas画布上画弧线已经实现,但是在vtk上画弧线虽然可以画出来,但是跟canvas上画的不太一样,大家有没有好的办法?

    0

    设为最佳答案

    置顶

    编辑

    删除

    举报

    #该内容仅管理员可见#

    #回复内容已被删除#

    #该内容正在审核#

    回复:

    4258966

    2512461

    23

    821817

    取消
    发送
    2
  • lihui710884923

    LV.1

    2022-04-22 11:17

    @

    费了很大劲,只有这个是在wpf中先画线然后再canvas中添加路径的,虽然不完美,但是够用

    0

    设为最佳答案

    置顶

    编辑

    删除

    举报

    #该内容仅管理员可见#

    #回复内容已被删除#

    #该内容正在审核#

    回复:

    4275856

    2512461

    23

    597597

    取消
    发送
    3
  • lihui710884923

    LV.1

    2022-04-22 11:18

    @

    找了很久,网上很多不符合我的要求,拿走了

    0

    设为最佳答案

    置顶

    编辑

    删除

    举报

    #该内容仅管理员可见#

    #回复内容已被删除#

    #该内容正在审核#

    回复:

    4275857

    2512461

    23

    597597

    取消
    发送
    4
  • 米修儿

    LV.1

    2022-04-22 11:21

    @lihui710884923

    费了很大劲,只有这个是在wpf中先画线然后再canvas中添加路径的,虽然不完美,但是够用

    是的,我也是费了很大劲,找到这个临时解决办法

    0

    设为最佳答案

    置顶

    编辑

    删除

    举报

    #该内容仅管理员可见#

    #回复内容已被删除#

    #该内容正在审核#

    回复:

    4275858

    2512461

    23

    821817

    取消
    发送
    5
  • 米修儿

    LV.1

    2022-04-22 11:22

    @lihui710884923

    找了很久,网上很多不符合我的要求,拿走了

    虽然可行,但是不是太完美,有更好的解决办法,欢迎留言交流

    0

    设为最佳答案

    置顶

    编辑

    删除

    举报

    #该内容仅管理员可见#

    #回复内容已被删除#

    #该内容正在审核#

    回复:

    4275859

    2512461

    23

    821817

    取消
    发送
    6
  • 现在还没有回复呢,说说你的想法

  • 回复

  • 收藏

  • 点赞

  • 举报有害信息

  • 已超出发布时间24小时,无法编辑与删除
    关于我们 联系方法 广告服务 会议服务 电子星球APP 网站地图 不良信息举报 热线:400-003-2006
    © 2002-2021 Netbroad(网博互动)公司版权所有 津ICP备 11006234号-2 联网备案号:12010402000747 增值电信业务经营许可证:津B2-20120058