Связь между объектами чертежа. Есть ли какие-нибудь инструменты?

Автор Тема: Связь между объектами чертежа. Есть ли какие-нибудь инструменты?  (Прочитано 83437 раз)

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

Оффлайн Андрей Бушман

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
Из минусов - если редактировать чертеж неаккуратно, то выноски могут указывать на пустое место
Проверка на пустое место выполняется легко: на основе хэндла пытаешься получить ObjectId (метод называется TryGetObjectId, если мне не изменяет память). если для указанного хэндла не существует соответствующего ObjectId, то это оно и есть - "пустое место".
или вообще на другой объект чертежа, т.к. они никак не связаны с блоком, на который должны указывать.
Чтобы это проверить, в том объекте, на который хранишь ссылку, создай РД в которых запиши, к примеру, GUID. А в РД своей ссылки, помимо ID связанного объекта, дополнительно храни так же значение этого GUID.

Т.о. сначала ищешь объект, ID которого соответствует значению хэндла, хранящегося в РД. Если объект не найден, значит ссылка битая (выполняешь соответствующие исправления). Если найден объект с указанным хэндлом, то на следующем этапе выполняешь проверку соответствия GUID. Ежели проверка прошла, значит объект, скорее всего корректен.


Оффлайн Алексей (IdeaSoft)

  • ADN
  • *
  • Сообщений: 1189
  • Карма: 9
    • idea-soft.ru
  • Skype: makar_govorun
Я бы решал так:
1) Создал библиотеку блоков (графических образов объектов) и в РД вставок блоков записывал следующее:
- Хендл объекта выноски.
- Хендл объекта таблицы спецификации.
- № выноски (для восстановления удаленного объекта выноски).
 
2) Сделал алгоритм обновления (генерации) содержимого в табличке спецификации на основе имеющихся вставок блоков на чертеже. В таблицу заносились бы только данные по утвержденному списку имен блоков. Справочник имен блоков хранил бы в соотв. dwg или dwt файле.

3) Анализ возможных действий пользователя:

   a) удаление объекта вставки блока – алгоритм обновления удаляет выноску и обновляет содержимое таблицы.
   b) удаление объекта выноски - алгоритм обновления снова возобновит объект выноски.
   c) удаление таблицы спецификации - алгоритм обновления создает таблицу снова и заполняет ее в соотв. с
       имеющимися объектами на чертеже.
   d) копирование или создание вставки блока -  алгоритм обновления создает выноску (если нужна),
       связывает ее     с    блоком и снова обновляет таблицу и заносит нужные данные в РД вставки блока.
   e) пользователь создает копию таблицы спецификации – алгоритм обновления ни как ни реагирует на эту
       таблицу, т.к. каждый объект вставки блока не хранит в РД Хендл в этой копии таблицы.
   f) копирование или создание выноски – если алгоритм обновления не найдет вставку блока в РД, которого
       есть Хандл этой выноски, то он проигнорирует ее. А если найдет, то связь есть, только вот геометрическое
       положение выноски может быть не таким, каким нужно.
   g) копирование примитивов в другой чертеж -  алгоритм обновления скорее не найдет связи таблицы
       и вставок блоков и сформирует новую таблицу. Выноски лучше вообще удалить и сформировать новые,
       взяв из РД блоков их номера.

Общий смысл работы в том, что есть алгоритм обновления который в текущей ситуации принимает решение и восстанавливает таблицу спецификации или обновляет ее.

Оффлайн Андрей Бушман

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
- Хендл объекта выноски.
- Хендл объекта таблицы спецификации.
- № выноски (для восстановления удаленного объекта выноски).
Юзер копирует вхождение блока из одного чертежа в другой, посредством Ctrl + C \ Ctrl + V и весь твой план сразу идёт лесом, ибо обозначенной тобой информации становится явно недостаточно.

Оффлайн Дмитрий ЗагорулькинАвтор темы

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 737
К тому же, идея такая, что пользователи будут сами создавать блоки для своих деталей, без моего участия...
Я как раз-расписывал "спецуху" как создавать такие аттрибуты (и не только их, там мануал на создание блоков на 3 страницы был).
лучше, чтобы проектировщик имел свободу для творчества в этом плане.
ИХМО наоборот "красивей" получается, когда все стрелочки в одинаковое место указывают.
Да, придется попотеть
- как сделаешь - напиши мне тоже интересно...
Вот и я об этом - хочется сделать так, чтобы пользователям потом было легче. Пусть для этого мне придется сейчас больше поработать. Думаю, все должно получиться. Если осилю - поделюсь :)

