Project Method Returning Null and Failing to Get Correct UV
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report
I have a project that inserts a precast concrete connection family onto the surface of another family representing a concrete double tee and then applies a rotation to that family to orient it correctly. In order to apply that rotation, I am trying to get the normal of a hermite face at a point to use as the axis of rotation. This point is already calculated from being projected onto the surface for insertion of the family and now I am converting it to a UV point so that I can use hermiteFace.ComputeNormal(UVPoint).
This is working great in my test environment, however now that I am trying it in another Revit project, the Project method is failing and just returning null, preventing me from getting the normal needed at that point. The hermite face is relatively flat, with just some slight sloping/twisting on it for drainage.
Is there a way to resolve this error or a better way to get the normal that does not require the use of the Project method to get the UV point?
Image for reference of the families
public static void ApplyRotation(Document doc, FamilyInstance instance, XYZ point, double startRotationRadians, Reference targetFaceRef)
{
double rotationTolerance = 0.001;
if (instance == null || Math.Abs(startRotationRadians) < rotationTolerance) return;
// Get the face from the reference
Element hostElement = doc.GetElement(targetFaceRef.ElementId);
GeometryObject geometryObject = hostElement?.GetGeometryObjectFromReference(targetFaceRef);
if (geometryObject == null)
{
System.Diagnostics.Debug.WriteLine("ApplyRotation Error: Could not retrieve geometry object from reference.");
return;
}
XYZ faceNormal;
if (geometryObject is PlanarFace planarFace)
{
faceNormal = planarFace.FaceNormal;
}
else if (geometryObject is CylindricalFace cylindricalFace)
{
XYZ origin = cylindricalFace.Origin;
XYZ axis = cylindricalFace.Axis;
XYZ pointOnAxis = origin + (point - origin).DotProduct(axis) * axis;
faceNormal = (point - pointOnAxis).Normalize();
if (faceNormal.Z < 0) faceNormal = -faceNormal;
}
else if (geometryObject is HermiteFace hermiteFace)
{
// Project the point onto the HermiteFace to get UV coordinates
//UV uv = hermiteFace.Project(point)?.UVPoint ?? new UV(0, 0); // Default to (0,0) if projection fails
IntersectionResult projectResult = hermiteFace.Project(point);
UV uv;
double dist = 0;
if (projectResult == null)
{
MessageBox.Show($"Project failed on HermiteFace ID {geometryObject.Id}. Point: {point}", "Debug: Project Failed");
return;
}
else
{
uv = projectResult.UVPoint;
dist = projectResult.Distance;
Debug.WriteLine($"Project success on HermiteFace ID {geometryObject.Id}. UV: {uv.U},{uv.V}, Distance: {dist}, Closest Point: {projectResult.XYZPoint}");
if (dist > 0.001) // Arbitrary small tolerance in feet; adjust as needed
{
MessageBox.Show($"High distance ({dist}) on HermiteFace ID {geometryObject.Id}. Point may not be precisely on face.", "Debug: High Distance");
}
}
faceNormal = hermiteFace.ComputeNormal(uv);
if (faceNormal.IsZeroLength()) // Handle potential computation failure
{
MessageBox.Show("ApplyRotation Warning: Failed to compute normal for HermiteFace. Using fallback - ensure accuracy after insertion.");
faceNormal = XYZ.BasisZ; // Fallback to Z-axis if normal computation fails
}
faceNormal = faceNormal.Normalize();
MessageBox.Show($"Face ID:{geometryObject.Id}\nFace Normal: {faceNormal.ToString()}\nUV: {uv.ToString()}");
}
else
{
MessageBox.Show("ApplyRotation Warning: Unsupported face type, skipping rotation.");
return;
}
Line rotationAxis = Line.CreateBound(point, point + faceNormal);
ElementTransformUtils.RotateElement(doc, instance.Id, rotationAxis, startRotationRadians);
}