# Solid Difference Failure

I ran into an issue using Solid Difference in Grasshopper. If the two objects are precisely on the same edge, it fails and produces an invalid Brep

Here is an example I made that demonstrates the issue:
Boolean Subtract Fail.gh (7.1 KB)

The center of the cylinder is 0.25" from the edge of the box. When I make the radius of the cylinder 0.25" the Solid difference fails.

If I make the radius 0.251" then it is fine

If I make it 0.2499" then it is also fine

Hello,

I think it is Non-manifold edges.

https://docs.mcneel.com/rhino/7/help/en-us/index.htm#popup_moreinformation/non-manifold_edges.htm

Boolean Subtract Fail.gh (21.4 KB)

If I understand the issue correctly, at that exact point the non-manifold condition results in some ambiguity that is causes the Boolean Subtract to failâ€¦ is there any way to make it work to get the desired result other than to make it slightly the wrong size?

If Non Manifold edges result in an invalid Brep, and effectively nothing is output, then isnâ€™t that the same as when Cap Holes fails to produce any output? So, shouldnâ€™t it turn red with an error the same way Cap Holes does?

@magicteddy put together a C# script that detects when a Boolean operation fails, but itâ€™s a workaround, I really think that if Solid Difference produces an invalid Brep for whatever reason, it should be producing the same error that Cap Holes produces. Just sitting there being all nice and grey like nothing is wrong makes it really difficult to figure out, especially if you have a complicated model and with a lot of operations, and the whole model just disappears, and you have no way to see why itâ€™s gone, you have to manually go look one item at a time until you figure it out, instead of just looking at the red thing.

I have no idea why this convoluted workaround works (at least, on this example), butâ€¦ it does !

ClosedBrep.gh (9.9 KB)

@magicteddy Thanks for figuring that out.

I can see why it works, Itâ€™s removing the Non-Manifold condition by breaking the part and creating a second intersection between the cylinder and the part.

It would only work if it was on one of the edges aligned with the Y axis, but I think I can make it work no matter what edge it is on. I thought I could just check to see if it was on the edge of X or Y and use whatever is needed, but then it would not work if the edge of the part was on a diagonal.

So I think I can maybe check to see if the cylinder is tangent to the closest edge of the part and if it is, put the plane in and rotate it 90 degrees to the tangent point and cut the part there, then it should work no matter what angle it happens to be at.

Edit:
I got to thinking about this and I think that if I cut the part in both the X and Y direction and then do the Solid Difference, then put them all back together, it would always work no matter the angle, because there would always be 2 points of contact with the cylinder no matter how it was rotated. It seems to work:

ClosedBrep XY.gh (11.8 KB)

Editâ€¦ Again:
using this method with both X and Y has a flawâ€¦ this can happen:

325 Degrees:

An alternate method that works in this case is to rebuild and replace the invalid brep face.

Bool_Sub_Fail_Repair_230108.gh (13.8 KB)

-Kevin

Doing the same operations in Rhino results in a Brep with a non-manifold edge.

Another topic with a similar problem:

@Gijs why isnâ€™t an invalid brep output displayed orange or red?

@Kevin
I like this idea better, because when you split the Brep and put it back together, you end up with these extra seams in the cylinder.

but this method doesnâ€™t do that. It also seems to work no matter the angle. I put the rotation in to test it, then I noticed that this only needs to be fixed when it lands on an edge that is aligned to the X or Y Axis. So I made it only run the repair if it is needed, that should speed things up.

180 Degrees:

239 Degrees:

Bool_Sub_Fail_Repair_Rotated.gh (12.6 KB)

It would be nice if the Boolean Subtract in both Rhino and Grasshopper checked for this issue and rebuilt the surface internally the way @kev.r fixed it. It seems it would be possible to have the boolean function just do a check at the end to see if the Brep is invalid, and if it is, apply the steps to repair it, otherwise just output it.

Hi,

