Узнать точку пересечения полилинии и блока c#

Автор Тема: Узнать точку пересечения полилинии и блока c#  (Прочитано 26003 раз)

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

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

  • ADN OPEN
  • **
  • Сообщений: 63
  • Карма: 2
Это уже не совсем по сабжу,но может быть вы сможете подсказать.
Я попытался сделать так:
1)Просканировать чертеж и собрать все блоки в List.
2)При помощи R-tree я создаю Коллекцию прямоугольников, на вход которой я подаю точки,полученные следующим образом:
Код - C# [Выбрать]
  1. Entity.GeometricExtents.MinPoint.X
3)Нахожу прямоугольник,который включает в себя точку начала полилинии.

Дальше я застрял.Идеальный вариант был бы еще узнать номер этого прямоугольника в коллекции,чтобы получить доступ к соответствующему блоку и вытащить из него нужные мне атрибуты.
Вытаскивать атрибуты я научился.
Может быть кто-то подскажет,как найти индекс прямоугольника?
Заранее спасибо!

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

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Может тип коллекции выбрал неудачный? Наверное нужно что-то типа Dictionary<Extents3d, ObjectId>, где Extents3d - габариты вставки блока, а ObjectId - его идентификатор.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн trir

  • ADN Club
  • ****
  • Сообщений: 475
  • Карма: 63
Можно создать класс, который будет содержать блок или ObjectId, а также умеет создавать MBR и хранится в дереве

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

  • ADN OPEN
  • **
  • Сообщений: 63
  • Карма: 2
Я уже возненавидел этот самый Автокад.
Я действительно создал коллекцию Dictionary следующим образом:
Код - C# [Выбрать]
  1. BlockReference ent = (BlockReference)obj;
  2.                                 list_bl.Add(ent);
  3.  
  4.                                 float xmin = (float)ent.GeometricExtents.MinPoint.X;
  5.                                 float ymin = (float)ent.GeometricExtents.MinPoint.Y;
  6.                                 float xmax = (float)ent.GeometricExtents.MaxPoint.X;
  7.                                 float ymax = (float)ent.GeometricExtents.MaxPoint.Y;
  8.  
  9.                                 RTree.Rectangle rect = new RTree.Rectangle(xmin, ymin, xmax, ymax, 0, 0);
  10.                                 dict.Add(rect,number++);
  11.                                
  12.                                 tree.Add(rect,rect);
Где list_bl это List с блоками на чертеже, для каждого блока создается Прямоугольник,который потом добавляется в коллекцию. nember - это ключ,который нужен для извлечения номера.

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

  • ADN OPEN
  • **
  • Сообщений: 63
  • Карма: 2
Случайно отправилось.
После этого я нахожу самый близкий блок к точкам начала и конца полилинии. Дальше я вытаскиваю номер этого блока,вывожу в эксель и кажется,что все правильно,а получить имя блока у меня уже не получается.
 Пытаюсь следующим образом:
         
Код - C# [Выбрать]
  1. Autodesk.AutoCAD.DatabaseServices.AttributeCollection attCol = list_bl[number].AttributeCollection;
  2.                                  foreach (ObjectId attId in attCol)
  3.                                  {
  4.                                      AttributeReference attRef = (AttributeReference)acTrans.GetObject(attId, OpenMode.ForRead);
  5.                                      if (attRef.Tag.Equals("SYSNAME"))
  6.                                      {
  7.                                          list_nm.Add(attRef.TextString);
  8.                                          sheet1.addCell(new Label(7, columns + i - 1, list_nm[0]));
  9.                                          list_nm.RemoveAt(0);
  10.                                      }
  11.                                  }
  12.                              }
Может быть вы увидите что-то,что я пропустил?Лежащее на самом верху. Я пытаюсь вытащить информацию по тегу SYSNAME.

Оффлайн trir

  • ADN Club
  • ****
  • Сообщений: 475
  • Карма: 63
