Revit API Forum
Welcome to Autodesk’s Revit API Forums. Share your knowledge, ask questions, and explore popular Revit API topics.
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Is there any api available to split a duct programmatically?

17 REPLIES 17
SOLVED
Reply
Message 1 of 18
saurav_dhir
3314 Views, 17 Replies

Is there any api available to split a duct programmatically?

Hello everyone, 

 

I really need to know can we split a duct programmatically ? Is there any API available to do so?

 

I searched in some old articles and it seems Revit doesn't provide any API for the split function. But I am hoping if they have added this in 2017 edition.

 

 

Any other ideas to achieve this will be highly appreciated.

 

Thanks

Saurabh 

17 REPLIES 17
Message 2 of 18

Hello @saurav_dhir,

See my comment in this post: https://forums.autodesk.com/t5/revit-api-forum/duct-splitting/m-p/6784012/highlight/true#M20243

 


Cheers,

-Matt
_______________________________________________________________________________
Marking a post as a 'solution' helps the community. Giving a post 'Kudos' is as good as saying thanks. Why not do both?
Message 3 of 18

Thanks Matthew for replying.  

 

I tried using the BreakCurve method for splitting a duct but it throws error at the time of execution.

can you please guide me on how to pass the third parameter i.e. XYZ ptBreak ?

BreakCurveIssue.jpg

 

Thanks

Saurabh

 

 

 

Message 4 of 18

Hi @saurav_dhir,

No problem.

Well, I think the error says it all! The point isn't on the duct curve.

Here's a simple example that breaks a duct 2 feet along its length.

 

<Transaction(TransactionMode.Manual)> _
<Regeneration(RegenerationOption.Manual)> _
<Journaling(JournalingMode.UsingCommandData)> _
Public Class TransactionCommand
    Implements UI.IExternalCommand
    Public Function Execute(ByVal commandData As UI.ExternalCommandData, ByRef message As String, ByVal elements As DB.ElementSet) As UI.Result Implements UI.IExternalCommand.Execute
        Dim app As ApplicationServices.Application = commandData.Application.Application
        Dim doc As DB.Document = commandData.Application.ActiveUIDocument.Document
        Dim docUi As UI.UIDocument = commandData.Application.ActiveUIDocument

        Execute = UI.Result.Failed
        Using transaction As New DB.Transaction(doc, "Break Duct")
            transaction.Start()
            Dim duct As DB.Mechanical.Duct = TryCast(doc.GetElement(New DB.ElementId(1789723)), DB.Mechanical.Duct)
            Dim curve As DB.Curve = TryCast(duct.Location, DB.LocationCurve).Curve
            Dim pt0 As DB.XYZ = curve.GetEndPoint(0)
            Dim pt1 As DB.XYZ = curve.GetEndPoint(1)
            Dim vector As DB.XYZ = pt1.Subtract(pt0).Normalize
            Dim breakPt As DB.XYZ = pt0.Add(vector.Multiply(2.0))
            Dim newDuctId As DB.ElementId = DB.Mechanical.MechanicalUtils.BreakCurve(doc, duct.Id, breakPt)
            transaction.Commit()
            ' change our result to successful
            Execute = UI.Result.Succeeded
        End Using
        Return Execute
    End Function
End Class

Cheers,

-Matt
_______________________________________________________________________________
Marking a post as a 'solution' helps the community. Giving a post 'Kudos' is as good as saying thanks. Why not do both?
Message 5 of 18

Thank you so much Matthew.

It worked pleasantly.  Smiley Happy

 

It will be great favor if you can help me in achieving my requirement.

Normally, if we split an duct from UI itself, then it adds an family instance i.e. duct between the two separated elements. 

But by using the BreakCurve method it breaks the element into two parts at specified length which is really good, But I also need a specific family instance i.e. duct to be added between the two elements, just like we do from UI in Revit application.

splittingDuct.jpg

 

 

Thanks

Saurabh

 

 

Message 6 of 18

Hi @saurav_dhir,

You're welcome.

 

Well, you probably need to break the duct in two places.

You have the elementIds of the two ducts after one break, you just need to use one of those in your second break.

The second break would have to be enclosed in a second transaction.

Once you have the 3rd elementId, you can get its duct element and use duct.ChangeTypeId to change the type should you desire it.

 


