- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report
Hi developers:
Let me brief my demand first:
- There is an API named BreakCurve, in both MechanicalUtils and PlumbingUtils.
It is a very safe and convenient way to split a duct or a pipe programmatically.
But I could not find a way to easily split a cable tray or a conduit.
So I did the following job:
- Implement a method to "deep copy" and mep curve element, especially cable trays and conduits. This method genrates a Line which is same as another existing mep curve element. Then a new element is created, along the copied Line. Considering the rotation of the element it self (Considering onlt the self rotation), I inspect the original self-rotation of the original element (even it is round, I can still get it's self rotation by it's connector coordinate system), then rotate the new element. I will also create the same insulation and lining if the original element has them (not important, we are talking about conduit).
- I "shrink" the old element as well as the new element. Suppose I picked a point, and project it into the element Location Line, then this point will be the new end point of both old and new element. I use the API Connector.Origin property to set a new XYZ point (which I described above).
- I inspect the old connection of the old element. Notice that I only move the connector at the end point (instead of the start point), so I get another connector (not belong to the old mep curve), reconnect it to the new mep curve element (new connecto of the new element is located at the same point of the original connector)
So far, everything goes well. I tested it on ducts, pipes, cable trays. But when I do it again on conduits, Revit throws a generation error 😞
Let me share my codes first:
//! *** My codes contain some extention methods. Ther are very easy to understand by their literal names. ***
-------------------- Copy a mep curve element -----------------------
Document doc = elem.Document; Line l = elem.GetLine(); XYZ refRight = elem.GetSelfRight(); XYZ p0 = l.GetEndPoint(0), p1 = l.GetEndPoint(1); Level refLevel = elem.ReferenceLevel; ElementId typeId = elem.GetTypeId(); MEPCurve toReturn; if (elem is Duct || elem is Pipe) { ElementId sysTypeId = elem.MEPSystem.GetTypeId(); if (elem is Duct) // 风管 { var newDuct = Duct.Create(doc, sysTypeId, typeId, refLevel.Id, p0, p1); var newInsulation = newDuct.CopySameInsulationAs(elem as Duct); var newLining = newDuct.CopySameLiningAs(elem as Duct); toReturn = newDuct; } else // 管道 { var newPipe = Pipe.Create(doc, sysTypeId, typeId, refLevel.Id, p0, p1); var newInsulation = newPipe.CopySameInsulationAs(elem as Pipe); toReturn = newPipe; } } else { if (elem is CableTray) // 电缆桥架 { var newCableTray = CableTray.Create(doc, typeId, p0, p1, refLevel.Id); newCableTray.SetWidth(elem.Width); newCableTray.SetHeight(elem.Height); toReturn = newCableTray; } else if (elem is Conduit) // 线管 { var newConduit = Conduit.Create(doc, typeId, p0, p1, refLevel.Id); newConduit.SetDiameter(SizeType.Nominal, elem.Diameter); toReturn = newConduit; } else { throw new NotSupportedException(); } }
--------------------- Self-rotate the new element -----------------------
double ang = refRight.AngleTo(toReturn.GetSelfRight()); using (SubTransaction subTrans = new SubTransaction(doc)) { subTrans.Start(); // 先尝试向一个方向自旋转
// First try rotating in a direction toReturn.Location.Rotate(l, ang); doc.Regenerate(); // 如果新图元自旋转之后与旧图元的自旋转方向不一致,则回滚子事务,并且尝试反向旋转
// Sometimes the rotation is in opposite direction other than we need,
// so I roll it back, and rotate it is another direction. if (toReturn.GetSelfRight().IsSameDirectionAs(refRight)) subTrans.Commit(); else { subTrans.RollBack(); subTrans.Start(); toReturn.Location.Rotate(l, -ang); subTrans.Commit(); } } doc.Regenerate();
------------------ Shrink a straight mep curve element (by setting the end connector)-----------
// shrink is XYZ
SubTransaction subt = new SubTransaction(elem.Document); try { subt.Start();
// IsOppositeDirection(XYZ) is my own ext method, it's easy to understand it :) if (l.Direction.IsOppositeDirection(shrink)) { var conn1 = elem.GetConnectorAt(l.GetEndPoint(1)); conn1.Origin = conn1.Origin + shrink; } else { var conn0 = elem.GetConnectorAt(l.GetEndPoint(0)); // 注意此时的延伸向量与管线的行进方向是反向的 conn0.Origin = conn0.Origin + shrink; } subt.Commit(); return true; } catch { subt.RollBack(); return false; } finally { l.Dispose(); subt.Dispose(); }
Thank you for your patience of reading towards here 🙂
The above mentioned methods work well for ducts, pipes, cable trays, but not conduits.
No I will show some screen shots if the result.
If conduit is a free one (no connection at both ends), it works fine.
If either of it's ends is connected, here comes the trouble:
The error message reads like that there is no available family symbols in the .rvt document.
But my implementation does not require any family instance creation.
I tested it in Revit 2019.
Can anyone help me???? Thanks a lot.
Solved! Go to Solution.