Разрезание полилиний на части полилинией

Автор Тема: Разрезание полилиний на части полилинией  (Прочитано 8567 раз)

0 Пользователей и 1 Гость просматривают эту тему.

Тема содержит сообщение с Решением. Нажмите здесь чтобы посмотреть его.

Оффлайн geosysАвтор темы

  • ADN OPEN
  • Сообщений: 25
  • Карма: 3
Доброго времени суток! Есть задача сделать в местах пересечения выбранной полилинии с остальными полилиниями разрез и сформировать самостоятельные замкнутые полилинии. В AutoCAD это просто делать командой "Контур" (Boundary). Чтобы было понятнее прикладываю три примера: исходный, с командой "Контур" и с моим кодом. Мой код не видит перемещение (вершины) разрезающей полилинии внутри других полилиний и режет по прямой от точки входа до точки выхода. Для обнаружения всех пересекаемых полилиний использую метод SelectByPolyline. Пытался таким же образом проставить точки из вершин пересекающей полилинии и выловить на пересекаемой, но метод новые точки не ловит. Прошу подсказать верный путь решения задачи :)
Заранее спасибо!
ps аргументы функции: закрыть формируемые полилинии (closepoly) и оставить только внутренний контур (onlyinner)
Код - C# [Выбрать]
  1. public static void sliceinside(bool closepoly, bool onlyinner)
  2.    {
  3.       bool crossing=true; string filter="LWPOLYLINE";
  4.       Document doc = Application.DocumentManager.MdiActiveDocument;
  5.       Database db = doc.Database;
  6.       Editor ed = doc.Editor;
  7.       TypedValue[] filList = new TypedValue[1] {new TypedValue((int)DxfCode.Start, filter)};
  8.       SelectionFilter sfilter = new SelectionFilter(filList);
  9.       PromptSelectionOptions pso = new PromptSelectionOptions();
  10.       pso.MessageForAdding = "\nВыбирете полилинию";
  11.       PromptSelectionResult per = ed.GetSelection(pso,sfilter);
  12.       if (per.Status == PromptStatus.OK)
  13.       {
  14.          Transaction tr =db.TransactionManager.StartTransaction();
  15.          using (tr)
  16.          {
  17.             BlockTable acBlkTbl = tr.GetObject(db.BlockTableId,OpenMode.ForRead) as BlockTable;
  18.             BlockTableRecord acBlkTblRec = tr.GetObject(acBlkTbl[BlockTableRecord.ModelSpace],OpenMode.ForWrite) as BlockTableRecord;
  19.             try {
  20.                SelectionSet acSSet = per.Value;
  21.                foreach (SelectedObject acSSObj in acSSet)
  22.                {
  23.                   Polyline pline=new Polyline();
  24.                   DBObject obj=(DBObject)tr.GetObject(acSSObj.ObjectId, OpenMode.ForRead);
  25.                   if (obj is Polyline)
  26.                   {
  27.                      pline = (Polyline)obj;
  28.                      PromptSelectionResult selection = SelectByPolyline(ed,pline, crossing, new TypedValue(0, filter));
  29.                      SelectionSet selSet= selection.Value;
  30.                      foreach (SelectedObject target in selSet)
  31.                      {
  32.                         DBObject targetobj=(DBObject)tr.GetObject(target.ObjectId, OpenMode.ForWrite);
  33.                         if ((targetobj is Polyline)&&(targetobj.ObjectId!=pline.ObjectId))
  34.                         {
  35.                            Polyline targetpoly = targetobj as Polyline;
  36.                            Point3dCollection points = new Point3dCollection();
  37.                            Point3dCollection origverticles=new Point3dCollection();
  38.                            List<double> pars = new List<double>();
  39.                            pline.IntersectWith(targetpoly, Intersect.OnBothOperands, points, new IntPtr(0), new IntPtr(0));
  40. //здесь проставляю все точки пересекающей полилинии чтобы потом выловить те, которые находятся внутри пересекаемых объектов
  41.                            for (int vn=0;vn<pline.NumberOfVertices;vn++)
  42.                            {
  43.                               DBPoint p3dvn=new DBPoint(pline.GetPoint3dAt(vn));
  44.                               origverticles.Add(p3dvn.Position);
  45.                               acBlkTblRec.AppendEntity(p3dvn);
  46.                               tr.AddNewlyCreatedDBObject(p3dvn,true);
  47.                               doc.TransactionManager.QueueForGraphicsFlush();
  48.                            }
  49.                            PromptSelectionResult pointsinsideselection = SelectByPolyline(ed,targetpoly,true,new TypedValue((int)DxfCode.Start, "POINT")); //здесь метод не работает
  50.                            SelectionSet pointsinsideselSet= pointsinsideselection.Value;
  51.                            foreach (SelectedObject pointinside in pointsinsideselSet)//соответственно точек нет
  52.                            {
  53.                               DBPoint p3dvn=(DBPoint)tr.GetObject(pointinside.ObjectId, OpenMode.ForWrite);
  54.                               origverticles=new Point3dCollection();
  55.                               origverticles.Add(p3dvn.Position);
  56.                            }
  57.                               foreach (Point3d p in points)
  58.                               {
  59.                                  pars.Add(targetpoly.GetParameterAtPoint(targetpoly.GetClosestPointTo(p, false)));
  60.                               }
  61.                               if (pars.Count == 0) continue;
  62.                               pars.Sort();
  63.                               try
  64.                               {
  65.                                  DBObjectCollection alonepolys= new DBObjectCollection();
  66.                                  foreach (Curve c in targetpoly.GetSplitCurves(new DoubleCollection(pars.ToArray())))
  67.                                  {
  68.                                     Polyline newpl = c as Polyline;
  69.                                     if (closepoly) newpl.Closed=true;
  70.                                     if (onlyinner)
  71.                                     {
  72.                                        foreach (Polyline offsetpline in pline.Offset(0.01,PolylineExtension.OffsetSide.Out))
  73.                                        {
  74.                                           Point3dCollection points2 = new Point3dCollection();
  75.                                           offsetpline.IntersectWith(newpl, Intersect.OnBothOperands, points2, new IntPtr(0), new IntPtr(0));
  76.                                           if (points2.Count==0)
  77.                                           {
  78.                                              acBlkTblRec.AppendEntity(newpl);
  79.                                              tr.AddNewlyCreatedDBObject(newpl,true);
  80.                                              if (newpl.Area==0) alonepolys.Add(newpl);
  81.                                           }
  82.                                        }
  83.                                     }
  84.                                     else
  85.                                     {
  86.                                        acBlkTblRec.AppendEntity(newpl);
  87.                                        tr.AddNewlyCreatedDBObject(newpl,true);
  88.                                        if (newpl.Area==0) alonepolys.Add(newpl);
  89.                                     }
  90.                                  }
  91.                                  if (alonepolys.Count!=0)
  92.                                  {
  93.                                     Polyline newpl2 = new Polyline();
  94.                                     int ver=0;
  95.                                     foreach (Polyline lonelypoly in alonepolys)
  96.                                     {
  97.                                        for (int i=0;i<lonelypoly.NumberOfVertices;i++)
  98.                                        {
  99.                                           newpl2.AddVertexAt(ver,lonelypoly.GetPoint2dAt(i),0,0,0);
  100.                                           ver++;
  101.                                        }
  102.                                     }
  103.                                     if (closepoly) newpl2.Closed=true;
  104.                                     acBlkTblRec.AppendEntity(newpl2);
  105.                                     tr.AddNewlyCreatedDBObject(newpl2,true);
  106.                                  }
  107.                                  targetpoly.Erase();
  108.                               }
  109.                               catch (PlatformDb.Runtime.Exception ex)
  110.                               {
  111.                                  Application.ShowAlertDialog(ex.Message + "\n" + ex.StackTrace);
  112.                               }
  113.                         }
  114.                      }
  115.                   }
  116.                }
  117.                tr.Commit();
  118.             } catch (PlatformDb.Runtime.Exception Ex) {ed.WriteMessage("Ошибка: " + Ex.Message);}
  119.          }
  120.       }
  121.    }
  122. public static PromptSelectionResult SelectByPolyline(Editor ed, Polyline pline, bool mode, params TypedValue[] filter)
  123. {
  124.    Point3dCollection polygon = new Point3dCollection();
  125.    for (int i = 0; i < pline.NumberOfVertices; i++)
  126.    {
  127.       polygon.Add(pline.GetPoint3dAt(i));
  128.    }
  129.    PromptSelectionResult result;
  130.    ViewTableRecord view = ed.GetCurrentView();
  131.    Zoom(ed,pline.GeometricExtents);
  132.    if (mode)
  133.       result = ed.SelectCrossingPolygon(polygon, new SelectionFilter(filter));
  134.    else
  135.       result = ed.SelectWindowPolygon(polygon, new SelectionFilter(filter));
  136.    ed.SetCurrentView(view);
  137.    return result;
  138. }
  139. public static void Zoom(Editor ed, Extents3d extents)
  140. {
  141.    using (ViewTableRecord view = ed.GetCurrentView())
  142.    {
  143.       Matrix3d worldToEye =
  144.          Matrix3d.Rotation(-view.ViewTwist, view.ViewDirection, view.Target) *
  145.          Matrix3d.Displacement(view.Target - Point3d.Origin) *
  146.          Matrix3d.PlaneToWorld(view.ViewDirection)
  147.          .Inverse();
  148.       extents.TransformBy(worldToEye);
  149.       view.Width = extents.MaxPoint.X - extents.MinPoint.X;
  150.       view.Height = extents.MaxPoint.Y - extents.MinPoint.Y;
  151.       view.CenterPoint = new Point2d(
  152.          (extents.MaxPoint.X + extents.MinPoint.X) / 2.0,
  153.          (extents.MaxPoint.Y + extents.MinPoint.Y) / 2.0);
  154.       ed.SetCurrentView(view);
  155.    }
  156. }

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
В AutoCAD это просто делать командой "Контур" (Boundary).
Пока не смотрел ни код, ни чертежи, но у команды Boundary есть аналог в AutoCAD .NET API: Editor.TraceBoundary
Не подойдёт? У неё те же ограничения, что и у команды Boundary.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн avc

  • ADN Club
  • *****
  • Сообщений: 822
  • Карма: 166
    • Мои плагины к Автокаду