Цитировать
Цитата: Загорулькин Дмитрий от 03-07-2014, 14:18:35
Из минусов - если редактировать чертеж неаккуратно, то выноски могут указывать на пустое место
Проверка на пустое место выполняется легко: на основе хэндла пытаешься получить ObjectId (метод называется TryGetObjectId, если мне не изменяет память). если для указанного хэндла не существует соответствующего ObjectId, то это оно и есть - "пустое место".
Цитировать
Цитата: Загорулькин Дмитрий от 03-07-2014, 14:18:35
или вообще на другой объект чертежа, т.к. они никак не связаны с блоком, на который должны указывать.
Чтобы это проверить, в том объекте, на который хранишь ссылку, создай РД в которых запиши, к примеру, GUID. А в РД своей ссылки, помимо ID связанного объекта, дополнительно храни так же значение этого GUID.
Т.о. сначала ищешь объект, ID которого соответствует значению хэндла, хранящегося в РД. Если объект не найден, значит ссылка битая (выполняешь соответствующие исправления). Если найден объект с указанным хэндлом, то на следующем этапе выполняешь проверку соответствия GUID. Ежели проверка прошла, значит объект, скорее всего корректен.
Я имел в виду геометрическое указание, как на картинке. После сдвига деталей, одна выноска указывает не на ту деталь, вторая - в пустое место. И в том варианте, в котором я озвучивал этот минус, никак не "отловить" такие невзаимные изменения.


Я бы решал так:
1) Создал библиотеку блоков (графических образов объектов) и в РД вставок блоков записывал следующее:
- Хендл объекта выноски.
- Хендл объекта таблицы спецификации.
- № выноски (для восстановления удаленного объекта выноски).
 
2) Сделал алгоритм обновления (генерации) содержимого в табличке спецификации на основе имеющихся вставок блоков на чертеже. В таблицу заносились бы только данные по утвержденному списку имен блоков. Справочник имен блоков хранил бы в соотв. dwg или dwt файле.

3) Анализ возможных действий пользователя:

   a) удаление объекта вставки блока – алгоритм обновления удаляет выноску и обновляет содержимое таблицы.
   b) удаление объекта выноски - алгоритм обновления снова возобновит объект выноски.
   c) удаление таблицы спецификации - алгоритм обновления создает таблицу снова и заполняет ее в соотв. с
       имеющимися объектами на чертеже.
   d) копирование или создание вставки блока -  алгоритм обновления создает выноску (если нужна),
       связывает ее     с    блоком и снова обновляет таблицу и заносит нужные данные в РД вставки блока.
   e) пользователь создает копию таблицы спецификации – алгоритм обновления ни как ни реагирует на эту
       таблицу, т.к. каждый объект вставки блока не хранит в РД Хендл в этой копии таблицы.
   f) копирование или создание выноски – если алгоритм обновления не найдет вставку блока в РД, которого
       есть Хандл этой выноски, то он проигнорирует ее. А если найдет, то связь есть, только вот геометрическое
       положение выноски может быть не таким, каким нужно.
   g) копирование примитивов в другой чертеж -  алгоритм обновления скорее не найдет связи таблицы
       и вставок блоков и сформирует новую таблицу. Выноски лучше вообще удалить и сформировать новые,
       взяв из РД блоков их номера.

Общий смысл работы в том, что есть алгоритм обновления который в текущей ситуации принимает решение и восстанавливает таблицу спецификации или обновляет ее.

Это уже другой вопрос - каким образом обрабатывать изменения объектов. В зависимости от задачи, могут быть совершенно разные действия.
Вопрос же стоит в том, чтобы связать два объекта между собой ссылками друг на друга и обеспечить сохранение/модификацию этой связи при создании, копировании и удалении объектов. А уже потом, поняв что объект меняется, решать что делать со  связанными объектами. Думаю, что можно сделать универсальный инструмент, который потом можно будет использовать не только для выносок и деталей, но и для любых других объектов чертежа, которые нужно будет связать.

Оффлайн Андрей Бушман

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
Я имел в виду геометрическое указание, как на картинке. После сдвига деталей, одна выноска указывает не на ту деталь, вторая - в пустое место. И в том варианте, в котором я озвучивал этот минус, никак не "отловить" такие невзаимные изменения.
Тогда, как вариант к размышлению:
1. При открытии чертежа производишь анализ РД объектов, извлекая информацию о связях.

2. Для каждого из объектов, участвующего в назначенных связях, получаешь геометрические границы (прямоугольные) и запоминаешь смещения, а так же диагональ прямоугольника.

3. Вычисляешь смещение центра геометрической границы своей выноски относительно центра геометрической границы объекта, на который она указывает. Все обозначенные извлечённые данные сохраняешь во временную базу данных (не Database). По мере изменений в чертеже, корректируешь содержимое этой базы (она живёт в памяти).

