Making Better Flex with API

Making Better Flex with API

mhillis
Advocate Advocate
2,220 Views
5 Replies
Message 1 of 6

Making Better Flex with API

mhillis
Advocate
Advocate

Hello everyone,

 

This is a pretty basic matter probably, but I wanted some outside perspective on making this work better.  I've currently got an add-in that inserts a bunch of duct and duct fittings.  My flex always seems to come out a little wonky.  It seems to work, but it needs serious improvment.  I was wondering if someone can help me understand what I'm doing wrong/missing with these.

 

Below is a snapshot of the resulting flex and code.  It's pretty basic.  I just get the points I need for the flex connections and then build out my FlexDuct object.  Once I've done that, I will look at the drawing and see if there is any connectors that reside on the flex connector locations, if not, I will make a temporary connector.  However, the issue I have is even when my flex finds a currently existing connector and connects to it, it comes in at weird angles.

 

Thanks!

 

public static void InsertFlex(Document doc)
{
            //Get Level for Flex.
            FilteredElementCollector floorColl = new FilteredElementCollector(doc);
            floorColl.OfClass(typeof(Level));
            ElementId lvl = floorColl.FirstElementId();

             //Get the Flex Type
            FilteredElementCollector flexType = new FilteredElementCollector(doc);
            collector.OfClass(typeof(FlexDuctType));
            ElementId flexType = null;

            foreach (Element e in collector)
                {
                    if (e.Name == "Flex - Round")
                    {
                        flexType = e.Id;
                    }
                }

            //Get System
            FilteredElementCollector sysColl =
            new FilteredElementCollector(doc);
            sysColl.OfClass(typeof(MechanicalSystemType));
            ElementId sysId = sysColl.FirstElementId();

            XYZ point1 = flexConn1Location // This will just be the location of FlexConn1, usually off of a tap.
            XYZ point2 = flexConn2Location // This will be the location for FlexConn2, usually to a grille/diffuser.

            List<XYZ> pnts = new List<XYZ>();

            pnts.Add(point1);
            pnts.Add(point2);

            FlexDuct flex = FlexDuct.Create(doc, sysId, flexType, lvl, pnts);

            Connector conn1 = GetConnectorAtPoint(point1); // This is a routine that will get a connector at flex loc 1.

            If (conn1 == null)
            {conn1 = CreateTemporaryConnector();}  // If we don't have a connector, I just create a temporary object that the flex can connect to)

            Connector conn2 = GetConnectorAtPoint(point2);

            If (conn2 == null)
            {conn2 = CreateTemporaryConnector()};

            //Connect the Flex to it's object.
            if ((conn1 != null) && (conn2 != null))
            {
                foreach (Connector c in flex.ConnectorManager.Connectors)
                {
                    if (c.Origin.IsAlmostEqualTo(conn1.Origin))
                    {
                        c.ConnectTo(conn1);
                    }
                    else if (c.Origin.IsAlmostEqualTo(conn2.Origin))
                    {
                        c.ConnectTo(conn2);
                    }
                }
            }

            doc.Regenerate();

            //Delete the temporary objects if needed.
}
0 Likes
2,221 Views
5 Replies
Replies (5)
Message 2 of 6

jeremytammik
Autodesk
Autodesk

Dear Mhillis,

 

Thank you for your query.

 

How do you specify the flex duct curve through the user interface?

 

Don't you need to specify more points somewhere, or a spline curve, or something to define where it should go?

 

I only see you specifying the start and end point above.

 

Furthermore, the temporary connector direction may be important for specifying the flex duct curve tangent at its start and end points.

 

Not being an expert, I do not really see what the problem is in the image you provide.

 

Maybe it would be clearer if you created one perfect flex duct manually, and an imperfect programmatically generated sample right next to it, so the difference becomes clearer.

 

Have you looked in detail at the flex duct curve of a perfect manually created specimen?

 

Can you reproduce the exact same properties programmatically?

 

I hope this helps.

 

Best regards,

 

Jeremy



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

0 Likes
Message 3 of 6

mhillis
Advocate
Advocate

Jeremy,

 

In my first post, the flex was horizontal to the duct it was actually suppose to connect to.

 

Fortunately!  I've been messing with this some more, thanks to your post here - http://thebuildingcoder.typepad.com/blog/2010/08/flex-duct-start-tangent.html - I got a better understanding of things. In fact, I've got my flex drawing routines working for the most part!  I've got one last stumbling block tripping me up.

 

