雪山飞狐_lzh 发表于 2010-6-9 20:28:00

优化多段线的倒角

在QQ群为风吹桥动改写优化多段线的倒角程序,
原代码使用DB库的曲线并用纯数学计算方式

      ///
      /// 通过一个顶点将多义线倒圆角,本程序不支持多义线起点和终点处倒圆角
      ///
      /// 多义线对象
      /// 顶点索引号
      /// 圆弧半径
      public static void FilletatVertex(Polyline polyline, int vertexIndex, double radius)
      {
            Database db = HostApplicationServices.WorkingDatabase;//获取数据库
            Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;//获取editor对象
            using (Transaction trans = db.TransactionManager.StartTransaction())//开始事务   
            {
                try
                {
                  //判断顶点索引号是否属于多义线;
                  if (vertexIndex = polyline.NumberOfVertices)
                  {
                        ed.WriteMessage("\n顶点无效。");
                        return;
                  }
                  else if ((polyline.GetBulgeAt(vertexIndex - 1) != 0) && (polyline.GetBulgeAt(vertexIndex) != 0))
                  {
                        ed.WriteMessage("\n顶点两侧不是直线。");
                        return;
                  }
                  else
                  {
                        Point2d pnt = polyline.GetPoint2dAt(vertexIndex);
                        Vector2d vec1 = polyline.GetPoint2dAt(vertexIndex - 1) - pnt;//由顶点与前一个顶点组成的向量
                        Vector2d vec2 = polyline.GetPoint2dAt(vertexIndex + 1) - pnt;//由顶点与后一个顶点组成的向量
                        double angle = vec1.GetAngleTo(vec2);//获得角点两侧线段间的角度变化
                        ed.WriteMessage(angle.ToString());
                        ed.WriteMessage("\n" + vec1.Length.ToString());
                        ed.WriteMessage("\n" + (radius / Math.Tan(angle / 2)).ToString());
                        ed.WriteMessage("\n" + vec2.Length.ToString());
                        ed.WriteMessage("\n" + (radius / Math.Tan(angle / 2)).ToString());
                        if ((vec1.Length
      /// 为优化多段线倒角
      ///
      /// 优化多段线
      /// 顶点索引号
      /// 倒角半径
      /// 倒角类型
      public static void ChamferAt(this Polyline polyline, int index, double radius, bool isFillet)
      {
            if (indexpolyline.NumberOfVertices - 2)
                throw new System.Exception("错误的索引号");
            if (polyline.GetSegmentType(index - 1) != SegmentType.Line || polyline.GetSegmentType(index) != SegmentType.Line)
                throw new System.Exception("非直线段不能倒角");
            //获取当前索引号的前后两段直线,并组合为Ge复合曲线
            Curve3d[] c3ds =
                new Curve3d[]
                  {
                        polyline.GetLineSegmentAt(index - 1),
                        polyline.GetLineSegmentAt(index)
                  };
            var cc3d = new CompositeCurve3d(c3ds);
            //试倒直角
            //子曲线的个数有三种情况:
            //1、=3时倒角方向正确
            //2、=2时倒角方向相反
            //3、=0或为直线时失败
            c3ds =
                cc3d.GetTrimmedOffset
                (
                  radius,
                  Vector3d.ZAxis,
                  OffsetCurveExtensionType.Chamfer
                );
            if (c3ds.Length > 0 && c3ds is CompositeCurve3d)
            {
                  var newcc3d = c3ds as CompositeCurve3d;
                  c3ds = newcc3d.GetCurves();
                  if (c3ds.Length == 3)
                  {
                        c3ds =
                            cc3d.GetTrimmedOffset
                            (
                              -radius,
                              Vector3d.ZAxis,
                              OffsetCurveExtensionType.Chamfer
                            );
                        if (c3ds.Length == 0 || c3ds is LineSegment3d)
                        {
                            throw new System.Exception("倒角半径过大");
                        }
                  }
                  else if (c3ds.Length == 2)
                  {
                        radius = -radius;
                  }
            }
            else
            {
                throw new System.Exception("倒角半径过大");
            }
            //GetTrimmedOffset会生成倒角+偏移,故先反方向倒角,再倒回
            c3ds =
                cc3d.GetTrimmedOffset
                (
                  -radius,
                  Vector3d.ZAxis,
                  OffsetCurveExtensionType.Extend
                );
            OffsetCurveExtensionType type =
                isFillet ?
                OffsetCurveExtensionType.Fillet : OffsetCurveExtensionType.Chamfer;
            c3ds =
                c3ds.GetTrimmedOffset
                (
                  radius,
                  Vector3d.ZAxis,
                  type
                );
            //将结果Ge曲线转为Db曲线,并将相关的数值反映到原曲线
            Polyline plTemp = c3ds.ToCurve() as Polyline;
            polyline.RemoveVertexAt(index);
            polyline.AddVertexAt(index, plTemp.GetPoint2dAt(1), plTemp.GetBulgeAt(1), 0, 0);
            polyline.AddVertexAt(index + 1, plTemp.GetPoint2dAt(2), 0, 0, 0);
      }

      
      public void test()
      {
            var db = HostApplicationServices.WorkingDatabase;
            var doc = Application.DocumentManager.GetDocument(db);
            var ed = doc.Editor;
            var resEnt = ed.GetEntity("\n请选择优化多段线:");
            var resInt = ed.GetInteger("\n请输入索引号:");
            bool isFillet = false;
            PromptDoubleOptions opt = new PromptDoubleOptions("\n请输入倒角半径:");
            opt.Keywords.Add("F");
            var resDbl = ed.GetDouble(opt);
            if (resDbl.Status == PromptStatus.Keyword)
            {
                isFillet = true;
                resDbl = ed.GetDouble(opt);
            }
            using (Transaction tr = db.TransactionManager.StartTransaction())
            {
                Polyline pl = resEnt.ObjectId.GetObject(OpenMode.ForWrite) as Polyline;
                ChamferAt(pl, resInt.Value, resDbl.Value, isFillet);
                tr.Commit();
            }
      }

命令行的输入:
命令: ctest
请选择优化多段线:
请输入索引号: 3
请输入倒角半径 : f
请输入倒角半径 : 5
命令: ctest
请选择优化多段线:
请输入索引号: 2
请输入倒角半径 : 5

倒角效果:


joyhai 发表于 2020-7-13 11:12:00

顶飞狐版主呀,学习了!

single-yu 发表于 2010-6-9 20:34:00

楼主强大,顶

hmxmylove 发表于 2010-6-9 20:36:00

修正试倒角时的Bug,2楼代码已更改

lincoln_ma 发表于 2010-6-9 22:01:00

太好的东西,正是需要的资料。

雪山飞狐_lzh 发表于 2010-6-10 13:56:00

要是有LISP代码就好了。

wenxi0504 发表于 2012-12-5 11:45:00

路过并表示强烈支持!
页: [1]
查看完整版本: 优化多段线的倒角