Can't rotate element into this position

Can't rotate element into this position

dirk.neethling
Advocate Advocate
6,734 Views
31 Replies
Message 1 of 32

Can't rotate element into this position

dirk.neethling
Advocate
Advocate

I created a Family composed of many Sweep and Revolution elements. I chose the mechanical template as it allowed Rotation about all 3 axes. The Family represents a segmental lining ring for a pre-cast tunnel lining.

After instantiating the ring using the FamilySymbol, I need to rotate and translate the ring several times in order to correctly place it adjacent to the previous ring. In fact it needs to be rotated about all 3 axes, and then also aruond ist own central axis.

 

Following this post,

 

https://forums.autodesk.com/t5/revit-architecture-forum/rotate-error-quot-can-t-rotate-element-into-...

 

I unchecked "Always Vertical" and checked "Work plane based"

 

//Always vertical

famDoc.OwnerFamily.get_Parameter(BuiltInParameter.FAMILY_ALWAYS_VERTICAL).Set(0);

//Work plane based

famDoc.OwnerFamily.get_Parameter(BuiltInParameter.FAMILY_WORK_PLANE_BASED).Set(1);

 

But it does not resolve the error.

Could anyone please Point me to a solution?

 

dirk

0 Likes
Accepted solutions (1)
6,735 Views
31 Replies
Replies (31)
Message 2 of 32

jeremytammik
Autodesk
Autodesk

Dear Dirk,

 

I am anything but a content creation expert.

 

However, I can imagine that some people might solve this by adding parameters controlling rotation to the family definition itself.

 

For instance, you could add one to control rotation around the Z axis through the insertion point (0 to 360 degrees), and another to control the rotation "out of" the XY plane through the insertion point (0 to 90 degrees).

 

Would that not be simple to achieve, understand and control?

 

Might it possibly be a best practice?

 

Have you ensured that you are following best practices in your family definitions?

 

Please do, for your own good!

 

I hope this helps.

 

Cheers,

 

Jeremy



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

Message 3 of 32

dirk.neethling
Advocate
Advocate

Hallo Jeremy,

 

thanks for the Suggestion, I agree this would be the best solution, and in fact similar to an Adaptive Element.

Unfortunatley I tried doing this, but could not figure out how to for example add a Parameter Controlling Rotation about ist own axis.

Could you pls Point me to a post where this would be described?

dirk

0 Likes
Message 4 of 32

dirk.neethling
Advocate
Advocate

Hello Jeremy,

 

you wrote:

 

"For instance, you could add one to control rotation around the Z axis through the insertion point (0 to 360 degrees), "

 

could you please point me to a post where this implementation is explained in detail?

dirk

0 Likes
Message 5 of 32

Anonymous
Not applicable
Use Like This,

XYZ point1 = new XYZ(10, 20, 0);
XYZ point2 = new XYZ(10, 20, 30);
// The axis should be a bound line.
Line axis = document.Application.Create.NewLineBound(point1, point2);
ElementTransformUtils.RotateElement(document, element.Id, axis, Math.PI / 3.0)
Message 6 of 32

dirk.neethling
Advocate
Advocate

Thanks! I'll try this.

0 Likes
Message 7 of 32

dirk.neethling
Advocate
Advocate

THanks Manish ,

 

I am trying to translate and rotate a Tunnel Lining Ring into Position. By Default, when it is instantiated, it is lying down on the XY-plane.

experimental_sector_15.png

 

I changed my code to use a Bound line.

By Default the BuiltInParameter "Always vertical" is checked. When I run the Rotation on that Family Instance, the ring stays flat on the xy-plane, because the tunnel lining ring instance is "always vertical".

 

So I uncheck it in the code using:

 

doc.OwnerFamily.get_Parameter(BuiltInParameter.FAMILY_ALWAYS_VERTICAL).Set(0);

 

However, then when I try to turn the ring upright, I get this error:

 

"Elemente können nicht in diese Position gedreht werden."

 

== Elements cannot be turned into this Position.

 

I would have thought that unchecking "Always vertical" would cause the Element to rotate, so this is confusing.

 

dirk

0 Likes
Message 8 of 32

Anonymous
Not applicable
Hi Dirk,

I guess...

Always vertical or Horizontal is set for fix the orientation of instance while place. You getting error "Elements cannot be turned into this Position" it means while rotate constraint is violated you need to correct Position and orientation of instance.
Message 9 of 32

