SweepTwoRail Command allways return no brep

I try to sweep a contur around two closed rails but without any success.

Since i like to use the MaintainHeight Option i using the SweepTwoRail Command:

SweepTwoRail sweep = new SweepTwoRail();
Brep[] brep = sweep.PerformSweep(inner_curver, outer_curve, conturs);

I have checked both rails direction to be the same and that the startpoint is on the contur.

I have attached a txt with all values from the debugger and a image with the startpoints and directions marked.

Any idee whats wrong?


data.txt (4.1 KB)

Here is an example command with the same problem:

using System;
using Rhino;
using Rhino.Commands;
using Rhino.Geometry;

namespace JewelryToolbox
{
    public class TestCommand : Command
    {
        static TestCommand _instance;
        public TestCommand()
        {
            _instance = this;
        }
public static TestCommand Instance
        {
            get { return _instance; }
        }

        public override string EnglishName
        {
            get { return "TestCommand"; }
        }

        protected override Result RunCommand(RhinoDoc doc, RunMode mode)
        {
            Point3d center = new Point3d(0, 0, 0);
            double radius = 7.5;
            Circle circle_in = new Circle(Plane.WorldXY, center, radius);
            var xform = Transform.Rotation(-90 * Math.PI / 180, center);
            circle_in.Transform(xform);

            double radius_circle_out = 10;
            Point3d center_circle_out = new Point3d(0, 1, 0);
            Circle circle_out = new Circle(Plane.WorldXY, center_circle_out, radius_circle_out);
            xform = Transform.Rotation(-90 * Math.PI / 180, center_circle_out);
            circle_out.Transform(xform);

            Curve contur = new Ellipse(Plane.WorldYZ, 1, 2).ToNurbsCurve();
            Point3d circle_point = new Point3d(0, -9, 0);
            xform = Transform.Translation(circle_point - new Point3d(0, -1, 0));
            contur.Transform(xform);

            doc.Objects.AddCircle(circle_in);
            doc.Objects.AddCircle(circle_out);
            doc.Objects.AddCurve(contur);

            if (!Curve.DoDirectionsMatch(circle_in.ToNurbsCurve(), circle_out.ToNurbsCurve()))
                circle_out.Reverse();

            SweepTwoRail sweep = new SweepTwoRail();
            //sweep.MaintainHeight = true;
            //sweep.ClosedSweep = true;
            //sweep.SweepTolerance = doc.ModelAbsoluteTolerance;
            Brep[] brep = sweep.PerformSweep(circle_in.ToNurbsCurve(), circle_out.ToNurbsCurve(), contur);
            if (brep.Length > 0)
                doc.Objects.AddBrep(brep[0]);
            return Result.Success;
        }
    }
}

I know i start to annoying but this is driving me crasy.

If i create a second contur in the top half and set ClosedSweep to false i get a complet valid sweep from one contur to the other but with ClosedSweep = true there is no brep again.

I get a valid closed brep if i move the single contur out of the boundery of the two rails but thats clearly not what i want.

Do nobody have a idee whats wrong with my code? Im need to fix this to get on with my project.

Hi @Felix1,

Any reason you want to use Sweep2? You could always do this:

protected override Result RunCommand(RhinoDoc doc, RunMode mode)
{
  const double min_radius = 7.5;
  const double max_radius = 10.0;      

  var radius = (max_radius + min_radius) / 2.0;
  var circle = new Circle(Plane.WorldXY, radius);
  var rail = new ArcCurve(circle);

  radius = max_radius - min_radius;
  rail.PerpendicularFrameAt(rail.Domain.Min, out Plane plane);
  circle = new Circle(plane, radius);
  var shape = new ArcCurve(circle);

  var breps = Brep.CreateFromSweep(rail, shape, true, doc.ModelAbsoluteTolerance);
  foreach (var b in breps)
    doc.Objects.AddBrep(b);

  doc.Views.Redraw();
  
  return Result.Success;
}

If your really lazy, you can just do this:

protected override Result RunCommand(RhinoDoc doc, RunMode mode)
{
  const double min_radius = 7.5;
  const double max_radius = 10.0;

  var major_radius = (max_radius + min_radius) / 2.0;
  var minor_radius = max_radius - min_radius;

  var torus = new Torus(Plane.WorldXY, major_radius, minor_radius);
  doc.Objects.AddSurface(torus.ToRevSurface());
  doc.Views.Redraw();

  return Result.Success;
}

– Dale

OK, here is a Sweep2 version…

protected override Result RunCommand(RhinoDoc doc, RunMode mode)
{
  const double min_radius = 7.5;
  const double max_radius = 10.0;

  var circle = new Circle(Plane.WorldXY, min_radius);
  var rail0 = new ArcCurve(circle);

  circle = new Circle(Plane.WorldXY, max_radius);
  var rail1 = new ArcCurve(circle);

  var radius = (max_radius + min_radius) / 2.0;
  circle = new Circle(Plane.WorldXY, radius);
  var center = new ArcCurve(circle);

  center.PerpendicularFrameAt(center.Domain.Min, out Plane plane);
  radius = max_radius - min_radius;
  circle = new Circle(plane, radius);
  var shape = new ArcCurve(circle);

  var breps = Brep.CreateFromSweep(rail0, rail1, shape, true, doc.ModelAbsoluteTolerance);
  foreach (var b in breps)
    doc.Objects.AddBrep(b);

  doc.Views.Redraw();

  return Result.Success;
}

– Dale

Thanks Fugier for your reply but my code is just an example:

  • there is an offset between the two rails so i need the MaintainHeight-Flag from sweeptworail to get the right output

  • the contur could be a other shape like a triangle or “complexer”

The Brep.CreateFromSweep is already working but not the sweeptworail.

Why is sweeptworail in my example code is not working?

Update!

The problem is the bigger circle. If i pass it as an arccurve everthing is working but if i cast it to an NurbsCurve with .ToNurbsCurve() the sweep is failling. It doesnt metter if the bigger curve is passed to SweepTwoRails as first or second rail. The other rail couldbe cast without problems. Problem is that the bigger curve could be something other than a circle inside my code.

Sorry to spam the thread but i found a workaround for me with some new problems:

If the rails not closed they could be NurbsCurve without a problem so i split the rails i two parts and doing two sweeptworail actions. This is working on many shapes but in this example the surface isnt following my second rail correct:

using System;
using System.Collections.Generic;
using System.Text;
using Rhino;
using Rhino.Collections;
using Rhino.Commands;
using Rhino.Geometry;

namespace JewelryToolbox
{
    public class TestCommand : Command
    {
        static TestCommand _instance;
        public TestCommand()
        {
            _instance = this;
        }
        public static TestCommand Instance
        {
            get { return _instance; }
        }

        public override string EnglishName
        {
            get { return "TestCommand"; }
        }

