Присоединение наклонного сегмента трубопровода к соседним трубам
Статья является продолжением предыдущих моих статей по вычислению наклонного сегмента между двумя трубами и созданию наклонного сегмента.
Следующий шаг состоит в том, что нужно корректно соединить все трубы в единую систему.
До сих пор я предполагал, что просто соединив трубы друг с другом, Revit автоматически создаст соответствующие фитинги.
К сожалению, мое предположение было ошибочным.
Утилиты для соединения MEP элементов
Я создал несколько вспомогательных утилит для примеров The Building Coder:
- GetConnectorManager. Возвращает ConnectorManager для заданного элемента, используя при этом либо свойство MEPModel элемента, если элемент является экземпляром семейства, либо напрямую, если заданный элемент является объектом класса MEPCurve, т.е. либо трубой, либо воздуховодом.
- GetConnectorClosestTo. Возвращает ближайший к заданной точки соединитель из набора соединителей
- Connect. Соединяет два элемента MEP в заданной точке.
В RevitAPI получить доступ к объекту ConnectorManager можно различными способами, с зависимости от того, является ли элемент трубой или воздуховодом, т.е. является объектом класса MEPCurve, или элемент является экземпляром семейства. Вспомогательный метод GetConnectorManager скрывает эти различия, и позволяет нам не беспокоиться о том, для какого элемента мы хотим получить ConenctorManager. Этот метод также полезен в методе Connect, где мы соединяем несколько MEP элементов.
- /// <summary>
- /// Возвращает ConnectorManager для заданного элемента,
- /// используя свойство MEPModel для экземпляра семейства
- /// или напрямую, если заданный элемент является
- /// трубой или воздуховодом
- /// </summary>
- static ConnectorManager GetConnectorManager(
- Element e )
- {
- MEPCurve mc = e as MEPCurve;
- FamilyInstance fi = e as FamilyInstance;
- if( null == mc && null == fi )
- {
- throw new ArgumentException(
- "Элемент не является ни фитингом, ни трубой или воздуховодом." );
- }
- return null == mc
- ? fi.MEPModel.ConnectorManager
- : mc.ConnectorManager;
- }
- /// <summary>
- /// Возвращает ближайший к заданной точке
- /// соединитель из набора соединителей
- /// </summary>
- static Connector GetConnectorClosestTo(
- ConnectorSet connectors,
- XYZ p )
- {
- Connector targetConnector = null;
- double minDist = double.MaxValue;
- foreach( Connector c in connectors )
- {
- double d = c.Origin.DistanceTo( p );
- if( d < minDist )
- {
- targetConnector = c;
- minDist = d;
- }
- }
- return targetConnector;
- }
- /// <summary>
- /// Соединяет два заданных элемента в точке p.
- /// </summary>
- /// <exception cref="ArgumentException">Возникает, если один из элементов не имеет соединителей
- /// </exception>
- public static void Connect(
- XYZ p,
- Element a,
- Element b )
- {
- ConnectorManager cm = GetConnectorManager( a );
- if( null == cm )
- {
- throw new ArgumentException(
- "Элемент А не имеет соединителей." );
- }
- Connector ca = GetConnectorClosestTo(
- cm.Connectors, p );
- cm = GetConnectorManager( b );
- if( null == cm )
- {
- throw new ArgumentException(
- " Элемент В не имеет соединителей." );
- }
- Connector cb = GetConnectorClosestTo(
- cm.Connectors, p );
- ca.ConnectTo( cb );
- //cb.ConnectTo( ca );
- }
Прямое соединение двух труб
Можно воспользоваться приведенным выше методом для соединения наклонного сегмента трубопровода к двум исходным трубам. Исходные трубы – это объекты pipe[0] и pipe[1] соответственно, а наклонный сегмент хранится в переменной pipe. Переменные q0 и q1 обозначают координаты начала и окончания наклонного сегмента.
- if( null != pipe )
- {
- // Соединим наклонный сегмент
- // с исходными трубами
- Util.Connect( q0, pipes[0], pipe );
- Util.Connect( q1, pipe, pipes[1] );
- }
Визуально, результат будет тот же самый, что мы получили в предыдущей статье.
Предположим мы начали так же с расположения двух труб:
После размещения наклонного сегмента, результат стал выглядеть так:
До того как я реализовал метод Connect, я мог передвинуть трубу и она будет перемещаться отдельно от наклонного сегмента, так как наклонный сегмент никак не связан с исходными трубами:
Но присоединив наклонный сегмент к исходным трубам с помощью метода Connect, мы можем быть уверены, что все трубы составляют одну систему и передвинув одну трубу, наклонный сегмент так и останется присоединен к ней, но изменит размер.
Так где же фитинги?
Тем не менее, результат все еще далек от идеала. Несмотря на то что трубы представляют собой единую систему, в модели все еще нет подходящих фитинов, соединяющих эти трубы.
Я честно ожидал, что они будут созданы автоматически. Возможны несколько причин, почему этого не произошло, например,
- Revit в принципе не может это сделать
- Трубы присоединится под углом, для которого нет подходящего фитинга
В классе PipeFittings определяются фитинги для труб. В описании метода GetSpecificFittingAngles этого класса говорится, «Revit будет использовать только определенные углы во время создания новых труб или изменения метаположения существующих. Когда происходит перемещение труб, Revit будет рассчитывать угол между ними и для фитинга будет использован ближайший разрешенный угол»
Таким образом, мне еще есть над чем подумать.
Тем не менее я уже рад, что получилось соединить трубы в одну систему.
Код, который я написал выше, доступен в примерах The Building Coder на GitHub в команде под названием CmdRollingOffset. Версия команды, которая обсуждалась в статье, находится в release 2014.0.106.3
Обсуждение: http://adn-cis.org/forum/index.php?topic=468
Опубликовано 18.01.2014