Части трубопроводной сети (трубы и колодцы) на виде профиля
На виде профиля, после добавления на него части трубопроводной сети (колодца или трубы), Civil 3D создает новый объект: ProfileViewPart. У этого объекта не много методов, но зато он является объектом базы данных чертежа (с ID и геометрией).
Итак, вопрос: как получить пикетаж и отметку части на виде профиля?
Используя габаритный контейнер части, мы можем получить доступ к координатам XY в модели. Тогда возможно получить среднюю точку (или какую-нибудь другую точку, например с максимальной и минимальной координатой Y). Используя эти координаты XY, мы можем вернуться обратно на вид профиля и запросить пикетаж и отметку для этой точки.
Пример кода ниже демонстрирует эту идею:
- // выбор части сети на виде профиля
- 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-продукт! Мы имеем дело с интеллектуальными объектами! Почему бы не получать нужные свойства напрямую? Приведенный ниже код использует как раз такой, цивилизованный подход:
- // выбор части сети на виде профиля
- 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);
- }
- }
- }
Источник: http://adndevblog.typepad.com/infrastructure/2014/07/pipe-network-parts-on-profile-view.html
Обсуждение: http://adn-cis.org/forum/index.php?topic=2961
Опубликовано 29.08.2015Отредактировано 30.08.2015 в 15:02:42