Я перевожу полилинии в наборы двухмерных линий и дуг, ищу пересечения (чистая школьная геометрия, хотя можно использовать кое-что из API, только тормозить будет и не распараллеливается), бью на части в точках пересечений. Потом ищу наружный максимальный контур перебирая все варианты на разветвлениях. Ну а потом конвертация обратно в полилинию.

Оффлайн geosysАвтор темы

  • ADN OPEN
  • Сообщений: 25
  • Карма: 3
В AutoCAD это просто делать командой "Контур" (Boundary).
Пока не смотрел ни код, ни чертежи, но у команды Boundary есть аналог в AutoCAD .NET API: Editor.TraceBoundary
Не подойдёт? У неё те же ограничения, что и у команды Boundary.
Спасибо за наводку! Буду пробовать, о результатах отпишу.
upd.: Editor.TraceBoundary подходит только для AutoCAD начиная с 2011. У нас используют в основном AutoCAD 2009, поэтому в моем случае этот метод не подходит.
Я перевожу полилинии в наборы двухмерных линий и дуг, ищу пересечения (чистая школьная геометрия, хотя можно использовать кое-что из API, только тормозить будет и не распараллеливается), бью на части в точках пересечений. Потом ищу наружный максимальный контур перебирая все варианты на разветвлениях. Ну а потом конвертация обратно в полилинию.
Спасибо за ответ, впринципе всё понятно, кроме вот этого
Цитировать
Потом ищу наружный максимальный контур перебирая все варианты на разветвлениях
Если не получится с Editor.TraceBoundary буду пробовать такой алгоритм, спасибо!
« Последнее редактирование: 30-01-2019, 10:31:26 от geosys »

