Определение точек пересечения Polyline3d и Polyline

Автор Тема: Определение точек пересечения Polyline3d и Polyline  (Прочитано 4473 раз)

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

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

Оффлайн Алексей ТерноАвтор темы

  • ADN Club
  • ****
  • Сообщений: 381
  • Карма: 33
    • C3D Extensions
  • Skype: alexeyterno
Все привет!
Нужно найти точки пересечения Polyline3d и Polyline, а точнее точки кажущегося пересечения.
Пока смог придумать только такой алгоритм:
  • Из Polyline3d получаю Polyline2d
  • Нахожу точки пересечения Polyline2d и Polyline
  • Нахожу проекцию полученных точек пересечения на Polyline3d

Все три пункта по отдельности были протестированы и доказана их работоспособность.
Вот итоговый код:
Код - C# [Выбрать]
  1. [CommandMethod("test_inter")]
  2.         public static void test_inter()
  3.         {
  4.             Document doc = Application.DocumentManager.MdiActiveDocument;
  5.             Database db = doc.Database;
  6.             Editor ed = doc.Editor;
  7.  
  8.             using (Transaction trans = db.TransactionManager.StartTransaction())
  9.             {
  10.                 BlockTable bt = (BlockTable)trans.GetObject(db.BlockTableId, OpenMode.ForRead);
  11.                 BlockTableRecord ms = (BlockTableRecord)trans.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite);
  12.  
  13.                 Polyline3d pline3d = (Polyline3d)trans.GetObject(ed.GetEntity("\npline3d:").ObjectId, OpenMode.ForWrite);
  14.  
  15.                 Curve crv = pline3d.GetOrthoProjectedCurve(new Plane(new Point3d(0, 0, 0), Vector3d.ZAxis));
  16.                 Polyline2d ppl = (Polyline2d)crv;
  17.                
  18.                 Polyline pline2d = (Polyline)trans.GetObject(ed.GetEntity("\npline2d:").ObjectId, OpenMode.ForWrite);
  19.  
  20.                 Point3dCollection ps = new Point3dCollection();
  21.                 IntPtr i1 = new IntPtr();
  22.                 IntPtr i2 = new IntPtr();
  23.                 ppl.IntersectWith(pline2d, Intersect.OnBothOperands, ps, i1, i2);
  24.  
  25.                 foreach (Point3d p in ps)
  26.                 {
  27.                     Point3d cp = p.OrthoProject(pline3d.GetPlane());
  28.                    
  29.                 }
  30.  
  31.                 trans.Commit();
  32.             }
  33.         }

И в строке 27:
Код - C# [Выбрать]
  1. Point3d cp = p.OrthoProject(pline3d.GetPlane());
возникает исключение eNotApplicable. В чем причина сей напасти? Как исправить?

Оффлайн Александр Пекшев aka Modis

  • ADN Club
  • *****
  • Сообщений: 1658
  • Карма: 366
  • Отец modplus.org
    • ModPlus
В чем причина сей напасти?
Потому что 3Д полилиния не может иметь плоскости! Элементарно же =)

Оффлайн avc

  • ADN Club
  • *****
  • Сообщений: 805
  • Карма: 166
    • Мои плагины к Автокаду
а какой вы ожидаете Plane от трехмерной полилинии? Понятно ж что будет eNotApplicable. А если она плоская, то вообще зачем Polyline3d?

Оффлайн Александр Пекшев aka Modis

  • ADN Club
  • *****
  • Сообщений: 1658
  • Карма: 366
  • Отец modplus.org
    • ModPlus
а точнее точки кажущегося пересечения.
А еще вопрос на засыпку - если я зажму Shift, зажму колёсик мышки и начну двигать мышкой, то я могу "увидеть" еще пару миллионов "кажущихся пересечений". Как вы планируете обрабатывать это?

Оффлайн Алексей ТерноАвтор темы

  • ADN Club
  • ****
  • Сообщений: 381
  • Карма: 33
    • C3D Extensions
  • Skype: alexeyterno
Потому что 3Д полилиния не может иметь плоскости! Элементарно же =)
а какой вы ожидаете Plane от трехмерной полилинии? Понятно ж что будет eNotApplicable. А если она плоская, то вообще зачем Polyline3d?
Действительно проекция работает только для плоской полилинии, которая может создать одну плоскость... а я уже обрадовался  :(

А еще вопрос на засыпку - если я зажму Shift, зажму колёсик мышки и начну двигать мышкой, то я могу "увидеть" еще пару миллионов "кажущихся пересечений". Как вы планируете обрабатывать это?
Точно так же, как это делает сам автокад - с учетом направления. Только моя задача упрощается тем, что работа идет исключительно в плоскости XY, соответственно проекция нужна только по оси Z.

Оффлайн Александр Пекшев aka Modis

  • ADN Club
  • *****
  • Сообщений: 1658
  • Карма: 366
  • Отец modplus.org
    • ModPlus
Точно так же, как это делает сам автокад - с учетом направления. Только моя задача упрощается тем, что работа идет исключительно в плоскости XY, соответственно проекция нужна только по оси Z
Ну если так, тогда вот в этом списке:
1. Из Polyline3d получаю Polyline2d
2. Нахожу точки пересечения Polyline2d и Polyline
3. Нахожу проекцию полученных точек пересечения на Polyline3d
Замените 3 на следующее:
Из точек пересечения Polyline2d и Polyline постройте оооооочень длинные отрезки "вверх по оси Z" и найдите точки пересечения этих отрезков с Polyline3d

Ну это на вскидку - чисто идея)

Оффлайн Алексей ТерноАвтор темы

  • ADN Club
  • ****
  • Сообщений: 381
  • Карма: 33
    • C3D Extensions
  • Skype: alexeyterno
оооооочень длинные отрезки
Наверное, имелось в виду XLine ))
А совет действительно интересный... пойду обдумаю его )
Спасибо!

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Алексей Терно,
Рекомендую воспользоваться методами из Autodesk.AutoCAD.Geometry
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Отмечено как Решение Алексей Терно 15-04-2018, 15:23:09

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Как вариант:

Код - C# [Выбрать]
  1. using System;
  2. using Autodesk.AutoCAD.Runtime;
  3. using Autodesk.AutoCAD.ApplicationServices;
  4. using Autodesk.AutoCAD.DatabaseServices;
  5. using Autodesk.AutoCAD.Geometry;
  6. using Autodesk.AutoCAD.EditorInput;
  7.  
  8. [assembly: CommandClass(typeof(PolyInters.Utils))]
  9.  
  10. namespace PolyInters
  11. {
  12.   public class Utils
  13.   {
  14.     [CommandMethod("GetInters", CommandFlags.Modal)]
  15.     public void GetInters()
  16.     {
  17.       Document doc = Application.DocumentManager.MdiActiveDocument;
  18.       if (doc == null) return;
  19.       Editor ed = doc.Editor;
  20.  
  21.       PromptEntityOptions pr3d =
  22.         new PromptEntityOptions("\nВыберите 3d-полилинию: ");
  23.       pr3d.SetRejectMessage("Это не 3d-полилиния!");
  24.       pr3d.AddAllowedClass(typeof(Polyline3d), false);
  25.       PromptEntityResult rs3d = ed.GetEntity(pr3d);
  26.       if (rs3d.Status != PromptStatus.OK) return;
  27.  
  28.       PromptEntityOptions pr2d =
  29.         new PromptEntityOptions("\nВыберите 2d-полилинию: ");
  30.       pr2d.SetRejectMessage("Это не 2d-полилиния!");
  31.       pr2d.AddAllowedClass(typeof(Polyline2d), false);
  32.       pr2d.AddAllowedClass(typeof(Polyline), false);
  33.       PromptEntityResult rs2d = ed.GetEntity(pr2d);
  34.       if (rs2d.Status != PromptStatus.OK) return;
  35.  
  36. #pragma warning disable 0618
  37.       using (Polyline3d p3d = rs3d.ObjectId.Open(OpenMode.ForRead) as Polyline3d)
  38.       using (Curve p2d = rs2d.ObjectId.Open(OpenMode.ForRead) as Curve)
  39. #pragma warning restore 0618
  40.       {
  41.         Plane pl = new Plane(Point3d.Origin, Vector3d.ZAxis);
  42.         using (Curve3d c3d = p3d.GetGeCurve())
  43.         using (Curve3d c2d = p2d.GetGeCurve())
  44.         {
  45.           // Проецируем обе кривые на плоскость X0Y
  46.           using (Curve3d c3dProject = c3d.GetOrthoProjectEntity(pl) as Curve3d)
  47.           using (Curve3d c2dProject = c2d.GetOrthoProjectEntity(pl) as Curve3d)
  48.           {
  49.             using (CurveCurveIntersector3d cInt =
  50.               new CurveCurveIntersector3d(c3dProject, c2dProject, Vector3d.ZAxis))
  51.             {
  52.               int nInt = cInt.NumberOfIntersectionPoints;
  53.               if (nInt > 0)
  54.               {
  55.                 cInt.OrderWithRegardsTo1(); // Упорядочиваем точки по 3d-полиниии
  56.                 for (int i = 0; i < nInt; i++)
  57.                 {
  58.                   if (cInt.IsTransversal(i)) // Это пересечение, а не касание
  59.                   {
  60.                     Point3d pnt2d = cInt.GetIntersectionPoint(i);
  61.                     // Вертикальная линия
  62.                     using (Line3d line = new Line3d(pnt2d, Vector3d.ZAxis))
  63.                     {
  64.                       // Находим проекцию точки пересечения на 3D-полилинию
  65.                       using (CurveCurveIntersector3d cIntVert =
  66.                         new CurveCurveIntersector3d(c3d, line, Vector3d.ZAxis))
  67.                       {
  68.                         if (cIntVert.NumberOfIntersectionPoints > 0)
  69.                         {
  70.                           Point3d pnt3d = cIntVert.GetIntersectionPoint(0);
  71.                           ed.WriteMessage("\nТочка пересечения {0} = {1}", i, pnt3d);
  72.                         }
  73.                       }
  74.                     }
  75.                   }
  76.                 }
  77.               }
  78.               else
  79.               {
  80.                 ed.WriteMessage("\nПересечений не нашли...");
  81.               }
  82.             }
  83.  
  84.           }
  85.         }
  86.       }
  87.     }
  88.   }
  89. }
« Последнее редактирование: 23-03-2018, 23:47:34 от Александр Ривилис »
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Алексей ТерноАвтор темы

  • ADN Club
  • ****
  • Сообщений: 381
  • Карма: 33
    • C3D Extensions
  • Skype: alexeyterno
Как вариант:
Таки работает :)
Спасибо!