I would like to remove all duplicated brep faces for a flown brep unsuccesfully using the methdod: _myBrep.MergeCoplanarFaces(double tolerance)
but it always return false and it doesn’t remove any coplanar face.
I also tried to use the mothod IsDuplicated with same result:
public static bool RemoveDuplicatedFaces(Brep input, bool removeBothFaces)
{
var duplicatedFaces = new List<int>();
for (var i = 0; i < input.Faces.Count; i++)
{
var face1 = input.DuplicateSubBrep(new[] { i});
for (var j = i+1; j < input.Faces.Count; j++)
{
var face2 = input.DuplicateSubBrep(new []{j});
if (face1.IsDuplicate(face2, 0.001)) //<- it always return false
{
duplicatedFaces.Add(i);
if (removeBothFaces)
duplicatedFaces.Add(j);
break;
}
}
}
duplicatedFaces = duplicatedFaces.OrderByDescending(_ => _).ToList();
if (duplicatedFaces.Any())
{
foreach (var dupIndex in duplicatedFaces)
{
input.Faces.RemoveAt(dupIndex);
}
}
return duplicatedFaces.Any();
}
Anyone know how to remove both coplanar faces, or in this case the faces with non manifold edges:
It not not clear to me what you are looking to do, nor why. I could use some more background on what you have an what you want. A sample .3dm file might also be useful.
Thanks for the advice, I need to remove the faces, only in the case that there are coplanar (so I have to do it after flow the object) Do you know any way to detect when 2 Brep faces has the same geometry, position and orientation by RhinoCommon? (like _SelDup command but with the faces of the same brep)
I Tried to duplicate all faces (DuplicateSubBrep() method) and compare them with .IsDuplicate but it doesn’t work, do you know if it could be a bug, or maybe the point is not use it with faces?
I have been testing both methods in Rhino 6 (myBrep.MergeComplanar and myBrep.IsDuplicated) and it seems that still not working in both Rhino 5 and 6.
Here the code:
protected override Result RunCommand(RhinoDoc doc, RunMode mode)
{
//Define sizes
const int boxHalfLegth = 10;
const double radius = boxHalfLegth / Math.PI;
//Create geometry
var boxBrep = new Box(Plane.WorldXY, new BoundingBox(-boxHalfLegth, -1, -1, boxHalfLegth, 1, 1)).ToBrep();
//Create flow curves
var line = new Line(new Point3d(-boxHalfLegth, 0, 0), new Point3d(boxHalfLegth, 0, 0));
var target = new Circle(Plane.WorldZX, radius);
//Flow Geometry & Show results
var mc = new FlowSpaceMorph(line.ToNurbsCurve(), target.ToNurbsCurve(), false);
RhinoApp.WriteLine($"Morph result = {mc.Morph(boxBrep)}");
RhinoApp.WriteLine($"Morph IsValid = {mc.IsValid}");
//Check if faces are mergeable and try to remove duplicates
RhinoApp.WriteLine($"Merge Coplanar Faces Result = {boxBrep.MergeCoplanarFaces(doc.ModelAbsoluteTolerance)}");
RhinoApp.WriteLine($"Remove Dup Faces Result = {RemoveDuplicatedFaces(boxBrep, doc.ModelAbsoluteTolerance, true)}");
//Add object and redraw
doc.Objects.Add(boxBrep);
doc.Views.Redraw();
return Result.Success;
}
public static bool RemoveDuplicatedFaces(Brep input, double tolerance, bool removeBothFaces)
{
//Used to store duplicated face indices
var duplicatedFaces = new SortedList<int, int>();
//Iterate all faces
for (var i = 0; i < input.Faces.Count; i++)
{
//Create a brep from current face
var face1 = input.DuplicateSubBrep(new[] { i });
//Iterate from next face to check duplicate
for (var j = i + 1; j < input.Faces.Count; j++)
{
//Create a brep from next face
var face2 = input.DuplicateSubBrep(new[] { j });
//Check if it's duplicated
if (!face1.IsDuplicate(face2, tolerance)) continue;
RhinoApp.WriteLine("Found a duplicated face");
//Add current face to delete index list
if (!duplicatedFaces.ContainsKey(i))
duplicatedFaces.Add(i, i);
//If both add other face to delete index list
if (removeBothFaces)
duplicatedFaces.Add(j, j);
break;
}
}
if (!duplicatedFaces.Any()) return false;
RhinoApp.WriteLine("Removing duplicated faces");
//Reverse to delete from latest one.
var list = duplicatedFaces.Reverse().ToList();
list.ForEach(_ => input.Faces.RemoveAt(_.Key));
return true;
}
Assuming that there will be no response and it will not be fixed, I wrote these methods which remove internal faces (full non-manifold edges faces) and remove duplicated faces (one of them or both)
/// <summary>
/// Remove brep faces which are full inside (all edges are non-manifold) of the brep.
/// </summary>
/// <param name="input">Brep to attempt to remove faces.</param>
/// <returns><see cref="input"/> brep without full non-manifold edge faces.</returns>
public static Brep RemoveInternalFaces(Brep input)
{
var facesToKeep = new List<Brep>();
foreach (var face in input.Faces)
{
if (face.AdjacentEdges().All(edgeIndex => input.Edges[edgeIndex].Valence == EdgeAdjacency.NonManifold))
facesToKeep.Add(face.DuplicateFace(true));
}
var jointBreps = Brep.JoinBreps(facesToKeep, RhinoDoc.ActiveDoc.ModelAbsoluteTolerance);
return jointBreps.Length != 1 ? input : jointBreps[0];
}
/// <summary>
/// Removes duplicated faces for a given brep.
/// </summary>
/// <param name="input">Brep to attempt to remove faces.</param>
/// <param name="removeBoth">If true it will remove both faces, otherwise only one of the duplicated faces</param>
/// <returns>><see cref="input"/> brep without duplicated edges.</returns>
public static Brep RemoveDuplicatedFaces(Brep input, bool removeBoth)
{
input.CullUnusedEdges();
var facesToKeep = new List<Brep>();
for (var i = 0; i < input.Faces.Count - 1; i++)
{
for (var j = i + 1; j < input.Faces.Count; j++)
{
if (!input.Faces[i].AdjacentEdges().All(_ => input.Faces[j].AdjacentEdges().Contains(_))) continue;
facesToKeep.Add(input.Faces[i].DuplicateFace(true));
if (removeBoth) facesToKeep.Add(input.Faces[j].DuplicateFace(true));
break;
}
}
var jointBreps = Brep.JoinBreps(facesToKeep, RhinoDoc.ActiveDoc.ModelAbsoluteTolerance);
return jointBreps.Length != 1 ? input : jointBreps[0];
}
because are coplanar, I guessed it will keep only one face but it doesn’t.
The other option was, extract subBreps for each face and Check brepFace.IsDuplacated(OtherBrepFace) but it doesn’t work either (even reversing face direction).
Don’t worry Dale, it already solved using these functions.
Thanks, I know, merge coplanar faces should merge coplanar faces into one (so if the faces are coincident, located at exactly the same place and have exactly the same size and topology it should merge them into single one) but it seems that it’s not working, by other hand, brep.IsDuplicate() method doesn’t seem to be working either for attached example.