How to flatten accurately?

Hello,
I’m trying to flatten a 3d shape. The 3d shape is a brace intended to fit a patient’s leg. I want to cut some foam to protect the leg from the brace.
In Solidworks, I create an offset surface 3mm from the brace, then I flatten, giving a seam right in the middle of the brace. The result is always accurate.
I’m trying to perform the same steps in Rhino but the result is quite different (blue: Solidworks).

The 3mm offset works fine.
toFlatten = Brep.CreateOffsetBrep(originalBrep, PluginModel.Instance.IsLeftLeg ? offsetInward : -offsetInward, false, false, tolerance, out _, out _).FirstOrDefault();

result_solidworks.DXF (84.0 KB)
sagittalPlane.dxf (158.9 KB)
squished.dxf (546.2 KB)
originalBrep.dxf (281.5 KB)
rhino settings.txt (2.5 KB)

Cutting with a vertical plane works fine:
var splitBreps = SplitBrepWithPlane(toFlatten, sagittalPlane, PluginConstant.Tolerance);
where

    public static Brep[] SplitBrepWithPlane(Brep brep, Plane plane, double tolerance)
    {
      var bbox = brep.GetBoundingBox(false);

      //Grow the boundingbox in all directions
      //If the boundingbox is flat (zero volume or even zero area)
      //then the CreateThroughBox method will fail.
      var min_point = bbox.Min;
      min_point.X -= 1.0;
      min_point.Y -= 1.0;
      min_point.Z -= 1.0;
      bbox.Min = min_point;
      var max_point = bbox.Max;
      max_point.X += 1.0;
      max_point.Y += 1.0;
      max_point.Z += 1.0;
      bbox.Max = max_point;

      var plane_surface = PlaneSurface.CreateThroughBox(plane, bbox);
      return brep.Split(plane_surface.ToBrep(), tolerance);
    }