Оффлайн avc

  • ADN Club
  • *****
  • Сообщений: 822
  • Карма: 166
    • Мои плагины к Автокаду
впринципе всё понятно, кроме вот этого
Перебираю сегменты начиная с самого левого-нижнего. В каждой точке ветвления выбираю сегмент с наибольшим углом относительно направления прихода в эту точку. Для дуг конечно направлением считаю косательную в этой точке. Код выкладывать нет смысла, т.к. он ссылается на кучу других моих структур и классов

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
geosys,
Если я правильно понял задачу (а она не вполне однозначная) и мы имеем дело:
1. С контурами - т.е. только замкнутыми полилиниями.
2. С режущей полилинией, которая тоже замкнута.
3. С контурами не имеющими дуговых сегментов - в противном случае нужно предварительно сделать аппроксимацию.
В этом случае код может выглядеть так:
Код - C# [Выбрать]
  1. using Autodesk.AutoCAD.ApplicationServices;
  2. using Autodesk.AutoCAD.DatabaseServices;
  3. using Autodesk.AutoCAD.EditorInput;
  4. using Autodesk.AutoCAD.Runtime;
  5. using Autodesk.AutoCAD.Geometry;
  6. using AcBr = Autodesk.AutoCAD.BoundaryRepresentation;
  7.  
  8. [assembly: CommandClass(typeof(Rivilis.PolyUtils))]
  9.  
  10. namespace Rivilis
  11. {
  12.   public class PolyUtils
  13.   {
  14.  
  15.     [CommandMethod("PolyInters")]
  16.     public void PolyIntersHandler()
  17.     {
  18.       Document doc = Application.DocumentManager.MdiActiveDocument;
  19.       if (doc == null) return;
  20.       Editor ed = doc.Editor;
  21.       Database db = doc.Database;
  22.       PromptEntityOptions prOpt = new PromptEntityOptions("");
  23.       prOpt.SetRejectMessage("Это не контур");
  24.       prOpt.AddAllowedClass(typeof(Polyline), true);
  25.       prOpt.Message = "Выберите режущий контур: ";
  26.       PromptEntityResult prRes1 = ed.GetEntity(prOpt);
  27.       if (prRes1.Status != PromptStatus.OK)
  28.         return;
  29.       prOpt.Message = "Выберите отрезаемый контур: ";
  30.       PromptEntityResult prRes2 = ed.GetEntity(prOpt);
  31.       if (prRes2.Status != PromptStatus.OK)
  32.         return;
  33.       if (prRes1.ObjectId == prRes2.ObjectId)
  34.       {
  35.         ed.WriteMessage("Вы выбрали один и тот же контур");
  36.         return;
  37.       }
  38.       using (Transaction tr = doc.TransactionManager.StartTransaction())
  39.       {
  40.         BlockTableRecord curBtr =
  41.           tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite) as BlockTableRecord;
  42.         using (DBObjectCollection dbcol1 = new DBObjectCollection())
  43.         using (DBObjectCollection dbcol2 = new DBObjectCollection())
  44.         {
  45.           Curve curve1 = tr.GetObject(prRes1.ObjectId, OpenMode.ForRead) as Curve;
  46.           Curve curve2 = tr.GetObject(prRes2.ObjectId, OpenMode.ForRead) as Curve;
  47.           dbcol1.Add(curve1); dbcol2.Add(curve2);
  48.           DBObjectCollection regs1 = null, regs2 = null;
  49.           // Преобразуем полилинии в области
  50.           try
  51.           {
  52.             regs1 = Region.CreateFromCurves(dbcol1);
  53.             regs2 = Region.CreateFromCurves(dbcol2);
  54.           } catch { };
  55.  
  56.           if (regs1 != null & regs2 != null &&
  57.               regs1.Count == 1 && regs2.Count == 1)
  58.           {
  59.             Region reg1 = regs1[0] as Region, reg2 = regs2[0] as Region;
  60.             Region reg1Clone = reg1.Clone() as Region;
  61.             Region reg2Clone = reg2.Clone() as Region;
  62.             // Это будет внешняя часть
  63.             reg2Clone.BooleanOperation(BooleanOperationType.BoolSubtract, reg1Clone);
  64.             CreatePolyLinesFromRegion(reg2Clone, curBtr, 5);
  65.             reg1Clone.Dispose(); reg2Clone.Dispose();
  66.             reg1Clone = reg1.Clone() as Region;
  67.             reg2Clone = reg2.Clone() as Region;
  68.             // Это будет внутренняя часть
  69.             reg2Clone.BooleanOperation(BooleanOperationType.BoolIntersect, reg1Clone);
  70.             CreatePolyLinesFromRegion(reg2Clone, curBtr, 2);
  71.             reg1Clone.Dispose(); reg2Clone.Dispose();
  72.             reg1.Dispose(); reg2.Dispose();
  73.             Curve curve = tr.GetObject(prRes2.ObjectId, OpenMode.ForWrite) as Curve;
  74.             curve.Erase(); // Удаляем отрезаемый контур
  75.  
  76.           }
  77.         }
  78.         tr.Commit();
  79.       }
  80.     }
  81.     /// <summary>
  82.     /// Creates the polylines from region.
  83.     /// </summary>
  84.     /// <param name="reg">The reg.</param>
  85.     /// <param name="btr">The BTR.</param>
  86.     public static void CreatePolyLinesFromRegion(Region reg, BlockTableRecord btr, int color = 256)
  87.     {
  88.       if (!reg.IsNull)
  89.       {
  90.         Transaction tr = btr.Database.TransactionManager.TopTransaction;
  91.         using (AcBr.Brep brep = new AcBr.Brep(reg))
  92.         {
  93.           foreach (AcBr.Face face in brep.Faces)
  94.           {
  95.             foreach (AcBr.BoundaryLoop loop in face.Loops)
  96.             {
  97.               int iVert = 0;
  98.               Polyline pl = new Polyline();
  99.               foreach (AcBr.Vertex p in loop.Vertices)
  100.               {
  101.                 pl.AddVertexAt(iVert++, new Point2d(p.Point.X, p.Point.Y), 0, 0, 0);
  102.               }
  103.               pl.Closed = true;
  104.               pl.ColorIndex = color;
  105.               btr.AppendEntity(pl);
  106.               tr.AddNewlyCreatedDBObject(pl, true);
  107.             }
  108.           }
  109.         }
  110.       }
  111.     }
  112.   }
  113. }

