Выноска с привязкой к блоку

Автор Тема: Выноска с привязкой к блоку  (Прочитано 16162 раз)

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

Оффлайн Константин КулябовАвтор темы

  • ADN Club
  • Сообщений: 5
  • Карма: 0
  • Skype: konstantin.kulyabov
Помогите, кто может!
  Есть программа, состоящая из 2х основных блоков.
1 - запрос выбора блока (как простой, так и динамический) и извлечение его имени.

                   
Код - C# [Выбрать]
  1. PromptEntityOptions peo = new PromptEntityOptions("\nВыделите оборудование: ");
  2.                     peo.SetRejectMessage("\nЭто не блок.");
  3.                     peo.AddAllowedClass(typeof(BlockReference), false);
  4.                     PromptEntityResult per = ed.GetEntity(peo);
  5.  
2 - создание выноски с именем этого блока

сейчас выноска строится по запросу 2х точек:
                   
Код - C# [Выбрать]
  1. // Первая точка выноски
  2.  
  3.                 PromptPointResult result = ed.GetPoint("\nУкажите первую точку выноски: ");
  4.                       if (result.Status != PromptStatus.OK)
  5.                         return;
  6.  
  7.                    Point3d startPt = result.Value;
  8.  
  9.                     //конечная точка выноски
  10.  
  11.                     PromptPointOptions opts = new PromptPointOptions("\nУкажите вторую точку выноски: ");
  12.  
  13.  
  14.                     opts.BasePoint = startPt;
  15.                     opts.UseBasePoint = true;
  16.                     result = ed.GetPoint(opts);
  17.  
  18.                     if (result.Status != PromptStatus.OK)
  19.                         return;
  20.  
  21.                     Point3d endPt = result.Value;

Нужно, чтобы первая точка бралась автоматически, к примеру таже самая точка, куда щёлкнули выделяя блок (без дополнительного запроса), а вторая строится как обычно (или, не критично, ещё вариант когда выноска имеет определённую длину, т.е. вторая точка на конкретном расстоянии от первой)
« Последнее редактирование: 08-08-2014, 14:21:14 от Александр Ривилис »

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

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Выноска с привязкой к блоку
« Ответ #1 : 08-08-2014, 14:29:56 »
Приветствую на форуме!
Так и в чем проблема передать во второй блок в качестве первой точки выноски per.PickedPoint (или точка вставки блока).
Соотвественно запрос первой точки выноски не нужен:
Код - C# [Выбрать]
  1. Point3d startPt = per.PickedPoint;
  2. PromptPointOptions opts =
  3.    new PromptPointOptions("\nУкажите вторую точку выноски: ");
  4. opts.BasePoint = startPt;
  5. opts.UseBasePoint = true;
  6. result = ed.GetPoint(opts);
  7. if (result.Status != PromptStatus.OK)
  8.     return;
  9. Point3d endPt = result.Value;
  10.  
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Выноска с привязкой к блоку
« Ответ #2 : 08-08-2014, 14:30:51 »
Да. Забыл напомнить, что затем точки нужно будет преобразовать UCS -> WCS
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Константин КулябовАвтор темы

  • ADN Club
  • Сообщений: 5
  • Карма: 0
  • Skype: konstantin.kulyabov
Re: Выноска с привязкой к блоку
« Ответ #3 : 08-08-2014, 16:13:01 »
Спасибо за идею. Всё получилось

Оффлайн Константин КулябовАвтор темы

  • ADN Club
  • Сообщений: 5
  • Карма: 0
  • Skype: konstantin.kulyabov
Re: Выноска с привязкой к блоку
« Ответ #4 : 25-11-2014, 14:41:12 »
Добрый день!

Всё-таки не смог уйти от проблемы с ПСК.
при прямом расположении блока всё хорошо, а вот при его повороте начало выноски ускакивает (в качестве начала выноски сделан параметр "Точечный" динамического блока)

а вот как провести преобразование координат блока, чтобы всё было хорошо -- не нашёл.
когда использовал ORIGIN - тоже всё работало, но пришлось немного поменять концепцию

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

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Выноска с привязкой к блоку
« Ответ #5 : 25-11-2014, 14:52:03 »
Так приведи свой код - будет понятно что нужно исправить.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Константин КулябовАвтор темы

  • ADN Club
  • Сообщений: 5
  • Карма: 0
  • Skype: konstantin.kulyabov
Re: Выноска с привязкой к блоку
« Ответ #6 : 25-11-2014, 15:10:16 »
прошу прощения за стилистику

в качестве передаваемых свойств передаётся имя параметров, они же совпадают с именами слоёв
string[] LayerName = { "Электрика", "Вода", "Дренаж","Выноски" };



