Обрезка полилиний

Автор Тема: Обрезка полилиний  (Прочитано 7758 раз)

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

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

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

  • ADN OPEN
  • Сообщений: 25
  • Карма: 3
Обрезка полилиний
« : 02-08-2018, 17:11:15 »
Доброго времени суток!
Имею следующий чертёж из полилиний:

Его необходимо привести к следующему виду:


Пробую сделать так:
Ищу пересечения каждого объекта с последующим, в результате получаю точки пересечения, если кол-во точек >=2, разделяю полилинию в точке пересечения. Из разделённых "вылавливаю" только полилинии, у которых длина больше указанного значения (не знаю к чему ещё привязаться). Но у меня выходит логический затык: в цикле сравнения если добавлять все эти разделённые полилинии - их получается очень много, и каждая с разным разрывом (в зависимости от того с каким элементом пересекается в цикле). Если присваивать полученную полилинию исходной - будет работать только в половине случаев, так как моя "ловля" может отлавливать и две части полилинии вместо одной.
Вобщем вот мой код, прошу помочь выйти из логического тупика, скорее всего я забрёл не туда и просто не вижу очевидного :)
Код - C# [Выбрать]
  1. //исходные полилинии находятся в одномерном массиве polosy типа Polyline[]
  2.                                                 for (int i = 0; i < polosy.Count() - 1; i++)
  3.                                 { //прохожусь по всем элементам, сравнивая каждый с каждым последующим
  4.                                         for (int j = i + 1; j < polosy.Count(); j++)
  5.                                         {
  6.                                                 Point3dCollection points = new Point3dCollection();
  7.                                                 polosy[i].IntersectWith(polosy[j], Intersect.OnBothOperands, points, new IntPtr(0), new IntPtr(0)); //пересекаю каждый с каждым последующим
  8.                                                 if (points.Count >= 2) //если количество точек пересечения >=2
  9.                                                 {
  10.                                                                 DBObjectCollection splitLines = polosy[i].GetSplitCurves(points); //разделяю исходную полилинию в точках пересечения
  11.                                                                 foreach (Polyline pline in splitLines)
  12.                                                                 {
  13.                                                                         if (pline.Length>(25))//вылавливаю только те полилинию из разделенных, длина которых больше 25
  14.                                                                         {
  15.                                                                                 pline.ColorIndex=1; //красные
  16.                                                                                 acBlkTblRec.AppendEntity(pline); //добавляю в чертёж
  17.                                                                                 tr.AddNewlyCreatedDBObject(pline, true);
  18.                                                                                 //polosy[i]=pline; //пытался присвоить разделенную часть линии исходной линии
  19.                                                                         }
  20.                                                                 }
  21.                                                                 DBObjectCollection splitLines2 = polosy[j].GetSplitCurves(points);//тоже самое делаю с пересекаемой линией
  22.                                                                 foreach (Polyline pline in splitLines2)
  23.                                                                 {
  24.                                                                         if (pline.Length>(25))
  25.                                                                         {
  26.                                                                                 pline.ColorIndex=1;
  27.                                                                                 acBlkTblRec.AppendEntity(pline);
  28.                                                                                 tr.AddNewlyCreatedDBObject(pline, true);
  29.                                                                                 //polosy[j]=pline;
  30.                                                                         }
  31.                                                                 }      
  32.                                                 }
  33.                                         }
  34.                                 }
  35.                                 for (int i = 0; i < polosy.Count() - 1; i++) //удаляю исходные полилинии
  36.                                 {
  37.                                         polosy[i].Erase();
  38.                                 }
