明经CAD社区

 找回密码
 注册

QQ登录

只需一步,快速开始

搜索
查看: 9408|回复: 13

[几何] 优化多段线的倒角

[复制链接]
发表于 2010-6-9 20:28:00 | 显示全部楼层 |阅读模式
在QQ群为风吹桥动改写优化多段线的倒角程序,
原代码使用DB库的曲线并用纯数学计算方式
  1.         /// <summary>
  2.         /// 通过一个顶点将多义线倒圆角,本程序不支持多义线起点和终点处倒圆角
  3.         /// </summary>
  4.         /// <param name="polyline">多义线对象</param>
  5.         /// <param name="vertexIndex">顶点索引号</param>
  6.         /// <param name="radius">圆弧半径</param>
  7.         public static void FilletatVertex(Polyline polyline, int vertexIndex, double radius)
  8.         {
  9.             Database db = HostApplicationServices.WorkingDatabase;//获取数据库
  10.             Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;//获取editor对象
  11.             using (Transaction trans = db.TransactionManager.StartTransaction())//开始事务     
  12.             {
  13.                 try
  14.                 {
  15.                     //判断顶点索引号是否属于多义线;
  16.                     if (vertexIndex <= 0 || vertexIndex >= polyline.NumberOfVertices)
  17.                     {
  18.                         ed.WriteMessage("\n顶点无效。");
  19.                         return;
  20.                     }
  21.                     else if ((polyline.GetBulgeAt(vertexIndex - 1) != 0) && (polyline.GetBulgeAt(vertexIndex) != 0))
  22.                     {
  23.                         ed.WriteMessage("\n顶点两侧不是直线。");
  24.                         return;
  25.                     }
  26.                     else
  27.                     {
  28.                         Point2d pnt = polyline.GetPoint2dAt(vertexIndex);
  29.                         Vector2d vec1 = polyline.GetPoint2dAt(vertexIndex - 1) - pnt;//由顶点与前一个顶点组成的向量
  30.                         Vector2d vec2 = polyline.GetPoint2dAt(vertexIndex + 1) - pnt;//由顶点与后一个顶点组成的向量
  31.                         double angle = vec1.GetAngleTo(vec2);//获得角点两侧线段间的角度变化
  32.                         ed.WriteMessage(angle.ToString());
  33.                         ed.WriteMessage("\n" + vec1.Length.ToString());
  34.                         ed.WriteMessage("\n" + (radius / Math.Tan(angle / 2)).ToString());
  35.                         ed.WriteMessage("\n" + vec2.Length.ToString());
  36.                         ed.WriteMessage("\n" + (radius / Math.Tan(angle / 2)).ToString());
  37.                         if ((vec1.Length < radius / Math.Tan(angle / 2)) || (vec2.Length < radius / Math.Tan(angle / 2)))
  38.                         {
  39.                             ed.WriteMessage("\n半径太大。");
  40.                             return;
  41.                         }
  42.                         else
  43.                         {
  44.                             double lentemp = radius / Math.Tan(angle / 2);
  45.                             Point2d addedVertex1 = pnt + vec1.GetNormal() * lentemp;
  46.                             Point2d addedVertex2 = pnt + vec2.GetNormal() * lentemp;
  47.                             polyline.RemoveVertexAt(vertexIndex);
  48.                             polyline.AddVertexAt(vertexIndex, addedVertex1, 0, 0, 0);
  49.                             polyline.AddVertexAt(vertexIndex + 1, addedVertex2, 0, 0, 0);
  50.                             //polyline.AddVertexAt(vertexIndex, addedVertex1.Convert2d(new Plane()), 0, 0, 0);
  51.                             //polyline.AddVertexAt(vertexIndex + 1, addedVertex2.Convert2d(new Plane()), 0, 0, 0);
  52.                             //根据前后三顶点判断该顶点处多义线的前进方向是顺时针还是逆时针
  53.                             CircularArc2d cir = new CircularArc2d(polyline.GetPoint2dAt(vertexIndex - 1), pnt, polyline.GetPoint2dAt(vertexIndex + 1));
  54.                             double ang = Math.PI - angle;
  55.                             double bulge = Math.Abs(Math.Tan(ang / 4));
  56.                             if (cir.IsClockWise)
  57.                             {
  58.                                 polyline.SetBulgeAt(vertexIndex, -1 * bulge);//若为顺时针,则凸度为负;否则为正
  59.                             }
  60.                             else
  61.                             {
  62.                                 polyline.SetBulgeAt(vertexIndex, bulge);
  63.                             }
  64.                         }
  65.                     }
  66.                 }
  67.                 catch (Autodesk.AutoCAD.Runtime.Exception e)
  68.                 {
  69.                     ed.WriteMessage(e.ToString());
  70.                     trans.Abort();
  71.                 }
  72.                 finally
  73.                 {
  74.                     trans.Commit();
  75.                 }
  76.             }
  77.         }

