Сообщество программистов Autodesk в СНГ

ADN Club => AutoCAD .NET API => Тема начата: Podushkin от 27-06-2021, 20:15:20

Название: Скорость нахождения точек пересечения
Отправлено: Podushkin от 27-06-2021, 20:15:20
Добрый вечер. Для нахождения точек пересечения проекции на плоскость полилинии с другими линиями использую метод IntersectWith(), все работает штатно. Однако, в моем конкретном случае линий 450 штук. К примеру, в цикле метод вызывается 450 раз, время выполнения около 50 сек. Из всех линий полилиния пересекает всего штук 20. Каким образом можно увеличить скорость обработки линий?
Вопрос 2.
Необходимо найти все точки пересечения проекций на плоскость полилиний, на каждой создать вершину . Пока добавляю все линии в лист, далее двумя циклами перебираю все линии и нахожу точки пересечений добавляю вершины. Но тут скорость обработки такая, что можно вообще на полчасика пойти погулять.... правильно ли использовать такое количество циклов?
Название: Re: Скорость нахождения точек пересечения
Отправлено: avc от 27-06-2021, 20:31:02
Возможно быстрей будет искать сначала пересечение габаритов линий. Погуглите тему RTree
Название: Re: Скорость нахождения точек пересечения
Отправлено: Александр Ривилис от 27-06-2021, 20:34:22
К примеру, в цикле метод вызывается 450 раз, время выполнения около 50 сек.
Это очень много. Что-то в алгоритме не то. Без кода непонятно в чем проблема.
Вопрос 2.
Один вопрос - одна тема.
Название: Re: Скорость нахождения точек пересечения
Отправлено: avc от 27-06-2021, 20:43:46
Попутно: пересечения линий и дуг в плоскости элементарно вычисляются чисто математически  - школьная геометрия. По моему опыту чистая математика дает ускорение раз в 10 по сравнению с простыми вызовами API. Плюс к тому можно загнать все данные в самодельные классы и обрабатывать параллельно.
Название: Re: Скорость нахождения точек пересечения
Отправлено: Podushkin от 27-06-2021, 20:53:51
Код - C# [Выбрать]
  1. Plane planeXoy = new Plane(
  2. Application.DocumentManager.MdiActiveDocument.Editor.CurrentUserCoordinateSystem.CoordinateSystem3d.Origin,
  3. Application.DocumentManager.MdiActiveDocument.Editor.CurrentUserCoordinateSystem.CoordinateSystem3d.Zaxis
  4. );
  5. Point3dCollection points = new Point3dCollection();
  6. Point3dCollection intersectionPoints = new Point3dCollection();
  7.                      
  8.  
  9. for (int i = 0; i < ListOfAllPolyline.Count; i++)
  10. {
  11.       Point3dCollection points = new Point3dCollection();
  12.  
  13.       c1.IntersectWith(ListOfAllPolyline[i], Intersect.OnBothOperands, planeXoy, points, IntPtr.Zero, IntPtr.Zero);
  14.       if (points.Count != 0)
  15.       {
  16.             ListOfPolyline.Add(ListOfAllPolyline[i]);
  17.             foreach (Point3d Point_ in points)
  18.             {
  19.                   var xline = new Xline();
  20.                   xline.BasePoint = Point_;
  21.                   xline.UnitDir = Vector3d.ZAxis;
  22.                   c1.IntersectWith(xline, Intersect.OnBothOperands, planeXoy, intersectionPoints, IntPtr.Zero, IntPtr.Zero);
  23.             }                              
  24.  
  25.       }
  26. }

