- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report
Hello, I made a command that splits ducts into chunks of maximum lengths 1500mm and 300 mm.
The problem I am faced with is that breaking the curve makes a new curve that has the correct length but when I add a union fitting between 2 ducts, the fitting width "eats a bit" out of my 1500mm duct and turns it into 1497 mm or something. I know this is because the union fitting has its own physical width, I am unsure how to tackle compensating for this width. Seeing as there can be may different families of unions with different widths.
I hard coded a value that have in the test project and used it to compensate , but that wont be the case in all projects...
Any ideas on how to resolve this issue without asking the user for the union width or hardcoding it?
Here is my code for the entire command (its called with one duct selected).
[Transaction(TransactionMode.Manual)]
class DuctSplitter : IExternalCommand
{
public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
{
UIDocument uiDoc = commandData.Application.ActiveUIDocument;
Document doc = uiDoc.Document;
using (Transaction trans = new Transaction(doc, "Trans1"))
{
trans.Start();
Split1DuctMutlipleTimes(uiDoc, doc);
trans.Commit();
}
return Result.Succeeded;
}
private void Split1DuctMutlipleTimes(UIDocument uiDoc, Document doc)
{
ICollection<ElementId> selectedIds = uiDoc.Selection.GetElementIds();
Element duct = doc.GetElement((selectedIds.ToList())[0]);
Element newDuct = null;
LocationCurve lCurve = duct.Location as LocationCurve;
Curve curve = lCurve.Curve;
double totalLength = curve.Length;
//convert length to mm
double realLen = UnitUtils.ConvertFromInternalUnits(totalLength, DisplayUnitType.DUT_MILLIMETERS);
double minLen = 300;
double maxLen = 1500;
//need to acount for union fitting width
double unionSize = 7;
//double internalLength = UnitUtils.ConvertToInternalUnits(maxLen, DisplayUnitType.DUT_MILLIMETERS);
//calculate the number of splits
int numOfSplits = (int)Math.Truncate(realLen / maxLen);
// the length of the final piece, if this is 0, then it still needs to reduce the number of splits because unions have their own lengths
double finalPiece = realLen - maxLen * numOfSplits;
bool needsFinalPiece = false;
//compensate for possible outcomes for final piece
double maxLenWithUnion = maxLen + unionSize / 2;
double minLenWithUnion = minLen + unionSize / 2;
if (finalPiece < minLenWithUnion)
{
numOfSplits -= 1;
needsFinalPiece = true;
}
for (int i = 0; i < numOfSplits; i++)
{
newDuct = SplitDuct(uiDoc, doc, duct, maxLenWithUnion);
}
placeFinalPiece(uiDoc, doc, duct, minLenWithUnion, maxLen, finalPiece, needsFinalPiece);
}
private void placeFinalPiece(UIDocument uiDoc, Document doc, Element duct, double minLen, double maxLen, double finalPiece, bool needsFinalPiece)
{
if (needsFinalPiece)
{
double len = (duct.Location as LocationCurve).Curve.Length;
double extLen = UnitUtils.ConvertFromInternalUnits(len, DisplayUnitType.DUT_MILLIMETERS);
// to cover for case when finalpiece = 0
if (extLen < maxLen) return;
finalPiece = extLen - minLen;
SplitDuct(uiDoc, doc, duct, finalPiece);
}
return;
}
Element SplitDuct(UIDocument uiDoc, Document doc, Element duct, double splitLen)
{
// get curve
LocationCurve lCurve = duct.Location as LocationCurve;
Curve curve = lCurve.Curve;
// get endpoins and a vector betwen them
XYZ pt0 = curve.GetEndPoint(0);
XYZ pt1 = curve.GetEndPoint(1);
XYZ vec = pt1.Subtract(pt0).Normalize();
double lenght = UnitUtils.ConvertToInternalUnits(splitLen, DisplayUnitType.DUT_MILLIMETERS);
// scale normalized vector
XYZ breakPt = pt0.Add(vec.Multiply(lenght));
// make new duct and get it
ElementId newDuctId = Autodesk.Revit.DB.Mechanical.MechanicalUtils.BreakCurve(doc, duct.Id, breakPt);
Element newDuct = doc.GetElement(newDuctId);
//create a union
Connector con1 = (duct as Autodesk.Revit.DB.Mechanical.Duct).ConnectorManager.Lookup(0);
Connector con2 = (newDuct as Autodesk.Revit.DB.Mechanical.Duct).ConnectorManager.Lookup(1);
doc.Create.NewUnionFitting(con1, con2);
return newDuct;
}
}
Solved! Go to Solution.