This solution is shared by my colleague Ryuji Ogasawara:
Question: I am trying to create a swept blend geometry and assign it to a DirectShape
element.
The initial code threw an exception when calling the GeometryCreationUtilities
CreateSweptBlendGeometry
method, saying:
Plane of profile loop is not perpendicular to the sweep path at the specified attachment point.
The Revit SDK sample GeometryCreation_BooleanOperation does not include any example code for CreateSweptBlendGeometry
.
How can I fix this exception?
Answer: The path parameters assume that they should be normalized or that the curve has a range of parameterization from 0 to 1.
To use the unnormalized bounds for the curve, you should probably add these calls:
pathParams->Add(pathCurve->GetEndParameter(0)); pathParams->Add(pathCurve->GetEndParameter(1));
Here is the working code in .NET C++ CLR:
Autodesk::Revit::DB::Element^ DirectShapeCreator::CreateDirectShape( Autodesk::Revit::DB::Document^ document) { Autodesk::Revit::DB::Category^ directShapeCategory = document->Settings->Categories->Item[ Autodesk::Revit::DB::BuiltInCategory::OST_GenericModel]; if (directShapeCategory == nullptr) return nullptr; Autodesk::Revit::DB::DirectShape^ directShape = Autodesk::Revit::DB::DirectShape::CreateElement( document, directShapeCategory->Id); if (directShape != nullptr) { // Create a path curve List<XYZ^>^ controlPoints = gcnew List<XYZ^>; controlPoints->Add(gcnew XYZ(0, 0, 0)); controlPoints->Add(gcnew XYZ(0, 0, 10)); controlPoints->Add(gcnew XYZ(0, 10, 10)); controlPoints->Add(gcnew XYZ(0, 10, 20)); List<double>^ weights = gcnew List<double>; weights->Add(1.0); weights->Add(1.0); weights->Add(1.0); weights->Add(1.0); Curve^ pathCurve = NurbSpline::CreateCurve( controlPoints, weights); // Create a bottom profile List<XYZ^>^ bottomProfilePoints = gcnew List<XYZ^>; bottomProfilePoints->Add(gcnew XYZ(5, 5, 0)); bottomProfilePoints->Add(gcnew XYZ(-5, 5, 0)); bottomProfilePoints->Add(gcnew XYZ(-5, -5, 0)); bottomProfilePoints->Add(gcnew XYZ(5, -5, 0)); CurveLoop^ bottomProfile = gcnew CurveLoop; bottomProfile->Append(Line::CreateBound( bottomProfilePoints[0], bottomProfilePoints[1])); bottomProfile->Append(Line::CreateBound( bottomProfilePoints[1], bottomProfilePoints[2])); bottomProfile->Append(Line::CreateBound( bottomProfilePoints[2], bottomProfilePoints[3])); bottomProfile->Append(Line::CreateBound( bottomProfilePoints[3], bottomProfilePoints[0])); // Create a top profile List<XYZ^>^ topProfilePoints = gcnew List<XYZ^>; topProfilePoints->Add(gcnew XYZ(2, 10 + 2, 20)); topProfilePoints->Add(gcnew XYZ(-2, 10 + 2, 20)); topProfilePoints->Add(gcnew XYZ(-2, 10 - 2, 20)); topProfilePoints->Add(gcnew XYZ(2, 10 - 2, 20)); CurveLoop^ topProfile = gcnew CurveLoop; topProfile->Append(Line::CreateBound( topProfilePoints[0], topProfilePoints[1])); topProfile->Append(Line::CreateBound( topProfilePoints[1], topProfilePoints[2])); topProfile->Append(Line::CreateBound( topProfilePoints[2], topProfilePoints[3])); topProfile->Append(Line::CreateBound( topProfilePoints[3], topProfilePoints[0])); List<CurveLoop^>^ profiles = gcnew List<CurveLoop^>; // Add above profiles profiles->Add(bottomProfile); profiles->Add(topProfile); // which value to be set exactly? He tried 0 and 1. List<double>^ pathParams = gcnew List<double>; pathParams->Add(pathCurve->GetEndParameter(0)); pathParams->Add(pathCurve->GetEndParameter(1)); // Create a swept blend geometry. Solid^ solid = GeometryCreationUtilities::CreateSweptBlendGeometry( pathCurve, pathParams, profiles, nullptr); List<GeometryObject^>^ gs = gcnew List<GeometryObject^>; gs->Add(solid); directShape->AppendShape(gs); } return directShape; }
The final result looks like this: