Reference plane absolute coordinates

Reference plane absolute coordinates

edgars_miskins
Advocate Advocate
2,798 Views
7 Replies
Message 1 of 8

Reference plane absolute coordinates

edgars_miskins
Advocate
Advocate

I'm looking for a way to translate between local coordinates of a given reference plane to absolute coordinates of the project.
Eg. I want to place bunch of families. I have absolute X and Y coordinates of where they need to go (from external source/ excel file). So I want to use horizontal reference planes to control the Z positions.
I figured out how to place families on a reference plane within it's coordinate system. But, like I said, I have absolute x and y coordinates for each family. Now I need to figure out how to compensate for the location of the reference plane itself. So I'm thinking either getting the location of the plane and subtracting it from my family positions or setting the reference plane x/y origins to project absolute x/y origins.
So I looked up Revit API.
Revit API documentation states, that a Reference plane location and orientation is defined by something called BubbleEnd, FreeEnd and Direction. What do these mean? Can someone please explain?
American English is not my native language, so I seem to be missing the "bubble" and "end" language references here.

0 Likes
Accepted solutions (1)
2,799 Views
7 Replies
Replies (7)
Message 2 of 8

TripleM-Dev.net
Advisor
Advisor

Hi,

 

See if this helps? ReferencePlane Class

The Bubble is the 2D representation end of the line of the 3D reference plane in a view (it has a Z-coordinate)

 

For the Z-coordinate of the ReferencePlane I would use the Plane property of the ReferencePlane: GetPlane Method 

And then use the origin property for the absolute Z-value.

Be sure to also check the normal vector, so it's a horizonal ReferencePlane.

 

Why do you need to compensate for the reference plane's coordinate system for X/Y?

Is NewFamilyInstance with a XYZ relative to the plane's origin and not absolute to Model origin? (Just curious as I only use levels)

 

- Michel

 

0 Likes
Message 3 of 8

edgars_miskins
Advocate
Advocate

OK. It seems, I have to look up general information on planes and their vectors. This is not clicking for me yet.


I tried using GetPlane() to get origins.X and origins.Y. and got some weird results, where a families with same XY placed on different Reference planes (after compensating for each planes XY) would result in different absolute XY. But maybe I did the compensation calculation wrong. Will try again.

Yes, NewFamilyInstance places the family within the coordinates of the reference plane, ie, relative to the plane's origin. Reference plane (or Workplane as it is called in GUI) can be moved around in Revit and all the elements placed on it move with it.

0 Likes
Message 4 of 8

RPTHOMAS108
Mentor
Mentor

Depends what .NewFamilyInstance overload you are using. Some will take the Z value from the XYZ you specify and automatically work out the offset from host plane based on that. Others such as those for curve based families ignore the Z value and you have to specify the host then change an offset from host parameter. 

 

Reference planes are not necessarily flat and often get deleted to leave the hosted element un-hosted. So in that sense there would be no benefit in using refplanes set to certain levels than a single base level. I tend to find the nearest level and use that as the host for point based families.

Message 5 of 8

edgars_miskins
Advocate
Advocate

I'm currently using this one. Or trying, at least.
I'd love if there was a placement method that takes absolute XY and places a family on a specified refPlane, regardless of plane's location, and works out the local XY relative to planes origin.

Yes. I was thinking about using levels, but there are some issues in my case.
In this particular case I wanted to use reference planes in order to place lighting fixtures. As to why not place the fixtures directly on the ceilings: architectural model is attached as a link (IFC) and is provided by another company as-is. It will change in the future and the fixtures will get un-hosted. More over the ceilings might even change, meaning I would have to do manual re-hosting. Also, most manufacturers provide fixtures as face-based, so it poses another problem when placing them on a level.
So I had the idea of placing them on a WorkPlane instead of ceilings, and then align the workplane to the ceiling. If ceilings move at some point, I would only need to move the refPlane and the fixtures will move with it.

 

0 Likes
Message 6 of 8

TripleM-Dev.net
Advisor
Advisor
Accepted solution

