Brep Face conversion problem

Hello everyone,

I’m developing a new plugin for Rhino, using Rhinocommon SDK and Visual Studio .NET C#.
I’m trying to convert a Trimmed Brep Face to our internal library NURBS format, but I get a surface that is different from the original, since it has several unwanted extensions.
When using the Rhinocommon function “Brep.CopyTrimCurves(face, surface, tolerance)“ I get the same wrong result.

If I export the surface as IGES file and reimport, then, on the new imported surface, everything works fine.

The attached image shows the original surface (green colored) and the wrong surface (red colored), it is easy to see the unwanted extensions.

In the 3dm attached file, there are: the original surface; the converted (wrong) surface; and the surface imported after exporting the original surface and for wich the conversion works fine.

Donato Bevilacqua.

Following a sample code, producing the wrong surface:

    public void DupBrepWithRhinoCopyTrimCurves()
        var doc = RhinoDoc.ActiveDoc;
        var att = new Rhino.DocObjects.ObjectAttributes();
        att.ColorSource = ObjectColorSource.ColorFromObject;

        // select a surface
        var gs = new GetObject();
        gs.SetCommandPrompt("select surface");
        gs.GeometryFilter = ObjectType.Surface;
        gs.SubObjectSelect = true;
        if (gs.CommandResult() != Result.Success)
            Rhino.UI.Dialogs.ShowMessageBox("Surface selection failed!", "surface selection");
        // get the selected face
        var face = gs.Object(0).Face();
        Brep selectedBrep = gs.Object(0).Brep();

        var surface = face.UnderlyingSurface().ToNurbsSurface();
        //var surface = face.ToNurbsSurface();

        var newBrep = Rhino.Geometry.Brep.CopyTrimCurves(face, surface, 1e-6);
        if (newBrep != null)
            att.Name = "NEW trimmed BREP";
            att.ObjectColor = System.Drawing.Color.DarkGreen;
            doc.Objects.AddBrep(newBrep, att);


Brep Face Conversion.3dm (363.9 KB)

Why not just duplicate the face as a new Brep:

var face = gs.Object(0).Face();
Brep newFace = face.DuplicateFace(false);

Yeah! But I don’t need just to duplicate Face into Rhino.
As I said, I need to export the Brep Face into our internal library, so, I need to convert it. In other words, I need to be able to reconstruct the Brep Face by using all the components (knots, control points, trim curves, loops etc.), that are the inputs to our internal library for CAM.
The code I posted was just an example on the wrong result I get, i.e. when reconstruct the BrepFace, I get that same wrong result as the Rhino function “CopyTrimCurves”.

I don’t understand why you need to rebuild or reconstruct the BrepFace, if your library knows about trimmed surfaces. I think I’m missing something here.

For CopyTrimCurves: it rebuilds the trim curve for the new surface with the tolerance that you give. Apparently that did not work very well. Have you tried making the tolerance more strict, for example RhinoMath.ZeroTolerance (which translates to 1e-12)?

Using the What command, I see the difference between the two surfaces (original, and after import): the original is a surface of revolution, whereas the after import is a “normal” surface, that is, the surface of revolution has been converted to a NURBS representation. This may be the origin of the problem? That the CopyTrimCurves does not work well when the underlying surface is a RevSurface and it works better if the underlying surface is a normal NurbsSurface?

My library knows about trimmed surfaces, but I have to create a trimmed surface (into my library) by using all the right parameters (extracted from Rhino): i.e. surfaces (knots, control points etc.), trim loops, and so on.
You noticed well, I saw the same differences, and I think that that is the problem: surface of revolution or not.
My problem is that, when I use the parameters of the source BrepFace (provided by a customer) in order to reconstruct the trimmed surface into my library, I get a wrong surface.
I suspect that the 2D trimming curve provided by the Loop.To2DCurve() of the BrepFace is not correct.
That is the reason of my question, and my hope to get an help by someone of the McNeel Team.
(anyway, it’s not a tolerance problem, tried also that)

My guess is that the 3D trimming curves are correct. But it is not clear to me why you’d want to use the 2D curve returned by Loop.To2DCurve as the basis for reconstructing a Brep. I would think you’d want to use the 2D trim and 3D edges instead. But then again, I don’t know enough about your library to know what is required.

I take it your library cannot deal with surfaces of revolution, which is why you trying to convert it to it’s NURB form.

This probably should be easier. But it should work in the case you’ve presented.

protected override Result RunCommand(RhinoDoc doc, RunMode mode)
  var gs = new GetObject();
  gs.SetCommandPrompt("Select surface");
  gs.GeometryFilter = ObjectType.Surface;
  gs.SubObjectSelect = true;
  if (gs.CommandResult() != Result.Success)
    return gs.CommandResult();

  var brep = gs.Object(0).Brep();
  var face = gs.Object(0).Face();
  if (null == brep || null == face)
    return Result.Failure;

  int fi = face.FaceIndex;

  // Duplicate the original brep
  var new_brep = brep.DuplicateBrep();
  // Get the NURB form of the face's underlying surface
  var new_nurb = new_brep.Faces[fi].UnderlyingSurface().ToNurbsSurface();
  // Convert trim curves from one surface to its NURBS form
  new_brep.RebuildTrimsForV2(new_brep.Faces[fi], new_nurb);
  // Replace the underlying face's surfaces with its NURB form
  // Clean up

  if (new_brep.IsValid)
    var att = doc.CreateDefaultAttributes();
    att.ColorSource = ObjectColorSource.ColorFromObject;
    att.ObjectColor = System.Drawing.Color.DarkGreen;
    att.Name = "NEW trimmed BREP";
    doc.Objects.AddBrep(new_brep, att);

  return Result.Success;

Does this help?

Thank you very much Dale! :smile:
Yes the 3D curves are fine, I already saw that.
Anyway, your code fixes my problem, and now my conversion seems to produce good results.
Thanks again.

1 Like

I have a similar problem …

I have a pointer to an ON_BrepFace (called pbrepface). This is part of an ON_Brep that contains many ON_BrepFaces, but I am only interested in making a copy of the ON_BrepFace (with all the trims). I wish to store the copy of the ON_BrepFace in a new ON_Brep.
I am doing the following
ON_Brep* brep = new ON_Brep();
brep->AddSurface( pbrepface->DuplicateSurface() ); <-- this stores the untrimmed surface

How do I get the surface trimmed and converted an single ON_BrepFace in the new brep?

Thank you

Use ON_Brep::DuplicateFace(). See opennurbs.brep.h for details.

– Dale