Cheers,

-Matt
_______________________________________________________________________________
Marking a post as a 'solution' helps the community. Giving a post 'Kudos' is as good as saying thanks. Why not do both?
Message 7 of 18

Hi Matthew,

 

I am doubtful if you are understanding my requirement or not..

 

The screenshot which i sent in the previous reply was what i need to achieve as final output. that was done manually from Revit Application.

 

and, below is what the BreakCurve method does:AfterUsingBreakCurve.jpg

 

 

Can I add a duct between the two child elements, which will act as a separation point?

 

Thanks

Saurabh Dhir

Message 8 of 18

@saurav_dhir,

You have not enlightened me.

Perhaps a before and after shot (in 3D?) would be beneficial.


Cheers,

-Matt
_______________________________________________________________________________
Marking a post as a 'solution' helps the community. Giving a post 'Kudos' is as good as saying thanks. Why not do both?
Message 9 of 18

Hi Matthew,

 

Sorry for the confusion. I am not good at explaining. But still trying Smiley Happy

 

Below are some screenshots for before and after case when splinting an element via application and via api, both:

 

BEFORE:

 

BeforeFromUI.jpg 

 

 

AFTER

 

1. WHEN SPLITTING MANUALLY VIA APPLICATION UI:

 

a. Here you can see 3 elements. two are child elements that was created after splitting the parent element and 3rd one is the duct which act as a separation point between those two.

AfterUsingSplitFromUI.jpg

 

b. Here you can see the duct which was added when split occurred:

ManualSplit.jpg

 

 

 

2. WHEN SPLITTING USING API (Via BreakCurve() method):

 

AfterUsingBreakCurve (2).jpg

So, here i need a duct to be added between those two elements, just like i did using the split button from application.

 

I hope I am going in the right direction to explain my requirement.

 

 

 

Thanks

Saurabh Dhir

 

 

 

 

Message 10 of 18

Hi @saurav_dhir,

Riiiiiiiight. You need to add a union fitting. That's not a duct; it's a duct fitting, and a familyInstance.

All else fails, describe the elements using the Revit descriptions, or the RevitLookup (API) names. That way it's obvious. 🙂

 

I originally used two transactions, but it appears a regen will do the trick:

<Transaction(TransactionMode.Manual)> _
<Regeneration(RegenerationOption.Manual)> _
<Journaling(JournalingMode.UsingCommandData)> _
Public Class TransactionCommand
    Implements UI.IExternalCommand
    Public Function Execute(ByVal commandData As UI.ExternalCommandData, ByRef message As String, ByVal elements As DB.ElementSet) As UI.Result Implements UI.IExternalCommand.Execute
        Dim app As ApplicationServices.Application = commandData.Application.Application
        Dim doc As DB.Document = commandData.Application.ActiveUIDocument.Document
        Dim docUi As UI.UIDocument = commandData.Application.ActiveUIDocument

        Execute = UI.Result.Failed
        Dim newDuctId As DB.ElementId = Nothing
        Dim ductOrig As DB.Mechanical.Duct = Nothing
        Dim duct2 As DB.Mechanical.Duct = Nothing
        Dim breakPt As DB.XYZ = Nothing
        Using transaction As New DB.Transaction(doc, "Break Duct + Add Fitting")
            transaction.Start()
            ductOrig = TryCast(doc.GetElement(New DB.ElementId(1789660)), DB.Mechanical.Duct)
            Dim curve As DB.Curve = TryCast(ductOrig.Location, DB.LocationCurve).Curve
            Dim pt0 As DB.XYZ = curve.GetEndPoint(0)
            Dim pt1 As DB.XYZ = curve.GetEndPoint(1)
            Dim vector As DB.XYZ = pt1.Subtract(pt0).Normalize
            breakPt = pt0.Add(vector.Multiply(2.0))
            newDuctId = DB.Mechanical.MechanicalUtils.BreakCurve(doc, ductOrig.Id, breakPt)
            duct2 = TryCast(doc.GetElement(newDuctId), DB.Mechanical.Duct)
            doc.Regenerate()
            Dim connectorOrig As DB.Connector = ductOrig.ConnectorManager.Lookup(0)
            Dim connector1 As DB.Connector = duct2.ConnectorManager.Lookup(1)
            Dim familySymbol As DB.FamilySymbol = TryCast(doc.GetElement(New DB.ElementId(755396)), DB.FamilySymbol)
            Dim famInstance As DB.FamilyInstance = doc.Create.NewFamilyInstance(breakPt, familySymbol, DB.Structure.StructuralType.NonStructural)
            Dim fitting As DB.MEPModel = famInstance.MEPModel
            Dim fittingConnector0 As DB.Connector = fitting.ConnectorManager.Lookup(0)
            Dim fittingConnector1 As DB.Connector = fitting.ConnectorManager.Lookup(1)

            connectorOrig.ConnectTo(fittingConnector1)
            connector1.ConnectTo(fittingConnector0)
            transaction.Commit()
            ' change our result to successful
            Return UI.Result.Succeeded
        End Using
        Return Execute
    End Function