In the attached screenshot, you'll see I've got some duct plenums with taps on the top.  Flex connects the taps together.  Now the flex actually 'comes in' correctly, it's all connected together.   However, it's not actually visible in some circumstances similar to this.  It isn't until I move the plenum away that all of the flex becomes visible.  Again, see the attached screenshot where I detail that whole thing.

 

I believe I understand *why* this is happening.  I believe it's because I'm not defining a mid point and, as a result, the flex comes in with a curve that's too tight to render correctly. (I hope that makes sense). It almost looks like the fellow you were talking to in the link I posted was defining a midpoint to alleviate that, but some info from his code is missing so I can't quite confirm.

 

Does that sound correct to you?  If so, I know then I need to begin defining a mid point that will loosen the curve needed for the flex to render. Smiley Happy

 

Thanks!

 

public static void InsertFlex()
{
    Autodesk.Revit.Creation.Document crDoc
        = doc.Create;

    XYZ conn1Location;
    XYZ conn2Location;
    double flexDiameter;

    //Get the Flex Type
    FilteredElementCollector collector = new FilteredElementCollector(doc);
    collector.OfClass(typeof(FlexDuctType));
    FlexDuctType flexTypeId = null;


    foreach (Element e in collector)
    {
        if (e.Name == "Flex - Round")
        {
            flexTypeId = e as FlexDuctType;
        }
    }

    Connector conn1 =
        Util_Revit.GetConnectorAtPoint(conn1Location);

    Connector conn2 =
        Util_Revit.GetConnectorAtPoint(conn2Location);

    List<XYZ> pnts =
        new List<XYZ>();

    pnts.Add(conn1Location);
    pnts.Add(conn2Location);

    FlexDuct flex = crDoc.NewFlexDuct(pnts, flexTypeId);

    //Set the diameter of flex.
    ParameterSet ps = flex.Parameters;
    foreach (Parameter p in ps)
    {
        if (p.Definition.Name == "Diameter")
        {
            p.Set(flexDiameter);
        }
    }

    flex.StartTangent = conn1.CoordinateSystem.BasisZ; //Set Tangent to Conn Direction.
    flex.EndTangent = conn2.CoordinateSystem.BasisZ.Negate(); //Set Tangent to Conn Direction.
}
0 Likes
Message 4 of 6

jeremytammik
Autodesk
Autodesk

Dear Mhillis,

 

Thank you for your update and congratulations on your progress.

 

Yes, I think your assumption and suggestion for proceeding forward makes perfect sense.

 

As I already asked in my first answer, though:

 

Have you looked at the manually generated flex pipes and analysed their geometry, especially what drives their geometry?

 

They are curve based, aren't they?

 

In that case, you can presumably specify a curve when creating them, or modify their curve after creation.

 

That would give you a possibility to specify the midpoint you mention, and much more besides, giving you total control over their exact routing.

 

I am not sure midpoint is the right word to use.

 

That would be useful for simple arcs.

 

Are the flex duct curves arcs, or possibly splines, or what?

 

I hope this helps.

 

Good luck and best regards,

 

Jeremy



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

0 Likes
Message 5 of 6

Anonymous
Not applicable

My guess touches on what is mentioned, the flex needs to follow a curve that is can actually follow ( and be renderable also), which is one where its surface does not intersect itself when it tries to bend a radius that is tighter than the flex diameter. One would see that happening in the manual placement method. The routing code needs to provide enough points so that the flex does not "over bend". It is interesting that you are testing an unusually unlikely routing situation if this were HVAC, but one that does reveal the problem. Where in any real situation would someone tap off the top of a supply duct to presumably an air device that is also tapped on its top? Maybe it is a return situation but a top tapped duct seems like one rare bird. If this were a typical air supply/return situation above a ceiling the duct would be side tapped and the air device boot would also be likely side tapped. The code routing problem might never show up. I don't know off hand what type of curve Revit requires for flex nor if you intend to let Revit perform some of the solution but this may be one very sticky thing to figure out a general solution for. The flex has to start at each connector. The next point away from each connector has to be along the connector's normal axis, at some distance related to the flex diameter, but all the other points in between those points get hairy. The flex cannot over bend and it must also follow a path that consumes all of its total length, if one is provided. It is an interesting problem. Keep posting. Thanks.

0 Likes
Message 6 of 6

mikukzaz55
Contributor
Contributor

Hi mhillis..

Can you share me this method "GetConnectorAtPoint" ?

Thanks a lot! 

0 Likes