Try this, no need to convert any coordinates it places the Family at the given coordinates (absolute to Revit internal point). Also tested it on a ReferencePlane which plane.orgin <> 0,0,0

 

public class TestCommand_C05_FamilyOnRefplane : IExternalCommand
    { 
		public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
        {
            UIDocument uidoc = commandData.Application.ActiveUIDocument;
            Autodesk.Revit.DB.Document doc = uidoc.Document;

            //https://thebuildingcoder.typepad.com/blog/2012/02/hosting-a-light-fitting-on-a-reference-plane.html

            ElementId refplaneid = new ElementId(344885);
			ElementId famsymbolid = new ElementId(345660);
            //ElementId levelid = new ElementId(311);
             
            ReferencePlane elemrefplane = (ReferencePlane)doc.GetElement(refplaneid);
			FamilySymbol elemfamsymbol = (FamilySymbol)doc.GetElement(famsymbolid);
            //Level elemlevel = (Level)doc.GetElement(levelid); // maybe usefull to set the schedule level.

            // XYZ ReferenceDir = XYZ.BasisZ; // Family made "always vertical" // nope see artical above needs to be XYZ.Zero

            using (var t = new Transaction(doc, "Place Family on ReferencePlane"))
            {
                t.Start();

                XYZ inspt = new XYZ(10, 20, elemrefplane.GetPlane().Origin.Z);  
                FamilyInstance instance = doc.Create.NewFamilyInstance(elemrefplane.GetReference(), inspt, XYZ.Zero, elemfamsymbol);

               // System.Windows.Forms.MessageBox.Show(inspt.XYZ_stringMM());

                t.Commit();
            }

			return Result.Succeeded;
        }
    }

 

- Michel

0 Likes
Message 7 of 8

edgars_miskins
Advocate
Advocate

Wow. This worked! Thank you very much!
Still, I don't understand why, exactly. 😄
I guess, I don't understand how these coordinates exactly work.
Just to be clear, previously I had this:

 

 

FamilySymbol symbol = (FamilySymbol)LightingFixtures.FirstOrDefault(x => x.Name == Lum.FamilyName);
XYZ location = new XYZ(Lum.X, Lum.Y, 0);
XYZ refDir = new XYZ(0, 1, 0);

symbol.Activate();
FamilyInstance instance = doc.Create.NewFamilyInstance(WorkPlane.GetReference(), 
location, refDir, symbol);
instance.IsWorkPlaneFlipped = true;

 

 


Then as per your suggestion I changed the Z for location and changed the referenceDirection to XYZ.Zero. 
So now it looks like this:

 

 

FamilySymbol symbol = (FamilySymbol)LightingFixtures.FirstOrDefault(x => x.Name == Lum.FamilyName);
XYZ location = new XYZ(Lum.X, Lum.Y, WorkPlane.GetPlane().Origin.Z);
XYZ refDir = new XYZ(0, 1, 0);

symbol.Activate();
FamilyInstance instance = doc.Create.NewFamilyInstance(WorkPlane.GetReference(), 
location, XYZ.Zero, symbol);
instance.IsWorkPlaneFlipped = true;

 

 

 And it works! Families are now placed in the correct absolute XY coordinates regardless of Reference Plane's XY location.

0 Likes
Message 8 of 8

TripleM-Dev.net
Advisor
Advisor

Yes, no idea why the direction needs to be Zero. (XYZ.Zero = 0,0,0) maybe depends on family

It's clearly documented.

 

form NewFamilyInstance Method (Reference, XYZ, XYZ, FamilySymbol) 

"referenceDirection
Type: Autodesk.Revit.DB XYZ
A vector that defines the direction of the family instance. Note that this direction defines the rotation of the instance on the face, and thus cannot be parallel to the face normal."

 

So zero would make sense if the family is marked "Always vertical" .....no rotation..

 

line below isn't needed anymore

XYZ refDir = new XYZ(0, 1, 0); // this would be XYZ.basisY (vector)

 

0 Likes