zoukankan      html  css  js  c++  java
  • AutoCAD 凸度(bulge)的概念及使用WPF函数画图

    前言  凸度(bulge)是AutoCAD 中一个非常重要的概念,凸度控制着两点之间弧度大小,弧度的方向。各种复杂的图像有可能就是成百上千的弧线组成的。从AutoCAD中导出的数据也有该值,一般的形式为两个点坐标、一个凸度值。所以理解凸度的概念是处理AutoCAD 文件重要的前提。本文会简要介绍一下凸度的概念,同时会给出如何根据点坐标和凸度划线。

    凸度演示程序

    1 凸度的概念

    凸度有两个作用控制顶点弧度的大小和弧度的方向。如果通过两个坐标点画弧,会有无数种可能性,所以必须引入第三个参数,来确定经过这两点的唯一弧线,这个参数就是凸度。

    凸度反应了两点之间对应弧度的大小,它的具体值为这段弧所包含角度的1/4角度的正切值。两点对应的弧度最大值为无限接近360度,凸度对应的值为接近90度的正切值,所以凸度最大值为无穷大。

    仔细观察上图,图B的弧度大于图A的弧度,但是图B的半径小于图A。

    为什么引入凸度值就能唯一确定弧线了?当凸度确定了,其实弧度对应的半径就确定了。考察一下图C,红线标识的部分为一个等腰三角形,等腰三角形底边长度和顶点角度确定了,就能唯一确定一个三角形大小(属于初中几何知识)。等腰三角形的两个腰长度就是圆的半径。

    2 根据凸度计算及画图

    不同的画图函数需要的参数也不同,我这里根据具体的画图函数来讲解,如何画图。

    WPF绘图上下文类为DrawingContext,这个类有一个绘图函数

    public abstract void DrawGeometry(Brush brush, Pen pen, Geometry geometry);

    这个函数很简单,但是这个函数可以画任意图形;因为Geometry 类功能太强大了,这个类可以描述任意几何形状。看一下如下代码:

     void AddArc(PathGeometry pathGeometry, System.Windows.Point point1, System.Windows.Point point2,  double bulge, double radius)
            {
                PathFigure pathFigure = new PathFigure();
                pathFigure.StartPoint = point1;//起点
    
                ArcSegment arcSegment = new ArcSegment();
                arcSegment.Point = point2; //终点
          
                //半径
                arcSegment.Size = new System.Windows.Size(radius, radius);
    
                //对应的角度
                double radian = Math.Atan(bulge) * 4;
                double angle = radian * 180 / Math.PI;
                arcSegment.RotationAngle =Math.Abs(angle); 
                //弧度的方向 顺时针还是逆时针
                arcSegment.SweepDirection = bulge>0? SweepDirection.Clockwise:SweepDirection.Counterclockwise;
                //是否大于180度
                arcSegment.IsLargeArc = Math.Abs(bulge) > 1;
                pathFigure.Segments.Add(arcSegment);
    
                pathGeometry.Figures.Add(pathFigure);
            }

     上述代码根据两点、凸度、圆半径来实现画图。(半径是根据前三个计算出来的,后面会讲该算法)

    一个PathGeometry由一个或多个图形暨PathFigure组成。PathFigure 就是一系列封闭或不封闭的线段或弧线组成。ArcSegment 代表一个弧线,将其加入到PathFigure,再将PathFigure加入到Geometry ,这样就可以根据DrawGeometry画出弧线了。函数有注释,非常容易理解。

    ArcSegment 还有一个参数就是圆的半径。其实根据两点、’凸度就可推导出半径,不知道为什么ArcSegment 不替我们计算出来。下面讲一下如何计算半径。

    3 根据凸度计算半径

      public static double CalBulgeRadius(System.Windows.Point point1, System.Windows.Point point2, double bulge)
            {
                //计算顶点角度
                double cicleAngle = Math.Atan(bulge) * 4;
    
                //两点之间的距离
                double pointLen = ImageHelper.CalPointLen(point1, point2);
                //根据正玄值反推
                double radius = (pointLen / 2) / Math.Sin(cicleAngle / 2);
                return Math.Abs(radius);
            }

    看左图,可知:顶点对应的角度的一半的正玄值就是 两点之间的长度除以半径。根据这一点就可以算出半径。

    3 计算圆点

    上述函数虽然可以画出圆弧,但是我们还是不知道圆心坐标。这里将一下如何推导出圆心坐标。

    这里有一个概念就是旋转,将求解圆心坐标分为两个步骤。第一步在两点之间取一点(点3),该点到点1的长度为半径;第二步,将此点旋转一定角度,就得到圆心坐标。

    求点3:

              //两点之间的距离
                double pointLen = ImageHelper.CalPointLen(point1, point2);
    
                //半径与两点之间距离的比值
                double lenRate = radius / pointLen;
                System.Windows.Point midPoint = ImageHelper.GetMidPoint(point1, point2, lenRate);
    
    internal static System.Windows.Point GetMidPoint(System.Windows.Point pt1, System.Windows.Point pt2, double lenRate) { Debug.Assert(lenRate>=0); if (lenRate == 1) return pt2; if (lenRate == 0) return pt1; System.Windows.Point result = new System.Windows.Point(); result.X = pt1.X + lenRate * (pt2.X - pt1.X); result.Y = pt1.Y + lenRate * (pt2.Y - pt1.Y); return result; }

    根据几何知识,可以得知:半径与两点之间的比率与点3的X坐标与两点的X坐标比率一样,这样就能求出X坐标。同理,可以求出Y坐标。

    旋转:

    点3以点1位圆心,旋转一定角度,点3就落在圆心上了。旋转的角度不难计算,顶点角度已知,又是等腰三角形,所以三角形的底角很容易算出。

    旋转计算涉及二维向量运算,不过.NET为我们提供了类Matrix。

     public static System.Drawing.Point RotationAt(System.Drawing.Point pointMove, System.Drawing.Point removeAt, 
                double rotateAngle, bool clockwise)
            {
                if (rotateAngle == 0)
                    return pointMove;
    
                lock (matrix)
                {
                    matrix.Reset();
                    //设置旋转的角度
                    matrix.Rotate((float)(clockwise ? rotateAngle : -rotateAngle));
    
                    //相对于removeAt旋转
                    System.Drawing.Point pt2 = new System.Drawing.Point(pointMove.X - removeAt.X, pointMove.Y - removeAt.Y);
                    System.Drawing.Point[] pts = new System.Drawing.Point[] { new System.Drawing.Point(pt2.X, pt2.Y) };
                    matrix.TransformPoints(pts);
    
                    //再变换到圆点位置
                    System.Drawing.Point result = new System.Drawing.Point(pts[0].X + removeAt.X, pts[0].Y + removeAt.Y);
                    return result;
                }
            }

     后记:在二维坐标上画图,需要有一定的几何基础和空间想象能力。初始接触这类编程,还是有一定难度的。就需要我们补充一些几何知识,同时多思考,总有一天会感觉豁然开朗。

  • 相关阅读:
    @ModelAttribute 与@InitBinder
    springboot开启矩阵传参MatrixVariable
    socket(一)
    request请求《一》
    Ajax请求中的async:false/true的作用
    java.lang.NullPointerException at org.apache.jsp.index_jsp._jspInit(index_jsp.java:40)
    shiro登录源码
    js(正则验证)
    多进程之间的通信
    队列中常用方法的使用
  • 原文地址:https://www.cnblogs.com/yuanchenhui/p/autocad_bulge.html
Copyright © 2011-2022 走看看