Brep.Edges.SplitEdgeAtParameters working in Python but not in C#

Hi there,

I found a very nice script for splitting brep edges a disontinuities in python.
Sadly I lost the link so I cannot give credits, but I will post it here.

I tried to code this in C#. It finds the kinks, but when I try to use SplitEdgeAtParameters it returns an invalid brep.

The challenge in this I see is of course that we collect edges and their indices and kinks.
Once we treat/split them we create new edges and indices might shift. But it actually works in the python version and I cannot see a difference in the C# version.

A possible solution for me would be to duplicate all edges, split them and create a new brep out of the curves afterwards.
I would like to avoid this, becuase I also wanna do this on solid breps and nurbs surfaces and rebuilding them would not be such a smart idea.

Thanks,
T.

Python version from the forum:

import Rhino
import Rhino.Geometry as rg
import scriptcontext as sc
from Rhino.Input import RhinoGet
from Rhino.DocObjects import ObjectType


def find_kinks(curve, angle_tolerance):
    """Find parameters where kinks (G1 discontinuities) occur."""
    kinks = []
    t = curve.Domain.Min
    t_end = curve.Domain.Max
    while True:
        success, next_t = curve.GetNextDiscontinuity(
            rg.Continuity.G2_locus_continuous, t, t_end)
        if not success:
            break
        kinks.append(next_t)
        t = next_t
    return kinks


def main():
    # Pick brep
    rc, obj_ref = RhinoGet.GetOneObject(
        "Select a Brep", False, ObjectType.Brep)
    if rc != Rhino.Commands.Result.Success or obj_ref is None:
        return

    brep = obj_ref.Brep()
    if brep is None:
        return

    angle_tol = sc.doc.ModelAngleToleranceRadians

    # Work on a duplicate
    new_brep = brep.DuplicateBrep()

    # Collect edges to split (index + kink parameters)
    edges_to_split = []
    for i in range(new_brep.Edges.Count):
        edge = new_brep.Edges[i]
        kinks = find_kinks(edge, angle_tol)
        if kinks:
            edges_to_split.append((i, kinks))

    # Split the edges
    for edge_index, kink_params in edges_to_split:
        new_brep.Edges.SplitEdgeAtParameters(
            edge_index, System.Array[float](kink_params))

    new_brep.Compact()

    # Replace object in document
    if sc.doc.Objects.Replace(obj_ref, new_brep):
        print("Brep edges split at kinks successfully.")
        sc.doc.Views.Redraw()
    else:
        print("Failed to replace brep.")


import System
if __name__ == "__main__":
    main()

My C# version

private List<double> FindKinks(Curve curve)
{
    List<double> kinks = new List<double>();

    double t = curve.Domain.Min;
    double tEnd = curve.Domain.Max;

    double nextT;
    while (true)
    {
        bool res = curve.GetNextDiscontinuity(Continuity.G2_locus_continuous, t, tEnd, out nextT);
        if (res == false)
            break;

        else
        {
            kinks.Add(nextT);
            t = nextT;
        }
    }

    return kinks;
}

public Brep SplitAtKinks(Brep brep)
{
    Brep dup = brep.DuplicateBrep();

    List<KeyValuePair<int, List<double>>> edges = new List<KeyValuePair<int, List<double>>>();

    for (int i = 0; i < dup.Edges.Count; i++)
    {
        BrepEdge edge = dup.Edges[i];
        List<double> kinks = FindKinks(edge);

        if (kinks.Count > 0)
        {
            edges.Add(new KeyValuePair<int, List<double>>(i, kinks));
        }
    }

    foreach (var edge in edges)
    {
        dup.Edges.SplitEdgeAtParameters(dup.Edges[edge.Key].EdgeIndex, edge.Value.ToArray());
    }

    dup.Compact();

    return dup;
}

@dale maybe you know something about this behaviour?

Hi @tobias.stoltmann,

The two versions are really doing the same thing — the C# and Python end up calling the same SplitEdgeAtParameters with the same edge index and parameters, so the code isn’t the difference.

My guess is the Python result is invalid too — you just don’t see it, since the script only prints success and Objects.Replace will accept an invalid brep without complaint. Try IsValidWithLog on both results and compare.

If you just want to split a brep at its kinks, I’d use the built-in Brep.SplitKinkyFaces() rather than rolling your own — it handles the trims and tolerances for you.

Post a sample .3dm if you’d like me to look closer.

Thanks,

– Dale

Hi @dale,

I will prepare a sample for you and run your options in the python code.

What I don’t understand is that the python-version splits everything as it’s supposed to be!

@dale
The output of IsValidWithLog() is: (True, None)
I guess I have a special case here.

I guess that Brep.Faces.SplitKinkyFaces() deals with kinks in solids or polysurfaces, right?
I tried using it in the first place, but it did not split the edges, as I suppose it is designed to split faces, right?
What I am referring to is a single-faced brep, or let’s say a surface.
Sometimes the edges are too smooth and I need to split them at significant transitions.

So in this case I think I really need SplitEdgeAtParameters - or am I using SplitKinkyFaces the wrong way maybe?

Hi @tobias.stoltmann,

It might help to know what problem you are trying to solve? Why do you want to split edges?

A .3dm file might be helpful.

– Dale

Thanks @dale.
when dealing with panels we usually operate with single-faces surfaces.
When we process them to panels with let’s say upturns, etc… it is essential that we know which edge is linear and which one is curved.
In the file I uploaded you can see that the curves are too smooth. So the idea is to run a kind of “therapy” that will e.g. split the edges into their linear parts and the curved parts.
(The next thing to think about is to merge edges with a certain tolerance, but I’ve seen there already is a method for it).

FileDale.3dm (47.6 KB)

So basically:

  1. DupBorder
  2. Explode
  3. Join
  4. PlanarSrf

This this correct?

– Dale

@dale, exactly.
Sometimes when you explode some curves are still to smooth and you have to run the FindKinks method (or maybe better DuplicateSegments())?

The thing is: It would basically be cool if this would work on solid breps as well.
I think the approach you described only works for single-faced breps, right?

Hi @tobias.stoltmann,

Give this a try.

TestSplitEdgesAtKinks.cs (3.7 KB)

– Dale

@dale, thanks a lot!