I’m writing a C# rhino plugin where I edit some geometries and then add them to the RhinoDoc by manually calling Rhino.RhinoDoc.ActiveDoc.Objects.Add, but then if I look at the added geometry in the doc I see that the number of faces, edges and vertices has changed.
Why is my geometry modified ? Is there a way to prevent this ?
If this is a quality check, how can I perform the same operations on my geometries beforehand to be iso ?
Also I’m not sure if this is related but when I try to call CreateFilletEdges on the added brep in the doc sometimes it fails to join the created fillets and the brep making 2 separate objects. Why is that and is there a way to know beforehand if this behaviour will happen (some kind of sanity check), so that I can avoid wasting time baking objects incompatible with filleting ?
Here is the Data that you can use : FailingData.zip (957.2 KB)
BakeDifferentThanGeometry : contains the data to run the following test where baked data is different than the starting geometry
FailingFillets : contains a brep example where fillet operation fails for some reason.
Here is the code for my baking test :
public void RegressionTestForMcNeel()
{
string file = [ADD_PATH_TO_FILE_HERE] + "\\BakeDifferentThanGeometry.3dm";
Rhino.RhinoDoc.Open(file, out bool _);
// load support curve and slices
RhinoObject[] objs = Rhino.RhinoDoc.ActiveDoc.Objects.FindByLayer("support");
NurbsCurve support = objs != null && objs.Length == 1 ? (NurbsCurve)objs[0].Geometry : null;
objs = Rhino.RhinoDoc.ActiveDoc.Objects.FindByLayer("slices");
var objList = objs.ToList();
objList.Sort((a, b) => a.Name.CompareTo(b.Name));
var slices = new List<NurbsCurve>();
foreach(var obj in objList)
{
slices.Add(obj != null ? (NurbsCurve)obj.Geometry : null);
}
// then compute sweep
Brep[] res = Brep.CreateFromSweep(support, slices, true, Rhino.RhinoDoc.ActiveDoc.ModelAbsoluteTolerance);
Assert.That(res.Length != 0);
var swept = res[0];
// bake it to compare
Guid addedId = Rhino.RhinoDoc.ActiveDoc.Objects.Add(swept);
Brep baked = (Brep)Rhino.RhinoDoc.ActiveDoc.Objects.FindId(addedId).Geometry;
Assert.That(AreBrepsIdentical(baked, swept, RhinoUtils.getTolerance()));
}
// utility functions for testing geometry equality
public static bool AreBrepsIdentical(Brep brep1, Brep brep2, double tolerance)
{
if (brep1.Faces.Count != brep2.Faces.Count ||
brep1.Edges.Count != brep2.Edges.Count ||
brep1.Vertices.Count != brep2.Vertices.Count)
return false;
// Compare surfaces
for (int i = 0; i < brep1.Faces.Count; i++)
{
Surface srf1 = brep1.Faces[i].UnderlyingSurface();
Surface srf2 = brep2.Faces[i].UnderlyingSurface();
if (!AreSurfacesIdentical(srf1, srf2, tolerance))
return false;
}
// Compare edges
for (int i = 0; i < brep1.Edges.Count; i++)
{
NurbsCurve curve1 = brep1.Edges[i].ToNurbsCurve();
NurbsCurve curve2 = brep2.Edges[i].ToNurbsCurve();
if (!AreCurvesIdentical(curve1, curve2, tolerance))
return false;
}
return true;
}
public static bool AreSurfacesIdentical(Surface srf1, Surface srf2, double tolerance)
{
if (srf1.Domain(0) != srf2.Domain(0) || srf1.Domain(1) != srf2.Domain(1))
return false;
for (double u = 0.0; u <= 1.0; u += 0.25)
{
for (double v = 0.0; v <= 1.0; v += 0.25)
{
Point3d p1 = srf1.PointAt(srf1.Domain(0).ParameterAt(u), srf1.Domain(1).ParameterAt(v));
Point3d p2 = srf2.PointAt(srf2.Domain(0).ParameterAt(u), srf2.Domain(1).ParameterAt(v));
if (!p1.EpsilonEquals(p2, tolerance))
return false;
}
}
return true;
}
public static bool AreCurvesIdentical(Curve curve1, Curve curve2, double tolerance)
{
if (!curve1.Domain.Equals(curve2.Domain))
return false;
for (double t = 0.0; t <= 1.0; t += 0.2)
{
Point3d p1 = curve1.PointAt(curve1.Domain.ParameterAt(t));
Point3d p2 = curve2.PointAt(curve2.Domain.ParameterAt(t));
if (!p1.EpsilonEquals(p2, tolerance))
return false;
}
return true;
}
Now that I have no more baking problem I still have to find a way to know beforehand if my brep is valid for fillet operation success… I’ll create a separate post about his maybe