newer 发表于 2021-1-17 03:51:11

LWPOLYLINE UNION

本帖最后由 newer 于 2021-1-17 03:52 编辑




using System;
using System.Collections.Generic;
using System.Globalization;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Runtime;
using AcAp = Autodesk.AutoCAD.ApplicationServices.Application;

namespace MergePlines
{
    public class Commands
    {
      bool _en;
      Document _doc;

      public Commands()
      {
            //System.Threading.Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US");
            //System.Threading.Thread.CurrentThread.CurrentUICulture = new CultureInfo("en-US");
            _en = CultureInfo.CurrentCulture.Name.StartsWith("en-");
            _doc = AcAp.DocumentManager.MdiActiveDocument;
      }

      class Segment
      {
            public Point2d StartPt { get; set; }
            public Point2d EndPt { get; set; }
            public double Bulge { get; set; }
      }

      private int MergePlines(ObjectIdCollection ids, bool erase)
      {
            Database db = _doc.Database;
            int result = 0;
            using (Transaction tr = db.TransactionManager.StartTransaction())
            using (DBObjectCollection segments = new DBObjectCollection())
            {
                BlockTableRecord btr =
                  (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite);
                List<Segment> segs = new List<Segment>();
                List<Polyline> plines = new List<Polyline>();
                Polyline pl;
                while (ids.Count > 0)
                {
                  pl = (Polyline)tr.GetObject(ids, OpenMode.ForWrite);
                  Vector3d normal = pl.Normal;
                  double elev = pl.Elevation;
                  Plane plane = new Plane(Point3d.Origin, normal);
                  plines.Add(pl);
                  ids.RemoveAt(0);
                  for (int i = 0; i < ids.Count; )
                  {
                        pl = (Polyline)tr.GetObject(ids, OpenMode.ForWrite);
                        if (Math.Abs(pl.Elevation - elev) < 1e-12 && pl.Normal.IsEqualTo(normal))
                        {
                            plines.Add(pl);
                            ids.RemoveAt(i);
                        }
                        else
                            i++;
                  }
                  if (plines.Count < 2)
                        continue;
                  for (int i = 0; i < plines.Count; i++)
                  {
                        pl = plines;
                        pl.Explode(segments);
                        if (erase) pl.Erase();
                  }
                  plines.Clear();
                  using (DBObjectCollection regions = Region.CreateFromCurves(segments))
                  {
                        Region reg = (Region)regions;
                        for (int i = 1; i < regions.Count; i++)
                        {
                            reg.BooleanOperation(BooleanOperationType.BoolUnite, (Region)regions);
                            regions.Dispose();
                        }
                        foreach (DBObject o in segments) o.Dispose();
                        segments.Clear();
                        reg.Explode(segments);
                        reg.Dispose();
                        for (int i = 0; i < segments.Count; i++)
                        {
                            if (segments is Region)
                            {
                              ((Region)segments).Explode(segments);
                              continue;
                            }
                            Curve crv = (Curve)segments;
                            Point3d start = crv.StartPoint;
                            Point3d end = crv.EndPoint;
                            double bulge = 0.0;
                            if (crv is Arc)
                            {
                              Arc arc = (Arc)crv;
                              double angle = arc.Center.GetVectorTo(start).GetAngleTo(arc.Center.GetVectorTo(end), arc.Normal);
                              bulge = Math.Tan(angle / 4.0);
                            }
                            segs.Add(new Segment { StartPt = start.Convert2d(plane), EndPt = end.Convert2d(plane), Bulge = bulge });
                        }
                        foreach (DBObject o in segments) o.Dispose();
                        segments.Clear();
                        while (segs.Count > 0)
                        {
                            using (Polyline pline = new Polyline())
                            {
                              pline.AddVertexAt(0, segs.StartPt, segs.Bulge, 0.0, 0.0);
                              Point2d pt = segs.EndPt;
                              segs.RemoveAt(0);
                              int vtx = 1;
                              while (true)
                              {
                                    int i = segs.FindIndex(delegate(Segment s)
                                    {
                                        return s.StartPt.IsEqualTo(pt) || s.EndPt.IsEqualTo(pt);
                                    });
                                    if (i < 0) break;
                                    Segment seg = segs;
                                    if (seg.EndPt.IsEqualTo(pt))
                                        seg = new Segment { StartPt = seg.EndPt, EndPt = seg.StartPt, Bulge = -seg.Bulge };
                                    pline.AddVertexAt(vtx, seg.StartPt, seg.Bulge, 0.0, 0.0);
                                    pt = seg.EndPt;
                                    segs.RemoveAt(i);
                                    vtx++;
                              }
                              pline.SetDatabaseDefaults();
                              pline.Closed = true;
                              pline.Normal = normal;
                              pline.Elevation = elev;
                              btr.AppendEntity(pline);
                              tr.AddNewlyCreatedDBObject(pline, true);
                              result++;
                            }
                        }
                        segs.Clear();
                  }
                }
                tr.Commit();
            }
            return result;
      }

      
      public void UnionPlines()
      {
            Editor ed = _doc.Editor;
            TypedValue[] filter = new TypedValue{
                new TypedValue(0, "LWPOLYLINE"),
                new TypedValue(-4, "&"),
                new TypedValue(70, 1)};
            PromptSelectionResult psr = ed.GetSelection(new SelectionFilter(filter));
            if (psr.Status != PromptStatus.OK)
                return;
            PromptKeywordOptions pko = new PromptKeywordOptions("\nEffacer les polylignes source ?: ");
            if (_en)
            {
                pko.Message = "\nErase source polylines ?: ";
                pko.Keywords.Add("Yes");
                pko.Keywords.Add("No");
                pko.Keywords.Default = "Yes";
            }
            else
            {
                pko.Keywords.Add("Oui");
                pko.Keywords.Add("Non");
                pko.Keywords.Default = "Oui";
            }
            pko.AllowNone = true;
            PromptResult pr = ed.GetKeywords(pko);
            if (pr.Status == PromptStatus.Cancel)
                return;
            bool erase = _en ? pr.StringResult == "Yes" : pr.StringResult == "Oui";
            try
            {
                ObjectIdCollection ids = new ObjectIdCollection(psr.Value.GetObjectIds());
                int n = MergePlines(ids, erase);
                if (_en)
                  ed.WriteMessage("\n{0} polyline{1} have been created", n, n > 1 ? "s" : "");
                else
                  ed.WriteMessage("\n{0} polyligne{1} créée{1}", n, n > 1 ? "s" : "");
            }
            catch (Autodesk.AutoCAD.Runtime.Exception e)
            {
                ed.WriteMessage("\n{0}: {1}\n{2}", _en ? "Error" : "Erreur", e.Message, e.StackTrace);
            }
      }
    }
}


