RhinoSweep1 and Rhino1RailSweep and sweep1 command

When I sweep those curves with the code from the message above I get a surface. I’ll attach the file.
Do you get any error messages?
Can you tell where your code fails?


there are no error mesages,my code fails just at RhinoSweep1 funtions.
my plugin is rhino5.
can you send your total test plugin workspace to me ,I can compare your whole codes to mine.

thanks for you hlep.
I test my sweep1 function in a smalll seperate test workspace right now,this will not fail.
but in my real workspace will fail.
I think maybe my real workspace’ other codes result this problem.
I will try to find the different between the two workspce.

I find the different of them.
when I select the shape curves in clockwise direction,sweep1 will not fail.
but when I select the shape curves in anticlockwise direction seeep1 will fail.
look like the shape curves must match the direction of the rail.
is it right?
if it is right, how can I promise my shape curves match the direction of the rail.
because my shape curves are alaws in anticlockwise ,that to say ,if my rail curve is clockwise
,I need chang the direction of my rail.
in this test 3dm file,my curve is on a plane,rhino has a funtion can get the curve’s direction is clockwise or anticlockwise ,but has no funtion can get the direction is clockwise or anticlockwise when the curves is not on a
plane.and my curves also maybe not on a plane in other 3dm files.

I solve this problem like that :smile:
I will sort the shape curves according to the parameters of GetShapeParameterOnRail function returned.
and it work fine right now.

but I still have another problem :
I need a more general way to set all of the shapes to go the same way.
the codes you provided just can fit a few conditions.


Do you mean that you need a more general way to sort the shapes along the rail, or that you need a more general way to orient the shape curve directions?

Below is the total of the code that I used.
(Much of it is from you)

//=============== Begin Nice Day ============================

bool GetShapeParameterOnRail( const ON_Curve& shape,  const ON_Curve& rail, double tol, double& t   )  
    ON_Interval rail_domain = rail.Domain();    
    double dis1=100000;
    double t1;
    double dis2=100000;
    double t2;

    bool rc = rail.GetClosestPoint( shape.PointAtStart(), &t1, tol );//得到起点;
    if( rc )
        if( rail.IsClosed() )
            if( fabs(t - rail_domain.Max()) < ON_SQRT_EPSILON )
                t1 = rail_domain.Min();
            if( fabs(t - rail_domain.Min()) < ON_SQRT_EPSILON )
                t1 = rail_domain.Min();
        ON_3dPoint point1=rail.PointAt(t1);

    // 测试端点;
    rc = rail.GetClosestPoint( shape.PointAtEnd(), &t2, tol );
    if( rc )
        if( rail.IsClosed() )
            if( fabs(t2 - rail_domain.Max()) < ON_SQRT_EPSILON )
                t2 = rail_domain.Min();
            if( fabs(t2 - rail_domain.Min()) < ON_SQRT_EPSILON )
                t2 = rail_domain.Min();
        ON_3dPoint point2=rail.PointAt(t2);


        return true;

    // 尝试相交
    ON_SimpleArray<ON_X_EVENT> x;
    if( 1 == rail.IntersectCurve(&shape, x, tol, 0.0) && x[0].IsPointEvent() )
        t = x[0].m_a[0];
        if( rail.IsClosed() )
            if( fabs(t - rail_domain.Max()) < ON_SQRT_EPSILON )
                t = rail_domain.Min();
        return true;

    return false;

bool Sweep1(ON_Curve* in_rail,ON_SimpleArray<const ON_Curve*>in_secs,ON_SimpleArray<ON_Brep*>& out_breps)  
  // I guess you're only doing closed rails here
        bool bClosed = true;

    CRhinoPolyEdge edge_copy;

  // Set seam on closed rail to first shape location
  if(bClosed && edge_copy.IsClosed())
    double t;
    if( !GetShapeParameterOnRail(*in_secs[0], edge_copy, 0.2, t) )
      return 0;
    ON_Interval domain = edge_copy.Domain();
    if(t != domain[0])
        return 0;

  CArgsRhinoSweep1 args;
    args.m_rail_curve = &edge_copy;
    args.m_bHaveRailPickPoint = false;
    args.m_bUsePivotPoint = false;

    for( int i = 0; i < in_secs.Count(); i++ )
    double t;
        if( !GetShapeParameterOnRail(*in_secs[i], edge_copy, 0.2, t) )
            return 0;
        args.m_shape_curves.Append( const_cast<ON_Curve*>(in_secs[i]));
        args.m_rail_params.Append( t );

    // Set all of the shapes to go the same way.
    // This isn't a very robust way to do that but it works with the kind of shapes you're using.
    ON_3dPoint p = edge_copy.PointAt(t);
    if(args.m_shape_curves[i]->PointAtStart().DistanceTo(p) > args.m_shape_curves[i]->PointAtEnd().DistanceTo(p))

    ON_Interval testdom = edge_copy.Domain();

    args.m_bUsePoints[0] = 0;
    args.m_bUsePoints[1] = 0;
    args.m_bClosed = true; 
    args.m_style = 0;
    args.m_planar_up = ON_zaxis; // Don't need this, but set it anyway.. 
    args.m_simplify = 0; // Simplify method for shape curves
    args.m_rebuild_count = -1; // Sample point count for rebuilding shapes
    args.m_refit_tolerance = 0.01;
    args.m_sweep_tolerance =0.01;
    args.m_angle_tolerance =0.01;// RhinoApp().ActiveDoc()->AngleToleranceRadians();

    RhinoSweep1(args, out_breps);

    return (out_breps.Count()>=1) ? true : false;