发表于 2020-7-13 11:12:41 | 显示全部楼层
你好,ToCurve() 是自定义的函数吗? 我这也提示缺这个函数,请指教,谢谢。
 楼主| 发表于 2010-6-9 20:32:00 | 显示全部楼层
本帖最后由 作者 于 2010-7-16 21:13:43 编辑

感觉直接用Ge库的曲线应该也可以做,改写代码如下
  1.         /// <summary>
  2.         /// 为优化多段线倒角
  3.         /// </summary>
  4.         /// <param name="polyline">优化多段线</param>
  5.         /// <param name="index">顶点索引号</param>
  6.         /// <param name="radius">倒角半径</param>
  7.         /// <param name="isFillet">倒角类型</param>
  8.         public static void ChamferAt(this Polyline polyline, int index, double radius, bool isFillet)
  9.         {
  10.             if (index < 1 || index > polyline.NumberOfVertices - 2)
  11.                 throw new System.Exception("错误的索引号");
  12.             if (polyline.GetSegmentType(index - 1) != SegmentType.Line || polyline.GetSegmentType(index) != SegmentType.Line)
  13.                 throw new System.Exception("非直线段不能倒角");
  14.             //获取当前索引号的前后两段直线,并组合为Ge复合曲线
  15.             Curve3d[] c3ds =
  16.                 new Curve3d[]
  17.                     {
  18.                         polyline.GetLineSegmentAt(index - 1),
  19.                         polyline.GetLineSegmentAt(index)
  20.                     };
  21.             var cc3d = new CompositeCurve3d(c3ds);
  22.             //试倒直角
  23.             //子曲线的个数有三种情况:
  24.             //1、=3时倒角方向正确
  25.             //2、=2时倒角方向相反
  26.             //3、=0或为直线时失败
  27.             c3ds =
  28.                 cc3d.GetTrimmedOffset
  29.                 (
  30.                     radius,
  31.                     Vector3d.ZAxis,
  32.                     OffsetCurveExtensionType.Chamfer
  33.                 );
  34.             if (c3ds.Length > 0 && c3ds[0] is CompositeCurve3d)
  35.             {
  36.                     var newcc3d = c3ds[0] as CompositeCurve3d;
  37.                     c3ds = newcc3d.GetCurves();
  38.                     if (c3ds.Length == 3)
  39.                     {
  40.                         c3ds =
  41.                             cc3d.GetTrimmedOffset
  42.                             (
  43.                                 -radius,
  44.                                 Vector3d.ZAxis,
  45.                                 OffsetCurveExtensionType.Chamfer
  46.                             );
  47.                         if (c3ds.Length == 0 || c3ds[0] is LineSegment3d)
  48.                         {
  49.                             throw new System.Exception("倒角半径过大");
  50.                         }
  51.                     }
  52.                     else if (c3ds.Length == 2)
  53.                     {
  54.                         radius = -radius;
  55.                     }
  56.             }
  57.             else
  58.             {
  59.                 throw new System.Exception("倒角半径过大");
  60.             }
  61.             //GetTrimmedOffset会生成倒角+偏移,故先反方向倒角,再倒回
  62.             c3ds =
  63.                 cc3d.GetTrimmedOffset
  64.                 (
  65.                     -radius,
  66.                     Vector3d.ZAxis,
  67.                     OffsetCurveExtensionType.Extend
  68.                 );
  69.             OffsetCurveExtensionType type =
  70.                 isFillet ?
  71.                 OffsetCurveExtensionType.Fillet : OffsetCurveExtensionType.Chamfer;
  72.             c3ds =
  73.                 c3ds[0].GetTrimmedOffset
  74.                 (
  75.                     radius,
  76.                     Vector3d.ZAxis,
  77.                     type
  78.                 );
  79.             //将结果Ge曲线转为Db曲线,并将相关的数值反映到原曲线
  80.             Polyline plTemp = c3ds[0].ToCurve() as Polyline;
  81.             polyline.RemoveVertexAt(index);
  82.             polyline.AddVertexAt(index, plTemp.GetPoint2dAt(1), plTemp.GetBulgeAt(1), 0, 0);
  83.             polyline.AddVertexAt(index + 1, plTemp.GetPoint2dAt(2), 0, 0, 0);
  84.         }
  85.         [CommandMethod("CTest")]
  86.         public void test()
  87.         {
  88.             var db = HostApplicationServices.WorkingDatabase;
  89.             var doc = Application.DocumentManager.GetDocument(db);
  90.             var ed = doc.Editor;
  91.             var resEnt = ed.GetEntity("\n请选择优化多段线:");
  92.             var resInt = ed.GetInteger("\n请输入索引号:");
  93.             bool isFillet = false;
  94.             PromptDoubleOptions opt = new PromptDoubleOptions("\n请输入倒角半径:");
  95.             opt.Keywords.Add("F");
  96.             var resDbl = ed.GetDouble(opt);
  97.             if (resDbl.Status == PromptStatus.Keyword)
  98.             {
  99.                 isFillet = true;
  100.                 resDbl = ed.GetDouble(opt);
  101.             }
  102.             using (Transaction tr = db.TransactionManager.StartTransaction())
  103.             {
  104.                 Polyline pl = resEnt.ObjectId.GetObject(OpenMode.ForWrite) as Polyline;
  105.                 ChamferAt(pl, resInt.Value, resDbl.Value, isFillet);
  106.                 tr.Commit();
  107.             }
  108.         }

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

倒角效果:

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

x
发表于 2010-6-9 20:34:00 | 显示全部楼层

顶飞狐版主呀,学习了!

发表于 2010-6-9 20:36:00 | 显示全部楼层
发表于 2010-6-9 22:01:00 | 显示全部楼层
楼主强大,顶
 楼主| 发表于 2010-6-10 13:56:00 | 显示全部楼层

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

发表于 2012-12-5 11:45:27 | 显示全部楼层
太好的东西,正是需要的资料。
卓kk 该用户已被删除
发表于 2013-1-31 22:51:48 | 显示全部楼层
提示: 作者被禁止或删除 内容自动屏蔽
发表于 2013-5-13 02:00:46 | 显示全部楼层
要是有LISP代码就好了。
发表于 2014-5-6 23:17:36 | 显示全部楼层
路过并表示强烈支持!
您需要登录后才可以回帖 登录 | 注册

本版积分规则

小黑屋|手机版|CAD论坛|CAD教程|CAD下载|联系我们|关于明经|明经通道 ( 粤ICP备05003914号 )  
©2000-2023 明经通道 版权所有 本站代码,在未取得本站及作者授权的情况下,不得用于商业用途

GMT+8, 2024-11-25 06:47 , Processed in 0.175315 second(s), 26 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表