Hi there,
I’m working on a plugin that includes functionality for algorithmically generating curves on the surface of an arbitrary Brep. In the process of generating these curves, I tend to first use the UnderlyingSurface of a BrepFace. But then I need to trim a generated curve according to the BrepFace, so that none of the curve spans a “hole” in the brep or go off the edge. I’ve managed to cobble something together to do this, but I feel it has some numerical issues, e.g. when dealing with very small BrepFaces with correspondingly small trim curve, sometimes my trimming function leaves segments of the curve that go off the surface, or span holes in the BrepFace. Additionally, I’ve found this to be rather slow when there are many holes/trims in the BrepFace.
Here is the function, which relies mainly on Intersection.CurveBrep to get curve parameters that intersect with the brep. Note the snippet contains some library functions for map/filter and Option (some/none), but hopefully it should still be understandable:
/// <summary>
/// Returns all the curve segments that rest on the brep in order of the curve's parameterization direction.
/// </summary>
public static Interval[] CookieCutCurveByBrep(Curve curve, Brep brep, double tolerance)
{
Rhino.Geometry.Intersect.Intersection.CurveBrep(curve, brep, tolerance,
tolerance, out var intersectionParams);
var parameters = intersectionParams
// Always append the start and end parameters of the curve, just in case those
// points are slightly away from the surface causing them not to be in the
// `interesectionParams` array
.Prepend(curve.Domain.T0).Append(curve.Domain.T1);
var segments = OverlappedSegments(curve, brep, parameters.OrderBy(a => a).ToList(), tolerance);
if (!segments.Any())
{
return [];
}
return segments;
// Using the intersection points, figure out which intervals are on the surface and which are off
static Interval[] OverlappedSegments(Curve curve, Brep brep, IEnumerable<double> intersectionPts, double distanceTolerance)
{
// works like rust's `Windows(2)`, returning adjacent entry pairs in the collection
return intersectionPts.Windows()
.FilterMap(pair =>
{
var (prev, next) = pair;
//------------------------------------------------
// The Intersection.CurveBrep(...) function can
// return noisy domain points--multiple points
// very close to each other which can create very
// small segments. We ignore those segments here
// ...............................................
var interval = new Interval(prev, next);
var segmentLength = curve.GetLength(interval);
if (segmentLength < distanceTolerance)
{
return Option.None;
}
var mid = (next + prev) / 2.0;
var midPt = curve.PointAt(mid);
var isPointOnSurface = brep.ClosestPoint(midPt, out _, out _, out _, out _, distanceTolerance, out _);
return isPointOnSurface
? Option<Interval>.Some(new Interval(prev, next))
: Option<Interval>.None();
}).ToArray();
}
}
I have just discovered a method BrepFace.TrimAwareIsoCurve(...) that I’ve found is much faster and provides better results than my method. However I can’t always use this function to generate my surface curves, b/c they may not always be isocurves, and might instead any arbitrary curve on the surface.
So my question is, does there exist a standard method for trimming my arbitrary surface curve according to the BrepFace’s trims? Perhaps it might include getting my surface curve into the underlying surface’s UV parameter space first?
Any help would be much appreciated.
Dustin