From c064090ef0a4ef354a07a9d2f1fbc13deeb6e1ac Mon Sep 17 00:00:00 2001 From: Lars Brubaker Date: Wed, 17 Nov 2021 18:20:36 -0800 Subject: [PATCH] Refactoring for union fixes --- .../BooleanProcessing.cs | 68 ++++--------- MatterControl.MeshOperations/CoPlanarFaces.cs | 96 +++++++++++++++++++ 2 files changed, 112 insertions(+), 52 deletions(-) create mode 100644 MatterControl.MeshOperations/CoPlanarFaces.cs diff --git a/MatterControl.MeshOperations/BooleanProcessing.cs b/MatterControl.MeshOperations/BooleanProcessing.cs index adcffb18f..c9575c7fd 100644 --- a/MatterControl.MeshOperations/BooleanProcessing.cs +++ b/MatterControl.MeshOperations/BooleanProcessing.cs @@ -46,10 +46,10 @@ using MatterHackers.VectorMath; namespace MatterHackers.PolygonMesh { - using Polygon = List; - using Polygons = List>; + using Polygon = List; + using Polygons = List>; - public static class BooleanProcessing + public static class BooleanProcessing { public enum CsgModes { @@ -243,35 +243,6 @@ namespace MatterHackers.PolygonMesh return implicitResult; } - private static void StoreFaceAdd(Dictionary>> addedFaces, - Plane facePlane, - int sourceMeshIndex, - int sourceFaceIndex, - int destFaceIndex) - { - foreach(var plane in addedFaces.Keys) - { - // check if they are close enough - if (facePlane.Equals(plane)) - { - facePlane = plane; - break; - } - } - - if (!addedFaces.ContainsKey(facePlane)) - { - addedFaces[facePlane] = new Dictionary>(); - } - - if (!addedFaces[facePlane].ContainsKey(sourceMeshIndex)) - { - addedFaces[facePlane][sourceMeshIndex] = new List<(int sourceFace, int destFace)>(); - } - - addedFaces[facePlane][sourceMeshIndex].Add((sourceFaceIndex, destFaceIndex)); - } - private static Mesh ExactBySlicing(IEnumerable<(Mesh mesh, Matrix4X4 matrix)> items2, CsgModes operation, IProgress reporter, CancellationToken cancellationToken) { var progressStatus = new ProgressStatus(); @@ -291,7 +262,7 @@ namespace MatterHackers.PolygonMesh // keep track of all the faces that added by their plane // the internal dictionary is sourceMeshIndex, sourceFaceIndex, destFaceIndex - var coPlanarFaces = new Dictionary>>(); + var coPlanarFaces = new CoPlanarFaces(); for (var mesh1Index = 0; mesh1Index < transformedMeshes.Count; mesh1Index++) { @@ -381,7 +352,7 @@ namespace MatterHackers.PolygonMesh // keep track of the adds so we can process the coplanar faces after for (int i = faceCountPreAdd; i < resultsMesh.Faces.Count; i++) { - StoreFaceAdd(coPlanarFaces, cutPlane, mesh1Index, faceIndex, i); + coPlanarFaces.StoreFaceAdd(cutPlane, mesh1Index, faceIndex, i); // make sure our added faces are the right direction if (resultsMesh.Faces[i].normal.Dot(expectedFaceNormal) < 0) { @@ -391,7 +362,7 @@ namespace MatterHackers.PolygonMesh } else // we did not add any faces but we will still keep track of this polygons plan { - StoreFaceAdd(coPlanarFaces, cutPlane, mesh1Index, faceIndex, -1); + coPlanarFaces.StoreFaceAdd(cutPlane, mesh1Index, faceIndex, -1); } } @@ -406,15 +377,14 @@ namespace MatterHackers.PolygonMesh } } - foreach (var kvp in coPlanarFaces) + foreach (var plane in coPlanarFaces.Planes) { - var plane = kvp.Key; - var flattenedMatrix = GetFlattenedMatrix(plane); - var polygonsByMeshIndex = kvp.Value; - // check if more than one mesh has this polygons on this plan - if (polygonsByMeshIndex.Count > 1) + var meshIndices = coPlanarFaces.MeshIndicesForPlane(plane); + if (meshIndices.Count() > 1) { - + // check if more than one mesh has this polygons on this plan + var flattenedMatrix = GetFlattenedMatrix(plane); + // depending on the opperation add or remove polygons that are planar switch (operation) { @@ -423,14 +393,11 @@ namespace MatterHackers.PolygonMesh // we need to add polygons for the intersection of all the co-planar faces // find the Polygons for each mesh and union per mesh var totalSlices = new List(); - foreach (var kvp2 in polygonsByMeshIndex) + foreach (var meshIndex in coPlanarFaces.MeshIndicesForPlane(plane)) { - var meshIndex = kvp2.Key; - var faceList = kvp2.Value; - var addedFaces = new HashSet(); var facePolygons = new Polygons(); - foreach (var (sourceFaceIndex, destFaceIndex) in faceList) + foreach (var (sourceFaceIndex, destFaceIndex) in coPlanarFaces.PolygonsForPlaneAndMesh(plane, meshIndex)) { if (!addedFaces.Contains(sourceFaceIndex)) { @@ -467,13 +434,10 @@ namespace MatterHackers.PolygonMesh // teselate and add what is left var totalSlices = new List(); var facesToRemove = new List(); - foreach (var kvp2 in polygonsByMeshIndex) + foreach (var meshIndex in coPlanarFaces.MeshIndicesForPlane(plane)) { - var meshIndex = kvp2.Key; - var faceList = kvp2.Value; - var facePolygons = new Polygons(); - foreach (var (sourceFaceIndex, destFaceIndex) in faceList) + foreach (var (sourceFaceIndex, destFaceIndex) in coPlanarFaces.PolygonsForPlaneAndMesh(plane, meshIndex)) { facePolygons.Add(GetFacePolygon(transformedMeshes[meshIndex], sourceFaceIndex, plane, flattenedMatrix)); facesToRemove.Add(destFaceIndex); diff --git a/MatterControl.MeshOperations/CoPlanarFaces.cs b/MatterControl.MeshOperations/CoPlanarFaces.cs new file mode 100644 index 000000000..803dc0285 --- /dev/null +++ b/MatterControl.MeshOperations/CoPlanarFaces.cs @@ -0,0 +1,96 @@ +/* +Copyright (c) 2019, Lars Brubaker, John Lewin +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +The views and conclusions contained in the software and documentation are those +of the authors and should not be interpreted as representing official policies, +either expressed or implied, of the FreeBSD Project. +*/ + +using System.Collections.Generic; +using ClipperLib; +using MatterHackers.VectorMath; + +namespace MatterHackers.PolygonMesh +{ + public class CoPlanarFaces + { + private new Dictionary>> coPlanarFaces + = new Dictionary>>(); + + public IEnumerable Planes + { + get + { + foreach (var plane in coPlanarFaces.Keys) + { + yield return plane; + } + } + } + + public IEnumerable MeshIndicesForPlane(Plane plane) + { + foreach (var kvp in coPlanarFaces[plane]) + { + yield return kvp.Key; + } + } + + public IEnumerable<(int sourceFaceIndex, int destFaceIndex)> PolygonsForPlaneAndMesh(Plane plane, int meshIndex) + { + foreach(var faceIndices in coPlanarFaces[plane][meshIndex]) + { + yield return faceIndices; + } + } + + public void StoreFaceAdd(Plane facePlane, + int sourceMeshIndex, + int sourceFaceIndex, + int destFaceIndex) + { + foreach (var plane in coPlanarFaces.Keys) + { + // check if they are close enough + if (facePlane.Equals(plane)) + { + facePlane = plane; + break; + } + } + + if (!coPlanarFaces.ContainsKey(facePlane)) + { + coPlanarFaces[facePlane] = new Dictionary>(); + } + + if (!coPlanarFaces[facePlane].ContainsKey(sourceMeshIndex)) + { + coPlanarFaces[facePlane][sourceMeshIndex] = new List<(int sourceFace, int destFace)>(); + } + + coPlanarFaces[facePlane][sourceMeshIndex].Add((sourceFaceIndex, destFaceIndex)); + } + } +} \ No newline at end of file