4. В обработчике события отслеживаешь перемещение объекта, на который указывает ссылка, синхронизируя перемещение ссылки (новое положение выноски расчитываешь относительно ранее вычисленного и сохранённого в записи базы смещения, а так же диагонали. Значение диагонали позволяет отследить факт масштабирования объекта и в соответствии с этим скорректировать расчёт.

5. При закрытии чертежа, информацию из базы данных записываешь в РД объектов, а саму базу - в утиль.

Думаю, что для перемещений и масштабирования это сработает. Но вот в случае поворота... В этом случае геометрические границы не поворачиваются, но вместо этого изменяют свои размеры. Поворот придётся обрабатывать как-то по иному...

Оффлайн Алексей (IdeaSoft)

  • ADN
  • *
  • Сообщений: 1189
  • Карма: 9
    • idea-soft.ru
  • Skype: makar_govorun
Юзер копирует вхождение блока из одного чертежа в другой, посредством Ctrl + C \ Ctrl + V и весь твой план сразу идёт лесом, ибо обозначенной тобой информации становится явно недостаточно.

Так я же и говорю, что через буфер обмена будут проблемы и программа генерации таблички все сделает по
новому, т.е. по вставкам блоков сформирует новую таблицу. Выноски летят к чертям и копируемая таблица тоже не актуальна. Так что перенос проекта через буфер обмена не возможет. Для переноса данных в другой чертеж просто написать алгоритм экспорта данных проекта в другой чертеж. Это не сложно.

Оффлайн Дмитрий ЗагорулькинАвтор темы

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 737
Действительно, все получилось сделать:
- создать связи
- сохранить связи в чертеже
- восстановить и актуализировать информацию при открытии чертежа
- отловить событие копирования связанных объектов внутри чертежа и добавить связь копиям
- отловить событие модификации связанных объектов и сгенерировать события для того, чтобы приложение, пользующееся функционалом связей, могло каким-то образом на это отреагировать

Но вот через буфер обмена никак не получается пробиться. Загвоздка в том, что такое копирование как-то хитро работает. Как показывают опыты, при этом создается в папке Temp временный чертеж (частичная копия исходного чертежа?), из которой уже объекты переносятся в чертеж назначения. Какие я только события не пробовал (Database.BeginDeepClone, Database.BeginDeepCloneTranslation, Database.BeginWblockEntireDatabase, Database.BeginWblockObjects, Database.BeginWblockSelectedObjects, Database.BeginDxfOut, Database.WblockMappingAvailable, Database.WblockNotice, Database.BeginWblockBlock) - создание временного чертежа никак не отлавливается.
При Ctrl+C возникает только событие WblockNotice, которое имеет в аргументах ссылку на базу данных исходного чертежа (непонятно зачем, ведь аргумент sender - это та же самая база данных).
При Ctrl+V в другом чертеже, срабатывают уже события базы данных того чертежа, в который вставляем - BeginDeepClone и BeginDeepCloneTranslation. В их аргументах OriginalDatabase - БД временного файла из Temp, DestinationDatabase - база данных чертежа, в который копируем. При этом, в NOD базы данных временного файла нет данных о ссылках, хотя в базе данных исходного чертежа в NOD эти данные есть.

Поэтому, теперь меня волнуют два вопроса:
- Все ли правильно с событием WblockNotice? Может быть, в аргументах там должна фигурировать еще и вторая база данных?
- Может быть, есть какое-то еще событие базы данных/документа/приложения/системы, чтобы можно было отловить копирование объектов через буфер обмена?

Буду благодарен, если кто-нибудь поможет с этим!

Оффлайн Алексей (IdeaSoft)

  • ADN
  • *
  • Сообщений: 1189
  • Карма: 9
    • idea-soft.ru
  • Skype: makar_govorun
- Может быть, есть какое-то еще событие базы данных/документа/приложения/системы, чтобы можно было отловить копирование объектов через буфер обмена?

Если нужно обратиться к добавляемому в документ примитиву,
то можно обработать событие добавления примитива в документ.
Когда через буфер обмена в документ вставляются примитивы, то это событие наступает.
В .NET пока не искал, но на ActiveX есть такое событие у документа
Вот код такой:

Код - vb.net [Выбрать]
  1.  
  2.         Private WithEvents myDoc As Autodesk.AutoCAD.Interop.AcadDocument
  3.         Private Sub myDoc_ObjectAdded(ByVal Obj As Object) Handles myDoc.ObjectAdded
  4.             Try
  5.                 Dim COM_Ent As Autodesk.AutoCAD.Interop.Common.AcadEntity = _
  6.                     DirectCast(Obj, Autodesk.AutoCAD.Interop.Common.AcadEntity)
  7.                 Dim HWND_ENT As String = COM_Ent.Handle
  8.                 ' по HWND_ENT из DataBase можно получить объект Autodesk.AutoCAD.DatabaseServices.Entity
  9.             Catch ex As Exception
  10.             End Try
  11.         End Sub
  12.  


Оффлайн Андрей Бушман

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
Действительно, все получилось сделать:- создать связи- сохранить связи в чертеже- восстановить и актуализировать информацию при открытии чертежа- отловить событие копирования связанных объектов внутри чертежа и добавить связь копиям- отловить событие модификации связанных объектов и сгенерировать события для того, чтобы приложение, пользующееся функционалом связей, могло каким-то образом на это отреагировать
А ежели Database отредактируют на машине, на которой нет твоего плагина?

Цитировать
Но вот через буфер обмена никак не получается пробиться. Загвоздка в том, что такое копирование как-то хитро работает.
В составе IdMapping хранится информация о том, какому идентификатору нового объекта соответствует какой идентификатор копируемого из др. чертежа объекта. Имея на руках эту инфу, ты можешь и расширенные данные подтянуть соответствующим образом и не важно сколько там промежуточных временных файлов создаётся за кулисами (если я верно понял твой вопрос).

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

  • ADN Club
  • ****
  • Сообщений: 473
  • Карма: 66
Если "нормально" совсем никак, то вариант - попробывать использовать грубый вариант - Document.CommandWillStart - смотреть соответствующие команды работы с буфером обмена и варианты завершения Document.Command... c дальнейшим анализом Clipboard.GetData(...).

Оффлайн Дмитрий ЗагорулькинАвтор темы

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 737
Если нужно обратиться к добавляемому в документ примитиву,
то можно обработать событие добавления примитива в документ.
С этим проблем нет, какие примитивы добавляются в базу я вижу через IdMapping.
В составе IdMapping хранится информация о том, какому идентификатору нового объекта соответствует какой идентификатор копируемого из др. чертежа объекта. Имея на руках эту инфу, ты можешь и расширенные данные подтянуть соответствующим образом и не важно сколько там промежуточных временных файлов создаётся за кулисами (если я верно понял твой вопрос).
Думаешь, в промежуточных Database ID и/или хендлы объектов не меняются? Мысль интересная, спасибо! Надо проверить. Завтра первым делом займусь этим :) Кстати, расширенные данные я не использую совсем. За основу взял твою идею "менеджера связей", между сеансами сохраняю его в NOD базы чертежа.
Если "нормально" совсем никак, то вариант - попробывать использовать грубый вариант - Document.CommandWillStart - смотреть соответствующие команды работы с буфером обмена и варианты завершения Command(...) c дальнейшим анализом Clipboard.GetData(...).
Тоже дельная мысль, спасибо!