dirk.neethling
Advocate
Advocate

Hello Manish,

 

thanks for your reply. I am trying to turn the ring upwards in order to correct the orientation. That is when the error comes.

I don't understand why this error comes when the constraint is turned off:

 

doc.OwnerFamily.get_Parameter(BuiltInParameter.FAMILY_ALWAYS_VERTICAL).Set(0);

 

dirk

0 Likes
Message 10 of 32

jeremytammik
Autodesk
Autodesk

Wouldn't it be nice if your requirement included the tunnel ring always to remain vertical?

 

Then you could make use of the functionaqlity provided by Revit, and redesign your family to create the tunnel ring in the XZ plane instead of XY.

 

Unfortunately, I assume that you sometimes need the ring to be slanted as well.

 

But wouldn't it be nice and powerful to make full use of all the available built-in functionality provided by Revit?

 

Cheers,

 

Jeremy



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

Message 11 of 32

dirk.neethling
Advocate
Advocate

Hello Jeremy,

like you say, the ring needs to be rotated around all axes, including its own longitudinal axis (i.e. 4 rotations), since the axis of the tunnel is a 3D curve, and the lining is constructed by ratcheting the rings around their own longitudinal axis after they have been positioned.

In my case the Revit constraints are just a problem to be overcome. Designing it in the XY plane has the benefit of being able to control the conicity and the built in elements by checking the Family.

dirk

0 Likes
Message 12 of 32

jeremytammik
Autodesk
Autodesk

Dear Dirk,

 

1. Any rotation you desire around "all axes" can be achieved with just two rotations: first, one of 0 to 180 degrees around the X axis to raise or lower your instance out of the XY plane, followed by one of 0 to 360 degrees around the Z axis.

 

2. Check out quaternions:

 

https://en.wikipedia.org/wiki/Quaternion

 

They provide the most powerful and easy-to-use rotation functionality in 3D space.

 

That is why they are popular in game development.

 

They should be used everywhere.

 

Are CAD developers less competent than gamers?

 

Cheers,

 

Jeremy



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

Message 13 of 32

dirk.neethling
Advocate
Advocate

Hello Jeremy,

 

thanks, for the info, I am aware of Quaternions and have used them in the past. Yes they are powerful as a compact way of writing the Transformation Matrix. But they are not the reason why I am not making headway.

I have a Routine which implements the rotations, and it works successfully with a simple adaptive tunnel ring.

The Problem is that these Rotation mechanisms do not work with FamilyInstance of an ordinary Family, because there are constraints in Revit which hinter rotations of a FamilyInstance about all 3 axes. This is where I am currently stuck. When I try to rotate a FamilyInstance obtained from the template "Metric Generic Model.rft", the "Always vertical" constraint is checked. so when I try to rotate the ring with this constraint checked, it does not react.

When I uncheck the constraint using

 

doc.OwnerFamily.get_Parameter(BuiltInParameter.FAMILY_ALWAYS_VERTICAL).Set(0);

 

the Rotation fails with the message

 

"Elements cannot be turned into this Position"

 

I do not understand what this message means. I've looked at the ring with a CAD Operator. He managed to turn the ring in the Family Editor, but could not do so as a FamilyInstance in a project. It then says that the ring is locked. What does that mean?

 

The other Option would be to generate the ring as an Adaptive Family using the "Metric Generic Model Adaptive.rft" template. But that template does not allow constructs such as Revolution elements.

 

So either way I am stuck.

 

dirk

0 Likes
Message 14 of 32

jeremytammik
Autodesk
Autodesk

Dear Dirk,

 

The best and most effective way forward is for you to create a reproducible case in which you prove that the desired orientation can be achieved manually through the user interface, and that the corresponding API manipulation fails.

 

If you cannot achieve what you want in the UI, then it is normally not possible in the API either.

 

Please provide the following:

 

http://thebuildingcoder.typepad.com/blog/about-the-author.html#1b

 

Thank you!

 

Cheers,

 

Jeremy



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

Message 15 of 32

FAIR59
Advisor
Advisor

a generic model family has a (internal) XY workplane . Always Vertical doesn't apply to the whole family, but rather to the direction of the Z axis.

 

If always vertical the Z - axis == Z-axis of the project.

 

see http://help.autodesk.com/view/RVT/2016/ENU/?guid=GUID-70F24230-D596-4AA3-A425-91B1E560BC53

 

 