However, flattening each part individually is inaccurate:

        foreach (var splitBrep in splitBreps)
        {
          var toSquish = CreateMeshFromBrep(splitBrep, MeshingParameters.QualityRenderMesh);
          SquishParameters squishparams = new SquishParameters();
          squishparams.Algorithm = SquishFlatteningAlgorithm.Geometric; // also tried PhysicalStress
          // tried default + various other parameters. Solidworks seemed to have a strong bias to preserving boundary lengths at the expense of interior distortion, and no preference between compression and stretching
          squishparams.SetSpringConstants(boundaryBias: 1.0, deformationBias: 0.0);
          Rhino.Geometry.Squisher squisher = new Squisher();
          // actually squish the mesh
          Mesh squished = squisher.SquishMesh(squishparams, toSquish, geometryToFollow, squishedGeometryToFollow);
          // then some logic to stitch the parts together

where

 public static Mesh CreateMeshFromBrep(Brep brep, MeshingParameters method)
    {
      var meshes = Mesh.CreateFromBrep(brep, method);
      if (meshes == null || meshes.Length == 0)
        return null;
      var result = new Mesh();
      foreach (var mesh in meshes)
        result.Append(mesh);
      return result;
    }

Stitching: Solidworks seemed to keep the beginning of the curve (boundary between the 2 meshes = intersection of plane with toFlatten).
I’m doing a best fit on 10 points at the beginning of the curve (first third), it seems to work fine.

Do you have any suggestions to get a result that matches the result by Solidworks?
I’ve tried to use an Unroller, a Squisher, each with many parameters, with and without the seam in the middle, and I’m running out of options.
Thanks!

Hi,
Sadly rhino unroll/smash doesnt work accurately, I had the same problem with curved parts
The solution I found is the following

  1. Create planes every X units (depending on accuracy required)
  2. Section the surface on every plane
  3. Get sectioned curve length
  4. Recreate the shape using the calculated length

If you need any help reach out to me at farouk.serragedine@gmail.com
https://www.youtube.com/@shipdesigner977/videos

Hi @osskin333,

Rhino has a couple of tools for flattening surfaces.

https://docs.mcneel.com/rhino/7/help/en-us/index.htm#seealso/sak_flatten.htm

Please try the Rhino commands. If you find something that works, per your requirement, then we can discuss how to access via some SDK.

Thanks,

– Dale

Hi @dale ,
Thanks for your reply.
My problem is that I could not get any of these to work.

  • InsertLineIntoCrv = not what I’m trying to achieve, this is trimming a curve
  • FlattenSrf = as per description, works only on developable surfaces (and then, may not work for all developable surfaces).
  • Smash = haven’t tried, said to be deprecated in favor of squish ( Advanced Flattening [McNeel Wiki] )
  • Squish = cannot get it to provide accurate results, see code snippet and result.
  • SquishBack = opposite of what I’m trying to do, from 2D to 3D.
  • Unrollsrf = cannot get it to provide accurate results, had even worse result than Squish, using similar code (replacing Squisher with Unroller).

I was hoping maybe there would be some parameters for Squish or Unroll that I should try and may yield better results?

Thanks @farouk.serragedine ,
It looks like a bit of custom code but it’s worth trying.
I will look at your videos to see if you give more details about the implementation (edit: videos didn’t provide implementation details). I will post my understanding but I’d appreciate if you can post your ideas too.

In particular, for step 1, I think there are 2 ways to do the planes (which one from your experience would give better results?):

  • horizontal planes = spaced every x mm
  • vertical planes = going through the leg axis (vertical) and angled every x degrees.

And I get how to get the length of the curve (step 3) but maybe not how to position each curve relative to the previous slice (step 4).

Hello
can you post the geometry of the Brep ? I have dome some tool to flatten curved surface so I want to test with your geometry.

It is a bit strange that you speak of accuracy for a such a problem. I don’t know an accurate 2D map of the Earth! Except Solidworks what is good for you ? The surface, the length, confort of patient … ?

1 Like

Hi,
Depending on how curved the object is, or if it presents any holes or irregular borders on the sides, you may have to do a matrix for vertical/horizontal planes and reconstruct.
That being said, if the outside borders are regaular, and there are no holes on the inside of the shape, I just run the planes along the longest edge.
If you need any help do not hesitate to contact me, I already have a working solution to your problem.

Farouk,

Hi @laurent_delrieu,
I’ve posted the brep: toFlatten.dxf but I’m not sure if you can use it as is, I will see if I can export to a different format.
What is good:
I laser cut the outline (2D) then I try to glue it to the (3d) brace.
Solidworks is good means: it just falls into place, the foam outline follows the brace outline.
Rhino is not good means: you can typically fit one side of the foam but then the rest is out of place.
The red curves are expected to match the green curves.


Sorry I could not get a better image: the foam has a square bottom left corner due to another step that is unrelated. Same with the top left corner that is cut. But the green line and red line should match (they match with the foam cut from Solidworks).

I am not used to open 3d dxf and for me it is just curves. So I can’t use it. I prefer to have a mesh.

In order to have flatten a surface I suppress all inner points of the mesh.

These spikes are usually an indicator that the original surface isn’t very good, either at all or for unrolling/squishing. Start by making a better surface. Squish and UnrollSrf work well if the input surface is good.

Give us a 3dm of the surface that you unrolled and we’ll see if we can help with improving the surface creation.

1 Like

Thanks @Ncik and @laurent_delrieu ,
Here are the 3dm files:
originalBrep.3dm (107.0 KB)
sagittalPlane.3dm (26.1 KB)
squished.3dm (60.4 KB)
I think you’re right that the mesh could be improved for the top right area.
The spike in the central area is “expected”, my steps are:

  1. split the originalBrep with sagittalPlane
  2. squish each side independently
  3. move and rotate the second side, so that the beginning of the curves match (see drawing below: after squish, the intersection with sagittal plane is not straight, so I rotate to attain best fit on the blue area).

    My problem really is that squish or unroll don’t give an accurate shape, whether I split or not.
    Thank you for helping me!

Hello
here are some test with my plugin
First step is to mesh the shape. Here I didn’t try to use options of remeshing.
After the remeshing I suppress all inner points. I have 2 slightly differences. So I let in the script the 2 meshes.

After that it is the unrolling.
What I can say f my algorithm is that it keeps the surface (of the mesh with no inner points) and it keeps the naked edges length (borders length). In “real” life in order to have good clearances I move the vertices of the mesh with no inner points. It allows me to have better objects for fabrication.
My tools allows then to come back in 3D if necessary

suppressInnerPointUnrol.gh (95.1 KB)

1 Like

Hi @osskin333

FWIW I did a quick test to illustrate how the input mesh for squishing affects the output.

First I created a fairly dense mesh from the brep, then used the quadremesh tool to make a clean homogeneous mesh and squised that.
The results are quite different as you can see.
squish.3dm (830.1 KB)

Not a big difference with my method with the advantage of being a Rhino method


squish.3dm (886.5 KB)

2 Likes

Thanks @Willem, the result does look much better with QuadRemesh before squish or unroll!
I will try on different geometries but this looks promising.
I tried to load @laurent_delrieu 's grasshopper module but got stuck loading Nautilus. Then I started implementing @farouk.serragedine 's solution but if this works, it will save me some time!

Yes my plugin is not yet published, in 1 week or 2. But it is not mandatory as you have many others ways.

Hi,
I’ve performed additionnal tests on other geometries.
I would say the result is amazing on 7 / 10 cases (within 1mm of Solidworks, which is always accurate).

3/10 cases are really weird.
See test 9:


I’ve attached:

  • the original brep
  • the mesh after quad remesh (looks good)
  • the result of squish operation (looks bad)
  • the outline from solidworks

test9_squished.3dm (73.1 KB)
test9_originalBrep.3dm (144.9 KB)
test9_quadRemeshed.3dm (116.0 KB)
test9_solidworks.DXF (87.4 KB)

Test 10 is similar:


Sending the attachments as well:
test10_squished.3dm (72.2 KB)
test10_originalBrep.3dm (198.1 KB)
test10_quadRemeshed.3dm (113.9 KB)
test10_solidworks.DXF (112.9 KB)

Do you have any idea what I could change to get a better result?
I’m using the default squish parameters, just setting SquishFlatteningAlgorithm.Geometric and PreserveTopology = true.

Edit: in case that can give a hint, I’ve tried to split the mesh in 2 like I was doing initially. One of the sides gets squished fine, the other one not so well.


I think I’ll try to increase the mesh density and post the result.
Edit: similar result with QuadRemesh target edge length = 0.2 (see below) or 1.0 (not shown).

I’ve decided to try a coarser mesh (QuadRemesh with target edge length = 20). The idea comes from @laurent_delrieu whose method removes the internal edges.
The resulting shape is not too bad (on examples 9 and 10 that failed).
Test 9


Test 10

The outline is very coarse so I tried some intermediate target length (5, 10, 12, 15) but all failed (QuadRemesh > returns null).

So I’ve tried to mesh the Brep into a coarser mesh (MeshingParameters.FastRenderMesh) then QuadRemesh with an intermediate target length (5) and the results look promising:
Test 9:


Test 10:

I’ll try the other tests and keep you posted.

My try on the 9


flatten.gh (105.3 KB)
If you want to try the plugin for 1 day !!
net48.zip (840.9 KB)


flatten10.gh (195.6 KB)

My tool is not perfect and mesh has to be sometime changed in order to make the suppress inner point work.

Hi and thanks a lot. With your help, now, on all my test cases, I have some parameters that work.
Short question:
How to get squish report (max compression / max stretch in %) programmatically?

Reason:
The parameters that work are not always the same and I cannot find a logical reason behind it.
For example: on one brep, I do quad remesh with target edge length 7.0mm, then SquishMesh is accurate. On the same brep offset by 0.5mm, I need to use target edge length 10mm (7.0 mm not accurate). Target edge 10mm does not work on the original brep.
I’m not planning on finding the root cause. Instead, I prefer to try many parameters and select the best.
I’ve noticed that:

  • the parameters that work, apply little compression/stretch.
  • the parameters that don’t work, apply a lot of compression/stretch.

I figured this out visually by setting AbsoluteLimit = 0.96 (or -0.96) to have at most 4% stretching (or compression). The parameters that work, give the same result with/without the absolute limit (this proves that compression and stretch were both < 4%). The parameters that don’t work give a different result (typically: scaled up / down).

I’ve noticed that the Squish command from Rhino can give a report with compression/stretch.

However, I cannot find this information in the Squisher class.
https://developer.rhino3d.com/api/RhinoCommon/html/Methods_T_Rhino_Geometry_Squisher.htm
Can someone explain how to get this information programmatically? I’m specifically looking for the maximum stretch / maximum compression in %. After a call to Squisher.SquishMesh.