Статьи > Тестирование статей

Части трубопроводной сети (трубы и колодцы) на виде профиля.

(1/1)

Дмитрий Загорулькин:
Оригинал статьи: http://adndevblog.typepad.com/infrastructure/2014/07/pipe-network-parts-on-profile-view.html

На виде профиля, после добавления на него части трубопроводной сети (колодца или трубы), Civil 3D создает новый объект: ProfileViewPart. У этого объекта не много методов, но зато он является объектом базы данных чертежа (с ID и геометрией).
Итак, вопрос: как получить пикетаж и отметку части на виде профиля?
Используя габаритный контейнер части, мы можем получить доступ к координатам XY в модели. Тогда возможно получить среднюю точку (или какую-нибудь другую точку, например с максимальной и минимальной координатой Y). Используя эти координаты XY, мы можем вернуться обратно на вид профиля и запросить пикетаж и отметку для этой точки.
Пример кода ниже демонстрирует эту идею:

--- Код - C# [Выбрать] ---// выбор части сети на виде профиляEditor ed = Application.DocumentManager.MdiActiveDocument.Editor;PromptEntityOptions peo = new PromptEntityOptions(  "\nВыберите часть сети на виде профиля: ");peo.SetRejectMessage("\nТолько части сети на виде профиля!");peo.AddAllowedClass(typeof(ProfileViewPart), true);PromptEntityResult per = ed.GetEntity(peo);if (per.Status != PromptStatus.OK) return; Database db = Application.DocumentManager.MdiActiveDocument.Database;using (Transaction trans = db.TransactionManager.StartTransaction()){  // получение части сети, отображенной на виде профиля  ProfileViewPart partPV = trans.GetObject(per.ObjectId,    OpenMode.ForRead) as ProfileViewPart;  Part part = trans.GetObject(partPV.ModelPartId,    OpenMode.ForRead) as Part;   // может иметься несколько видов профилей, отображающих эту часть...  ObjectIdCollection pvIds = part.GetProfileViewsDisplayingMe();  foreach (ObjectId pvId in pvIds)  {    // получаем среднюю точку этого колодца на виде профиля (зам. пер. – это может быть и труба)    // вы можете изменить эти координаты X,Y для максимальных или минимальных значений...    Extents3d ext = partPV.GeometricExtents;    double x = (ext.MaxPoint.X - ext.MinPoint.X) / 2 + ext.MinPoint.X;    double y = (ext.MaxPoint.Y - ext.MinPoint.Y) / 2 + ext.MinPoint.Y;     // получение вида профиля    ProfileView pv = trans.GetObject(pvId, OpenMode.ForRead) as ProfileView;     // и пикетаж с отметкой на виде профиля    double station = 0.0;    double elevation = 0.0;    pv.FindStationAndElevationAtXY(x, y, ref station, ref elevation);     ed.WriteMessage(      "\n{0} отображается на виде профиля {1} на пикете: {2:0.00} | Отметка: {3:0.00}",      part.Name, pv.Name, station, elevation);  }} 

Александр Ривилис:
Опубликовал на сайте: Части трубопроводной сети (трубы и колодцы) на виде профиля

Дмитрий Загорулькин:
В результате проверки работы кода, обнаружилось, что в алгоритме имеется ошибка. Автор кода учел, что часть может отображаться на нескольких видах профилей. Однако, в этом случае, габаритный контейнер для части на виде профиля будет вычисляться охватыванием всех отображений части на всех видах профилей, т.к. это не несколько разных объектов, а один! Координаты габаритного контейнера получаются несколько иными, чем ожидается, и практического смысла от них мало. Подробно я показал это на видео: https://screencast.autodesk.com/main/details/4fba5135-8cd6-4949-988d-e3e6c239d99c.
В общем-то, использование габаритного контейнера для получения точек части сети на виде профиля – это довольно грубый способ. В конце-концов, это же BIM-продукт! Мы имеем дело с интеллектуальными объектами! Почему бы не получать нужные свойства напрямую? Приведенный ниже код использует как раз такой, цивилизованный подход:

--- Код - C# [Выбрать] ---// выбор части сети на виде профиляEditor ed = Application.DocumentManager.MdiActiveDocument.Editor;PromptEntityOptions peo = new PromptEntityOptions(  "\nВыберите часть сети на виде профиля: ");peo.SetRejectMessage("\nТолько части сети на виде профиля!");peo.AddAllowedClass(typeof(ProfileViewPart), true);PromptEntityResult per = ed.GetEntity(peo);if (per.Status != PromptStatus.OK) return; Database db = Application.DocumentManager.MdiActiveDocument.Database;using (Transaction trans = db.TransactionManager.StartTransaction()){    // получение части сети, отображенной на виде профиля    ProfileViewPart partPV = trans.GetObject(per.ObjectId,      OpenMode.ForRead) as ProfileViewPart;    Part part = trans.GetObject(partPV.ModelPartId,      OpenMode.ForRead) as Part;     // может иметься несколько видов профилей, отображающих эту часть...    ObjectIdCollection pvIds = part.GetProfileViewsDisplayingMe();    foreach (ObjectId pvId in pvIds)    {        // получение вида профиля        ProfileView pv = trans.GetObject(pvId, OpenMode.ForRead) as ProfileView;         // получение трассы вида профиля        Alignment align = trans.GetObject(pv.AlignmentId, OpenMode.ForRead) as Alignment;         // если объект - колодец        if (part is Structure)        {            // получение колодца            Structure structure = part as Structure;             // получение точки вставки колодца в модели            Point3d strLoc = structure.Location;             // получение пикетажа колодца по трассе вида профиля            // как побочные данные, будет получено еще смещение            // колодца от трассы вида профиля в плане            double                station = 0.0,                offset = 0.0;                                    align.StationOffset(strLoc.X, strLoc.Y, ref station, ref offset);                              // вывод сообщения о положении колодца            ed.WriteMessage(              "\nКолодец '{0}' отображается на виде профиля '{1}' на пикете: {2:0.00}",              part.Name, pv.Name, station);             // если колодец соединительный - вывод отметки его крышки и дна            if (structure.PartType == PartType.StructJunction)            {                ed.WriteMessage                    ("\nОтметка крышки колодца: {0:0.00}, дна: {1:0.00}",                    structure.RimElevation, structure.SumpElevation);            }        }        // если объект - труба        else if (part is Pipe)        {            // получение трубы            Pipe pipe = part as Pipe;             // ... и ее начальной и конечной точек (на оси трубы)            Point3d                startPt = pipe.StartPoint,                endPt = pipe.EndPoint;                                    // получение пикетажей и смещений начальной и конечной точек            double                startStation = 0.0,                startOffset = 0.0,                endStation = 0.0,                endOffset = 0.0;             align.StationOffset(startPt.X, startPt.Y, ref startStation, ref startOffset);            align.StationOffset(endPt.X, endPt.Y, ref endStation, ref endOffset);             // вывод значения пикетажей и отметок начальной и конечной точек            ed.WriteMessage(              "\nТруба '{0}' отображается на виде профиля '{1}'."              + "\nНачало - пикет: {2:0.00}, отметка: {3:0.00}"              + "\nКонец - пикет: {4:0.00}, отметка: {5:0.00}",              part.Name, pv.Name, startStation, startPt.Z, endStation, endPt.Z);        }    }} 

Александр Ривилис:
Отлично! Я исправил статью на сайте согласно с твоими исправлениям и дополнениями.

Навигация

[0] Главная страница сообщений

Перейти к полной версии