/// <summary> /// Rotates the element based only on the direction of the placement connector. /// </summary> private static void RotateElementInPosition(XYZ placementPoint, Connector conOnFamilyToConnect, Connector startCon, Element element) { #region Geometric manipulation //http://thebuildingcoder.typepad.com/blog/2012/05/create-a-pipe-cap.html XYZ start = startCon.Origin; XYZ end = start - startCon.CoordinateSystem.BasisZ * 2; XYZ dirToAlignTo = (start - end); XYZ dirToRotate = -conOnFamilyToConnect.CoordinateSystem.BasisZ; double rotationAngle = dirToAlignTo.AngleTo(dirToRotate); XYZ normal = dirToAlignTo.CrossProduct(dirToRotate); //Case: Normal is 0 vector -> directions are already aligned, but may need flipping if (normal.Equalz(new XYZ(), 1.0e-6)) { //Subcase: Element needs flipping if (rotationAngle > 0) { Line axis2; if (dirToRotate.X.Equalz(1, 1.0e-6) || dirToRotate.Y.Equalz(1, 1.0e-6)) { axis2 = Line.CreateBound(placementPoint, placementPoint + new XYZ(0, 0, 1)); } else { axis2 = Line.CreateBound(placementPoint, placementPoint + new XYZ(1, 0, 0)); } ElementTransformUtils.RotateElement(element.Document, element.Id, axis2, rotationAngle); return; } //Subcase: Element already in correct alignment return; } Transform trf = Transform.CreateRotationAtPoint(normal, rotationAngle, placementPoint); XYZ testRotation = trf.OfVector(dirToAlignTo).Normalize(); if (testRotation.DotProduct(dirToAlignTo) < 0.00001) { rotationAngle = -rotationAngle; } Line axis = Line.CreateBound(placementPoint, placementPoint + normal); ElementTransformUtils.RotateElement(element.Document, element.Id, axis, rotationAngle); #endregion }