Для работы с деревом можно создать такой класс
Код - Visual Basic [Выбрать]
  1. Public Class MyClass1
  2.  
  3.     Public wObjID As Objectid
  4.     Public wRrect As Rectangle
  5.  
  6.     Public Sub New(nEnt As Entity)
  7.         Me.wObjID = nEnt.ObjectId
  8.         wRrect = MyClass1.GetRect(nEnt)
  9.     End Sub
  10.  
  11.     Public Shared Function GetRect(nEnt As Entity) As Rectangle
  12.         If nEnt.Bounds IsNot Nothing Then
  13.             Dim wExt As Extents3d = nEnt.Bounds
  14.             Return New Rectangle(wExt.MinPoint.X, wExt.MinPoint.Y, wExt.MinPoint.Z, wExt.MaxPoint.X, wExt.MaxPoint.Y, wExt.MaxPoint.Z)
  15.         Else
  16.             Return Nothing
  17.         End If
  18.     End Function
  19.  
  20.     Public Sub AddToTree(wTree As RTree(Of MyClass1))
  21.         wTree.Add(Me.wRrect, Me)
  22.     End Sub
  23.  
  24. End Class

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

  • ADN OPEN
  • **
  • Сообщений: 63
  • Карма: 2
Разобрался,все спасибо за помощь!!
Класс я приблизительно такой и создал.Проблема была в том,что почему-то есть разница в номере конкретного блока между способом перебора и способом дерева.
На старом чертеже эта разница была постоянной и равнялась 362, после переноса на новый чертеж все пришло в норму и способ дерева стал работать.Скорость его потрясает,практически мгновенно.
Еще раз спасибо!

Оффлайн Дима_

  • ADN Club
  • ****
  • Сообщений: 473
  • Карма: 66
Проблема была в том,что почему-то есть разница в номере конкретного блока между способом перебора и способом дерева.
Индексировать по порядковому номеру - ихмо это очень плохая идея - лишнию сущность вводите - бесполезную. Либо ObjectId с дальнейшим извлечением объекта из транзакции (надежный метод - при "правильной" реализации), либо (если памяти не жалко) сразу объект блока - но можно попасть на переполнение памяти с "зависоном" или фаталом. У вас получается сложены худшие стороны обоих методов.

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

  • ADN OPEN
  • **
  • Сообщений: 63
  • Карма: 2
Поменял на ObjectId.Действительно,все заработало и на старом чертеже!

Оффлайн Вильдар

  • ADN Club
  • ****
  • Сообщений: 409
  • Карма: 77
  • Skype: vildar82
Denis, можешь показать код работы с деревьями (RTree правильно?). Спасибо.
Попробовал код из этого проекта https://sourceforge.net/projects/cspatialindexrt/
Норм получилось.
Создаю "дерево" преобразуя все Extents3d из автокада в объекты Rectangle (из проекта по ссылке):
Код - C# [Выбрать]
  1.          RTree<Area> rtree = new RTree<Area>();          
  2.          foreach (Area area in _areas)
  3.          {
  4.             Rectangle rectTree = new Rectangle(area.Bounds.MinPoint.X, area.Bounds.MinPoint.Y,
  5.                                                area.Bounds.MaxPoint.X, area.Bounds.MaxPoint.Y, 0, 0);
  6.             rtree.Add(rectTree, area);
  7.          }
Потом получаю области в нужной точке
Код - C# [Выбрать]
  1.             Point p = new Point(location.X, location.Y, 0);
  2.             List<Area> areas = rtree.Nearest(p, 300);
Работает супер.
« Последнее редактирование: 14-10-2015, 18:09:25 от vildar82 »

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

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

Оффлайн Вильдар

  • ADN Club
  • ****
  • Сообщений: 409
  • Карма: 77
  • Skype: vildar82
Да, я заменил все float на double. Вроде ничего не сломал  ;D

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

  • ADN OPEN
  • **
  • Сообщений: 63
  • Карма: 2
Извините за долгий ответ.
Только добрался до компьютера после командировки.
Код очень похожий у меня,так что все то,что я знаю,ты уже написал!
Еще раз извини за то,что не успел ответить

Оффлайн Вильдар

  • ADN Club
  • ****
  • Сообщений: 409
  • Карма: 77
  • Skype: vildar82
Вначале думал что просто не получиться использовать rtree. Но оказалось, что использовать его просто. Только непонятно как он работает  :o

Оффлайн trir

  • ADN Club
  • ****
  • Сообщений: 475
  • Карма: 63
читай

Обратите внимание, что приведённая мной реализация RTree работает только в 2D, хотя её можно расширить и на 3D! А при большом желании и на ND. И вообще это порт с Джавы, классического алгоритма Гутмана (там даже в комментариях есть цитаты из статьи)

https://habrahabr.ru/post/224965/