When dealing with generic models, I find it most easy to place an instance on its own special created reference plane and rotate that plane.

(workplane based - checked, and always vertical - not checked)

Message 16 of 32

dirk.neethling
Advocate
Advocate

Thanks FAIR59,

I've read about this type of solution elsewhere. I think it may work.

How to implement?

 

I've defined the following plane which lies in the Center of the ring:

 

XYZ bubbleEnd = new XYZ(10, 0, 0);

XYZ freeEnd = new XYZ(-10, 0, 0);

XYZ cutVec = new XYZ(0, 0, 1);

doc.FamilyCreate.NewReferencePlane(bubbleEnd, freeEnd, cutVec, doc.ActiveView);

 

In the Family document I can see the plane, but how do I get a handle on this plane in the FamilyInstance in order to be able to rotate the FamilyInstance?

And why do I Keep getting the error message "Elements cannot be turned into this Position" when I set

 

(workplane based - checked, and always vertical - not checked), i.e.

 

doc.OwnerFamily.get_Parameter(BuiltInParameter.FAMILY_ALWAYS_VERTICAL).Set(0);

doc.OwnerFamily.get_Parameter(BuiltInParameter.FAMILY_WORK_PLANE_BASED).Set(1);

 

dirk

 

referenzebene.png

 

0 Likes
Message 17 of 32

dirk.neethling
Advocate
Advocate

Hello FAIR59,

Could this be the solution?

 

1. I define a Referenceplane in the Family

2. I set (workplane based - checked, and always vertical - not checked)

3. In the project, I rotate/translate a plane instance into the desired final Location/Orientation along the tunnel axis for the ring

4. I instantiate a FamilyInstance on that transformed plane using the following overload,

public FamilyInstance NewFamilyInstance(
	Reference reference,
	XYZ location,
	XYZ referenceDirection,
	FamilySymbol symbol
)

dirk

 

0 Likes
Message 18 of 32

FAIR59
Advisor
Advisor

Hello dirk,

 

no need for the extra reference plane in the family.

 

workflow:

1. in Family: set (workplane based - checked, and always vertical - not checked)

2. in Project: create referenceplane refPlane

3. in Project: host a new FamilyInstance on the refPlane using doc.Create.NewFamilyInstance(refPlane.reference, location, referenceDirection, symbol)

 

this is the code I used in the past:

 

        public FamilyInstance PlaceInstance(FamilySymbol symb, XYZ placementPoint, XYZ planeNormal, XYZ instHandDirection, bool OnReferencePlane = true)
        {
            if (symb == null) return null;
            Document doc = symb.Document;
            Family _family = symb.Family;
            if (_family.FamilyPlacementType != FamilyPlacementType.WorkPlaneBased) return null;
            if (planeNormal.IsAlmostEqualTo(XYZ.Zero)) planeNormal = new XYZ(0, 0, 1);
            if (instHandDirection.IsAlmostEqualTo(XYZ.Zero)) instHandDirection = new XYZ(1, 0, 0);
            if (planeNormal.DotProduct(instHandDirection).CompareTo(0) != 0) return null; // check instHandDirection perpendicular to planeNormal.
            ReferencePlane refPlane = null;
            FamilyInstance _instance1 = null;
            XYZ YVec = planeNormal.CrossProduct(instHandDirection).Normalize();
            using (SubTransaction trn = new SubTransaction(doc))
            {
                trn.Start();
                refPlane = doc.Create.NewReferencePlane(placementPoint.Add(instHandDirection), placementPoint, YVec, doc.ActiveView);
                refPlane.Name = "ref" + Guid.NewGuid().ToString();
                _instance1 = doc.Create.NewFamilyInstance(refPlane.GetReference(), placementPoint, instHandDirection, symb);
                trn.Commit();
            }
            if (!OnReferencePlane)
            {
                using (SubTransaction trn = new SubTransaction(doc))
                {
                    trn.Start();
                    doc.Delete(refPlane.Id);
                    trn.Commit();
                }
            }

            return _instance1;
        }

 if you call this method with OnReferencePlane = true, then you can rotate the familyInstance by rotating its host (the referenceplane).

 

Message 19 of 32

dirk.neethling
Advocate
Advocate

Thanks FAIR59,

 

I will try this and give feedback.

dirk

0 Likes
Message 20 of 32

dirk.neethling
Advocate
Advocate

Hello FAIR59,

 

what does "instHandDirection" represent?

dirk

 

0 Likes