Cherish易 发表于 2021-3-4 10:08:03

学习一下,试试看!

dnbcgrass 发表于 2021-3-4 16:53:46

修改了几处错误
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.Globalization;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Runtime;
using AcAp = Autodesk.AutoCAD.ApplicationServices.Application;


namespace MergePlines
{
       public class Commands
    {
      bool _en;
      Document _doc;

      public Commands()
      {
            //System.Threading.Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US");
            //System.Threading.Thread.CurrentThread.CurrentUICulture = new CultureInfo("en-US");
            _en = CultureInfo.CurrentCulture.Name.StartsWith("en-");
            _doc = AcAp.DocumentManager.MdiActiveDocument;
      }

      class Segment
      {
            public Point2d StartPt { get; set; }
            public Point2d EndPt { get; set; }
            public double Bulge { get; set; }
      }

      private int MergePlines(ObjectIdCollection ids, bool erase)
      {
            Database db = _doc.Database;
            int result = 0;
            using (Transaction tr = db.TransactionManager.StartTransaction())
            using (DBObjectCollection segments = new DBObjectCollection())
            {
                BlockTableRecord btr =
                  (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite);
                List<Segment> segs = new List<Segment>();
                List<Polyline> plines = new List<Polyline>();
                Polyline pl;
                while (ids.Count > 0)
                {
                  pl = (Polyline)tr.GetObject(ids, OpenMode.ForWrite);
                  Vector3d normal = pl.Normal;
                  double elev = pl.Elevation;
                  Plane plane = new Plane(Point3d.Origin, normal);
                  plines.Add(pl);
                  ids.RemoveAt(0);
                  for (int i = 0; i < ids.Count; )
                  {
                        pl = (Polyline)tr.GetObject(ids, OpenMode.ForWrite);
                        if (Math.Abs(pl.Elevation - elev) < 1e-12 && pl.Normal.IsEqualTo(normal))
                        {
                            plines.Add(pl);
                            ids.RemoveAt(i);
                        }
                        else
                            i++;
                  }
                  if (plines.Count < 2)
                        continue;
                  for (int i = 0; i < plines.Count; i++)
                  {
                        pl = plines;
                        pl.Explode(segments);
                        if (erase) pl.Erase();
                  }
                  plines.Clear();
                  using (DBObjectCollection regions = Region.CreateFromCurves(segments))
                  {
                        Region reg = (Region)regions;
                        for (int i = 1; i < regions.Count; i++)
                        {
                            reg.BooleanOperation(BooleanOperationType.BoolUnite, (Region)regions);
                            regions.Dispose();
                        }
                        foreach (DBObject o in segments) o.Dispose();
                        segments.Clear();
                        reg.Explode(segments);
                        reg.Dispose();
                        for (int i = 0; i < segments.Count; i++)
                        {
                            if (segments is Region)
                            {
                              ((Region)segments).Explode(segments);
                              continue;
                            }
                            Curve crv = (Curve)segments;
                            Point3d start = crv.StartPoint;
                            Point3d end = crv.EndPoint;
                            double bulge = 0.0;
                            if (crv is Arc)
                            {
                              Arc arc = (Arc)crv;
                              double angle = arc.Center.GetVectorTo(start).GetAngleTo(arc.Center.GetVectorTo(end), arc.Normal);
                              bulge = Math.Tan(angle / 4.0);
                            }
                            segs.Add(new Segment { StartPt = start.Convert2d(plane), EndPt = end.Convert2d(plane), Bulge = bulge });
                        }
                        foreach (DBObject o in segments) o.Dispose();
                        segments.Clear();
                        while (segs.Count > 0)
                        {
                            using (Polyline pline = new Polyline())
                            {
                              pline.AddVertexAt(0, segs.StartPt, segs.Bulge, 0.0, 0.0);
                              Point2d pt = segs.EndPt;
                              segs.RemoveAt(0);
                              int vtx = 1;
                              while (true)
                              {
                                    int i = segs.FindIndex(delegate(Segment s)
                                    {
                                        return s.StartPt.IsEqualTo(pt) || s.EndPt.IsEqualTo(pt);
                                    });
                                    if (i < 0) break;
                                    Segment seg = segs;
                                    if (seg.EndPt.IsEqualTo(pt))
                                        seg = new Segment { StartPt = seg.EndPt, EndPt = seg.StartPt, Bulge = -seg.Bulge };
                                    pline.AddVertexAt(vtx, seg.StartPt, seg.Bulge, 0.0, 0.0);
                                    pt = seg.EndPt;
                                    segs.RemoveAt(i);
                                    vtx++;
                              }
                              pline.SetDatabaseDefaults();
                              pline.Closed = true;
                              pline.Normal = normal;
                              pline.Elevation = elev;
                              btr.AppendEntity(pline);
                              tr.AddNewlyCreatedDBObject(pline, true);
                              result++;
                            }
                        }
                        segs.Clear();
                  }
                }
                tr.Commit();
            }
            return result;
      }

      
      public void UnionPlines()
      {
            Editor ed = _doc.Editor;
            TypedValue[] filter = new TypedValue{
                new TypedValue(0, "LWPOLYLINE"),
                new TypedValue(-4, "&"),
                new TypedValue(70, 1)};
            PromptSelectionResult psr = ed.GetSelection(new SelectionFilter(filter));
            if (psr.Status != PromptStatus.OK)
                return;
            PromptKeywordOptions pko = new PromptKeywordOptions("\nEffacer les polylignes source ?: ");
            if (_en)
            {
                pko.Message = "\nErase source polylines ?: ";
                pko.Keywords.Add("Yes");
                pko.Keywords.Add("No");
                pko.Keywords.Default = "Yes";
            }
            else
            {
                pko.Keywords.Add("Oui");
                pko.Keywords.Add("Non");
                pko.Keywords.Default = "Oui";
            }
            pko.AllowNone = true;
            PromptResult pr = ed.GetKeywords(pko);
            if (pr.Status == PromptStatus.Cancel)
                return;
            bool erase = _en ? pr.StringResult == "Yes" : pr.StringResult == "Oui";
            try
            {
                ObjectIdCollection ids = new ObjectIdCollection(psr.Value.GetObjectIds());
                int n = MergePlines(ids, erase);
                if (_en)
                  ed.WriteMessage("\n{0} polyline{1} have been created", n, n > 1 ? "s" : "");
                else
                  ed.WriteMessage("\n{0} polyligne{1} créée{1}", n, n > 1 ? "s" : "");
            }
            catch (Autodesk.AutoCAD.Runtime.Exception e)
            {
                ed.WriteMessage("\n{0}: {1}\n{2}", _en ? "Error" : "Erreur", e.Message, e.StackTrace);
            }
      }
    }
}
页: [1]
查看完整版本: LWPOLYLINE UNION