Announcements
Attention for Customers without Multi-Factor Authentication or Single Sign-On - OTP Verification rolls out April 2025. Read all about it here.

Unable to set Family Symbol Orientation with NewFamilyInstance in Revit2024

davidcalvermace
Contributor

Unable to set Family Symbol Orientation with NewFamilyInstance in Revit2024

davidcalvermace
Contributor
Contributor

I am trying to use the API to add a family symbol to a room as a proof of concept (in this case, a wall hosted commercial toilet). My code calls 

 

new_instance = doc.Create.NewFamilyInstance(new_location, symbol, -wall_direction, wall, Structure.StructuralType.NonStructural)

 

where new_location is where on the wall I want to place, symbol is the commercial toilet symbol, wall_direction is the orientation of the wall (I've tried to make it negative or positive to swap the orientation but it hasn't been working), and wall is the hosted element.

 

I am using this link for reference: https://help.autodesk.com/view/RVT/2024/ENU/?guid=Revit_API_Revit_API_Developers_Guide_Revit_Geometr... with "XYZ, FamilySymbol, XYZ, Element, StructuralType" parameters. Thanks in advance!

 

However no matter what parameters I use (I can make location's Y coordinate negative or the wall_direction also negative) the toilet is always upright. What is the best way to flip the orientation of the symbol (similar to clicking the flip arrows on the symbol)?

davidcalvermace_0-1704306844090.png

 

0 Likes
Reply
Accepted solutions (1)
676 Views
15 Replies
Replies (15)

sragan
Collaborator
Collaborator

I just posted the exact same response to another question on this forum.  I think you need to use a different overload for hosted families.   I believe the one you are using works best for non-hosted families that are just placed at an XYZ point.

 

Try looking at this;

 

The Building Coder: Hosting a Light Fitting on a Reference Plane (typepad.com)

 

0 Likes

davidcalvermace
Contributor
Contributor

Hey, thanks for the response! From the documentation, I was trying to use this overload where the first XYZ is the location, the second XYZ is the orientation, and the element is the wall element I'm attaching to. I can give attaching to a face a shot.

davidcalvermace_0-1704500895342.png

 

0 Likes

davidcalvermace
Contributor
Contributor

Just tried and to no avail still.

 

I wrote the following code

# Function to find the top and bottom face of the wall
def get_top_and_bottom_faces_2d(wall):
    options = DB.Options()
    geometryElement = wall.get_Geometry(options)
    top_face = None
    bottom_face = None

    for geometryObject in geometryElement:
        if isinstance(geometryObject, DB.Solid):
            for face in geometryObject.Faces:
                normal = face.FaceNormal
                if normal.IsAlmostEqualTo(
                    DB.XYZ(0, 1, 0)
                ๐Ÿ˜ž  # "Top" face in 2D (Y direction)
                    top_face = face
                elif normal.IsAlmostEqualTo(
                    DB.XYZ(0, -1, 0)
                ๐Ÿ˜ž  # "Bottom" face in 2D (Y direction)
                    bottom_face = face

    return top_face, bottom_face

top_point = get_middle_point(top_face)
ref = top_face.Reference
doc.Create.NewFamilyInstance(ref, top_point, DB.XYZ(0, 1, 0), symbol)

to try to attach it to a specific face (top or bottom face) of my wall but I think ref=top_face.Reference ends up being None for some reason for my wall, and the call to NewFamilyInstance fails.

 

With some debugging and experimentation we have figured out how Revit chooses the orientation to mount the symbol to in the NewFamilyInstance (XYZ, FamilySymbol, XYZ, Element, Structural) overload based on if you draw the original host element from left to right or right to left (someone feel free to correct me if this is wrong, we spent a couple of hours drawing different types of walls and this is the conclusion that we came up with).

 

For example, the red toilet is when the wall is drawn right to left and the black one is from left to right when using the NewFamilyInstance (XYZ, FamilySymbol, XYZ, Element, Structural) overload. Thus, even when changing the XYZ location (first parameter) or orientation (3rd parameter) does not change which side the symbol is mounted on the wall.

davidcalvermace_0-1704692617654.png

 


@jeremy_tammik I noticed you wrote the original article that was linked here - would appreciate any help here if you have any insights! I've tried my best to include as many details as possible but please let me know if there is information that I should provide in my query.

0 Likes

jeremy_tammik
Autodesk
Autodesk

When you say, I think ref=top_face.Reference ends up being None, I respond:

  

You need to be sure. Without being sure, very hard to progress. Use a debugger, or add some logging code.

  

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

davidcalvermace
Contributor
Contributor

davidcalvermace_0-1704719976006.png

Was able to confirm this with a logging statement in the IronPython interpreter - top_face and bottom_face grabbed by using the following snippet:

 

def get_top_and_bottom_faces_2d(wall):
    options = DB.Options()
    geometryElement = wall.get_Geometry(options)
    top_face = None
    bottom_face = None

    for geometryObject in geometryElement:
        if isinstance(geometryObject, DB.Solid):
            for face in geometryObject.Faces:
                normal = face.FaceNormal
                if normal.IsAlmostEqualTo(
                    DB.XYZ(0, 1, 0)
                ๐Ÿ˜ž  # "Top" face in 2D (Y direction)
                    top_face = face
                elif normal.IsAlmostEqualTo(
                    DB.XYZ(0, -1, 0)
                ๐Ÿ˜ž  # "Bottom" face in 2D (Y direction)
                    bottom_face = face

    return top_face, bottom_face

 

Reading the documentation on .Reference here, perhaps PlanarFace class does not allow a Reference to be made?

 

In general, is the overload I'm attempting to use correct for trying to create a hosted NewFamilyInstance on a specific side of a wall? One other option I saw online could be to create it on whichever default side first and then try to flip / mirror it across the wall but it feels like there could be an easier way with just NewFamilyInstance.

 

Thank you for the help!

0 Likes

jeremy_tammik
Autodesk
Autodesk

Populating the references when querying element geometry is a costly operation and very often not needed. Therefore, it is turned off by default. To turn it on and retrieve references, please set the ComputeReferences property:

  

  

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

davidcalvermace
Contributor
Contributor

Thank you for the tip! ComputeReference Option worked great - was able to get the reference. However, was running into a very interesting issue that might be a difference between the NewFamilyInstance call in RevitPythonShell and the documentation.

 

davidcalvermace_0-1704735900463.png

 

It looks like the overload on the API documentation might not support Face / Reference as an input parameter

 

davidcalvermace_1-1704735945261.png

 

If this is the case, do you have any recommendations for getting unblocked on RevitPythonShell / other API functions to look into to create the family symbol instance and control which side of the wall the symbol shows up on? Appreciate your help here a lot - haven't been able to crack this one for a while

 

EDIT: Figured this overload out: need to specify it manually as per this post.

Getting this error now - seems like something I should debug with the symbol, but really not sure anymore what the most optimal way to place the family symbol on the host is if face/reference does not work either ๐Ÿ˜ž

davidcalvermace_0-1704737162928.png

 

0 Likes

davidcalvermace
Contributor
Contributor

Oh wow, is the solution from older post really the best way to do it? (place and mirror)

0 Likes

sragan
Collaborator
Collaborator

@davidcalvermace wrote:

 

With some debugging and experimentation we have figured out how Revit chooses the orientation to mount the symbol to in the NewFamilyInstance (XYZ, FamilySymbol, XYZ, Element, Structural) overload based on if you draw the original host element from left to right or right to left (someone feel free to correct me if this is wrong, we spent a couple of hours drawing different types of walls and this is the conclusion that we came up with).

 


Yes, somewhere it is stated that that is how ceilings and workplanes work, with the direction you draw them.  So you are probably right about that.

 

But I am confused.  Your code is looking for the top and bottom of the wall?  Don't you want to look for the front and back sides of the wall?  Isn't that the side of the wall the toilet would be hosted to?

 

I would be suprised if you have to mirror and rotate to get something on the other side of the wall.  That doesn't seem right.  

 

Here is a suggestion if you don't mind:  Manually place a family where you want it.   Then edit your code to get all the data from that family (the hostface, insertion point, rotation, etc.)   Then use all that data to try and insert another family (all within your code).   See if it goes on the right side of the wall.   I hope it does.  Then you will know that what you want is possible, and it should be just a matter of inspecting the data you are getting to find out what you need to do to get it to insert correctly.

 

 

0 Likes

sragan
Collaborator
Collaborator

Now I get what you mean by "top face" and "bottom face".  You are referring to the sides of the wall when looking at a plan view.  I thought you meant you were actually getting the top and bottom sides of the wall (ie. the part that goes along the floor and the part that runs along the ceiling.)

 

One more question for you:  what is your family like?  Can you upload it?  Is it actually hosted to the wall, or is it hosted to the floor and just aligned to the wall?   I guess i should have asked that to start with.

 

Our default toilet fixtures hosts to the floor, and just aligns with the wall.   

0 Likes

davidcalvermace
Contributor
Contributor

Hi @sragan - thanks for the reply! Sorry for the confusion - indeed referring to the the top and bottom faces in the floor plan view. I've attached the symbol - its the basic 3d toilet that comes with the content pack. I'm pretty sure its hosted against the wall, but I could be wrong.

0 Likes

davidcalvermace
Contributor
Contributor

Here is a suggestion if you don't mind:  Manually place a family where you want it.   Then edit your code to get all the data from that family (the hostface, insertion point, rotation, etc.)   Then use all that data to try and insert another family (all within your code).   See if it goes on the right side of the wall.   I hope it does.  Then you will know that what you want is possible, and it should be just a matter of inspecting the data you are getting to find out what you need to do to get it to insert correctly.

This was great advice! We actually tried this and it unfortunately didn't work because we found the only thing that mattered in determining which side of the wall the fixture appeared on was how the wall was originally drawn (e.g. drawing the wall left to right guaranteed the toilet appeared on top while right to left guaranteed it appeared facing down regardless of what input parameters we used).  To do this, we printed the position data and orientation of the manually placed object and tried to map this to our NewFamilyInstance overload as close as possible. This is why I think the only way to do it might be to flip (unless @jeremy_tammik has any NewFamilyInstance magic we can try to get it in a single step ๐Ÿ˜€)

0 Likes

davidcalvermace
Contributor
Contributor
Accepted solution

Hope this isn't spamming an inbox but also from this post, I've also tried all the methods (they list out 5 methods and the errors they ran into for each one). I think this person and I have come to a similar conclusion where NewFamilyInstance does not work well for this - there may also be another API function that works better for this placement but I'm yet to find it in either the docs or online throughout the forums.

0 Likes

sragan
Collaborator
Collaborator

yes, its definitely a wall hosted fixture.   I also think you may have to use the flip facing. 

When placing fixtures like this in the UI, the mouse cursor location determines which side of the wall the fixture lands on.   

 

However, it's starting to sound like there isn't any way to do this with the API.

 

0 Likes

davidcalvermace
Contributor
Contributor

Yup! I think so too - will mark this as resolved for now

0 Likes