End Class

Cheers,

-Matt
_______________________________________________________________________________
Marking a post as a 'solution' helps the community. Giving a post 'Kudos' is as good as saying thanks. Why not do both?
Message 11 of 18

Hi Matthew,

 

Thanks for your assistance. Smiley Happy 

It works great.

 

Yet, I have another issue. This method only works well if we are not modifying the element's orientation. 

I tested this on a duct. I first added a duct and implemented the method just after placing an instance of that duct and it worked great.

But, If I rotate the element to its opposite direction and then implementing that methods throws multiple errors. 

Do you have any idea how to resolve these.

 

Instructions to reproduce the issue:

Step-1-AddedDuct.jpgStep-2-RotateDuct.jpgSplitError.jpg

 

 

 

Thanks

Saurabh Dhir

Message 12 of 18

Hi @saurav_dhir,

The familyinstance needs rotating in the same orientation as the duct curve.

I'm sure there are plenty of examples of how to rotate family instances on this forum. Report back with how you get on!


Cheers,

-Matt
_______________________________________________________________________________
Marking a post as a 'solution' helps the community. Giving a post 'Kudos' is as good as saying thanks. Why not do both?
Message 13 of 18

Hi Matthew,

 

I searched but haven't got much on how to adjust(rotate) the duct fitting as per element's direction/shape. I just tried the rotate method that just rotates the new instance(duct fitting) to 180 degree angle. So this case only works if i have rotated the element to 180 degree angle (opposite direction). But not in other cases.

 

Can you please assist?

 

splitissue.jpg

 

Thanks

Saurabh Dhir

Message 14 of 18

Hi @saurav_dhir,

Did you get this sorted out yet?

@aksaks has an example of this in his repo:

https://github.com/akseidel/WTA_FireP/blob/feb6cff675a2143fffb55e65dd95eb9a73b9c553/WTA_FireP/PlunkO...


Cheers,

-Matt
_______________________________________________________________________________
Marking a post as a 'solution' helps the community. Giving a post 'Kudos' is as good as saying thanks. Why not do both?
Message 15 of 18

Hi Matthew,

 

I checked the link.

There are lots of methods.

Not sure which one to choose.I tried implementing few of them but there are many undefined/unknown classes.

 

Can you please show me a precise way to get the resolution ?

 

Thanks

Saurabh Dhir

Message 16 of 18
FAIR59
in reply to: saurav_dhir

no need for the rotation , you can place the duct fitting with the right direction.

 

Dim famInstance As DB.FamilyInstance = doc.Create.NewFamilyInstance(breakPt, familySymbol, vector, null,  DB.Structure.StructuralType.NonStructural)
  

Ofcourse it can't hurt to learn how to rotate an element.         

Message 17 of 18
saurav_dhir
in reply to: FAIR59

Thank you so much,

 

It worked pleasantly Smiley Happy

 

Thanks

Saurabh Dhir

Message 18 of 18
jeremytammik
in reply to: saurav_dhir

@FAIR59 @matthew_taylor Thank you very much for this brilliant, very patient and comprehensive tutorial, and for pointing it out again in the recent comment on The Building Coder. Preserved for posterity and better readability now in the blog:

 

https://thebuildingcoder.typepad.com/blog/2020/03/splitting-a-duct-in-more-depth.html

 



Jeremy Tammik
Developer Technical Services
Autodesk Developer Network, ADN Open
The Building Coder

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Autodesk DevCon in Munich May 28-29th


Rail Community