apply transform from one FamilyInstance to the other, to restore its original or

apply transform from one FamilyInstance to the other, to restore its original or

Anonymous
Not applicable
2,097 Views
2 Replies
Message 1 of 3

apply transform from one FamilyInstance to the other, to restore its original or

Anonymous
Not applicable

Hello all,

 

I want my plugin to save the orientation/transformation of a duct fitting FamilyInstance (for example an Elbow) from source drawing to a database, mostly want to save duct fitting's rotation angles by X axis, Y axis and Z axis. The user can use Rotate (RO) command to rotate fitting by Z axis, or click on rotate icons on screen when fitting is selected.

 

I have tried the following two options,
1. get the Transform of the fitting FamilyInstance in source drawing. but cannot find how to get its matrix data in order to save it to database, cannot find how to recreate a Transform and apply to FamilyInstance either.

2. get the X, Y and Z rotation angles from the fitting FamilyInstance in source drawing, on a separate drawing I can insert the same fitting FamilySymbol and then perform rotate by X, by Y and by Z using the rotation angles retained from source drawing.

 

The option 2 seems more feasible to try. So I create the following plugin command. It works on some rotation/flipping cases and fails on some. The attached screen image shows the case that restored elbow is in the wrong orientation.

 

Could you tell me if I am working on this issue the wrong way? What is the correct way to handle this?

 

Thanks

 

===

To run this command, please do the following before starting the command,

1. drawing two duct fittings (for example two Elbow) with the same type.

2. Rotate and/or use small rotation icons on screen to flip the first duct fitting, 

3. make sure to select the first fitting instance and then select the second fitting instance.

 

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;

namespace MyTest.Commands
{
    [Transaction(TransactionMode.Manual)]
    [Regeneration(RegenerationOption.Manual)]
    class MyTestCommand : IExternalCommand
    {
        public Result Execute(ExternalCommandData cmdData, ref string msg, ElementSet elems)
        {
            UIDocument uiDocument = cmdData.Application.ActiveUIDocument;
            List<ElementId> selectedElementids = uiDocument.Selection.GetElementIds().ToList();
            ElementId elementId0 = selectedElementids[0];
            ElementId elementId1 = selectedElementids[1];

            Element element0 = uiDocument.Document.GetElement(elementId0);
            Transform transform = (element0 as FamilyInstance).GetTransform();

            XYZ axisX = transform.OfVector(transform.BasisX);
            XYZ axisY = transform.OfVector(transform.BasisY);
            XYZ axisZ = transform.OfVector(transform.BasisZ);

            // fix floating number
            axisX = new XYZ(Math.Round(axisX.X, 4), Math.Round(axisX.Y, 4), Math.Round(axisX.Z, 4));
            axisY = new XYZ(Math.Round(axisY.X, 4), Math.Round(axisY.Y, 4), Math.Round(axisY.Z, 4));
            axisZ = new XYZ(Math.Round(axisZ.X, 4), Math.Round(axisZ.Y, 4), Math.Round(axisZ.Z, 4));

            XYZ basisY = new XYZ(Math.Round(transform.BasisY.X, 4), Math.Round(transform.BasisY.Y, 4), Math.Round(transform.BasisY.Z, 4));
            XYZ basisX = new XYZ(Math.Round(transform.BasisX.X, 4), Math.Round(transform.BasisX.Y, 4), Math.Round(transform.BasisX.Z, 4));

            // rotate by x axis
            double rotXRadian = basisY.AngleOnPlaneTo(axisY, axisX);
            double rotXDegree = rotXRadian * (180 / Math.PI);

            // rotate by y axis
            double rotYRadian = basisX.AngleOnPlaneTo(axisX, axisY);
            double rotYDegree = rotYRadian * (180 / Math.PI);

            // rotate by z axis
            double rotZRadian = basisX.AngleOnPlaneTo(axisX, axisZ);
            double rotZDegree = rotZRadian * (180 / Math.PI);

            double rotRadian = ((element0 as FamilyInstance).Location as LocationPoint).Rotation;
            double rotDegree = rotRadian * (180 / Math.PI);

            using (Transaction transaction = new Transaction(uiDocument.Document))
            {
                transaction.Start("test");

                Element element1 = uiDocument.Document.GetElement(elementId1);
                XYZ point = (element1.Location as LocationPoint).Point;

                Line axisz = Line.CreateBound(point, new XYZ(point.X, point.Y, point.Z + 10));
                ElementTransformUtils.RotateElement(uiDocument.Document, element1.Id, axisz, rotZRadian);
                Line axisy = Line.CreateBound(point, new XYZ(point.X, point.Y + 10, point.Z));
                ElementTransformUtils.RotateElement(uiDocument.Document, element1.Id, axisy, rotYRadian);
                Line axisx = Line.CreateBound(point, new XYZ(point.X + 10, point.Y, point.Z));
                ElementTransformUtils.RotateElement(uiDocument.Document, element1.Id, axisx, rotXRadian);

                transaction.Commit();
            }

            return Result.Succeeded;
        }
    }
}

 

 

screen imagescreen image

0 Likes
2,098 Views
2 Replies
Replies (2)
Message 2 of 3

jeremytammik
Autodesk
Autodesk

Thank you for your query.

 

I cannot tell for sure off-hand whether your approach is optimal or not.

 

Revit supports several different approaches to efficiently place fittings and pipe- or ductwork.

 

One good way to get a clear idea of the different possibly approaches and functionality supporting them is to read through my series of research steps involved in implementing a rolling offset:

 

http://thebuildingcoder.typepad.com/blog/2014/01/final-rolling-offset-using-pipecreate.html

 

I hope this helps.

 

Cheers,

 

Jeremy

 



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

0 Likes
Message 3 of 3

stever66
Advisor
Advisor

I think you may just have something wrong with your code for all the math:  One misplaced X instead of a Y or something similar.

 

Take baby steps to find your problem.  


For example, place two identical fittings.  Run your program. They both stay the same.  Good.

 

Then just rotate one in the plan view.  Run your program.  "Error- Normal vector must be normal."


Still Good - because it is a clue that something isn't quite right.

0 Likes