        protected override Result RunCommand(RhinoDoc doc, RunMode mode)
        {
            double radius = 7.5;
            double height = 2.5;
            double offset = 5;
            double radius_rail2 = radius + height;

            Point3d center = new Point3d(0, 0, 0);
            NurbsCurve rail1 = new Circle(Plane.WorldXY, center, radius).ToNurbsCurve();
            NurbsCurve rail2 = new Circle(Plane.WorldXY, center, radius_rail2).ToNurbsCurve();

            var xform = Transform.Rotation(-90 * Math.PI / 180, center);
            rail1.Transform(xform);
            rail2.Transform(xform);

            var railpoint = rail2.Points[4];
            railpoint.Y += offset;
            rail2.Points[4] = railpoint;

            if (!Curve.DoDirectionsMatch(rail1, rail2))
                rail2.Reverse();

            Curve shape1 = new Ellipse(Plane.WorldYZ, height /2, 2).ToNurbsCurve();
            Point3d circle_point = new Point3d(0, -radius - height / 2, 0);
            xform = Transform.Translation(circle_point - center);
            shape1.Transform(xform);

            Curve shape2 = new Ellipse(Plane.WorldYZ, (height + offset) /2, 3).ToNurbsCurve();
            Point3d circle_point2 = new Point3d(0, radius + height /2 + offset / 2, 0);
            xform = Transform.Translation(circle_point2 - center);
            shape2.Transform(xform);
            
            double new_t;
            shape1.ClosestPoint(center, out new_t);
            shape1.ChangeClosedCurveSeam(new_t);

            shape2.ClosestPoint(center, out new_t);
            shape2.ChangeClosedCurveSeam(new_t);
            
            Interval dom = rail1.Domain;
            double t = (dom.Max + dom.Min) * 0.5;
            NurbsCurve rail1part1 = rail1.Trim(dom.Min, t).ToNurbsCurve();
            NurbsCurve rail1part2 = rail1.Trim(t, dom.Max).ToNurbsCurve();

            dom = rail2.Domain;
            t = (dom.Max + dom.Min) * 0.5;
            NurbsCurve rail2part1 = rail2.Trim(dom.Min, t).ToNurbsCurve();
            NurbsCurve rail2part2 = rail2.Trim(t, dom.Max).ToNurbsCurve();

            rail1part2.Reverse();
            rail2part2.Reverse();

            if (Curve.DoDirectionsMatch(shape1, shape2))
                shape2.Reverse();

            doc.Objects.AddCurve(rail1part1);
            doc.Objects.AddCurve(rail1part2);
            doc.Objects.AddCurve(rail2part1);
            doc.Objects.AddCurve(rail2part2);
            doc.Objects.AddCurve(shape1);
            doc.Objects.AddCurve(shape2);

            SweepTwoRail sweep = new SweepTwoRail();
            sweep.MaintainHeight = true;
            sweep.ClosedSweep = false;
            List<Brep> final_breps = new List<Brep>();
            final_breps.Add(sweep.PerformSweep(rail1part1, rail2part1, new Curve[] { shape1, shape2 })[0]);
            final_breps.Add(sweep.PerformSweep(rail1part2, rail2part2, new Curve[] { shape1, shape2 })[0]);
            Brep final_brep = Brep.JoinBreps(final_breps, doc.ModelAbsoluteTolerance)[0];
            
            doc.Objects.AddBrep(final_brep);
            
            return Result.Success;
        }
    }
}

This is the result:

if im using the ui-command sweep2 the result is following my rails correct. Whats the different?

Hi @Felix1,

Yes I see this. There are two problems here:

1.) The SweepTwoRail class uses some older sweeping code that is no longer used by the Sweep2 command.

2.) The Brep.CreateFromSweep method uses the newer sweeping code. However, there is not an override in RhinoCommon that provides all of the parameters that are used by the Sweep2 command.

Here is the YouTrack item that (somewhat) documents this.

https://mcneel.myjetbrains.com/youtrack/issue/RH-31673

There is a new Brep.CreateFromSweep override in the Rhino WIP that will do exactly what you want.

– Dale

So there is no real equal for sweep2 in rhinocommon?! No workaround, nothing?

Thats mean i need to switch an maybe unstable version to use a really basic tool like sweep in a script. Thats sad.

Could sweeptworail marked as deprecated and remove the tip to use sweeptworail in the Brep.CreateFromSweep documentation so the next programmer isnt wasting his/her time.

Hi @Felix1,

Like I said, the Brep.CreateFromSweep method uses the newer sweeping code. However, there is not an override in RhinoCommon that provides all of the parameters that are used by the current Sweep2 command. I’ll see if I can back-port the extended function, added to the WIP and referenced in the YT item, to Rhino 6. Here is an example of it’s output.

TestBrepCreateFromSweep.3dm (82.9 KB)

Also, I doubt we will deprecate or obsolete the SweepTwoRail class, as we are trying to minimize deletions in RhinoCommon in order to keep as many existing plug-ins and GH components and scripts running as possible. We will probably try to modify it’s functionality so as to use the newer sweeping functionality.

Thanks,

– Dale

Thank you, i really hope there will be a backport. I like to use my code every day and there are no much change to use a wip-programm in my company.

Hi @Felix1,

You’ll see the extended function appear in SR16.

– Dale

1 Like

Thats fantastic. Thank you very much