// BEGIN TestSweep command

#pragma region TestSweep command

class CCommandTestSweep : public CRhinoTestCommand
	CCommandTestSweep() {}
	~CCommandTestSweep() {}
	UUID CommandUUID()
		// {449D8857-878-4482-ADB6-A677DF4B1698}
		static const GUID TestSweepCommand_UUID =
		{ 0x449D8857, 0x878, 0x4482, { 0xAD, 0xB6, 0xA6, 0x77, 0xDF, 0x4B, 0x16, 0x98 } };
		return TestSweepCommand_UUID;
	const wchar_t* EnglishCommandName() { return RHINOSTRING_COMMAND_NAME(L"TestSweep"); }
	CRhinoCommand::result RunCommand( const CRhinoCommandContext& );

// The one and only CCommandTestSweep object
static class CCommandTestSweep theTestSweepCommand;

CRhinoCommand::result CCommandTestSweep::RunCommand( const CRhinoCommandContext& context )
    CRhinoGetObject go;
    go.SetCommandPrompt( L"Select rail curve" );
    go.SetGeometryFilter( CRhinoGetObject::curve_object );
    if( go.CommandResult() != success )
        return go.CommandResult();

    const CRhinoObjRef& rail_ref = go.Object(0);
    const CRhinoObject* rail_obj = rail_ref.Object();
    if( !rail_obj )
        return failure;
    const ON_Curve* rail_crv = rail_ref.Curve();
    if( !rail_crv )
        return failure;

    CRhinoGetObject gx;
    gx.SetCommandPrompt( L"Select cross section curves" );
    gx.SetGeometryFilter( CRhinoGetObject::curve_object );
    gx.EnablePreSelect( false );
    gx.EnableDeselectAllBeforePostSelect( false );
    if( gx.CommandResult() != success )
        return gx.CommandResult();

    ON_Curve* rail=rail_crv->DuplicateCurve();
    ON_SimpleArray<const ON_Curve*>shapes;

    int i;
    for( i = 0; i < gx.ObjectCount(); i++ )
        const CRhinoObjRef& obj_ref = gx.Object(i);
        const ON_Curve* crv = obj_ref.Curve();
        if( crv )
            ON_Curve* dup_crv = crv->DuplicateCurve();

    ON_SimpleArray<ON_Brep*> breps;
#if 1

    for( i = 0; i < breps.Count(); i++ )
        context.m_doc.AddBrepObject( *breps[i] );
        delete breps[i];

    delete rail;
    for( i = 0; i < shapes.Count(); i++ )
        delete shapes[i];

    return success;

#pragma endregion

// END TestSweep command

//=============== End Nice Day ============================

I need a more general way to orient the shape curve directions
next codes are too simple and only can fit a few conditions

ON_3dPoint p = edge_copy.PointAt(t);
if(args.m_shape_curves[i]->PointAtStart().DistanceTo§ > args.m_shape_curves[i]->PointAtEnd().DistanceTo§)

I’ll see if I can make an example that helps.
Are your shapes always open curves? Or do you need to deal with closed curves also?
This is a harder problem than it seems at first and there is a lot of effort in Rhino to deal with it.

my sharp curves and rail curves maybe open curves or closed curves.
so I need I genenal way ,just like sweep1 command can do .

Here’s a start at doing that. (Attached file)TestSweep.cpp.txt(12.7 KB)
I don’t know how well it will work in all cases, but its what I could come up with from functions in the sdk


lowell,thanks very much!