Код - C# [Выбрать]
  1.   private static void DisplayDynBlockProperties(Editor ed, BlockReference br, Transaction tr, string name, string LayerName)
  2.       {
  3.           Document doc = Application.DocumentManager.MdiActiveDocument;
  4.           Database db = doc.Database;
  5.  
  6.  
  7.              Boolean AddLead = false;  
  8.          
  9.           DynamicBlockReferencePropertyCollection pc = br.DynamicBlockReferencePropertyCollection;
  10.               AttributeCollection attCol = br.AttributeCollection;
  11.               Point3d startPt = br.Position;
  12.               double StX=startPt.X;
  13.               double StY=startPt.Y;
  14.  
  15.            LayerTable lt = (LayerTable)tr.GetObject(db.LayerTableId, OpenMode.ForRead);    
  16.           LayerTableRecord ltr = new LayerTableRecord();
  17.               ltr.Name = LayerName;
  18.  
  19.               lt.UpgradeOpen();
  20.               ObjectId idl = lt[LayerName];
  21.    
  22.               lt.DowngradeOpen();
  23.          
  24.           db.Clayer = idl;
  25.  
  26.               // Цикл получения свойств для каждого поля
  27.               foreach (DynamicBlockReferenceProperty prop in pc)
  28.               {
  29.  
  30.                   // Начать по свойству, типу и описанию
  31.  //                 ed.WriteMessage("\nProperty: \"{0}\" : {1}, значение {2}", prop.PropertyName, prop.UnitsType, prop.Value);
  32.  
  33.                   if (prop.PropertyName.Contains(LayerName) && prop.PropertyName.Contains("Y"))
  34.                   {
  35.                       double Y = Convert.ToDouble(prop.Value);
  36.                       StY = startPt.Y + Y;  
  37. //                      ed.WriteMessage("\n  Ура!! работает {0} \n  {1}",startPt.Y,Y);
  38.                       AddLead = true;
  39.                   }
  40.  
  41.                   if (prop.PropertyName.Contains(LayerName) && prop.PropertyName.Contains("X"))
  42.                   {
  43.                       double X = Convert.ToDouble(prop.Value);
  44.                       StX = startPt.X + X;
  45. //                      ed.WriteMessage("\n  Ура!! работает {0} \n  {1}", startPt.X, X);
  46.                       AddLead = true;
  47.                   }
  48.  
  49.  
  50.               }
  51.  
  52.             foreach (ObjectId attId in attCol)
  53.               {
  54.                  AttributeReference attRef = (AttributeReference)tr.GetObject(attId, OpenMode.ForRead);
  55.                  if ((attRef.Tag == LayerName) && (attRef.TextString != ""))
  56.      //                string str=("" + name +": "+attRef.TextString);
  57.                      name = (name + ":" +attRef.TextString);
  58.    //           string str = ("\n  Attribute Tag: " + attRef.Tag + "\n    Attribute String: " + attRef.TextString);
  59.    //               ed.WriteMessage(str);
  60.  
  61.               }
  62.  
  63.           if (AddLead)
  64.               DrawLeaderName(ed, br, name, StX, StY, startPt.Z);
  65.  
  66.           idl = lt["Выноски"];
  67.           db.Clayer = idl;
  68.       }
« Последнее редактирование: 25-11-2014, 15:11:05 от Александр Ривилис »

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

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Выноска с привязкой к блоку
« Ответ #7 : 25-11-2014, 15:10:35 »
В принципе должно быть достаточно такого преобразования:
Код - C# [Выбрать]
  1. startPt = startPt.TransformBy(ed.ed.CurrentUserCoordinateSystem);
  2. endPt = endPt.TransformBy(ed.ed.CurrentUserCoordinateSystem);
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Константин КулябовАвтор темы

  • ADN Club
  • Сообщений: 5
  • Карма: 0
  • Skype: konstantin.kulyabov
Re: Выноска с привязкой к блоку
« Ответ #8 : 25-11-2014, 15:12:56 »
ок. попробую

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

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Выноска с привязкой к блоку
« Ответ #9 : 25-11-2014, 15:20:35 »
прошу прощения за стилистику
Это не стилистика. Это хуже:
1) Не отформатированный код без тэгов
2) Нет функции DrawLeaderName
3) Нет чертежа с блоком, чтобы можно было понять о чем идёт речь.
4) Не вижу какое отношение проблема имеет к ПСК, так что предыдущая моя подсказка точно не поможет.

 
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
Re: Выноска с привязкой к блоку
« Ответ #10 : 25-11-2014, 23:05:44 »
Цитата: Константин Кулябов
Помогите, кто может!
Да уж... Начало не настраивает на позитив.