« Последнее редактирование: 02-08-2018, 17:14:49 от Александр Ривилис »

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

  • Administrator
  • *****
  • Сообщений: 13830
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Обрезка полилиний
« Ответ #1 : 02-08-2018, 17:14:10 »
geosys
Прочитай у меня в подписи как следует форматировать код на форуме и придерживайся этого правила! И измени величину табуляции в коде  - не больше 4. Иначе смотреть код невозможно.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • Administrator
  • *****
  • Сообщений: 13830
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Обрезка полилиний
« Ответ #2 : 02-08-2018, 17:23:09 »
скорее всего я забрёл не туда и просто не вижу очевидного :)
Очевидно здесь то, что задача на порядок сложнее, чем представляется с первого раза и с наскока без изучения соответствующей теории ты её не решишь.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • Administrator
  • *****
  • Сообщений: 13830
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Обрезка полилиний
« Ответ #3 : 02-08-2018, 17:42:34 »
Вот так это можно сделать вообще без программирования:
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN OPEN
  • Сообщений: 25
  • Карма: 3
Re: Обрезка полилиний
« Ответ #4 : 02-08-2018, 17:49:36 »
Ухты,  большое спасибо за подсказку и оперативность! Буду пытаться сделать то же программно :)
На крайняк SendStringToExecute мне в помощь :D

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

  • Administrator
  • *****
  • Сообщений: 13830
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Обрезка полилиний
« Ответ #5 : 02-08-2018, 21:41:46 »
Без большого количества проверок и не слишком оптимально, но работает. Во всяком случае в тестовом чертеже.

Код - C# [Выбрать]
  1. using Autodesk.AutoCAD.ApplicationServices;
  2. using Autodesk.AutoCAD.DatabaseServices;
  3. using Autodesk.AutoCAD.EditorInput;
  4. using Autodesk.AutoCAD.Runtime;
  5.  
  6. [assembly: CommandClass(typeof(Rivilis.PolyUnion))]
  7.  
  8. namespace Rivilis
  9. {
  10.   public class PolyUnion
  11.   {
  12.     [CommandMethod("PolyUnion")]
  13.     public void PolyUnionHandler()
  14.     {
  15.       Document doc = Application.DocumentManager.MdiActiveDocument;
  16.       if (doc == null) return;
  17.       Editor ed = doc.Editor;
  18.       Database db = doc.Database;
  19.       SelectionFilter sf = new SelectionFilter(new TypedValue[]
  20.         {
  21.           new TypedValue((int) DxfCode.Start,"POLYLINE,LWPOLYLINE")
  22.         }
  23.       );
  24.       PromptSelectionResult psr = ed.GetSelection(sf);
  25.       if (psr.Status == PromptStatus.OK && psr.Value.Count > 0)
  26.       {
  27.         using (Transaction tr = doc.TransactionManager.StartTransaction())
  28.         {
  29.           BlockTableRecord curBtr =
  30.             tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite) as BlockTableRecord;
  31.           DBObjectCollection dbcol = new DBObjectCollection();
  32.           foreach (ObjectId id in psr.Value.GetObjectIds())
  33.           {
  34.             Curve curve = tr.GetObject(id, OpenMode.ForRead) as Curve;
  35.             if (curve != null) dbcol.Add(curve);
  36.           }
  37.           DBObjectCollection dbRegions = null;
  38.           try  { dbRegions = Region.CreateFromCurves(dbcol); } catch { }
  39.           int nRegs = 0;
  40.           if (dbRegions != null && (nRegs = dbRegions.Count) > 0)
  41.           {
  42.             for (int i = 0; i < nRegs; i++)
  43.             {
  44.               if (dbRegions[i] == null) continue;
  45.               Region reg1 = dbRegions[i] as Region;
  46.               for (int j = i+1; j < nRegs; j++)
  47.               {
  48.                 if (dbRegions[j] == null) continue;
  49.                 Region reg2 = dbRegions[j] as Region;
  50.                 try {
  51.                   reg1.BooleanOperation(BooleanOperationType.BoolUnite, reg2);
  52.                   dbRegions[j].Dispose();
  53.                   dbRegions[j] = null;
  54.                 } catch { }
  55.               }
  56.               if (!reg1.IsNull)
  57.               {
  58.                 curBtr.AppendEntity(reg1);
  59.                 tr.AddNewlyCreatedDBObject(reg1, true);
  60.               }
  61.             }
  62.           }
  63.           tr.Commit();
  64.         }
  65.       }
  66.     }
  67.   }
  68. }



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

Отмечено как Решение Александр Ривилис 03-08-2018, 17:09:01

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

  • Administrator
  • *****
  • Сообщений: 13830
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Обрезка полилиний
« Ответ #6 : 02-08-2018, 22:38:35 »
А вот этот вариант позволяет получить коллекцию замкнутых не пересекающихся полилиний:
Код - 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.PolyUnion))]
  9.  
  10. namespace Rivilis
  11. {
  12.   public class PolyUnion
  13.   {
  14.     [CommandMethod("PolyUnion2")]
  15.     public void PolyUnionHandler2()
  16.     {
  17.       Document doc = Application.DocumentManager.MdiActiveDocument;
  18.       if (doc == null) return;
  19.       Editor ed = doc.Editor;
  20.       Database db = doc.Database;
  21.       SelectionFilter sf = new SelectionFilter(new TypedValue[]
  22.         {
  23.           new TypedValue((int) DxfCode.Start,"POLYLINE,LWPOLYLINE")
  24.         }
  25.       );
  26.       PromptSelectionResult psr = ed.GetSelection(sf);
  27.       if (psr.Status == PromptStatus.OK && psr.Value.Count > 0)
  28.       {
  29.         using (Transaction tr = doc.TransactionManager.StartTransaction())
  30.         {
  31.           BlockTableRecord curBtr =
  32.             tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite) as BlockTableRecord;
  33.           DBObjectCollection dbcol = new DBObjectCollection();
  34.           foreach (ObjectId id in psr.Value.GetObjectIds())
  35.           {
  36.             Curve curve = tr.GetObject(id, OpenMode.ForRead) as Curve;
  37.             if (curve != null) dbcol.Add(curve);
  38.           }
  39.           DBObjectCollection dbRegions = null;
  40.           try  { dbRegions = Region.CreateFromCurves(dbcol); } catch { }
  41.           int nRegs = 0;
  42.           if (dbRegions != null && (nRegs = dbRegions.Count) > 0)
  43.           {
  44.             for (int i = 0; i < nRegs; i++)
  45.             {
  46.               if (dbRegions[i] == null) continue;
  47.               Region reg1 = dbRegions[i] as Region;
  48.               for (int j = i+1; j < nRegs; j++)
  49.               {
  50.                 if (dbRegions[j] == null) continue;
  51.                 Region reg2 = dbRegions[j] as Region;
  52.                 try {
  53.                   reg1.BooleanOperation(BooleanOperationType.BoolUnite, reg2);
  54.                   dbRegions[j].Dispose();
  55.                   dbRegions[j] = null;
  56.                 } catch { }
  57.               }
  58.               if (!reg1.IsNull)
  59.               {
  60.                 // Преобразуем области (Region) в набор замкнутых полилиний
  61.                 // Для этой цели используем BREP .NET API
  62.                 using (AcBr.Brep brep = new AcBr.Brep(reg1))
  63.                 {
  64.                   foreach (AcBr.Face face in brep.Faces)
  65.                   {
  66.                     foreach (AcBr.BoundaryLoop loop in face.Loops)
  67.                     {
  68.                       int iVert = 0;
  69.                       Polyline pl = new Polyline();
  70.                       foreach (AcBr.Vertex p in loop.Vertices)  {
  71.                         pl.AddVertexAt(iVert++, new Point2d(p.Point.X, p.Point.Y), 0, 0,0);
  72.                       }
  73.                       pl.Closed = true;
  74.                       curBtr.AppendEntity(pl);
  75.                       tr.AddNewlyCreatedDBObject(pl, true);
  76.                     }
  77.                   }
  78.                 }
  79.                 reg1.Dispose();
  80.               }
  81.             }
  82.           }
  83.           // Удаляем исходные полилинии
  84.           foreach (DBObject obj in dbcol)
  85.           {
  86.             DBObject objwr = tr.GetObject(obj.Id, OpenMode.ForWrite);
  87.             objwr.Erase();
  88.           }
  89.           tr.Commit();
  90.         }
  91.       }
  92.     }
  93.   }
  94. }
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN OPEN
  • Сообщений: 25
  • Карма: 3