Оффлайн Андрей Бушман

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
Если "нормально" совсем никак, то вариант - попробывать использовать грубый вариант - Document.CommandWillStart
Кстати, именно этот вариант я несколько лет назад использовал, когда нужно было отслеживать копирование пользователем таблиц из Excel и вставку их в AutoCAD: отлавливал запуск команды вставки из буфера (сейчас точного имени не помню, но ты и сам можешь легко это выяснить) и анализировал содержимое буфера обмена. Если там находился OLE объект от Excel'я, то выполнял преобразование контента в соответствующим образом отформатированную таблицу AutoCAD, которую затем вставлял в указанное юзером место (висела на курсоре, ожидая вставки). Так что способ отслеживания Ctrl + V посредством мониторинга Document.CommandWillStart работает на 100%.

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

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
1. Команд копирования в буфер (насколько я помню) две: COPYCLIP и COPYBASE, а вставки три: PASTECLIP, PASTEORIG, PASTEBLOCK
2. Воспользуйся утилитой ARXDBG (из состава ObjectARX SDK, готовые arx-файлы можно скачать у меня: http://www.maestrogroup.com.ua/support/ ) для того, чтобы понять какие события возникают при операциях копирования в буфер и вставки из буфера. В контекстном меню выберешь команду REACTORS и включишь все флажки. Желательно сразу включить запись лога в файл, так как будет очень много сообщений. Проблемой может быть то, что не все реакторы, которые есть в ObjectARX реализованы в виде событий в AutoCAD .NET API.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
- Все ли правильно с событием WblockNotice? Может быть, в аргументах там должна фигурировать еще и вторая база данных?
Всё правильно, но ты сравниваешь не те базы. Нужно сравнивать e.To и HostApplicationServices.WorkingDatabase
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Думаешь, в промежуточных Database ID и/или хендлы объектов не меняются?
Меняются конечно, но через IdMapping ты как раз можешь отследить что было и что стало. И более то ты можешь в нужный момент в IdMapping подсунуть NOD, чтобы и она скопировалась, если в этом есть необходимость.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение