Создание группы осей сечений и оси сечения с помощью AutoCAD Civil 3D .NET API

Автор Тема: Создание группы осей сечений и оси сечения с помощью AutoCAD Civil 3D .NET API  (Прочитано 9408 раз)

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

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

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 735
Оригинал статьи тут: http://adndevblog.typepad.com/infrastructure/2013/08/creating-samplelinegroup-and-sampleline-using-autocad-civil-3d-net-api.html
В этой статье рассмотрим, как создать группу осей сечений и ось сечения, используя .NET API в Civil 3D версии 2014.
Оси сечения используются для расположения поперечных сечений на трассе. Оси сечения представляют собой отрезки, размещенные по длине трассы на заданных интервалах пикетажа (или в определенных интересующих пикетах, таких как конструкции объекта-коридора), использующие заданные левую и правую ширину захвата. Объекты осей сечений содержатся в объектах групп осей сечений, которые организуют несколько связанных осей сечений. Ось сечения используется для создания объекта «вид сечения», который отображает все или некоторые сечения, образованные этой осью сечения. Мы можем создать новый объект «группа осей сечения» используя (метод) SampleLineGroup.Create(string groupName, ObjectId AlignmentId). И мы можем создать новую ось сечения, используя статический метод SampleLine.Create(), который имеет два различных варианта –
Код - C# [Выбрать]
  1. public static ObjectId Create(string sampleLineName, ObjectIdsampleLineGroupId, double station);  
  2.  public static ObjectId Create(string sampleLineName,ObjectId sampleLineGroupId, Point2dCollection points);
C#-код ниже показывает как добавить группу осей сечений и ось сечения используя Create(string sampleLineName, ObjectId sampleLineGroupId, Point2dCollection points) –
Код - C# [Выбрать]
  1. Alignment alignment = trans.GetObject(alignmentId, OpenMode.ForWrite) as Alignment;
  2.  
  3. ObjectId slgId = SampleLineGroup.Create("Моя группа осей сечения", alignment.ObjectId);
  4. SampleLineGroup sampleLineGroup = trans.GetObject(slgId, OpenMode.ForWrite) as SampleLineGroup;
  5.  
  6. // Создание оси сечения из выбранного набора точек
  7.  
  8. Point2dCollection points = new Point2dCollection();
  9. Point2d samplelineVertexPoint1 = new Point2d(4528.7808, 3884.1900);
  10. points.Add(samplelineVertexPoint1);
  11. Point2d samplelineVertexPoint2 = new Point2d(4545.6858, 3859.4065);
  12. points.Add(samplelineVertexPoint2);
  13. ObjectId slatStationId = SampleLine.Create("ОсьСеченияПоТочкам", slgId, points);
  14. SampleLine sampleLine = trans.GetObject(slatStationId, OpenMode.ForWrite) as SampleLine;
  15. sampleLine.StyleId = civilDoc.Styles.SampleLineStyles[0];
  16.  
Это результат -