При отладке основное время занимает вот этот код.
Название: Re: Скорость нахождения точек пересечения
Отправлено: Александр Ривилис от 27-06-2021, 21:00:16
Podushkin,
Это не код, а огрызок кода. Для того, чтобы оценить производительность этого кода нужно понять порядок количества вершин у этих полилиний и возможность дуговых сегментов у них.
Название: Re: Скорость нахождения точек пересечения
Отправлено: Podushkin от 27-06-2021, 21:06:59
Код - C# [Выбрать]
  1.  public void iterateObjects( List <string> b)
  2.         {
  3.            
  4.             Database db = HostApplicationServices.WorkingDatabase;
  5.             Document acDoc = acad.DocumentManager.MdiActiveDocument;
  6.             Editor ed = acDoc.Editor;
  7.  
  8.             using (DocumentLock docLock = acDoc.LockDocument())
  9.             {
  10.                
  11.                 using (Transaction tr = db.TransactionManager.StartTransaction())
  12.                 {
  13.                  
  14.                     BlockTableRecord ms = (BlockTableRecord)tr.GetObject(SymbolUtilityServices.GetBlockModelSpaceId(db), OpenMode.ForRead);
  15.  
  16.                     Polyline3d c1 = new Polyline3d();
  17.                     Polyline c2 = new Polyline();
  18.                     List<Polyline> ListOfPolyline = new List<Polyline>();
  19.                     List<Polyline> ListOfAllPolyline = new List<Polyline>();
  20.  
  21.                     PromptSelectionResult selectionRes = ed.SelectImplied();
  22.                     if (selectionRes.Status == PromptStatus.Error)
  23.                     {
  24.                         PromptSelectionOptions selectionOpts = new PromptSelectionOptions();
  25.                      
  26.                         selectionOpts.SingleOnly = true;
  27.                         selectionRes = ed.GetSelection(selectionOpts);
  28.                         ed.WriteMessage(selectionRes.ToString());
  29.                     }
  30.                     else
  31.                     {
  32.                         ed.SetImpliedSelection(new ObjectId[0]);
  33.                     }
  34.                     if (selectionRes.Status == PromptStatus.OK)
  35.                     {
  36.                         try
  37.                         {
  38.                             objIds = selectionRes.Value.GetObjectIds();
  39.                             foreach (ObjectId objId in objIds)
  40.                             {
  41.                                 DBObject targetobj = (DBObject)tr.GetObject(objId, OpenMode.ForWrite);
  42.                                 c1 = targetobj as Polyline3d;
  43.                             }
  44.                         }
  45.  
  46.                         catch (Autodesk.AutoCAD.Runtime.Exception ex)
  47.                         {
  48.                             ed.WriteMessage(ex.Message);
  49.                             tr.Abort();
  50.                         }
  51.  
  52.                     }
  53.  
  54.                     if(c1.Id != ObjectId.Null)
  55.                     {
  56.                         // "пробегаем" по всем объектам в пространстве модели
  57.                         foreach (ObjectId id in ms)
  58.                         {
  59.                            
  60.                             Entity entity = (Entity)tr.GetObject(id, OpenMode.ForRead);
  61.                             foreach (string a in b)
  62.                             {
  63.                                 if (entity.Layer == a) //ИИ_Горизонтали_М
  64.                                 {
  65.                                     if (entity.GetType() == typeof(Polyline))
  66.                                     {
  67.                                        
  68.                                         acad.DocumentManager.MdiActiveDocument.Editor.WriteMessage(string.Format("\nLayer:{0}; Type:{1}; Color: {2},{3},{4}\n",
  69.                                         entity.Layer, entity.GetType().ToString(), entity.Color.Red.ToString(), entity.Color.Green.ToString(), entity.Color.Blue.ToString()));
  70.                                         c2 = entity as Polyline;
  71.                                         ListOfAllPolyline.Add(c2);
  72.                                     }
  73.                                 }
  74.                             }
  75.                                
  76.  
  77.                         }
  78.                         Plane planeXoy = new Plane(
  79.                         Application.DocumentManager.MdiActiveDocument.Editor.CurrentUserCoordinateSystem.CoordinateSystem3d.Origin,
  80.                         Application.DocumentManager.MdiActiveDocument.Editor.CurrentUserCoordinateSystem.CoordinateSystem3d.Zaxis
  81.                         );
  82.                         Point3dCollection intersectionPoints = new Point3dCollection();
  83.                      
  84.  
  85.                         for (int i = 0; i < ListOfAllPolyline.Count; i++)
  86.                         {
  87.                             Point3dCollection points = new Point3dCollection();
  88.                          
  89.                             c1.IntersectWith(ListOfAllPolyline[i], Intersect.OnBothOperands, planeXoy, points, IntPtr.Zero, IntPtr.Zero);
  90.                             if (points.Count != 0)
  91.                             {
  92.                                 ListOfPolyline.Add(ListOfAllPolyline[i]);
  93.                                 foreach (Point3d Point_ in points)
  94.                                 {
  95.                                     var xline = new Xline();
  96.                                     xline.BasePoint = Point_;
  97.                                     xline.UnitDir = Vector3d.ZAxis;
  98.                                     c1.IntersectWith(xline, Intersect.OnBothOperands, planeXoy, intersectionPoints, IntPtr.Zero, IntPtr.Zero);
  99.                                 }
  100.  
  101.                             }
  102.                         }
  103.                        
  104.                         List<double> intersectionDistances = new List<double>();
  105.                      
  106.                         foreach (Point3d intersectionPoint in intersectionPoints)
  107.                         {
  108.  
  109.                             try
  110.                             {
  111.                                 intersectionDistances.Add(c1.GetParameterAtPoint(intersectionPoint));
  112.                             }
  113.                             catch (Autodesk.AutoCAD.Runtime.Exception ex)
  114.                             {
  115.                                 continue;
  116.                             }
  117.  
  118.                         }
  119.  
  120.  
  121.                        
  122.                         intersectionDistances.Insert(0, c1.StartParam);
  123.                         intersectionDistances.Add(c1.EndParam);
  124.  
  125.                        
  126.                         intersectionDistances.Sort();
  127.  
  128.                        
  129.                         DBObjectCollection splitCurves = c1.GetSplitCurves(new DoubleCollection(intersectionDistances.ToArray()));
  130.  
  131.                        
  132.                         IList<Entity> splitEntities = splitCurves.OfType<Entity>().ToList();
  133.                         Polyline3d poly = new Polyline3d();
  134.                         if (splitEntities.Count > 0)
  135.                         {
  136.                             using (BlockTable blockTable = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead))
  137.                             {
  138.                                 using (BlockTableRecord blockTableRecord = (BlockTableRecord)tr.GetObject(blockTable[BlockTableRecord.ModelSpace], OpenMode.ForWrite))
  139.                                 {
  140.                                    
  141.                                     Entity polyline = splitEntities[0];
  142.  
  143.                                     polyline.SetDatabaseDefaults();
  144.                                  
  145.                                     splitEntities.RemoveAt(0);
  146.  
  147.                                     if (splitEntities.Count > 0)
  148.                                     {
  149.                                        
  150.                                         polyline.JoinEntities(splitEntities.ToArray());
  151.  
  152.                                     }
  153.  
  154.                                     blockTableRecord.AppendEntity(polyline);
  155.  
  156.                                     tr.AddNewlyCreatedDBObject(polyline, true);
  157.                                     poly = polyline as Polyline3d;
  158.                                 }
  159.                             }
  160.                         }
  161.                         Entity entity2 = (Entity)tr.GetObject(c1.Id, OpenMode.ForWrite, false, true);
  162.                         entity2.Erase();
  163.                         tr.Commit();
  164.                        
  165.                     }
  166.                    
  167.                    
  168.                 }
  169.             }
  170.            
  171.         }
