Create Swept Blend DirectShape in C++

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::Documentdocument)
  {
    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:

Swept blend DirectShape