Вот так выглядит его работа на чертеже - образце:




Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Отмечено как Решение geosys 31-01-2019, 15:41:42

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Ну а так сразу со всеми пересекающимися контурами:
Код - C# [Выбрать]
  1. using System;
  2. using Autodesk.AutoCAD.ApplicationServices;
  3. using Autodesk.AutoCAD.DatabaseServices;
  4. using Autodesk.AutoCAD.EditorInput;
  5. using Autodesk.AutoCAD.Runtime;
  6. using Autodesk.AutoCAD.Geometry;
  7. using AcBr = Autodesk.AutoCAD.BoundaryRepresentation;
  8.  
  9. [assembly: CommandClass(typeof(Rivilis.PolyUtils))]
  10.  
  11. namespace Rivilis
  12. {
  13.   public class PolyUtils
  14.   {
  15.     [CommandMethod("PolyInters2")]
  16.     public void PolyIntersHandler2()
  17.     {
  18.       Document doc = Application.DocumentManager.MdiActiveDocument;
  19.       if (doc == null) return;
  20.       Editor ed = doc.Editor;
  21.       Database db = doc.Database;
  22.       PromptEntityOptions prOpt = new PromptEntityOptions("");
  23.       prOpt.SetRejectMessage("Это не контур");
  24.       prOpt.AddAllowedClass(typeof(Polyline), true);
  25.       prOpt.Message = "Выберите режущий контур: ";
  26.       PromptEntityResult prRes = ed.GetEntity(prOpt);
  27.       if (prRes.Status != PromptStatus.OK)
  28.         return;
  29.       TypedValue[] filList = new TypedValue[] {
  30.         new TypedValue((int)DxfCode.Start, "LWPOLYLINE")
  31.       };
  32.       SelectionFilter sf = new SelectionFilter(filList);
  33.       PromptSelectionOptions pso = new PromptSelectionOptions();
  34.       pso.MessageForAdding = "\nВыберите полилинию";
  35.       PromptSelectionResult psr = ed.GetSelection(pso, sf);
  36.       if (psr.Status != PromptStatus.OK)
  37.         return;
  38.  
  39.       using (Transaction tr = doc.TransactionManager.StartTransaction())
  40.       {
  41.         BlockTableRecord curBtr =
  42.           tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite) as BlockTableRecord;
  43.         Curve curveInt = tr.GetObject(prRes.ObjectId, OpenMode.ForRead) as Curve;
  44.         using (DBObjectCollection dbCurvs = new DBObjectCollection())
  45.         {
  46.           foreach (ObjectId id in psr.Value.GetObjectIds())
  47.           {
  48.             if (id == prRes.ObjectId)
  49.               continue;
  50.             Curve curve = tr.GetObject(id, OpenMode.ForRead) as Curve;
  51.             if (curve != null)
  52.             {
  53.               using (Point3dCollection pts = new Point3dCollection())
  54.               {
  55.                 using (Plane plan = new Plane(Point3d.Origin, Vector3d.ZAxis))
  56.                 {
  57.                   // Отбираем только те контуры, которые пересекаются с секущим контуром
  58.                   curve.IntersectWith(curveInt, Intersect.OnBothOperands, plan, pts, new IntPtr(0), new IntPtr(0));
  59.                   if (pts.Count > 0)
  60.                     dbCurvs.Add(curve);
  61.                 }
  62.               }
  63.             }
  64.           }
  65.           // Выполняем попарно пересечение секущего контура с выбранными
  66.           foreach (Curve curve in dbCurvs)
  67.           {
  68.             using (DBObjectCollection dbcol1 = new DBObjectCollection())
  69.             using (DBObjectCollection dbcol2 = new DBObjectCollection())
  70.             {
  71.               dbcol1.Add(curveInt); dbcol2.Add(curve);
  72.               DBObjectCollection regs1 = null, regs2 = null;
  73.               // Преобразуем полилинии в области
  74.               try
  75.               {
  76.                 regs1 = Region.CreateFromCurves(dbcol1);
  77.                 regs2 = Region.CreateFromCurves(dbcol2);
  78.               }
  79.               catch { };
  80.  
  81.               if (regs1 != null & regs2 != null &&
  82.                   regs1.Count == 1 && regs2.Count == 1)
  83.               {
  84.                 Region reg1 = regs1[0] as Region, reg2 = regs2[0] as Region;
  85.                 Region reg1Clone = reg1.Clone() as Region;
  86.                 Region reg2Clone = reg2.Clone() as Region;
  87.                 // Это будет внешняя часть
  88.                 reg2Clone.BooleanOperation(BooleanOperationType.BoolSubtract, reg1Clone);
  89.                 CreatePolyLinesFromRegion(reg2Clone, curBtr, 5);
  90.                 reg1Clone.Dispose(); reg2Clone.Dispose();
  91.                 reg1Clone = reg1.Clone() as Region;
  92.                 reg2Clone = reg2.Clone() as Region;
  93.                 // Это будет внутренняя часть
  94.                 reg2Clone.BooleanOperation(BooleanOperationType.BoolIntersect, reg1Clone);
  95.                 CreatePolyLinesFromRegion(reg2Clone, curBtr, 2);
  96.                 reg1Clone.Dispose(); reg2Clone.Dispose();
  97.                 reg1.Dispose(); reg2.Dispose();
  98.                 Curve curveDel = tr.GetObject(curve.ObjectId, OpenMode.ForWrite) as Curve;
  99.                 curveDel.Erase(); // Удаляем отрезаемый контур
  100.               }
  101.             }
  102.  
  103.           }
  104.         }
  105.         tr.Commit();
  106.       }
  107.     }
  108.  
  109.     /// <summary>
  110.     /// Creates the polylines from region.
  111.     /// </summary>
  112.     /// <param name="reg">The reg.</param>
  113.     /// <param name="btr">The BTR.</param>
  114.     public static void CreatePolyLinesFromRegion(Region reg, BlockTableRecord btr, int color = 256)
  115.     {
  116.       if (!reg.IsNull)
  117.       {
  118.         Transaction tr = btr.Database.TransactionManager.TopTransaction;
  119.         using (AcBr.Brep brep = new AcBr.Brep(reg))
  120.         {
  121.           foreach (AcBr.Face face in brep.Faces)
  122.           {
  123.             foreach (AcBr.BoundaryLoop loop in face.Loops)
  124.             {
  125.               int iVert = 0;
  126.               Polyline pl = new Polyline();
  127.               foreach (AcBr.Vertex p in loop.Vertices)
  128.               {
  129.                 pl.AddVertexAt(iVert++, new Point2d(p.Point.X, p.Point.Y), 0, 0, 0);
  130.               }
  131.               pl.Closed = true;
  132.               pl.ColorIndex = color;
  133.               btr.AppendEntity(pl);
  134.               tr.AddNewlyCreatedDBObject(pl, true);
  135.             }
  136.           }
  137.         }
  138.       }
  139.     }
  140.   }
  141. }

Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн geosysАвтор темы

  • ADN OPEN
  • Сообщений: 25
  • Карма: 3