От переводчика.
Эта статья, насколько я понимаю, появилась в результате моего запроса в ADN, который в переводе на русский язык выглядел примерно так (я надеюсь  :D):
Цитировать
Прошу подсказать, как я могу создать ось сечения на трассе по параметрам, аналогичным задаваемым с помощью пользовательского интерфейса: пикетаж, левая полоса захвата, правая полоса захвата.
В результате, Partha Sarkar прислал мне ссылку на вот эту вот статью. Как нетрудно догадаться, меня такой вариант не устроил и я нашел другой выход - использование метода создания оси сечения из COM API Civil 3D. Ниже - код, демонстрирующий решение задачи:
Код - C# [Выбрать]
  1. [CommandMethod("CreateSLTest")]
  2. public void CreateSampleLinesMy()
  3. {
  4.     // Получаем ссылки на активный документ AutoCAD ...
  5.     Document adoc = Application.DocumentManager.MdiActiveDocument;
  6.     // базу данных ...
  7.     Database db = adoc.Database;
  8.     // редактор ...
  9.     Editor ed = adoc.Editor;
  10.     // и документ Civil
  11.     CivilDocument civilDoc = CivilDocument.GetCivilDocument(db);
  12.  
  13.     // Выбираем трассу на чертеже
  14.     PromptEntityOptions alignSelOpt = new PromptEntityOptions("\nВыберите трассу: ");
  15.     alignSelOpt.SetRejectMessage("\nЭто не трасса!");
  16.     alignSelOpt.AddAllowedClass(typeof(Alignment), true);
  17.     PromptEntityResult alignSelRes = ed.GetEntity(alignSelOpt);
  18.     if (alignSelRes.Status != PromptStatus.OK) return;            
  19.  
  20.     // Указываем точку вставки оси сечения
  21.     PromptPointResult ptRes = ed.GetPoint("\nТочка для вставки оси сечения на трассе: ");
  22.     if (ptRes.Status != PromptStatus.OK) return;
  23.  
  24.     // Задаем ширины полос захвата
  25.     PromptDoubleResult leftSwL = ed.GetDistance("\nЛевая ширина полосы захвата: ");
  26.     if (leftSwL.Status != PromptStatus.OK) return;
  27.     PromptDoubleResult rightSwL = ed.GetDistance("\nПравая ширина полосы захвата: ");
  28.     if (rightSwL.Status != PromptStatus.OK) return;
  29.  
  30.     // Запускаем транзакцию
  31.     using (Transaction trans = db.TransactionManager.StartTransaction())
  32.     {
  33.         // Получаем объект трассы
  34.         Alignment alignment = trans.GetObject(alignSelRes.ObjectId, OpenMode.ForRead) as Alignment;
  35.  
  36.         // Вычисляем пикетаж указанной точки на трассе
  37.         double station = 0.0, offset = 0.0;
  38.         alignment.StationOffset(ptRes.Value.X, ptRes.Value.Y, ref station, ref offset);
  39.  
  40.         // Id для группы осей сечений
  41.         ObjectId slgId;
  42.         // Получаем коллекцию Id групп осей сечений трассы
  43.         using (ObjectIdCollection slGroupsIds = alignment.GetSampleLineGroupIds())
  44.         {
  45.             // Если коллекция не пустая
  46.             if (slGroupsIds.Count != 0)
  47.             {
  48.                 // берем Id первой группы
  49.                 slgId = slGroupsIds[0];
  50.             }
  51.             // иначе
  52.             else
  53.             {
  54.                 // Создаем новую группу с гарантированно уникальным названием
  55.                 string sLineGrUniqueName = "SLG-" + Guid.NewGuid().ToString();
  56.                 slgId = SampleLineGroup.Create(sLineGrUniqueName, alignment.ObjectId);
  57.             }
  58.         }
  59.  
  60.         // Получаем объект для группы осей сечений
  61.         SampleLineGroup sampleLineGroup = trans.GetObject(slgId, OpenMode.ForWrite) as SampleLineGroup;
  62.  
  63.         // Формируем уникальное название для новой оси сечения
  64.         string slUniqueName = "SL-" + Guid.NewGuid().ToString();
  65.  
  66.         // Получаем COM-объект для группы осей сечений
  67.         dynamic sLgCOM = sampleLineGroup.AcadObject;
  68.         // Создаем новую ось сечения через COM, сохраняем ее COM-идентификатор
  69.         long newSlOldId = sLgCOM.SampleLines.AddByStation
  70.             (slUniqueName, station, leftSwL.Value, rightSwL.Value).ObjectID;
  71.         // Конвертируем COM-идентификатор в ObjectId
  72.         ObjectId slId = new ObjectId(new IntPtr(newSlOldId));
  73.         // Получаем объект .NET созданной оси сечения
  74.         SampleLine sampleLine = trans.GetObject(slId, OpenMode.ForWrite) as SampleLine;
  75.         // Назначаем ей первый из списка стиль
  76.         sampleLine.StyleId = civilDoc.Styles.SampleLineStyles[0];
  77.         trans.Commit();
  78.     }
  79. }

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

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

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

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 735
Хм... Мне это кажется настолько очевидным, что я даже теряюсь - как это можно объяснять :). Ладно, попробую.
Начну с того, что лично мне оси сечений нужны были на трассе в местах установки колодцев. Ось сечения можно использовать как источник данных для области данных вида профиля. Пример - есть участок сети:

