Mesh.QuadRemeshBrep fails on seemingly arbitrary translations of objects

Hi there,

I’m writing a plugin that involves generating a quad mesh from a Brep using Mesh.QuadRemeshBrep. I’ve noticed that this method will fail and return null consistently for certain Breps when they’re translated to certain locations. However, if I nudge the object over a fraction of a millimetre it will successfully mesh it.

I have a small test project which includes a Brep that illustrates this:
image

Looking at the two test cases that have a (0,0,0) offset that fail–notice that just a nudge of 0.001mm in the y direction can make them both pass

Is this known behaviour? Am I using QuadRemeshBrep incorrectly? Any help would be much appreciated!

Here’s the small unit test project:
QuadRemesh_ForumPost.zip (16.9 KB)

Hi @Dustin_Condon,

Attached is code to a simple Rhino command sample that seems to work with your model.

SampleQuadRemesh.cs (1.8 KB)

Note, I have not looked at your source code.

– Dale

Thanks for the reply!

Oh, so the source code involves translating the object to the problem position:

        [MemberData(nameof(TestData))]
        [Theory]
        public void QuadRemesh(Vector3d offset, double targetEdgeLength)
        {
            var center = new Point3d(48.799839823176981, 121.7702136798768, -2.2204460492503131E-16) + offset;

            var file = File3dm.Read("HalfConeCustom.3dm");
            var cone = file.Objects.Where(obj => obj.Geometry is Brep).Select(obj => obj.Geometry as Brep).First();

            var bb = cone.GetBoundingBox(false);
            var delta = center - bb.Center;
            Assert.True(cone.Translate(delta));

            var quadRemeshParams = new Rhino.Geometry.QuadRemeshParameters
            {
                TargetEdgeLength = targetEdgeLength
            };

            Assert.NotNull(Rhino.Geometry.Mesh.QuadRemeshBrep(cone, quadRemeshParams));
        }

Oh sorry I didn’t directly reply to your previous message, so you may not have gotten the notification. I also just wanted to note that this same thing has happened for some other Breps. This is just the first one I recorded and noted a problem position for.

Just to make make it easier to try out without trying to build that unit project, here’s a revised command that translates the object to the problem position and then tries to QuadRemesh it


  public class SampleQuadRemesh : Command
  {
      public override string EnglishName => "SampleQuadRemesh";

      protected override Result RunCommand(RhinoDoc doc, RunMode mode)
      {
          var go = new GetObject();
          go.SetCommandPrompt("Select object to remesh");
          go.GeometryFilter = ObjectType.Brep | ObjectType.Mesh;
          go.SubObjectSelect = false;
          go.Get();
          if (go.CommandResult() != Result.Success)
              return go.CommandResult();

          var rhinoObject = go.Object(0).Object();
          if (null == rhinoObject)
              return Result.Failure;

          var parameters = new QuadRemeshParameters()
          {
              TargetEdgeLength = 1,
              DetectHardEdges = true,
              SymmetryAxis = QuadRemeshSymmetryAxis.None,
              GuideCurveInfluence = 0,
          };

          if (rhinoObject.ObjectType == ObjectType.Brep)
          {
              if (rhinoObject.Geometry is Brep brep)
              {
                  var center = new Point3d(48.799839823176981, 121.7702136798768, -2.2204460492503131E-16);

                  var bb = brep.GetBoundingBox(false);
                  var delta = center - bb.Center;
                  brep.Translate(delta);

                  var remeshed = Mesh.QuadRemeshBrep(brep, parameters);
                  if (null != remeshed)
                  {
                      doc.Objects.AddMesh(remeshed);
                      doc.Views.Redraw();
                      RhinoApp.WriteLine("1 Brep successfully remeshed");
                  }
              }
          }
          else if (rhinoObject.ObjectType == ObjectType.Mesh)
          {
              if (rhinoObject.Geometry is Mesh mesh)
              {
                  var remeshed = mesh.QuadRemesh(parameters);
                  if (null != remeshed)
                  {
                      doc.Objects.AddMesh(remeshed);
                      doc.Views.Redraw();
                      doc.Views.Redraw();
                      RhinoApp.WriteLine("1 Mesh successfully remeshed");
                  }
              }
          }

          return Result.Success;
      }
  }

Hi @Dustin_Condon QuadRemesh doesn’t support double precision floating points. So, you’ll always want to remesh as close to origin as possible and then translate the results to your final location (center).

Something like this should do the trick.

if (rhinoObject.Geometry is Brep brep)
        {
          var center = new Point3d(48.799839823176981, 121.7702136798768, -2.2204460492503131E-16);
          var bb = brep.GetBoundingBox(false);
          brep.Translate(Point3d.Origin - bb.Center);
          var remeshed = Mesh.QuadRemeshBrep(brep, parameters);
          if (null != remeshed)
          {
            remeshed.Translate(center - Point3d.Origin);
            doc.Objects.AddMesh(remeshed);
            doc.Views.Redraw();
            RhinoApp.WriteLine("1 Brep successfully remeshed");
          }
        }
2 Likes