Пробежался по диагонали по исходникам... Александр Наумович предпочитает говорить в несколько сглаженной манере. Код автора данной темы, мягко говоря отвратителен. В суть клинописи не вникал, далее лишь самые поверхностные замечания.

1. Не забывай проверять результат, полученный из Application.DocumentManager.MdiActiveDocument на равенство null (актуально для AutoCAD 2015 и более новых версий, но заблаговременно можно добавить и в код более старых). Мало ли кто и когда дёрнет твой метод...

2. В первой строке кода метода ты создаёшь и инициализируешь переменную doc. Соответственно у тебя автоматом отпадает необходимость в первом параметре метода, поскольку Editor ты можешь спокойно получить от Document. Вообще в сигнатуре метода слишком много лишних, а так же непродуманных параметров:
 - от параметра Editor ed можно спокойно избавиться, т.к. он легко получается из doc.
 - Вместо BlockReference br лучше\надёжней\безопасней передавать его ObjectId.
 - Transaction tr лишний, его можно получить из db.

3. Начинать код тела метода всегда следует с проверки валидности переданных аргументов. У тебя какая-либо проверка напрочь отсутствует.

4. Что это за хитрая конструкция?

   
Код - C# [Выбрать]
  1. lt.UpgradeOpen();
  2.         ObjectId idl = lt[LayerName];  
  3.         lt.DowngradeOpen();
   
   Для того, чтобы получить идентификатор нужного слоя, нет никакой необходимости дёргать UpgradeOpen()\DowngradeOpen().
   
   Кроме того, прежде чем получать идентификатор слоя, неплохо сначала проверить, а есть ли он вообще (см. метод SymbolTable.Has(string)), а то может и дёргать-то не за что...
   
5. prop.PropertyName.Contains(LayerName)... А если рЕгИстрЫ символов вдруг не совпадут, то Титаник потонет? Вопрос риторический, положительный ответ очевиден.

6. prop.PropertyName.Contains(LayerName) && prop.PropertyName.Contains("X")...
   А ежели в имени слоя вдруг так же окажется буква "X", то можно кричать "Браво"? Аналогично и для "Y"...
   
7. double X = Convert.ToDouble(prop.Value); А если вдруг окажется не Double? Почитай о методе Double.TryParse.

8. if ((attRef.Tag == LayerName) && (attRef.TextString != ""))... Во первых, в случае несовпадения регистров символов, оператор == пошлёт тебе пламенный привет. Во вторых, вместо второй конструкции прочитай об String.IsNullOrEmpty.

9. применительно к DrawLeaderName(ed, br, name, StX, StY, startPt.Z); справедливо всё то, что изложено в п.2.

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

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 737
Re: Выноска с привязкой к блоку
« Ответ #11 : 25-11-2014, 23:11:25 »
- Transaction tr лишний, его можно получить из db.
Ну, кстати, на мой взгляд, иногда передача ссылки на транзакцию имеет смысл - чтобы не плодить вложенных транзакций. Я нередко пользуюсь таким приемом.

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

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
Re: Выноска с привязкой к блоку
« Ответ #12 : 25-11-2014, 23:16:23 »
Ну, кстати, на мой взгляд, иногда передача ссылки на транзакцию имеет смысл - чтобы не плодить вложенных транзакций. Я нередко пользуюсь таким приемом.
Зависит от контекста использования. Если ты в цикле перебираешь все объекты базы данных чертежа, то это будет целесообразным. Случай автора мне не напоминает данную ситуацию. чтобы не плодить вложенных транзакций он мог бы, как вариант, воспользоваться OpenCloseTransaction. Порой я тоже передаю ссылку на Transaction, например если использую лямбда-выражения в цикле, который может оказаться большим, но в случае обозначенном автором мне видится это излишним.

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

  • ADN Club
  • ****
  • Сообщений: 473
  • Карма: 66
Re: Выноска с привязкой к блоку
« Ответ #13 : 25-11-2014, 23:20:18 »
- Вместо BlockReference br лучше\надёжней\безопасней передавать его ObjectId.
 - Transaction tr лишний, его можно получить из db.
Это спорные утверждения...
з.ы. по второму уже без меня разобрались

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

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Выноска с привязкой к блоку
« Ответ #14 : 25-11-2014, 23:25:40 »
Ну, кстати, на мой взгляд, иногда передача ссылки на транзакцию имеет смысл - чтобы не плодить вложенных транзакций. Я нередко пользуюсь таким приемом.
А Database.TransactionManager.TopTransaction тебя не устроит для этой цели?
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение