diff --git a/MatterControl.MeshOperations/BooleanProcessing.cs b/MatterControl.MeshOperations/BooleanProcessing.cs index 9d64989c0..6d22b9962 100644 --- a/MatterControl.MeshOperations/BooleanProcessing.cs +++ b/MatterControl.MeshOperations/BooleanProcessing.cs @@ -28,6 +28,7 @@ either expressed or implied, of the FreeBSD Project. */ using System; +using System.Collections.Generic; using System.IO; using System.Linq; using System.Runtime.InteropServices; @@ -38,17 +39,25 @@ using MatterHackers.MatterControl.DesignTools; using MatterHackers.PolygonMesh; using MatterHackers.VectorMath; -namespace MatterHackers.MatterControl.PartPreviewWindow.View3D +namespace MatterHackers.PolygonMesh { - public enum CsgModes - { - Union, - Subtract, - Intersect - } - public static class BooleanProcessing { + public enum CsgModes + { + Union, + Subtract, + Intersect + } + + public enum ProcessingModes + { + Exact, + Volume_64, + Volume_128, + Volume_256, + } + private const string BooleanAssembly = "609_Boolean_bin.dll"; [DllImport(BooleanAssembly, CallingConvention = CallingConvention.Cdecl)] @@ -60,49 +69,120 @@ namespace MatterHackers.MatterControl.PartPreviewWindow.View3D [DllImport(BooleanAssembly, CallingConvention = CallingConvention.Cdecl)] public static extern void DoBooleanOperation(double[] va, int vaCount, int[] fa, int faCount, double[] vb, int vbCount, int[] fb, int fbCount, int operation, out IntPtr pVc, out int vcCount, out IntPtr pVf, out int vfCount); - public static Mesh DoArray(System.Collections.Generic.IEnumerable<(Mesh mesh, Matrix4X4 matrix)> items, + public static Mesh DoArray(IEnumerable<(Mesh mesh, Matrix4X4 matrix)> items, CsgModes operation, + ProcessingModes processingMode, IProgress reporter, CancellationToken cancellationToken) { - var progressStatus = new ProgressStatus(); - var totalOperations = items.Count() - 1; - double amountPerOperation = 1.0 / totalOperations; - double percentCompleted = 0; - - var first = items.First(); - var resultsMesh = first.mesh; - var firstWorldMatrix = first.matrix; - - foreach (var item in items) + if (processingMode == ProcessingModes.Exact) { - if (item != first) + var progressStatus = new ProgressStatus(); + var totalOperations = items.Count() - 1; + double amountPerOperation = 1.0 / totalOperations; + double percentCompleted = 0; + + var first = items.First(); + var resultsMesh = first.mesh; + var firstWorldMatrix = first.matrix; + + foreach (var item in items) { - var itemWorldMatrix = item.matrix; - resultsMesh = BooleanProcessing.Do(item.mesh, - itemWorldMatrix, - // other mesh - resultsMesh, - firstWorldMatrix, - // operation - operation, - // reporting - reporter, - amountPerOperation, - percentCompleted, - progressStatus, - cancellationToken); + if (item != first) + { + var itemWorldMatrix = item.matrix; + resultsMesh = Do(item.mesh, + itemWorldMatrix, + // other mesh + resultsMesh, + firstWorldMatrix, + // operation + operation, + processingMode, + // reporting + reporter, + amountPerOperation, + percentCompleted, + progressStatus, + cancellationToken); - // after the first union we are working with the transformed mesh and don't need the first transform - firstWorldMatrix = Matrix4X4.Identity; + // after the first union we are working with the transformed mesh and don't need the first transform + firstWorldMatrix = Matrix4X4.Identity; - percentCompleted += amountPerOperation; - progressStatus.Progress0To1 = percentCompleted; - reporter?.Report(progressStatus); + percentCompleted += amountPerOperation; + progressStatus.Progress0To1 = percentCompleted; + reporter?.Report(progressStatus); + } + } + + return resultsMesh; + } + else + { + var resolution = 64; + switch (processingMode) + { + case ProcessingModes.Volume_128: + resolution = 128; + break; + + case ProcessingModes.Volume_256: + resolution = 256; + break; + } + var marchingCells = resolution; + var implicitCells = resolution; + + var implicitMeshs = new List(); + foreach (var item in items) + { + implicitMeshs.Add(GetImplicitFromMesh(item.mesh, item.matrix, implicitCells)); + } + + DMesh3 GenerateMeshF(BoundedImplicitFunction3d root, int numCells) + { + var bounds = root.Bounds(); + + var c = new MarchingCubes() + { + Implicit = root, + RootMode = MarchingCubes.RootfindingModes.LerpSteps, // cube-edge convergence method + RootModeSteps = 5, // number of iterations + Bounds = bounds, + CubeSize = bounds.MaxDim / numCells, + }; + + c.Bounds.Expand(3 * c.CubeSize); // leave a buffer of cells + c.Generate(); + + MeshNormals.QuickCompute(c.Mesh); // generate normals + return c.Mesh; + } + + switch (operation) + { + case CsgModes.Union: + return GenerateMeshF(new ImplicitNaryUnion3d() + { + Children = implicitMeshs + }, marchingCells).ToMesh(); + + case CsgModes.Subtract: + return GenerateMeshF(new ImplicitNaryDifference3d() + { + A = implicitMeshs.First(), + BSet = implicitMeshs.GetRange(0, implicitMeshs.Count - 1) + }, marchingCells).ToMesh(); + + case CsgModes.Intersect: + return GenerateMeshF(new ImplicitNaryIntersection3d() + { + Children = implicitMeshs + }, marchingCells).ToMesh(); } } - return resultsMesh; + return null; } public static Mesh Do(Mesh inMeshA, @@ -112,6 +192,7 @@ namespace MatterHackers.MatterControl.PartPreviewWindow.View3D Matrix4X4 matrixB, // operation CsgModes operation, + ProcessingModes processingMode, // reporting IProgress reporter, double amountPerOperation, @@ -119,148 +200,200 @@ namespace MatterHackers.MatterControl.PartPreviewWindow.View3D ProgressStatus progressStatus, CancellationToken cancellationToken) { - // process using marching cubes - { - var meshA2 = inMeshA.Copy(CancellationToken.None); - meshA2.Transform(matrixA); - - var meshB2 = inMeshB.Copy(CancellationToken.None); - meshB2.Transform(matrixB); - - // Convert to DMesh3 - var meshA3 = meshA2.ToDMesh3(); - var meshB3 = meshB2.ToDMesh3(); - - var xxx = new MeshBoolean(); - xxx.Target = meshA3; - xxx.Tool = meshB3; - - return xxx.Result.ToMesh(); - } - bool externalAssemblyExists = File.Exists(BooleanAssembly); - if (externalAssemblyExists - && IntPtr.Size == 8) // only try to run the improved booleans if we are 64 bit and it is there + if (processingMode == ProcessingModes.Exact) { - IntPtr pVc = IntPtr.Zero; - IntPtr pFc = IntPtr.Zero; - try + // only try to run the improved booleans if we are 64 bit and it is there + if (externalAssemblyExists && IntPtr.Size == 8) { - double[] va; - int[] fa; - va = inMeshA.Vertices.ToDoubleArray(matrixA); - fa = inMeshA.Faces.ToIntArray(); - double[] vb; - int[] fb; - vb = inMeshB.Vertices.ToDoubleArray(matrixB); - fb = inMeshB.Faces.ToIntArray(); - - DoBooleanOperation(va, - va.Length, - fa, - fa.Length, - // object B - vb, - vb.Length, - fb, - fb.Length, - // operation - (int)operation, - // results - out pVc, - out int vcCount, - out pFc, - out int fcCount); - - var vcArray = new double[vcCount]; - Marshal.Copy(pVc, vcArray, 0, vcCount); - - var fcArray = new int[fcCount]; - Marshal.Copy(pFc, fcArray, 0, fcCount); - - return new Mesh(vcArray, fcArray); - } - catch (Exception ex) - { - //ApplicationController.Instance.LogInfo("Error performing boolean operation: "); - //ApplicationController.Instance.LogInfo(ex.Message); - } - finally - { - if (pVc != IntPtr.Zero) + IntPtr pVc = IntPtr.Zero; + IntPtr pFc = IntPtr.Zero; + try { - DeleteDouble(ref pVc); + double[] va; + int[] fa; + va = inMeshA.Vertices.ToDoubleArray(matrixA); + fa = inMeshA.Faces.ToIntArray(); + double[] vb; + int[] fb; + vb = inMeshB.Vertices.ToDoubleArray(matrixB); + fb = inMeshB.Faces.ToIntArray(); + + DoBooleanOperation(va, + va.Length, + fa, + fa.Length, + // object B + vb, + vb.Length, + fb, + fb.Length, + // operation + (int)operation, + // results + out pVc, + out int vcCount, + out pFc, + out int fcCount); + + var vcArray = new double[vcCount]; + Marshal.Copy(pVc, vcArray, 0, vcCount); + + var fcArray = new int[fcCount]; + Marshal.Copy(pFc, fcArray, 0, fcCount); + + return new Mesh(vcArray, fcArray); } - - if (pFc != IntPtr.Zero) + catch (Exception ex) { - DeleteInt(ref pFc); + //ApplicationController.Instance.LogInfo("Error performing boolean operation: "); + //ApplicationController.Instance.LogInfo(ex.Message); } - - if (progressStatus != null) + finally { - progressStatus.Progress0To1 = percentCompleted + amountPerOperation; - reporter.Report(progressStatus); + if (pVc != IntPtr.Zero) + { + DeleteDouble(ref pVc); + } + + if (pFc != IntPtr.Zero) + { + DeleteInt(ref pFc); + } + + if (progressStatus != null) + { + progressStatus.Progress0To1 = percentCompleted + amountPerOperation; + reporter.Report(progressStatus); + } + } + } + else + { + Console.WriteLine($"libigl skipped - AssemblyExists: {externalAssemblyExists}; Is64Bit: {IntPtr.Size == 8};"); + + var meshA = inMeshA.Copy(CancellationToken.None); + meshA.Transform(matrixA); + + var meshB = inMeshB.Copy(CancellationToken.None); + meshB.Transform(matrixB); + + switch (operation) + { + case CsgModes.Union: + return Csg.CsgOperations.Union(meshA, + meshB, + (status, progress0To1) => + { + // Abort if flagged + cancellationToken.ThrowIfCancellationRequested(); + progressStatus.Status = status; + progressStatus.Progress0To1 = percentCompleted + (amountPerOperation * progress0To1); + reporter?.Report(progressStatus); + }, + cancellationToken); + + case CsgModes.Subtract: + return Csg.CsgOperations.Subtract(meshA, + meshB, + (status, progress0To1) => + { + progressStatus.Status = status; + progressStatus.Progress0To1 = percentCompleted + (amountPerOperation * progress0To1); + reporter?.Report(progressStatus); + }, + cancellationToken); + + case CsgModes.Intersect: + return Csg.CsgOperations.Intersect(meshA, + meshB, + (status, progress0To1) => + { + // Abort if flagged + cancellationToken.ThrowIfCancellationRequested(); progressStatus.Status = status; + progressStatus.Progress0To1 = percentCompleted + (amountPerOperation * progress0To1); + reporter.Report(progressStatus); + }, + cancellationToken); } } } else { - Console.WriteLine($"libigl skipped - AssemblyExists: {externalAssemblyExists}; Is64Bit: {IntPtr.Size == 8};"); - } + var resolution = 64; + switch (processingMode) + { + case ProcessingModes.Volume_128: + resolution = 128; + break; - var meshA = inMeshA.Copy(CancellationToken.None); - meshA.Transform(matrixA); + case ProcessingModes.Volume_256: + resolution = 256; + break; + } + var marchingCells = resolution; + var implicitCells = resolution; + var implicitA = GetImplicitFromMesh(inMeshA, matrixA, implicitCells); + var implicitB = GetImplicitFromMesh(inMeshB, matrixB, implicitCells); - var meshB = inMeshB.Copy(CancellationToken.None); - meshB.Transform(matrixB); + DMesh3 GenerateMeshF(BoundedImplicitFunction3d root, int numCells) + { + var bounds = root.Bounds(); - switch (operation) - { - case CsgModes.Union: - return PolygonMesh.Csg.CsgOperations.Union(meshA, - meshB, - (status, progress0To1) => + var c = new MarchingCubes() + { + Implicit = root, + RootMode = MarchingCubes.RootfindingModes.LerpSteps, // cube-edge convergence method + RootModeSteps = 5, // number of iterations + Bounds = bounds, + CubeSize = bounds.MaxDim / numCells, + }; + + c.Bounds.Expand(3 * c.CubeSize); // leave a buffer of cells + c.Generate(); + + MeshNormals.QuickCompute(c.Mesh); // generate normals + return c.Mesh; + } + + switch (operation) + { + case CsgModes.Union: + return GenerateMeshF(new ImplicitUnion3d() { - // Abort if flagged - cancellationToken.ThrowIfCancellationRequested(); + A = implicitA, + B = implicitB + }, marchingCells).ToMesh(); - progressStatus.Status = status; - progressStatus.Progress0To1 = percentCompleted + (amountPerOperation * progress0To1); - reporter?.Report(progressStatus); - }, - cancellationToken); - - case CsgModes.Subtract: - return PolygonMesh.Csg.CsgOperations.Subtract(meshA, - meshB, - (status, progress0To1) => + case CsgModes.Subtract: + return GenerateMeshF(new ImplicitDifference3d() { - // Abort if flagged - cancellationToken.ThrowIfCancellationRequested(); + A = implicitA, + B = implicitB + }, marchingCells).ToMesh(); - progressStatus.Status = status; - progressStatus.Progress0To1 = percentCompleted + (amountPerOperation * progress0To1); - reporter?.Report(progressStatus); - }, - cancellationToken); - - case CsgModes.Intersect: - return PolygonMesh.Csg.CsgOperations.Intersect(meshA, - meshB, - (status, progress0To1) => + case CsgModes.Intersect: + return GenerateMeshF(new ImplicitIntersection3d() { - // Abort if flagged - cancellationToken.ThrowIfCancellationRequested(); - - progressStatus.Status = status; - progressStatus.Progress0To1 = percentCompleted + (amountPerOperation * progress0To1); - reporter.Report(progressStatus); - }, - cancellationToken); + A = implicitA, + B = implicitB + }, marchingCells).ToMesh(); + } } return null; } + + public static BoundedImplicitFunction3d GetImplicitFromMesh(Mesh mesh, Matrix4X4 matrix, int numCells) + { + var meshCopy = mesh.Copy(CancellationToken.None); + meshCopy.Transform(matrix); + + var meshA3 = meshCopy.ToDMesh3(); + double meshCellsize = meshA3.CachedBounds.MaxDim / numCells; + var signedDistance = new MeshSignedDistanceGrid(meshA3, meshCellsize); + signedDistance.Compute(); + return new DenseGridTrilinearImplicit(signedDistance.Grid, signedDistance.GridOrigin, signedDistance.CellSize); + } } } \ No newline at end of file diff --git a/MatterControlLib/DesignTools/Obsolete/CombineObject3D.cs b/MatterControlLib/DesignTools/Obsolete/CombineObject3D.cs index 3ec652ef3..ee75b4ad9 100644 --- a/MatterControlLib/DesignTools/Obsolete/CombineObject3D.cs +++ b/MatterControlLib/DesignTools/Obsolete/CombineObject3D.cs @@ -40,6 +40,7 @@ using MatterHackers.Agg; using MatterHackers.Agg.UI; using MatterHackers.DataConverters3D; using MatterHackers.Localizations; +using MatterHackers.PolygonMesh; namespace MatterHackers.MatterControl.PartPreviewWindow.View3D { @@ -131,10 +132,17 @@ namespace MatterHackers.MatterControl.PartPreviewWindow.View3D { if (item != first) { - var result = BooleanProcessing.Do(item.Mesh, item.WorldMatrix(), - first.Mesh, first.WorldMatrix(), - 0, - reporter, amountPerOperation, percentCompleted, progressStatus, cancellationToken); + var result = BooleanProcessing.Do(item.Mesh, + item.WorldMatrix(), + first.Mesh, + first.WorldMatrix(), + BooleanProcessing.CsgModes.Union, + BooleanProcessing.ProcessingModes.Exact, + reporter, + amountPerOperation, + percentCompleted, + progressStatus, + cancellationToken); var inverse = first.WorldMatrix(); inverse.Invert(); diff --git a/MatterControlLib/DesignTools/Obsolete/IntersectionObject3D.cs b/MatterControlLib/DesignTools/Obsolete/IntersectionObject3D.cs index 208757fbb..6f32aa674 100644 --- a/MatterControlLib/DesignTools/Obsolete/IntersectionObject3D.cs +++ b/MatterControlLib/DesignTools/Obsolete/IntersectionObject3D.cs @@ -40,6 +40,7 @@ using MatterHackers.Agg; using MatterHackers.Agg.UI; using MatterHackers.DataConverters3D; using MatterHackers.Localizations; +using MatterHackers.PolygonMesh; namespace MatterHackers.MatterControl.PartPreviewWindow.View3D { @@ -117,9 +118,17 @@ namespace MatterHackers.MatterControl.PartPreviewWindow.View3D { if (remove != first) { - var result = BooleanProcessing.Do(remove.Mesh, remove.WorldMatrix(), - first.Mesh, first.WorldMatrix(), - CsgModes.Intersect, reporter, amountPerOperation, percentCompleted, progressStatus, cancellationToken); + var result = BooleanProcessing.Do(remove.Mesh, + remove.WorldMatrix(), + first.Mesh, + first.WorldMatrix(), + BooleanProcessing.CsgModes.Intersect, + BooleanProcessing.ProcessingModes.Exact, + reporter, + amountPerOperation, + percentCompleted, + progressStatus, + cancellationToken); var inverse = first.WorldMatrix(); inverse.Invert(); diff --git a/MatterControlLib/PartPreviewWindow/View3D/Actions/CombineObject3D_2.cs b/MatterControlLib/PartPreviewWindow/View3D/Actions/CombineObject3D_2.cs index 2d3315e6b..f3ed38c43 100644 --- a/MatterControlLib/PartPreviewWindow/View3D/Actions/CombineObject3D_2.cs +++ b/MatterControlLib/PartPreviewWindow/View3D/Actions/CombineObject3D_2.cs @@ -35,7 +35,9 @@ using MatterHackers.Agg; using MatterHackers.Agg.UI; using MatterHackers.DataConverters3D; using MatterHackers.Localizations; +using MatterHackers.MatterControl.DesignTools; using MatterHackers.MatterControl.DesignTools.Operations; +using MatterHackers.PolygonMesh; namespace MatterHackers.MatterControl.PartPreviewWindow.View3D { @@ -46,6 +48,10 @@ namespace MatterHackers.MatterControl.PartPreviewWindow.View3D Name = "Combine"; } + + [EnumDisplay(Mode = EnumDisplayAttribute.PresentationMode.Buttons)] + public BooleanProcessing.ProcessingModes Processing { get; set; } = BooleanProcessing.ProcessingModes.Exact; + public override Task Rebuild() { this.DebugDepth("Rebuild"); @@ -104,7 +110,8 @@ namespace MatterHackers.MatterControl.PartPreviewWindow.View3D var items = participants.Select(i => (i.Mesh, i.WorldMatrix(SourceContainer))); var resultsMesh = BooleanProcessing.DoArray(items, - CsgModes.Union, + BooleanProcessing.CsgModes.Union, + Processing, reporter, cancellationToken); diff --git a/MatterControlLib/PartPreviewWindow/View3D/Actions/IntersectionObject3D_2.cs b/MatterControlLib/PartPreviewWindow/View3D/Actions/IntersectionObject3D_2.cs index 6d5c0b7e3..479dac83a 100644 --- a/MatterControlLib/PartPreviewWindow/View3D/Actions/IntersectionObject3D_2.cs +++ b/MatterControlLib/PartPreviewWindow/View3D/Actions/IntersectionObject3D_2.cs @@ -35,7 +35,9 @@ using MatterHackers.Agg; using MatterHackers.Agg.UI; using MatterHackers.DataConverters3D; using MatterHackers.Localizations; +using MatterHackers.MatterControl.DesignTools; using MatterHackers.MatterControl.DesignTools.Operations; +using MatterHackers.PolygonMesh; using MatterHackers.VectorMath; namespace MatterHackers.MatterControl.PartPreviewWindow.View3D @@ -47,6 +49,9 @@ namespace MatterHackers.MatterControl.PartPreviewWindow.View3D Name = "Intersection"; } + [EnumDisplay(Mode = EnumDisplayAttribute.PresentationMode.Buttons)] + public BooleanProcessing.ProcessingModes Processing { get; set; } = BooleanProcessing.ProcessingModes.Exact; + public override Task Rebuild() { this.DebugDepth("Rebuild"); @@ -103,38 +108,18 @@ namespace MatterHackers.MatterControl.PartPreviewWindow.View3D return; } - var first = participants.First(); - var resultsMesh = first.Mesh; - var firstWorldMatrix = first.WorldMatrix(SourceContainer); - - var totalOperations = participants.Count() - 1; - double amountPerOperation = 1.0 / totalOperations; - double percentCompleted = 0; - - ProgressStatus progressStatus = new ProgressStatus(); - foreach (var item in participants) - { - if (item != first) - { - var itemWorldMatrix = item.WorldMatrix(SourceContainer); - resultsMesh = BooleanProcessing.Do(item.Mesh, itemWorldMatrix, - resultsMesh, firstWorldMatrix, - CsgModes.Intersect, - reporter, amountPerOperation, percentCompleted, progressStatus, cancellationToken); - // after the first union we are working with the transformed mesh and don't need the first transform - firstWorldMatrix = Matrix4X4.Identity; - - percentCompleted += amountPerOperation; - progressStatus.Progress0To1 = percentCompleted; - reporter?.Report(progressStatus); - } - } + var items = participants.Select(i => (i.Mesh, i.WorldMatrix(SourceContainer))); + var resultsMesh = BooleanProcessing.DoArray(items, + BooleanProcessing.CsgModes.Intersect, + Processing, + reporter, + cancellationToken); var resultsItem = new Object3D() { Mesh = resultsMesh }; - resultsItem.CopyProperties(first, Object3DPropertyFlags.All & (~Object3DPropertyFlags.Matrix)); + resultsItem.CopyProperties(participants.First(), Object3DPropertyFlags.All & (~Object3DPropertyFlags.Matrix)); this.Children.Add(resultsItem); SourceContainer.Visible = false; } diff --git a/MatterControlLib/PartPreviewWindow/View3D/Actions/SubtractAndReplaceObject3D.cs b/MatterControlLib/PartPreviewWindow/View3D/Actions/SubtractAndReplaceObject3D.cs index fa786c02a..a982a256f 100644 --- a/MatterControlLib/PartPreviewWindow/View3D/Actions/SubtractAndReplaceObject3D.cs +++ b/MatterControlLib/PartPreviewWindow/View3D/Actions/SubtractAndReplaceObject3D.cs @@ -120,10 +120,29 @@ namespace MatterHackers.MatterControl.PartPreviewWindow.View3D transformedKeep.Transform(keep.matrix); // remove the paint from the original - var subtract = BooleanProcessing.Do(keep.obj3D.Mesh, keep.matrix, - paint.obj3D.Mesh, paint.matrix, CsgModes.Subtract, reporter, amountPerOperation, percentCompleted, progressStatus, cancellationToken); - var intersect = BooleanProcessing.Do(keep.obj3D.Mesh, keep.matrix, - paint.obj3D.Mesh, paint.matrix, CsgModes.Intersect, reporter, amountPerOperation, percentCompleted, progressStatus, cancellationToken); + var subtract = BooleanProcessing.Do(keep.obj3D.Mesh, + keep.matrix, + paint.obj3D.Mesh, + paint.matrix, + BooleanProcessing.CsgModes.Subtract, + BooleanProcessing.ProcessingModes.Exact, + reporter, + amountPerOperation, + percentCompleted, + progressStatus, + cancellationToken); + + var intersect = BooleanProcessing.Do(keep.obj3D.Mesh, + keep.matrix, + paint.obj3D.Mesh, + paint.matrix, + BooleanProcessing.CsgModes.Intersect, + BooleanProcessing.ProcessingModes.Exact, + reporter, + amountPerOperation, + percentCompleted, + progressStatus, + cancellationToken); var inverseKeep = keep.matrix.Inverted; subtract.Transform(inverseKeep); @@ -139,8 +158,17 @@ namespace MatterHackers.MatterControl.PartPreviewWindow.View3D } else // union into the current paint { - paintMesh = BooleanProcessing.Do(paintMesh, Matrix4X4.Identity, - intersect, Matrix4X4.Identity, 0, reporter, amountPerOperation, percentCompleted, progressStatus, cancellationToken); + paintMesh = BooleanProcessing.Do(paintMesh, + Matrix4X4.Identity, + intersect, + Matrix4X4.Identity, + BooleanProcessing.CsgModes.Subtract, + BooleanProcessing.ProcessingModes.Exact, + reporter, + amountPerOperation, + percentCompleted, + progressStatus, + cancellationToken); } if (cancellationToken.IsCancellationRequested) diff --git a/MatterControlLib/PartPreviewWindow/View3D/Actions/SubtractAndReplaceObject3D_2.cs b/MatterControlLib/PartPreviewWindow/View3D/Actions/SubtractAndReplaceObject3D_2.cs index b3d699a0a..510692217 100644 --- a/MatterControlLib/PartPreviewWindow/View3D/Actions/SubtractAndReplaceObject3D_2.cs +++ b/MatterControlLib/PartPreviewWindow/View3D/Actions/SubtractAndReplaceObject3D_2.cs @@ -53,6 +53,9 @@ namespace MatterHackers.MatterControl.PartPreviewWindow.View3D Name = "Subtract and Replace"; } + [EnumDisplay(Mode = EnumDisplayAttribute.PresentationMode.Buttons)] + public BooleanProcessing.ProcessingModes Processing { get; set; } = BooleanProcessing.ProcessingModes.Exact; + [HideFromEditor] public SelectedChildren ComputedChildren { get; set; } = new SelectedChildren(); @@ -267,7 +270,8 @@ namespace MatterHackers.MatterControl.PartPreviewWindow.View3D paint.Mesh, paint.WorldMatrix(SourceContainer), // operation type - CsgModes.Intersect, + BooleanProcessing.CsgModes.Intersect, + Processing, // reporting data reporter, amountPerOperation, @@ -281,7 +285,8 @@ namespace MatterHackers.MatterControl.PartPreviewWindow.View3D paint.Mesh, paint.WorldMatrix(SourceContainer), // operation type - CsgModes.Subtract, + BooleanProcessing.CsgModes.Subtract, + Processing, // reporting data reporter, amountPerOperation, diff --git a/MatterControlLib/PartPreviewWindow/View3D/Actions/SubtractObject3D.cs b/MatterControlLib/PartPreviewWindow/View3D/Actions/SubtractObject3D.cs index aea510a11..4bc0377ec 100644 --- a/MatterControlLib/PartPreviewWindow/View3D/Actions/SubtractObject3D.cs +++ b/MatterControlLib/PartPreviewWindow/View3D/Actions/SubtractObject3D.cs @@ -41,6 +41,7 @@ using MatterHackers.Agg.UI; using MatterHackers.DataConverters3D; using MatterHackers.Localizations; using MatterHackers.MatterControl.DesignTools; +using MatterHackers.PolygonMesh; namespace MatterHackers.MatterControl.PartPreviewWindow.View3D { @@ -160,8 +161,17 @@ namespace MatterHackers.MatterControl.PartPreviewWindow.View3D progressStatus.Status = "Do CSG"; reporter?.Report(progressStatus); - var result = BooleanProcessing.Do(keep.obj3D.Mesh, keep.matrix, - remove.obj3D.Mesh, remove.matrix, CsgModes.Subtract, reporter, amountPerOperation, percentCompleted, progressStatus, cancellationToken); + var result = BooleanProcessing.Do(keep.obj3D.Mesh, + keep.matrix, + remove.obj3D.Mesh, + remove.matrix, + BooleanProcessing.CsgModes.Subtract, + BooleanProcessing.ProcessingModes.Exact, + reporter, + amountPerOperation, + percentCompleted, + progressStatus, + cancellationToken); var inverse = keep.matrix.Inverted; result.Transform(inverse); diff --git a/MatterControlLib/PartPreviewWindow/View3D/Actions/SubtractObject3D_2.cs b/MatterControlLib/PartPreviewWindow/View3D/Actions/SubtractObject3D_2.cs index 113d6f8c4..2644fb9a5 100644 --- a/MatterControlLib/PartPreviewWindow/View3D/Actions/SubtractObject3D_2.cs +++ b/MatterControlLib/PartPreviewWindow/View3D/Actions/SubtractObject3D_2.cs @@ -39,6 +39,7 @@ using MatterHackers.DataConverters3D; using MatterHackers.Localizations; using MatterHackers.MatterControl.DesignTools; using MatterHackers.MatterControl.DesignTools.Operations; +using MatterHackers.PolygonMesh; using MatterHackers.RenderOpenGl; using MatterHackers.VectorMath; @@ -52,6 +53,9 @@ namespace MatterHackers.MatterControl.PartPreviewWindow.View3D Name = "Subtract"; } + [EnumDisplay(Mode = EnumDisplayAttribute.PresentationMode.Buttons)] + public BooleanProcessing.ProcessingModes Processing { get; set; } = BooleanProcessing.ProcessingModes.Exact; + [DisplayName("Part(s) to Subtract")] public SelectedChildren SelectedChildren { get; set; } = new SelectedChildren(); @@ -209,7 +213,8 @@ namespace MatterHackers.MatterControl.PartPreviewWindow.View3D remove.Mesh, remove.WorldMatrix(SourceContainer), // operation type - CsgModes.Subtract, + BooleanProcessing.CsgModes.Subtract, + Processing, // reporting reporter, amountPerOperation, diff --git a/Submodules/agg-sharp b/Submodules/agg-sharp index fe836aa86..00bc84b3a 160000 --- a/Submodules/agg-sharp +++ b/Submodules/agg-sharp @@ -1 +1 @@ -Subproject commit fe836aa86ac3770055fae71c88d7f031e08f19ad +Subproject commit 00bc84b3a03076286812a880de3d8d4db66f41e2 diff --git a/Submodules/geometry3Sharp b/Submodules/geometry3Sharp index 41d236867..5d5639d79 160000 --- a/Submodules/geometry3Sharp +++ b/Submodules/geometry3Sharp @@ -1 +1 @@ -Subproject commit 41d23686781fb365fad5b5acabf4196a9b0bfe5f +Subproject commit 5d5639d79646300ff6fb2911bfcef246eac140d2