Testing Plane IsCoplanar Equation

@dale

I’m following this SampleCsExtrusion sample code by Dale Fugier as a guide to creating some extrusions of concrete slabs.

I am reading point list data from a text based file. The file contains outer profile points for the boundary of the slab and inner profile points for the openings (voids) in the slab.

The notation used is:
Outer profile points are ordered clockwise.
Inner profile points are ordered anti-clockwise.

The extension method in the sample code that checks if profile planes are Coplanar will never be true in my case as the “Cz” parameter of the GetPlaneEquation() returns 1 and -1 due to normals pointing in opposite directions.

My work around at the moment is to flip the inner profile plane before the check.

Question 1:
I this the best approach to construct extrusions with inner profiles from points sorted in opposite directions or is there a better method in doing this.

Question 2:
The points always reference the top of the slab, so my extrusion direction is down rather than the usual up direction. Not quite clear on how to go about it. Currently I am feeding in a negative double, but it makes the code messy and not very readable.

Question 3:
Is there a way to achieve this by using Brep and is this recommended. I read elsewhere in the forum that boolean operation can get tricky?

Further to my questions above, I have also discovered that if the innerprofiles shares a edge with the outerprofile the subtraction of innerprofile does not work properly. :smirk: :grimacing:

image

Any advice will be appreciated. :pray: :roll_eyes:

In Grasshopper my issue get worse.
image

Maybe if I add the code I’ll get a better response.
The line below the comment is the only change made to @dale (Dale Fugier) method.

public Extrusion CreateExtrusion(Curve outerprofile, List<Curve> innercurves, double height)
        {
            if (!outerprofile.TryGetPlane(out Plane plane))
                return null;
            var path = new Line
            {
                From = plane.PointAt(0.0, 0.0, -height),
                To = plane.PointAt(0.0, 0.0, 0.0)
            };
            if (!path.IsValid || !(path.Length > RhinoMath.ZeroTolerance))
                return null;
            var up = plane.YAxis;
            var tangent = path.To - path.From;
            tangent.Unitize();
            if (!up.IsValid || !up.IsUnitVector || Math.Abs(up * tangent) > RhinoMath.SqrtEpsilon)
                return null;
            var xform = Transform.ChangeBasis(Plane.WorldXY, plane);
            var curve = outerprofile.DuplicateCurve();
            curve.Transform(xform);
            curve.ChangeDimension(2);
            var extrusion = new Extrusion();
            extrusion.SetOuterProfile(curve, true);
            foreach (var profile in innercurves)
            {
                if (profile.TryGetPlane(out Plane curve_plane))
                {
                    /*This is the only line of code I added.
                      Else all is the same as Dale Fugier's Method.*/
                    curve_plane.Flip();

                    if (plane.IsCoplanar(curve_plane, RhinoMath.ZeroTolerance))
                    {
                        curve = profile.DuplicateCurve();
                        curve.Transform(xform);
                        curve.ChangeDimension(2);
                        extrusion.AddInnerProfile(curve);
                    }
                }
            }
            extrusion.SetPathAndUp(path.From, path.To, up);
            return extrusion.IsValid ? extrusion : null;
        }

Since you didnt mention it, first question would be: what tolerance setting are you using, and if you see any improvement if you lower, eg from 0.01 to 0.1 your settings.

Q3: If you boolean difference from a brep, i noticed its more reliable if your difference volume is larger than the actual cut. So in your case, that would mean the inner profile should be extruded larger than the slab.

@rgr thanks for your reply.

Tolerances is one off the first things I tried, but sadly had no effect. The sides are 100% collinear.

As I am reading the data from a foreign file I don’t have much room to change geometry. If I roll with a brep alternative I could extend the capped faces by say 10mm up and down to ensure the boolean difference succeeds.

I think l’ll code up brep methods and see how this works out.

I was hoping there would be a fix for @dale methods as I like the principal of outer and inner curves before extrusion. Make the code so clear. But no suggestion yet.

We have always encountered uncertain behaviour with overlapping curves as the base of intersecting volumes, so my best bet would be to go for brep difference and, if possible, extend your brep so you have no overlapping edges at all.

However, maybe as a workaround, you can check if curve boolean gives you a viable result and then skip the inner curves at all.

@rgr That’s exactly my thoughts.

What I’m doing at the moment is to code up a IsCollinear check. Basically enumerating through the edges of the outer curve and check if any pair of points in sequence falls on top of the curve within ModelAbsoluteTolerance. If true, CreateBooleanUnion() the outer curve and that particular inner curve to form a new outer curve. Then repeat the process with the new outer curve.

Will post if I can get this working. Sounds like the way to go anyway.

Hi @Big_G,

Rather than using the sample’s IsCoplanar method, you might also just compare plane normals using Vector.IsParallelTo, which allows you to specify an angle tolerance.

Since your points are oriented, you can create polyline curves from them and then figure out their orientation using Curve.ClosedCurveOrientation.

Does this help?

– Dale

Hi @dale,

I am already creating polyline curve from the points.

My issue is really the the two curves being outer curve and inner curve have a collinear edge and this results in and extrusion that fail to recognise the inner curve void. I end up with a unwanted face or a double extrusion.

I have some pictures and code earlier in the post.

Thanks for the reply.

Hi @Big_G,

In this case, I’d subtract the ‘inner’ curve from the outer curve using Curve.CreateBooleanDifference.

– Dale

Thanks @dale. The Curve.CreateBooleanDifference() works well.