How to split Duct by 2 picked point

How to split Duct by 2 picked point

duongf7a
Explorer Explorer
704 Views
6 Replies
Message 1 of 7

How to split Duct by 2 picked point

duongf7a
Explorer
Explorer

Hi Everyone,

I'm trying to split Duct by 2 points from user, but I can only split duct when the user pick point from left to right. If the user pick 2 points from right to left I will get the error. Can anyone help me fix that.

Thank you.

 

The following is my code:

 

using Autodesk.Revit.Attributes;
using Nice3point.Revit.Toolkit.External;
using Autodesk.Revit.UI.Selection;
using Autodesk.Revit.DB.Mechanical;

namespace RevitAddIn2.Commands
{
/// <summary>
/// External command entry point invoked from the Revit interface
/// </summary>
[UsedImplicitly]
[Transaction(TransactionMode.Manual)]
public class DuctUpDownCmd : ExternalCommand
{
public override void Execute()
{
var ductRefer = UiDocument.Selection.PickObject(ObjectType.Element);

var ductElement = Document.GetElement(ductRefer);

var ductLocationCurve = ductElement.Location as LocationCurve;

var ductCurve = ductLocationCurve.Curve;

using (var tx = new Transaction(Document, "Break Duct"))
{
tx.Start();

var startRefPoint = UiDocument.Selection.PickObject(ObjectType.PointOnElement);

var insectStartPoint = ductCurve.Project(startRefPoint.GlobalPoint).XYZPoint;

var splitedDuctIdAtStartPoint = MechanicalUtils.BreakCurve(Document, ductRefer.ElementId, insectStartPoint);

var splitedDuctAtStartPoint = Document.GetElement(splitedDuctIdAtStartPoint);

var newDuctCurveLocation = splitedDuctAtStartPoint.Location as LocationCurve;

var newDuctCurve = newDuctCurveLocation.Curve;

var endRef = UiDocument.Selection.PickObject(ObjectType.PointOnElement);

var insectPtEnd = newDuctCurve.Project(endRef.GlobalPoint).XYZPoint;

var eleIdEnd = MechanicalUtils.BreakCurve(Document, splitedDuctIdAtStartPoint, insectPtEnd);

tx.Commit();
}

}

}
}

0 Likes
Accepted solutions (1)
705 Views
6 Replies
Replies (6)
Message 2 of 7

Mohamed_Arshad
Advisor
Advisor
Accepted solution

Hi @duongf7a 

 

    Duct split is based on the Duct draw direction, kindly refer the below code snippet and reference image for additional information.

 

Code Snippet

public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
{
    ///Get Document Properties
    UIDocument uiDoc = commandData.Application.ActiveUIDocument;
    Document doc = uiDoc.Document;

    ///Select Duct
    Reference ductRefer = uiDoc.Selection.PickObject(ObjectType.Element);

    ///Get Element from the Reference
    Element ductElement = doc.GetElement(ductRefer);

    ///Get Location Curve of the Duct
    LocationCurve ductLocationCurve = ductElement.Location as LocationCurve;

    ///Get Curve from Location Curve
    Curve ductCurve = ductLocationCurve.Curve;

    ///Get Duct Direction
    XYZ ductDir = ductCurve.GetEndPoint(1).Subtract(ductCurve.GetEndPoint(0)).Normalize();

    ///Get Break Point from the User
    Reference breakPoint_1_Ref = uiDoc.Selection.PickObject(ObjectType.PointOnElement);
    Reference breakPoint_2_Ref = uiDoc.Selection.PickObject(ObjectType.PointOnElement);

    ///Project Pick Point to the Duct Center Line
    XYZ breakPoint_1 = ductCurve.Project(breakPoint_1_Ref.GlobalPoint).XYZPoint;
    XYZ breakPoint_2 = ductCurve.Project(breakPoint_2_Ref.GlobalPoint).XYZPoint;

    using (Transaction breakDuct = new Transaction(doc,"Break Duct"))
    {
        breakDuct.Start();

        ///Break Duct using first Point
        ElementId splitDuctIdAtBreakPoint_1 = MechanicalUtils.BreakCurve(doc, ductRefer.ElementId, breakPoint_1);

        //Get Duct of the First Breaking
        Element splitDuctAtBreakPoint_1 = doc.GetElement(splitDuctIdAtBreakPoint_1);
        LocationCurve newDuctCurveLocation = splitDuctAtBreakPoint_1.Location as LocationCurve;
        Curve newDuctCurve = newDuctCurveLocation.Curve;

        ElementId secondSplitId = null;

        ///Get Start point of the duct
        XYZ pointPickDir = breakPoint_2.Subtract(breakPoint_1).Normalize();

        ///Direction Validation
        if (pointPickDir.IsAlmostEqualTo(ductDir, Math.Pow(10, -5)))
        {
            secondSplitId = ductElement.Id;
        }
        else
        {
            secondSplitId = splitDuctAtBreakPoint_1.Id;
        }

        ///Second Split
        ElementId secondElementId = MechanicalUtils.BreakCurve(doc, secondSplitId, breakPoint_2);

        breakDuct.Commit();

    }

    return Result.Succeeded;
}

Image Explanation

Mohamed_Arshad_0-1729246005694.png

Output

 

Hope this will Helps 🙂


Mohamed Arshad K
Software Developer (CAD & BIM)

0 Likes
Message 3 of 7

jeremy_tammik
Alumni
Alumni

In wonder whether any of these articles are of use to you, in addition to Mohamed's very kind and helpful suggestion?

 

 

Jeremy Tammik Developer Advocacy and Support + The Building Coder + Autodesk Developer Network + ADN Open
Message 4 of 7

Mohamed_Arshad
Advisor
Advisor

Hi @jeremy_tammik  
Thank you for your kind words 🙂


Mohamed Arshad K
Software Developer (CAD & BIM)

0 Likes
Message 5 of 7

duongf7a
Explorer
Explorer
 

Thank you so much Mohamed Arsha. You do exactly that I need to

0 Likes
Message 6 of 7

duongf7a
Explorer
Explorer

Thank you  jeremy tammik, I will take all of that and spend time to read it.

Actually, I've already read so many your articles and I found the Project method, but I still get stuck when I try to fix my error.

So I think my big problem here is I'm not familiar about the computional geometry algorithms such as finding the relative position of the line and point and apply to Revit API. Can you give me some advice. Thank you so much

0 Likes
Message 7 of 7

jeremy_tammik
Alumni
Alumni

Sure. The Revit API provides a method to project a point onto a line, Line.Project:

  

  

However, you can also easily implement it yourself:

  

  

Jeremy Tammik Developer Advocacy and Support + The Building Coder + Autodesk Developer Network + ADN Open