Re: Обрезка полилиний
« Ответ #7 : 03-08-2018, 08:32:27 »
Александр Ривилис, я Вас люблю! Спасибо большое за Вашу помощь, время и опыт! Код правда даёт Exception во второй части, но после проставления try catch всё работает как часы!

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

  • Administrator
  • *****
  • Сообщений: 13830
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Обрезка полилиний
« Ответ #8 : 03-08-2018, 17:08:04 »
Код правда даёт Exception во второй части, но после проставления try catch всё работает как часы!
Уточни где код выдаёт exception и где ты поставил try/catch. На твоём примере у меня исключений не было. Поэтому и интересно что я не учел.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN OPEN
  • Сообщений: 25
  • Карма: 3
Re: Обрезка полилиний
« Ответ #9 : 06-08-2018, 10:29:54 »
Вот на этом участке:
  • if (!reg1.IsNull)
  • {
  • curBtr.AppendEntity(reg1);
  • tr.AddNewlyCreatedDBObject(reg1, true);
  • }
Но в Автокаде действительно этот участок ошибок не вызывает (проверил), а вот при компиляции под Teigha (Bricscad, nanoCAD, zwCAD) проверка reg1.IsNull вызывает NullReferenceException :)

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

  • Administrator
  • *****
  • Сообщений: 13830
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Обрезка полилиний
« Ответ #10 : 06-08-2018, 10:56:56 »
Но в Автокаде действительно этот участок ошибок не вызывает (проверил), а вот при компиляции под Teigha (Bricscad, nanoCAD, zwCAD) проверка reg1.IsNull вызывает NullReferenceException
На нашем форуме не обсуждаюся клоны AutoCAD!
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN OPEN
  • Сообщений: 25
  • Карма: 3
Re: Обрезка полилиний
« Ответ #11 : 06-08-2018, 11:04:08 »
Пардон, в таком случае всё корректно  :)
Ещё раз, огромное спасибо!

Оффлайн avc

  • ADN Club
  • *****
  • Сообщений: 809
  • Карма: 166
    • Мои плагины к Автокаду
Re: Обрезка полилиний
« Ответ #12 : 07-08-2018, 14:54:27 »
Приведенный пример с преобразованием в регионы не корректно создает новые полилинии - все сегменты-дуги превратятся в прямые. Лучше было бы без Brep просто взорвать регион.
А полная версия поиска внешних контуров с сохранением всех обрезков у меня занимает тыщи 3 строк :) Но работает (см. OSL https://sites.google.com/site/avcprg/cnc

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

  • Administrator
  • *****
  • Сообщений: 13830
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Обрезка полилиний
« Ответ #13 : 07-08-2018, 15:27:03 »
Приведенный пример с преобразованием в регионы не корректно создает новые полилинии - все сегменты-дуги превратятся в прямые.
Скажем так, что я писал упрощенный вариант под пример чертежа.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн avc

  • ADN Club
  • *****
  • Сообщений: 809
  • Карма: 166
    • Мои плагины к Автокаду
Re: Обрезка полилиний
« Ответ #14 : 07-08-2018, 15:36:15 »
Скажем так, что я писал упрощенный вариант под пример чертежа.
Да, конечно. Я просто оставил пометку для тех кто бездумно скопирует код