Can't rotate element into this position

Can't rotate element into this position

dirk.neethling
Advocate Advocate
6,763 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,764 Views
31 Replies
Replies (31)
Message 21 of 32

FAIR59
Advisor
Advisor

that's the referenceDirection.

 

default placement

placementPoint XYZ(0,0,0)

planeNormal XYZ(0,0,1)

instHandDirection XYZ(1,0,0)

 

placing the ring vertical:

 

placementPoint XYZ(0,0,0)

planeNormal XYZ(1,0,0)

instHandDirection XYZ(0,0,-1)

 

or

 

placementPoint XYZ(0,0,0)

planeNormal XYZ(0,1,0)

instHandDirection XYZ(1,0,0)

 

Message 22 of 32

dirk.neethling
Advocate
Advocate

Does instHandDirection  need to be normal to planeNormal ?

dirk

0 Likes
Message 23 of 32

FAIR59
Advisor
Advisor

as I recollect, instHandDirection doesn't need to be normal to planeNormal, but it can't be equal to the planeNormal. You must do some testing to be completely certain. 

Message 24 of 32

dirk.neethling
Advocate
Advocate

instHandDirection is causing Problems. Is it possible to implement your method without this vector?

dirk

0 Likes
Message 25 of 32

dirk.neethling
Advocate
Advocate

Hello FAIR59,

 

I don't really know what  instHandDirection means or have any use for it, so I try to generate it on the fly in order to satisfy the demands of the method PlaceInstance. Before calling PlaceInstance , I generate  instHandDirection  using,

 

instHandDirection = RING_VECTOR.CrossProduct(XYZ.BasisZ).Normalize();

 

Being the result of a CrossProduct, one would assume that the two vectors (RING_VECTOR and instHandDirection) are normal to each other. However when I run the DotProduct of the two vectors [RING_VECTOR.DotProduct(instHandDirection)] , i.e. the projection of the one vector on to the other, I get a residual number:

 

RING_VECTOR.DotProduct(instHandDirection) -0.000000000000000055511151231257827 double

 

This causes PlaceInstance to fail in the line,

 

if (planeNormal.DotProduct(instHandDirection).CompareTo(0) != 0)

return null;

 

Is there another approach to generate instHandDirection ?

 

dirk

0 Likes
Message 26 of 32

dirk.neethling
Advocate
Advocate

Hello FAIR59,

 

In your method there is the following line:

 

if (planeNormal.DotProduct(instHandDirection).CompareTo(0) != 0)

return null;

 

Since the DotProduct is equal to Abs(planeNormal.length)*Abs(instHandDirection.length)*Abs(Cos(AngleBetweenTheTwoVectors)), this can only be equal to 0 if either the angle between the two vectors is 90°, or one or both of the vectors have zero length.

From this I conclude that the vectors instHandDirection and planeNormal do in fact need to be normal to each other.

Or am I wrong?

 

dirk

0 Likes
Message 27 of 32

FAIR59
Advisor
Advisor

First I'd like to mention that the method double.CompareTo() is too strict. It will only return 0 if the 2 doubles are exactly the same. To test if doubles are equal, nowadays I use Math.Abs(a-b)<0.0001.

 

The method I supplied is a abbreviated version of a method I used in the past. In that version it was necessary that the 2 vectors were perpendicular.

In this version that is no longer required. For the creation of the reference plane and FamilyInstance, we only need instHandDirection and the vector YVec.

 

So the method will work as long as the 2 vectors not parallel. ( then the calculation of YVec will succeed)

 

if (planeNormal.IsAlmostEqualTo(XYZ.Zero)) planeNormal = new XYZ(0, 0, 1);
if (instHandDirection.IsAlmostEqualTo(XYZ.Zero)) instHandDirection = new XYZ(1, 0, 0);
if (planeNormal.Normalize().IsAlmostEqualTo(instHandDirection.Normalize()) || planeNormal.Normalize().IsAlmostEqualTo(instHandDirection.Normalize().Negate()))  return null; // check instHandDirection not parallel to planeNormal.
            
Message 28 of 32

dirk.neethling
Advocate
Advocate

Thanks FAIR59, I ended up using

 

double dot = planeNormal.DotProduct(instHandDirection);

if (Math.Round(dot, 15).CompareTo(0) != 0)

return null;

 

I calculate instHandDirection using

instHandDirection = RING_VECTOR.CrossProduct(XYZ.BasisX).Normalize();

 

I tried

instHandDirection = RING_VECTOR.CrossProduct(XYZ.BasisZ).Normalize();

 

but it would fail at times.

 

I still don't really unsderstand the purpose of instHandDirection, so I hope I am not making a mistake. 

 

0 Likes
Message 29 of 32

FAIR59
Advisor
Advisor

what does "RING_VECTOR" represent??

 

have tried Math.Round(dot,5)  ??

0 Likes
Message 30 of 32

dirk.neethling
Advocate
Advocate

It's the same as planeNormal. I use RING_VECTOR for planeNormal and do all the transformations on it (rotations and translations), then I generate instHandDirection like so,

 

instHandDirection = RING_VECTOR.CrossProduct(XYZ.BasisX).Normalize();

 

then I pass everything to your method.

0 Likes
Message 31 of 32

FAIR59
Advisor
Advisor
Accepted solution

instHandDirection should be the required direction of the X-axis of the Family.

Message 32 of 32

dirk.neethling
Advocate
Advocate

Thanks FAIR59 for your Support on this Topic!

 

dirk

0 Likes