Да! Это оно! Спасибо огромное! Гениально и просто!
Вот слегка переделал код, чтобы не нужно было выбирать все пересекаемые объекты. В итоге программа выглядит так:
Код - C# [Выбрать]
  1. using System;
  2. using Autodesk.AutoCAD.ApplicationServices;
  3. using Autodesk.AutoCAD.DatabaseServices;
  4. using Autodesk.AutoCAD.EditorInput;
  5. using Autodesk.AutoCAD.Runtime;
  6. using Autodesk.AutoCAD.Geometry;
  7. using AcBr = Autodesk.AutoCAD.BoundaryRepresentation;
  8. using Platform = Autodesk.AutoCAD;
  9. using PlatformDb = Autodesk.AutoCAD;
  10.  
  11. [assembly: CommandClass(typeof(Rivilis.PolyUtils))]
  12.  
  13.  
  14. namespace Rivilis
  15. {
  16.     public class PolyUtils
  17.     {
  18.         [CommandMethod("slicetest")]
  19.         public static void sliceinside()
  20.         {
  21.  
  22.             bool crossing = true; string filter = "LWPOLYLINE";
  23.             Document doc = Application.DocumentManager.MdiActiveDocument;
  24.             Database db = doc.Database;
  25.             Editor ed = doc.Editor;
  26.  
  27.             TypedValue[] filList = new TypedValue[1] { new TypedValue((int)DxfCode.Start, "LWPOLYLINE") };
  28.             SelectionFilter sfilter = new SelectionFilter(filList);
  29.             PromptSelectionOptions pso = new PromptSelectionOptions();
  30.             pso.MessageForAdding = "\nВыбирете полилинию";
  31.             PromptSelectionResult per = ed.GetSelection(pso, sfilter);
  32.             if (per.Status == PromptStatus.OK)
  33.             {
  34.  
  35.                 Transaction tr = db.TransactionManager.StartTransaction();
  36.                 using (tr)
  37.                 {
  38.  
  39.                     BlockTable acBlkTbl = tr.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable;
  40.                     BlockTableRecord acBlkTblRec = tr.GetObject(acBlkTbl[BlockTableRecord.ModelSpace], OpenMode.ForWrite) as BlockTableRecord;
  41.                     try
  42.                     {
  43.                         SelectionSet acSSet = per.Value;
  44.                         foreach (SelectedObject acSSObj in acSSet)
  45.                         {
  46.                             Polyline pline = new Polyline();
  47.                             DBObject obj = (DBObject)tr.GetObject(acSSObj.ObjectId, OpenMode.ForRead);
  48.                             if (obj is Polyline)
  49.                             {
  50.                                 pline = (Polyline)obj;
  51.                                 PromptSelectionResult selection = SelectByPolyline(ed, pline, crossing, new TypedValue(0, filter));
  52.                                 SelectionSet selSet = selection.Value;
  53.                                 // //
  54.                                 DBObjectCollection dbCurvs = new DBObjectCollection();
  55.                                 foreach (ObjectId id in selection.Value.GetObjectIds())
  56.                                 {
  57.                                     Curve curve = tr.GetObject(id, OpenMode.ForRead) as Curve;
  58.                                     if (curve != null)
  59.                                     {
  60.                                         dbCurvs.Add(curve);
  61.                                     }
  62.                                 }
  63.                                 foreach (Curve curve in dbCurvs)
  64.                                 {
  65.                                     using (DBObjectCollection dbcol1 = new DBObjectCollection())
  66.                                     using (DBObjectCollection dbcol2 = new DBObjectCollection())
  67.                                     {
  68.                                         dbcol1.Add(pline as Curve); dbcol2.Add(curve);
  69.                                         DBObjectCollection regs1 = null, regs2 = null;
  70.                                         // Преобразуем полилинии в области
  71.                                         try
  72.                                         {
  73.                                             regs1 = Region.CreateFromCurves(dbcol1);
  74.                                             regs2 = Region.CreateFromCurves(dbcol2);
  75.                                         }
  76.                                         catch { };
  77.  
  78.                                         if (regs1 != null & regs2 != null &&
  79.                                             regs1.Count == 1 && regs2.Count == 1)
  80.                                         {
  81.                                             Region reg1 = regs1[0] as Region, reg2 = regs2[0] as Region;
  82.                                             Region reg1Clone = reg1.Clone() as Region;
  83.                                             Region reg2Clone = reg2.Clone() as Region;
  84.                                             // Это будет внешняя часть
  85.                                             reg2Clone.BooleanOperation(BooleanOperationType.BoolSubtract, reg1Clone);
  86.                                             CreatePolyLinesFromRegion(reg2Clone, acBlkTblRec);
  87.                                             reg1Clone.Dispose(); reg2Clone.Dispose();
  88.                                             reg1Clone = reg1.Clone() as Region;
  89.                                             reg2Clone = reg2.Clone() as Region;
  90.                                             // Это будет внутренняя часть
  91.                                             reg2Clone.BooleanOperation(BooleanOperationType.BoolIntersect, reg1Clone);
  92.                                             CreatePolyLinesFromRegion(reg2Clone, acBlkTblRec);
  93.                                             reg1Clone.Dispose(); reg2Clone.Dispose();
  94.                                             reg1.Dispose(); reg2.Dispose();
  95.                                             Curve curveDel = tr.GetObject(curve.ObjectId, OpenMode.ForWrite) as Curve;
  96.                                             curveDel.Erase(); // Удаляем отрезаемый контур
  97.                                         }
  98.                                     }
  99.  
  100.                                 }
  101.                             }
  102.                         }
  103.  
  104.                         tr.Commit();
  105.                     }
  106.                     catch (PlatformDb.Runtime.Exception Ex) { ed.WriteMessage("Ошибка: " + Ex.Message); }
  107.                 }
  108.  
  109.             }
  110.         }
  111.  
  112.         public static void CreatePolyLinesFromRegion(Region reg, BlockTableRecord btr)
  113.         {
  114.             if (!reg.IsNull)
  115.             {
  116.                 Transaction tr = btr.Database.TransactionManager.TopTransaction;
  117.                 using (AcBr.Brep brep = new AcBr.Brep(reg))
  118.                 {
  119.                     foreach (AcBr.Face face in brep.Faces)
  120.                     {
  121.                         foreach (AcBr.BoundaryLoop loop in face.Loops)
  122.                         {
  123.                             int iVert = 0;
  124.                             Polyline pl = new Polyline();
  125.                             foreach (AcBr.Vertex p in loop.Vertices)
  126.                             {
  127.                                 pl.AddVertexAt(iVert++, new Point2d(p.Point.X, p.Point.Y), 0, 0, 0);
  128.                             }
  129.                             pl.Closed = true;
  130.                             btr.AppendEntity(pl);
  131.                             tr.AddNewlyCreatedDBObject(pl, true);
  132.                             LayerTable ltb = (LayerTable)tr.GetObject(btr.Database.LayerTableId, OpenMode.ForRead);
  133.                             if (!ltb.Has("narezka"))
  134.                             {
  135.                                 ltb.UpgradeOpen();
  136.                                 LayerTableRecord newLayer = new LayerTableRecord();
  137.                                 newLayer.Name = "narezka";
  138.                                 ltb.Add(newLayer);
  139.                                 tr.AddNewlyCreatedDBObject(newLayer, true);
  140.                             }
  141.                             pl.LayerId = ltb["narezka"];
  142.                         }
  143.                     }
  144.                 }
  145.             }
  146.         }
  147.  
  148.         public static PromptSelectionResult SelectByPolyline(Editor ed, Polyline pline, bool mode, params TypedValue[] filter)
  149.         {
  150.             Point3dCollection polygon = new Point3dCollection();
  151.             for (int i = 0; i < pline.NumberOfVertices; i++)
  152.             {
  153.                 polygon.Add(pline.GetPoint3dAt(i));
  154.             }
  155.             PromptSelectionResult result;
  156.             ViewTableRecord view = ed.GetCurrentView();
  157.             Zoom(ed, pline.GeometricExtents);
  158.             if (mode)
  159.                 result = ed.SelectCrossingPolygon(polygon, new SelectionFilter(filter));
  160.             else
  161.                 result = ed.SelectWindowPolygon(polygon, new SelectionFilter(filter));
  162.             ed.SetCurrentView(view);
  163.             return result;
  164.         }
  165.  
  166.         public static void Zoom(Editor ed, Extents3d extents)
  167.         {
  168.             using (ViewTableRecord view = ed.GetCurrentView())
  169.             {
  170.                 Matrix3d worldToEye =
  171.                     Matrix3d.Rotation(-view.ViewTwist, view.ViewDirection, view.Target) *
  172.                     Matrix3d.Displacement(view.Target - Point3d.Origin) *
  173.                     Matrix3d.PlaneToWorld(view.ViewDirection)
  174.                     .Inverse();
  175.                 extents.TransformBy(worldToEye);
  176.                 view.Width = extents.MaxPoint.X - extents.MinPoint.X;
  177.                 view.Height = extents.MaxPoint.Y - extents.MinPoint.Y;
  178.                 view.CenterPoint = new Point2d(
  179.                     (extents.MaxPoint.X + extents.MinPoint.X) / 2.0,
  180.                     (extents.MaxPoint.Y + extents.MinPoint.Y) / 2.0);
  181.                 ed.SetCurrentView(view);
  182.             }
  183.         }
  184.     }
  185. }