[Rhinocommon] Possible bug when splitting a brep face multiple times

When I run the command given in the code below on just a simple Plane surface, the splitting the plane’s only BrepFace (let’s call it I) once results in a Brep with two faces. Let’s call them A and B.

Split(I) => [A|B]

When I subsequently split face A again, let’s call the two halves of this splitting A1 and A2. The result, however, is a Brep with three faces: A1, A2 and B. I think that the split operation on A should not include face B.

Split(A) => [A1|A2|B] This is what I find
Split(A) => [A1|A2] This is what I expect

Brepface Split Results.3dm (48.9 KB)

protected override Result RunCommand(RhinoDoc doc, RunMode mode)
{
    ObjRef srfRef;

    Result res = RhinoGet.GetOneObject("Select surface to split", false, ObjectType.Surface, out srfRef);
    if (res != Result.Success) return res;

    BrepFace bf = srfRef.Surface() as BrepFace;
    if (null == bf)
        return Result.Failure;

    bool atV = false;
    res = RhinoGet.GetBool("Split at U or V isocurve?", true, "U", "V", ref atV);
    if (res != Result.Success) return res;

    Split( new[] {bf}, atV, doc);
    doc.Views.Redraw();
    return Result.Success;

}

private Result Split(BrepFace[] faces, bool atV, RhinoDoc doc)
{
    foreach (var bf in faces)
    {
        GetPoint splitAtPoint = new GetPoint();
        splitAtPoint.Constrain(bf, false);
        splitAtPoint.DynamicDraw += (o, a) =>
        {
            double u, v;
            if (bf.ClosestPoint(a.CurrentPoint, out u, out v))
            {
                Curve iso = bf.IsoCurve(atV ? 0 : 1, atV ? v : u);
                a.Display.DrawCurve(iso, Color.LightGray);
            }
        };
        GetResult res = splitAtPoint.Get();
        if (res == GetResult.Point)
        {
            double u, v;
            if (bf.ClosestPoint(splitAtPoint.Point(), out u, out v))
            {
                Curve[] iso = bf.TrimAwareIsoCurve(atV ? 0 : 1, atV ? v : u);
                if (iso.Length == 1)
                {
                    Brep split = bf.Split(iso, doc.ModelAbsoluteTolerance);
                    if (split.Faces.Count > 2)
                    {
                        doc.Objects.Add(bf.DuplicateFace(false), new ObjectAttributes {Name = "input"});
                        doc.Objects.Add(split, new ObjectAttributes {Name = "result with >2 faces!"});
                        return Result.Failure;
                    }
                            
                    doc.Objects.Add(split, new ObjectAttributes {Name = "split with <= 2 faces!"});
                    Split(split.Faces.ToArray(), atV, doc);
                }
            }
        }
        if (res == GetResult.Cancel)
            return Result.Cancel;
    }
    return Result.Success;
}

I will look at this today.

– Dale

Thanks for looking into it. It had me puzzled for a while, but I have a workaround now.

I think there is some confusion on what BrepFace.Split returns. Keep in mind that a BrepFace is owned by a Brep. When you split a face, the split pieces are added to the owning Brep. I believe you are assuming that BrepFace.Split returns a new Brep created from the pieces of the split face, which is not how the function works.

Does this help?

Thanks @dale that clears this up.

I have also splitted one surface into two, but when I am drawing the splitted brep, it is giving a polysurface…

How to keep one part of the surface and delete the other part? Should I use trim? For trim I have an irregular curve , which is cutting the surface properly. I need to keep one part of the surface and delete the other part…

Which one I should use trim or split? I need to keep one part of the splitted surface or trimmed surface…
Any source code sample will be a big help.

Sorry for bothering you, found the answer from another post… Thanks !