NewFamilyInstance - project base point instead of internal origin

NewFamilyInstance - project base point instead of internal origin

thom-g
Advocate Advocate
724 Views
3 Replies
Message 1 of 4

NewFamilyInstance - project base point instead of internal origin

thom-g
Advocate
Advocate

We create family instances in Revit using coordinates from an Excel file.
The values of these coordinates are relative to the project base point.
The project base point in Revit is not at 0,0,0 and has an angle.

 

Unfortunately, when we create the family instances using Revit API, they are always placed relative to Revit's internal origin, which is wrong.
How can we use the Revit API to create new family instances relative to the project base point instead of the internal origin?
I'm sure I'm missing something, and using trigonometric functions can't be the solution in my opinion.

 

This is the relevant part of the code:

// get the Revit app and the active document
UIApplication uiApplication = commandData.Application;
UIDocument uiDocument = uiApplication.ActiveUIDocument;
Document doc = uiDocument.Document;

// get the level
FilteredElementCollector levels = new FilteredElementCollector(doc).WhereElementIsNotElementType().OfCategory(BuiltInCategory.INVALID).OfClass(typeof(Level));
Level projectBasePointLevel = levels.FirstElement() as Level;

// convert the Excel coordinates from metric to internal Revit units
double pointX = UnitUtils.ConvertToInternalUnits(excelPointX, UnitTypeId.Meters);
double pointY = UnitUtils.ConvertToInternalUnits(excelPointY, UnitTypeId.Meters);
double pointZ = UnitUtils.ConvertToInternalUnits(excelPointZ, UnitTypeId.Meters);

// create Revit coordinates for the family instance location
XYZ instanceLocation = new XYZ(pointX, pointY, pointZ);

using (Transaction transaction = new Transaction(doc, transactionName))
{
    _ = transaction.Start(transactionName);

    // get the family symbol
    FamilySymbol familySymbol = doc.GetElement(familyId) as FamilySymbol;
    if (!familySymbol.IsActive)
    {
        familySymbol.Activate();
    }

    // create a new family instance
    familyInstance = doc.Create.NewFamilyInstance(instanceLocation, familySymbol, projectBasePointLevel, Autodesk.Revit.DB.Structure.StructuralType.UnknownFraming);
}

 

Accepted solutions (3)
725 Views
3 Replies
Replies (3)
Message 2 of 4

jeremy_tammik
Alumni
Alumni
Accepted solution

Afaik, the Revit database only knows one single coordinate system. That is what is used to place family instances and for every single other geometric operation as well. I suppose that is what you refer to as Revit's internal origin.

  

Coordinates given in any and all other coordinate systems will have to be transformed into the Revit database  coordinate system.

  

So, the most useful path forward for the situation you describe will be to research how to transform from the coordinate system you are using in your Excel data into the Revit database coordinate system.

   

Searching the Internet for "revit api transform project base coordinates" yields a solution right here in the forum:

   

  

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

rhanzlick
Advocate
Advocate
Accepted solution

Have you tried skipping lines 10-13, and just instantiating your placementPoint as:
new XYZ(excelPointX,excelPointY,excelPointZ)?

 

If so, you can try to use the document's Transform.OfPoint() to make additional conversions, but I'm not sure thats applicable here. If you are referring to the translation of the Family coordinate system to the document coordinate system, you can try FamilyInstance.GetTotalTransform.Inverse.OfPoint(). Let us know how this works out.

Message 4 of 4

thom-g
Advocate
Advocate
Accepted solution

@jeremy_tammik  & @rhanzlick : thank you both for your help.

Now it works correctly.

All I had to do was to replace this line

// create Revit coordinates for the family instance location
XYZ instanceLocation = new XYZ(pointX, pointY, pointZ);

with these lines

// create a Revit point with the Excel coordinates
XYZ excelLocation = new XYZ(pointX, pointY, pointZ);

// get the transform information of the project base point
Transform projectBasePointTransform = doc.ActiveProjectLocation.GetTransform();

// apply the project base point transform to the Excel point to get the absolute family instance location
XYZ instanceLocation = projectBasePointTransform.OfPoint(excelLocation);