Название: Re: Скорость нахождения точек пересечения
Отправлено: Александр Ривилис от 27-06-2021, 21:23:45
Для начала отсеки те горизонтали, у которых BoundingBox не имеет пересечения с BoundingBox линии, пересечение с которой ты ищешь.
Название: Re: Скорость нахождения точек пересечения
Отправлено: Podushkin от 27-06-2021, 21:28:45
Спасибо
Название: Re: Скорость нахождения точек пересечения
Отправлено: Александр Ривилис от 27-06-2021, 21:51:57
Podushkin,
Следующее. Хотя код и достаточно путанный, но мне кажется что я сумел понять, что ты находишь пересечение Polyline3d со всеми Polyline определенного слоя и в точках пересечения хочешь добавить вершины в Polyline3d. Если я прав, то тебе незачем сначала эту Polyline3d расчленять на сегменты, а затем объединять обратно, удалять старую Polyline3d и добавлять новую. Достаточно добавить новые вершины при помощи метода Polyline3d.InsertVertexAt в старую Polyline3d.
Название: Re: Скорость нахождения точек пересечения
Отправлено: Podushkin от 27-06-2021, 22:15:53
Да, Вы правы. Переделаю.
Название: Re: Скорость нахождения точек пересечения
Отправлено: Александр Ривилис от 27-06-2021, 22:18:24
Ну и если приложишь dwg-файл, на котором тестировал, то возможно я смогу подсказать еще варианты для оптимизации.
Название: Re: Скорость нахождения точек пересечения
Отправлено: Podushkin от 27-06-2021, 23:12:19
Александр, можно ссылку на пример работы с BoundingBox? Как я понял это некий контейнер (контур), и для начала необходимо найти количество объектов, которые входят в этот контур?
Название: Re: Скорость нахождения точек пересечения
Отправлено: Александр Ривилис от 28-06-2021, 00:21:40
Entity.GeometricExtents
Нужно найти его для Polyline3d и для всех Polyline горизонталей. После это отбираешь только те Polyline у которых GeometricExtents пересекаются с GeometricExtents твоей Polyline3d. Проверять пересечение нужно по X и Y игнорируя Z.