В местах установки колодцев "Уг.2" и "Уг.3" оси сечения есть. В местах установки колодцев "Возд.1", "ПГ-1", "ВУз-3" и "ВУз-4" осей сечений нет. вот так это выглядит на виде профиля:

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


Итак, моя задача: программно создать оси сечения на трассе в местах установки колодцев. Исходные данные - трасса и точки, в которых находятся колодцы. С помощью метода Alignment.StationOffset я могу получить пикетаж положения колодца на трассе. Ширина полосы захвата мне нужна 2м в каждую сторону. Не потому, что потом будут строиться виды сечения по ним, просто проектировщики должны иметь возможность визуально контролировать наличие оси сечения в каком-либо месте и 2м - оптимальный для этого размер. Инструмент пользовательского интерфейса для добавления оси сечения на трассу имеет как раз такие запросы:
Цитировать
Команда: _AeccCreateSampleLines
Выберите трассу <либо нажмите клавишу Enter для выбора трассы из списка>:
Задайте пикет вдоль трассы:
Введите ширину левого захвата<2.000м>:
Введите ширину правого захвата<2.000м>:
Я предполагал, что метод для создания оси сечения будет иметь те же самые параметры. Но это оказалось не так, почему-то. Первый метод:
Код - C# [Выбрать]
  1. public static ObjectId Create(string sampleLineName, ObjectIdsampleLineGroupId, double station);
создает ось сечения в указанном пикетаже с шириной захвата 0 в обе стороны - это неудобно, т.к. визуально сложно понять на плане есть в нужном месте ось сечения или нет. У оси сечения в .NET API нет ни свойств ни методов для задания ее геометрии.
Второй метод:
Код - C# [Выбрать]
  1. public static ObjectId Create(string sampleLineName,ObjectId sampleLineGroupId, Point2dCollection points);
подразумевает, что мы откуда-то уже знаем точки кривой, обозначающей ось сечения на плане. Но у нас есть только пикетаж и желаемая ширина (иными словами - отступ в сторону от трассы). Если бы был какой-то метод трассы, обратный методу Alignment.StationOffset (например, Alignment.GetPointLocation(double station, double offset, SideType side, ref double x, ref double y)), то можно было бы вычислить нужные точки. Но такого метода нет. Конечно, проанализировав геометрию трассы в нужном пикете, можно разработать такой метод самостоятельно (и я уже собирался это делать), но, к счастью, нужный метод присутствует в COM API. И в данном случае гораздо целесообразнее воспользоваться им.

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Хм... Мне это кажется настолько очевидным, что я даже теряюсь - как это можно объяснять :).
Я же не пользуюсь Civil 3D ни как пользователь, ни как программист. Поэтому для меня это было не очевидно. И прочитав твоё объяснение я понял:
1. В Civil 3D .NET API нет метода, позволяющего создать нужный тебе тип оси.
2. В Civil 3D ActiveX/COM API такой метод есть и поэтому ты воспользовался им.
Убедил! :)
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 735
В Civil 3D .NET API нет метода, позволяющего создать нужный тебе тип оси.
Немного не так. Типа у осей сечений нет. И там и там создается одинаковая ось сечения, но задать ее геометрию проще и удобнее используя COM.

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
И там и там создается одинаковая ось сечения, но задать ее геометрию проще и удобнее используя COM.
Тип я ассоциировал с возможностью задания ненулевой "величины захвата". Я правильно понял, что в Civil 3D .NET API задать "величину захвата" для оси нельзя?
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 735
Да, все верно. Более того, у меня есть подозрение, что для уже созданной оси сечения изменить ее геометрию с помощью .NET API вообще нет возможности. Можно только передвинуть ее по трассе, изменив ее свойство Station и еще есть свойство Vertices, но оно только для получения коллекции вершин, которая не имеет свойств или методов для редактирования.
P.S. Хотя, если копать еще глубже, то у вершины в коллекции есть редактируемые свойства. Сейчас поковыряю, может оказаться, что я ошибался все эти годы :)

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

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 735
Проверил. Нет, не ошибался. У объекта SampleLineVertex (вершина оси сечения) можно изменить положение только задав новые координаты, которые все равно нужно как-то высчитывать. По простому задать ширину захвата нет возможности.