Найти пересечение Extents3d и линии проходящей через две Point3d

Автор Тема: Найти пересечение Extents3d и линии проходящей через две Point3d  (Прочитано 8049 раз)

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

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

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

  • ADN Club
  • **
  • Сообщений: 78
  • Карма: 2
Переопределяю отрисовку объектов в AutoCAD с помощью:
Код - C# [Выбрать]
  1. public class AlxdDrawOverrule : DrawableOverrule
  2. {
  3.         public override bool WorldDraw(Drawable drawable, WorldDraw wd)
  4.         {
  5.  
  6.         }
  7. }
В частности, надо между двумя текстовыми (пока только текстовыми) объектами начертить линию, как бы показать между ними некую связь. Сделал вот так:
Код - C# [Выбрать]
  1.                     Vector3d normal = new Vector3d();
  2.                     if (drawable is Autodesk.AutoCAD.DatabaseServices.MText)
  3.                     {
  4.                         normal = (drawable as Autodesk.AutoCAD.DatabaseServices.MText).Normal;
  5.                     }
  6.                     else
  7.                         if (drawable is Autodesk.AutoCAD.DatabaseServices.DBText)
  8.                         {
  9.                             normal = (drawable as Autodesk.AutoCAD.DatabaseServices.DBText).Normal;
  10.                         }
  11.                         else
  12.                             return base.WorldDraw(mydrawable, wd);
  13.  
  14.                     Extents3d extents1 = drawable.Bounds.Value;
  15.                     Point3d midPoint = extents1.MaxPoint + extents1.MaxPoint.GetVectorTo(extents1.MinPoint).DivideBy(2);
  16.  
  17.                     if (validatedGroundElevations.Count > iofDistanceBetweenElevations)
  18.                     {
  19.                         Extents3d extents2 = validatedGroundElevations[iofDistanceBetweenElevations].Open(OpenMode.ForRead).Bounds.Value;
  20.                         Point3d midPointGroundElevation = extents2.MaxPoint + extents2.MaxPoint.GetVectorTo(extents2.MinPoint).DivideBy(2);
  21.                            
  22.                         wd.Geometry.WorldLine(midPoint, midPointGroundElevation);
  23.                     }
  24.  
  25.                     if (validatedGroundElevations.Count > iofDistanceBetweenElevations + 1)
  26.                     {
  27.                         Extents3d extents2 = validatedGroundElevations[iofDistanceBetweenElevations + 1].Open(OpenMode.ForRead).Bounds.Value;
  28.                         Point3d midPointGroundElevation = extents2.MaxPoint + extents2.MaxPoint.GetVectorTo(extents2.MinPoint).DivideBy(2);
  29.                         wd.Geometry.WorldLine(midPoint, midPointGroundElevation);
  30.                     }

Все отлично отрисовывается. Но очень некрасиво, что линии исходят из центра текстовых объектов. Как бы их так аккуратненько подрезать до границ (extent) текстовых объектов?
В моем случае есть Extents3d и две точки Point3d. Надо найти точку пересечения мнимой линии проходящей через указанные точки с экстентами. Сперва с экстентами первого текстового объекта, а потом с экстентами второго. Таким образом получить две новые точки и их использовать для построения линии связи.
Голову сломал, как вычислить точки не "городя огород".
« Последнее редактирование: 18-03-2016, 12:24:54 от Александр Ривилис »

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

  • ADN Club
  • *****
  • Сообщений: 1658
  • Карма: 366
  • Отец modplus.org
    • ModPlus
Про форматирование кода на форуме вам напишет Александр Ривилис  ;)

По теме - я бы вот не стал так усложнять и прибег к обычной математике: получили extents - знаете ширину и высоту. Из нужной вам точки (из координат) вычли или прибавили значения

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

  • ADN Club
  • *****
  • Сообщений: 1658
  • Карма: 366
  • Отец modplus.org
    • ModPlus
Еще вариант - если мне память не изменят, то extents - это набор точек. По этим точкам можно построить примитивы (полилинию, отрезки) и уже найти пересечение с ними

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

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Кроме форматирования я еще отмечу, что ObjectId.Open(...) следует выполнять внутри using или (в крайнем случае) не забывать делать DBObject.Close
Пример: http://adn-cis.org/sozdanie-polyline3d-bez-ispolzovaniya-tranzakczii.html
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN Club
  • **
  • Сообщений: 78
  • Карма: 2
Про using забыл. Сделал так:
Код - C# [Выбрать]
  1.                         using (DBObject obj = validatedGroundElevations[iofDistanceBetweenElevations + 1].Open(OpenMode.ForRead))
  2.                         {
  3.                             Extents3d extents2 = obj.Bounds.Value;
  4.                             Point3d midPointGroundElevation = extents2.MaxPoint + extents2.MaxPoint.GetVectorTo(extents2.MinPoint).DivideBy(2);
  5.                             wd.Geometry.WorldLine(midPoint, midPointGroundElevation);
  6.                         }
  7.  

Но по теме конкретного ответа не получил. Теорию я знаю. Спасибо. Надеялся на пример.

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

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Но по теме конкретного ответа не получил. Теорию я знаю. Спасибо. Надеялся на пример.
Попробуй воспользоваться методом Entity.BoundingBoxIntersectWith - думаю, что это будет оптимальным решением.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN Club
  • **
  • Сообщений: 78
  • Карма: 2
В этом случае надо создавать Entity для мнимой линии. Некрасиво как-то.
Сделал так:
Код - C# [Выбрать]
  1. private bool intersectExtentsWithLine(Extents3d extents, Point3d firstPoint, Point3d secondPoint, out Point3d[] intersects)
  2.         {
  3.             LineSegment3d line = new LineSegment3d(firstPoint, secondPoint);
  4.             //check top line
  5.             LineSegment3d extentsLine = new LineSegment3d(extents.MaxPoint, new Point3d(extents.MinPoint.X, extents.MaxPoint.Y, 0));
  6.             intersects = line.IntersectWith(extentsLine);
  7.             if (intersects != null)
  8.                 return true;
  9.  
  10.             //check right line
  11.             extentsLine = new LineSegment3d(extents.MaxPoint, new Point3d(extents.MaxPoint.X, extents.MinPoint.Y, 0));
  12.             intersects = line.IntersectWith(extentsLine);
  13.             if (intersects != null)
  14.                 return true;
  15.  
  16.             //check bottom line
  17.             extentsLine = new LineSegment3d(extents.MinPoint, new Point3d(extents.MaxPoint.X, extents.MinPoint.Y, 0));
  18.             intersects = line.IntersectWith(extentsLine);
  19.             if (intersects != null)
  20.                 return true;
  21.  
  22.             //check left line
  23.             extentsLine = new LineSegment3d(extents.MinPoint, new Point3d(extents.MinPoint.X, extents.MaxPoint.Y, 0));
  24.             intersects = line.IntersectWith(extentsLine);
  25.             if (intersects != null)
  26.                 return true;
  27.  
  28.             return false;
  29.         }
  30.  

Беда только с координатой Z.

Отмечено как Решение Александр Ривилис 04-08-2016, 11:07:32

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

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Беда только с координатой Z.
Вот поэтому я и предлагал Entity.BoundingBoxIntersectWith, так как там пересечение в заданной плоскости.
Код - C# [Выбрать]
  1. А Entity - это что-то типа
  2. using (Line ln = new Line(p1, p2)) {
  3. // А здесь проверка на пересечение
  4. }
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN Club
  • **
  • Сообщений: 78
  • Карма: 2
Александр, вы гений!

Сделал так:

Код - C# [Выбрать]
  1.                         using (DBObject obj = validatedGroundElevations[iofTextDistanceBetweenElevations].Open(OpenMode.ForRead))
  2.                         {
  3.                             Extents3d extents2 = obj.Bounds.Value;
  4.                             Point3d midPointGroundElevation = extents2.MaxPoint + extents2.MaxPoint.GetVectorTo(extents2.MinPoint).DivideBy(2);
  5.  
  6.                             Point3d midPointBase = midPoint;
  7.                             using (Line line = new Line(midPoint, midPointGroundElevation)) {
  8.                                 Point3dCollection intersects = new Point3dCollection();
  9.                                 (obj as Entity).BoundingBoxIntersectWith(line, Intersect.OnBothOperands, intersects, IntPtr.Zero, IntPtr.Zero);
  10.                                 if (intersects.Count > 0)
  11.                                     midPointGroundElevation = intersects[0];
  12.  
  13.                                 intersects.Clear();
  14.                                 (drawable as Entity).BoundingBoxIntersectWith(line, Intersect.OnBothOperands, intersects, IntPtr.Zero, IntPtr.Zero);
  15.                                 if (intersects.Count > 0)
  16.                                     midPointBase = intersects[0];
  17.  
  18.                                 Vector3d v = (midPointBase - midPointGroundElevation).MultiplyBy(0.1);
  19.                                 midPointBase -= v;
  20.                                 midPointGroundElevation += v;
  21.                             }
  22.  
  23.                             wd.SubEntityTraits.Color = 253;
  24.                             wd.Geometry.WorldLine(midPointBase, midPointGroundElevation);
  25.                         }
  26.