明经CAD社区

 找回密码
 注册

QQ登录

只需一步,快速开始

搜索
12
返回列表 发新帖
楼主: single-yu

[基础] 如何实现动态面积呢

[复制链接]
发表于 2020-8-23 00:03:55 来自手机 | 显示全部楼层
可以用overrule
发表于 2023-12-3 21:29:34 | 显示全部楼层
好东西,求LISP源码
发表于 2023-12-4 10:53:12 | 显示全部楼层


分享一个 Overrule的,VB.net源码

  1. '建筑面积
  2. Namespace ZtJZMJ
  3.     Public Class JZMJ_Overule
  4.         Dim NewRule As New JZMJ
  5.         <CommandMethod("ZtJZMJStart")> _
  6.         Public Sub OveruleStart()
  7.             On Error Resume Next
  8.             ACADFunctions.CreateLayer("Zt_全建筑面积标注", 2, "continuous", LineWeight.ByLineWeightDefault, False, False) '不可打印
  9.             ACADFunctions.CreateLayer("Zt_半建筑面积标注", 2, "continuous", LineWeight.ByLineWeightDefault, False, False) '不可打印

  10.             StartOverRule(RXClass.GetClass(GetType(Autodesk.AutoCAD.DatabaseServices.Polyline)), NewRule)
  11.             Dim acDoc As Document = Application.DocumentManager.MdiActiveDocument
  12.             acDoc.Editor.WriteMessage(vbCrLf & "图层分别为: Zt_全建筑面积标注 和 Zt_全建筑面积标注")
  13.             acDoc.Editor.Regen()
  14.         End Sub
  15.         <CommandMethod("ZtJZMJEnd")> _
  16.         Public Sub OveruleEnd()
  17.             EndOverRule(RXClass.GetClass(GetType(Autodesk.AutoCAD.DatabaseServices.Polyline)), NewRule)
  18.             Dim acDoc As Document = Application.DocumentManager.MdiActiveDocument
  19.             acDoc.Editor.Regen()
  20.         End Sub
  21.         Public Shared Sub StartOverRule(ByVal CADClass As RXClass, ByVal Rule As Overrule)
  22.             Overrule.AddOverrule(CADClass, Rule, False)
  23.             Overrule.Overruling = True
  24.         End Sub
  25.         Public Shared Sub EndOverRule(ByVal CADClass As RXClass, ByVal Rule As Overrule)
  26.             Overrule.Overruling = False
  27.             Overrule.RemoveOverrule(CADClass, Rule)
  28.         End Sub
  29.     End Class
  30.     Public Class JZMJ
  31.         Inherits DrawableOverrule
  32.         Public Overrides Function WorldDraw(ByVal drawable As Autodesk.AutoCAD.GraphicsInterface.Drawable, ByVal wd As Autodesk.AutoCAD.GraphicsInterface.WorldDraw) As Boolean
  33.             Dim acDoc As Document = Application.DocumentManager.MdiActiveDocument
  34.             If TypeOf drawable Is Autodesk.AutoCAD.DatabaseServices.Polyline Then
  35.                 Dim PL As Autodesk.AutoCAD.DatabaseServices.Polyline = DirectCast(drawable, Autodesk.AutoCAD.DatabaseServices.Polyline)
  36.                 'Dim PL As Autodesk.AutoCAD.DatabaseServices.Polyline = TryCast(drawable, Autodesk.AutoCAD.DatabaseServices.Polyline)
  37.                 Dim LN As String = PL.Layer
  38.                 If LN.Contains("Zt_全建筑面积") = True And PL.Closed = True Then
  39.                     Dim A As Double = PL.Area
  40.                     Dim P As Point3d = GetCentroid(PL)
  41.                     'P = GetPointAR_Radian(P, Math.PI, 2000)
  42.                     'P = GetPointAR_Radian(P, Math.PI / 2, 200)
  43.                     P = GetPointXY(P, -2000, 200)
  44.                     Dim acMText As MText = New MText()
  45.                     acMText.Layer = "0"     '保存图层,否则双击修改后会变为当前图层
  46.                     acMText.ColorIndex = 256
  47.                     acMText.Rotation = 0
  48.                     acMText.Location = P
  49.                     acMText.Width = 4000
  50.                     acMText.TextHeight = 350
  51.                     acMText.Contents = "\pxqc;{\fSimHei;\W0.7;" & "全建筑面积:" & Format(A / 1000 / 1000, "0.00") & "m2}"
  52.                     acMText.WorldDraw(wd)
  53.                     acMText.Dispose()
  54.                     Return MyBase.WorldDraw(drawable, wd)
  55.                 ElseIf LN.Contains("Zt_半建筑面积") = True And PL.Closed = True Then
  56.                     Dim A As Double = PL.Area
  57.                     Dim P As Point3d = GetCentroid(PL)
  58.                     'P = GetPointAR_Radian(P, Math.PI, 2000)
  59.                     'P = GetPointAR_Radian(P, Math.PI / 2, 200)
  60.                     P = GetPointXY(P, -2000, 200)
  61.                     Dim acMText As MText = New MText()
  62.                     acMText.Layer = "0"     '保存图层,否则双击修改后会变为当前图层
  63.                     acMText.ColorIndex = 256
  64.                     acMText.Rotation = 0
  65.                     acMText.Location = P
  66.                     acMText.Width = 4000
  67.                     acMText.TextHeight = 350
  68.                     acMText.Contents = "\pxqc;{\fSimHei;\W0.7;" & "半建筑面积:" & Format(A / 2 / 1000 / 1000, "0.00") & "m2}"
  69.                     acMText.WorldDraw(wd)
  70.                     acMText.Dispose()
  71.                     Return MyBase.WorldDraw(drawable, wd)
  72.                 Else
  73.                     Return MyBase.WorldDraw(drawable, wd)
  74.                 End If
  75.                 Return MyBase.WorldDraw(drawable, wd)
  76.             Else
  77.                 '不是多段线
  78.                 Return MyBase.WorldDraw(drawable, wd)
  79.             End If
  80.         End Function
  81.         Private Function VectorQ(ByVal pl As Autodesk.AutoCAD.DatabaseServices.Polyline, ByVal pt As Point3d) As Vector3d
  82.             Dim vecDir As New Vector3d(1, 0, 0)
  83.             Dim gripPts As Point3dCollection = New Point3dCollection
  84.             Dim IC1 As IntegerCollection = New IntegerCollection
  85.             Dim IC2 As IntegerCollection = New IntegerCollection
  86.             pl.GetGripPoints(gripPts, IC1, IC2)
  87.             'gripPts.ClearCenterPt(1)
  88.             Dim i As Integer = 0
  89.             While i < gripPts.Count - 1
  90.                 Dim ln As New LineSegment3d(gripPts(i), gripPts(i + 1))
  91.                 Dim ptOnCrv3d As PointOnCurve3d = ln.GetClosestPointTo(pt)
  92.                 Dim dDis As Double = ptOnCrv3d.Point.DistanceTo(pt)
  93.                 If dDis < 0.0001 Then
  94.                     vecDir = ln.Direction
  95.                     Return vecDir
  96.                 End If
  97.                 i += 1
  98.             End While
  99.             Return vecDir
  100.         End Function
  101.         Public Function GetPointAR_Radian(ByVal P As Point3d, ByVal Angle As Double, ByVal Radius As Double) As Point3d
  102.             GetPointAR_Radian = New Point3d(P.X + System.Math.Cos(Angle) * Radius, P.Y + System.Math.Sin(Angle) * Radius, P.Z)
  103.         End Function
  104.         Public Function GetPointXY(ByVal P As Point3d, ByVal X As Double, ByVal Y As Double) As Point3d
  105.             GetPointXY = New Point3d(P.X + X, P.Y + Y, P.Z)
  106.         End Function
  107.         '返回两点间中心点
  108.         ''' <summary>
  109.         ''' 返回两点间中心点
  110.         ''' </summary>
  111.         ''' <param name="P1"></param>
  112.         ''' <param name="P2"></param>
  113.         ''' <returns></returns>
  114.         ''' <remarks></remarks>
  115.         Public Function P2P_Center(ByVal P1 As Point3d, ByVal P2 As Point3d) As Point3d
  116.             Return New Point3d((P1.X + P2.X) / 2, _
  117.                             (P1.Y + P2.Y) / 2, _
  118.                             (P1.Z + P2.Z) / 2)
  119.         End Function
  120.         Public Function GetCentroid(ByVal pl As Autodesk.AutoCAD.DatabaseServices.Polyline) As Point3d
  121.             Dim p0 As Point2d = pl.GetPoint2dAt(0)
  122.             Dim cen As New Point2d(0.0, 0.0)
  123.             Dim area As Double = 0.0
  124.             Dim bulge As Double = pl.GetBulgeAt(0)
  125.             Dim last As Integer = pl.NumberOfVertices - 1
  126.             Dim tmpArea As Double
  127.             Dim tmpPoint As Point2d

  128.             If bulge <> 0.0 Then
  129.                 Dim datas As Double() = GetArcGeom(pl, bulge, 0, 1)
  130.                 area = datas(0)
  131.                 cen = New Point2d(datas(1), datas(2)) * datas(0)
  132.             End If
  133.             Dim i As Integer = 1
  134.             While i < last
  135.                 tmpArea = TriangleAlgebricArea(p0, pl.GetPoint2dAt(i), pl.GetPoint2dAt(i + 1))
  136.                 tmpPoint = TriangleCentroid(p0, pl.GetPoint2dAt(i), pl.GetPoint2dAt(i + 1))
  137.                 cen += (tmpPoint * tmpArea).GetAsVector()
  138.                 area += tmpArea
  139.                 bulge = pl.GetBulgeAt(i)
  140.                 If bulge <> 0.0 Then
  141.                     Dim datas As Double() = GetArcGeom(pl, bulge, i, i + 1)
  142.                     area += datas(0)
  143.                     cen += New Vector2d(datas(1), datas(2)) * datas(0)
  144.                 End If
  145.                 System.Math.Max(System.Threading.Interlocked.Increment(i), i - 1)
  146.             End While
  147.             bulge = pl.GetBulgeAt(last)
  148.             If bulge <> 0.0 Then
  149.                 Dim datas As Double() = GetArcGeom(pl, bulge, last, 0)
  150.                 area += datas(0)
  151.                 cen += New Vector2d(datas(1), datas(2)) * datas(0)
  152.             End If
  153.             cen = cen.DivideBy(area)
  154.             Dim result As New Point3d(cen.X, cen.Y, pl.Elevation)
  155.             Return result.TransformBy(Matrix3d.PlaneToWorld(pl.Normal))
  156.         End Function
  157.         Public Function GetArcGeom(ByVal pl As Autodesk.AutoCAD.DatabaseServices.Polyline, ByVal bulge As Double, ByVal index1 As Integer, ByVal index2 As Integer) As Double()
  158.             Dim arc As CircularArc2d = pl.GetArcSegment2dAt(index1)
  159.             Dim arcRadius As Double = arc.Radius
  160.             Dim arcCenter As Point2d = arc.Center
  161.             Dim arcAngle As Double = 4.0 * Math.Atan(bulge)
  162.             Dim tmpArea As Double = ArcAlgebricArea(arcRadius, arcAngle)
  163.             Dim tmpPoint As Point2d = ArcCentroid(pl.GetPoint2dAt(index1), pl.GetPoint2dAt(index2), arcCenter, tmpArea)
  164.             Dim D As Double() = Nothing
  165.             D.SetValue(tmpArea, 0)
  166.             D.SetValue(tmpPoint.X, 1)
  167.             D.SetValue(tmpPoint.Y, 2)
  168.             Return D
  169.         End Function
  170.         Public Function TriangleCentroid(ByVal p0 As Point2d, ByVal p1 As Point2d, ByVal p2 As Point2d) As Point2d
  171.             Return (p0 + p1.GetAsVector() + p2.GetAsVector()) / 3.0
  172.         End Function
  173.         Public Function TriangleAlgebricArea(ByVal p0 As Point2d, ByVal p1 As Point2d, ByVal p2 As Point2d) As Double
  174.             Return (((p1.X - p0.X) * (p2.Y - p0.Y)) - ((p2.X - p0.X) * (p1.Y - p0.Y))) / 2.0
  175.         End Function
  176.         Public Function ArcCentroid(ByVal start As Point2d, ByVal [end] As Point2d, ByVal cen As Point2d, ByVal tmpArea As Double) As Point2d
  177.             Dim chord As Double = start.GetDistanceTo([end])
  178.             Dim angle As Double = AngleFromTo(start, [end])
  179.             Return Polar2d(cen, angle - (Math.PI / 2.0), (chord * chord * chord) / (12.0 * tmpArea))
  180.         End Function
  181.         Public Function ArcAlgebricArea(ByVal rad As Double, ByVal ang As Double) As Double
  182.             Return rad * rad * (ang - Math.Sin(ang)) / 2.0
  183.         End Function
  184.         Public Function AngleFromTo(ByVal p1 As Point2d, ByVal p2 As Point2d) As Double
  185.             Return (p2 - p1).Angle
  186.         End Function
  187.         Public Function Polar2d(ByVal org As Point2d, ByVal angle As Double, ByVal distance As Double) As Point2d
  188.             Return New Point2d(org.X + distance, org.Y).RotateBy(angle, org)
  189.         End Function
  190.     End Class
  191. End Namespace


本帖子中包含更多资源

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

x
发表于 2023-12-4 19:46:34 | 显示全部楼层
ifox写的要不要
发表于 2023-12-4 20:46:27 | 显示全部楼层

效果如下






powered By IFox 需要使用ifox类库才可使用
https://gitee.com/inspirefunction/ifoxcad


  1. namespace DYH.Demo测试;

  2. public static class Test
  3. {
  4.     [CommandMethod(nameof(TestArea))]
  5.     public static void TestArea()
  6.     {
  7.         // 提示用户选择
  8.         var r1 = Env.Editor.GetEntity("\n选择闭合多段线");
  9.         if (r1.Status != PromptStatus.OK)
  10.             return;
  11.         // 开ifox事务
  12.         using var tr = new DBTrans();
  13.         // 如果对象不是点数量大于2的闭合多段线,则程序结束
  14.         if (tr.GetObject(r1.ObjectId, OpenMode.ForWrite) is not Polyline
  15.                 {
  16.                     Closed: true, NumberOfVertices: > 2, HasBulges: false
  17.                 }
  18.                 pl)
  19.             return;
  20.         // 获取中心点
  21.         var midPoint = pl.GetBoundingBoxEx()!.Value.MidCenter;
  22.         // 文字创建
  23.         using var text1 = DBTextEx.CreateDBText(midPoint, (pl.Area / 1e6).ToString("0.00"), 300,
  24.             AttachmentPoint.MiddleCenter);
  25.         text1.ColorIndex = 1;
  26.         var pickedPoint = r1.PickedPoint.Ucs2Wcs();
  27.         var selectedIndex = (int)Math.Floor(pl.GetParameterAtPoint(pl.GetClosestPointTo(pickedPoint, false)));
  28.         // 拿到两个拉伸坐标
  29.         var stretchIndex1 = selectedIndex;
  30.         var stretchIndex2 = (selectedIndex + 1) % pl.NumberOfVertices;
  31.         // 拿到对应线段
  32.         var ls1 = pl.GetLineSegment2dAt((stretchIndex1 - 1 + pl.NumberOfVertices) % pl.NumberOfVertices);
  33.         var ls2 = pl.GetLineSegment2dAt(stretchIndex2);
  34.         var lsJig = pl.GetLineSegment2dAt(stretchIndex1);
  35.         // 拿到构造线
  36.         var line2d1 = new Line2d(ls1.StartPoint, ls1.Direction);
  37.         var line2d2 = new Line2d(ls2.StartPoint, ls2.Direction);
  38.         var line2dJig = new Line2d(lsJig.StartPoint, lsJig.Direction);
  39.         // 拿到两个
  40.         var lastPoint = lsJig.StartPoint;
  41.         var cci2d = new CurveCurveIntersector2d();
  42.         using var j2 = new JigEx((mpw, _) =>
  43.         {
  44.             var mp2d = mpw.Point2d();
  45.             line2dJig.TransformBy(Matrix2d.Displacement(mp2d - lastPoint));
  46.             cci2d.Set(line2dJig, line2d1);
  47.             if (cci2d.NumberOfIntersectionPoints == 1)
  48.             {
  49.                 var pt1 = cci2d.GetPointOnCurve2(0).Point;
  50.                 cci2d.Set(line2dJig, line2d2);
  51.                 if (cci2d.NumberOfIntersectionPoints == 1)
  52.                 {
  53.                     var pt2 = cci2d.GetPointOnCurve2(0).Point;
  54.                     pl.SetPointAt(stretchIndex1, pt1);
  55.                     pl.SetPointAt(stretchIndex2, pt2);
  56.                     pl.Draw();
  57.                     text1.TextString = (pl.Area / 1e6).ToString("0.00");
  58.                     var box = pl.GetBoundingBoxEx()!.Value;
  59.                     text1.Move(text1.AlignmentPoint, box.MidCenter);
  60.                     text1.Height = Math.Min(box.Width, box.Height) * 0.1;
  61.                     text1.AdjustAlignment(tr.Database);
  62.                 }
  63.             }

  64.             lastPoint = mp2d;
  65.         });
  66.         j2.DatabaseEntityDraw(wd => wd.Geometry.Draw(pl, text1));
  67.         j2.SetOptions("\n选择位置");
  68.         var r2 = Env.Editor.Drag(j2);
  69.         if (r2.Status != PromptStatus.OK)
  70.         {
  71.             tr.Abort();
  72.             return;
  73.         }

  74.         Env.Editor.Redraw(pl);
  75.     }
  76. }

本帖子中包含更多资源

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

x
回复 支持 1 反对 0

使用道具 举报

发表于 2023-12-4 20:55:42 | 显示全部楼层

拉角点更简单,同样需要使用ifox






https://gitee.com/inspirefunction/ifoxcad

  1. public static class Test2
  2. {
  3.     [CommandMethod(nameof(TestArea2))]
  4.     public static void TestArea2()
  5.     {
  6.         // 提示用户选择
  7.         var r1 = Env.Editor.GetEntity("\n选择闭合多段线");
  8.         if (r1.Status != PromptStatus.OK)
  9.             return;
  10.         // 开ifox事务
  11.         using var tr = new DBTrans();
  12.         // 如果对象不是点数量大于2的闭合多段线,则程序结束
  13.         if (tr.GetObject(r1.ObjectId, OpenMode.ForWrite) is not Polyline
  14.                 {
  15.                     Closed: true, NumberOfVertices: > 2, HasBulges: false
  16.                 }
  17.                 pl)
  18.             return;
  19.         // 获取中心点
  20.         var midPoint = pl.GetBoundingBoxEx()!.Value.MidCenter;
  21.         // 文字创建
  22.         using var text1 = DBTextEx.CreateDBText(midPoint, (pl.Area / 1e6).ToString("0.00"), 300,
  23.             AttachmentPoint.MiddleCenter);
  24.         text1.ColorIndex = 1;
  25.         var pickedPoint = r1.PickedPoint.Ucs2Wcs();
  26.         var pts = pl.GetPoints();
  27.         var selectedIndex = pts.FindIndex(e1=> e1== pts.FindByMin(e2 => pickedPoint.DistanceTo(e2)));
  28.         // 拿到两个
  29.         using var j2 = new JigEx((mpw, _) =>
  30.         {
  31.             var mp2d = mpw.Point2d();
  32.             pl.SetPointAt(selectedIndex,mp2d);
  33.             pl.Draw();
  34.             text1.TextString = (pl.Area / 1e6).ToString("0.00");
  35.             var box = pl.GetBoundingBoxEx()!.Value;
  36.             text1.Move(text1.AlignmentPoint, box.MidCenter);
  37.             text1.Height = Math.Min(box.Width, box.Height) * 0.1;
  38.             text1.AdjustAlignment(tr.Database);
  39.         });
  40.         j2.DatabaseEntityDraw(wd => wd.Geometry.Draw(pl, text1));
  41.         j2.SetOptions("\n选择位置");
  42.         var r2 = Env.Editor.Drag(j2);
  43.         if (r2.Status != PromptStatus.OK)
  44.         {
  45.             tr.Abort();
  46.             return;
  47.         }

  48.         Env.Editor.Redraw(pl);
  49.     }
  50. }

本帖子中包含更多资源

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

x
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2024-11-25 05:57 , Processed in 0.156979 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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