I have merged several ideas posted here, and made the pipe so that the seam of the cylinder is always on the inside. This seems to be consistent, whatever rotation, position of the point, radius or depth is chosen.

ClosedBrep.gh (16.4 KB)

1 Like

Rotating the cube and cylinder around a common center point should produce the same result. As long as they have faces that are touching, they should produce a non-manifold edge.

You need to be careful about passing data through text panels like you are doing here:

This is rounding these values to what you see in the text panel (looks like 6 decimal places here but depends on grasshopper settings). Itâ€™s strange but even with the text panel bypassed your file only produces an invalid brep at certain rotation angles.

Check this file:

Bool_Sub_Fail_Repair_Rotated_re.gh (14.8 KB)
The Solid Difference component here produces an invalid brep regardless of the rotation angle.

Same result here (as expected) invalid brep at all rotation angles:

Bool_Sub_Fail_Repair_Rotated_re2.gh (15.3 KB)

The difference between your file with the text panel bypassed and these two methods is minute (centroids of the cylinders differ by 3.17E-15 or less) but itâ€™s apparently enough to change the results.

-Kevin

1 Like

@kev.r I didnâ€™t realize the output of the panel was any different than the input, unless I typed something in there. Thank you for letting me know that, I will avoid using the panels in this way.

James

I just noticed a new issue, if I pass supply multiple inputs, it works up to the point where it needs to be repaired, but then it doesnâ€™t continue with the rest of the inputs.

Here I gave it 5 input points, and I get 5 holes as expected:

But when I rotate it to a position where I have the invalid Brep, everything after the invalid Brep disappears.

Also, I am not passing through the panels anymore but I still get this only when itâ€™s at angles aligned to the XY axis. maybe it has to do with my Rhino tolerances? I think I am just in inches - small parts

It works if the â€śproblematicâ€ť hole is the last one on the listâ€¦ I guess the Solid difference stops working when it hits an invalid Brep ?

1 Like

Thatâ€™s what seems to be happening. Is there some way to process each hole one at a time and keep passing the output of each stage to the next so that one in the middle could be fixed if needed and continue?

Bruteforce, maybe ?

``````private void RunScript(Brep B, List<Brep> cutters, ref object holedBrep)
{
Brep brep = B;
for (int i = 0; i < cutters.Count; i++)
{
Brep[] sd = Brep.CreateBooleanDifference(brep, cutters[i], Rhino.RhinoDoc.ActiveDoc.ModelAbsoluteTolerance);
brep = sd[0];
if (!brep.IsValid)
{
List<Brep> bps = new List<Brep>();
foreach (BrepFace bf in brep.Faces)
{
Brep bfp = bf.DuplicateFace(false);
if(!bfp.IsValid)
{
Curve[] nedges = bfp.DuplicateNakedEdgeCurves(true, false);
Curve[] contour = Curve.JoinCurves(nedges);
Brep[] newfaces = Brep.CreatePlanarBreps(contour, Rhino.RhinoDoc.ActiveDoc.ModelAbsoluteTolerance);
}
else
{
}

}

brep = Brep.JoinBreps(bps, Rhino.RhinoDoc.ActiveDoc.ModelAbsoluteTolerance)[0];

}
}
holedBrep = brep;

}
``````

Thatâ€™s a great solution!

I thought it would be nice to know if the repair was needed, so I added a warningâ€¦ but then I thought it would be even better if there was a second test after the repair, and if it was invalid again to issue an errorâ€¦ in case there is some situation where itâ€™s not able to be repaired in this way, but Iâ€™m not sure what the syntax would be to make the second test after the repair.

So if it detected the invalid Brep and was able to repair it, issue a warning of â€śInvalid Brep Detected and Repairedâ€ť
and if it detects an invalid Brep a second time after the repair, issue an error of â€śInvalid Brep Detected. Unable to repair.â€ť

I donâ€™t know, but it would make sense to have it turn red though.
RH-72320 solid difference component doesnâ€™t turn red on invalid result