private void SubtractAndReplace(CancellationToken cancellationToken, IProgress <ProgressStatus> reporter) { SourceContainer.Visible = true; RemoveAllButSource(); var parentOfPaintTargets = SourceContainer.DescendantsAndSelfMultipleChildrenFirstOrSelf(); if (parentOfPaintTargets.Children.Count() < 2) { if (parentOfPaintTargets.Children.Count() == 1) { this.Children.Add(SourceContainer.Clone()); SourceContainer.Visible = false; } return; } SubtractObject3D_2.CleanUpSelectedChildrenNames(this); var paintObjects = parentOfPaintTargets.Children .Where((i) => SelectedChildren .Contains(i.ID)) .SelectMany(c => c.VisibleMeshes()) .ToList(); var keepItems = parentOfPaintTargets.Children .Where((i) => !SelectedChildren .Contains(i.ID)); var keepVisibleItems = keepItems.SelectMany(c => c.VisibleMeshes()).ToList(); if (paintObjects.Any() && keepVisibleItems.Any()) { var totalOperations = paintObjects.Count * keepVisibleItems.Count; double amountPerOperation = 1.0 / totalOperations; double percentCompleted = 0; var progressStatus = new ProgressStatus { Status = "Do CSG" }; foreach (var keep in keepVisibleItems) { var keepResultsMesh = keep.Mesh; var keepWorldMatrix = keep.WorldMatrix(SourceContainer); foreach (var paint in paintObjects) { Mesh paintMesh = BooleanProcessing.Do(keepResultsMesh, keepWorldMatrix, // paint data paint.Mesh, paint.WorldMatrix(SourceContainer), // operation type 2, // reporting data reporter, amountPerOperation, percentCompleted, progressStatus, cancellationToken); keepResultsMesh = BooleanProcessing.Do(keepResultsMesh, keepWorldMatrix, // point data paint.Mesh, paint.WorldMatrix(SourceContainer), // operation type 1, // reporting data reporter, amountPerOperation, percentCompleted, progressStatus, cancellationToken); // after the first time we get a result the results mesh is in the right coordinate space keepWorldMatrix = Matrix4X4.Identity; // store our intersection (paint) results mesh var paintResultsItem = new Object3D() { Mesh = paintMesh, Visible = false, OwnerID = paint.ID }; // copy all the properties but the matrix paintResultsItem.CopyWorldProperties(paint, SourceContainer, Object3DPropertyFlags.All & (~(Object3DPropertyFlags.Matrix | Object3DPropertyFlags.Visible))); // and add it to this this.Children.Add(paintResultsItem); // report our progress percentCompleted += amountPerOperation; progressStatus.Progress0To1 = percentCompleted; reporter?.Report(progressStatus); } // store our results mesh var keepResultsItem = new Object3D() { Mesh = keepResultsMesh, Visible = false, OwnerID = keep.ID }; // copy all the properties but the matrix keepResultsItem.CopyWorldProperties(keep, SourceContainer, Object3DPropertyFlags.All & (~(Object3DPropertyFlags.Matrix | Object3DPropertyFlags.Visible))); // and add it to this this.Children.Add(keepResultsItem); } foreach (var child in Children) { child.Visible = true; } SourceContainer.Visible = false; } }
private void Subtract(CancellationToken cancellationToken, IProgress <ProgressStatus> reporter) { SourceContainer.Visible = true; RemoveAllButSource(); var parentOfSubtractTargets = SourceContainer.DescendantsAndSelfMultipleChildrenFirstOrSelf(); if (parentOfSubtractTargets.Children.Count() < 2) { if (parentOfSubtractTargets.Children.Count() == 1) { this.Children.Add(SourceContainer.Clone()); SourceContainer.Visible = false; } return; } CleanUpSelectedChildrenNames(this); var removeVisibleItems = parentOfSubtractTargets.Children .Where((i) => SelectedChildren .Contains(i.ID)) .SelectMany(c => c.VisiblePaths()) .ToList(); var keepItems = parentOfSubtractTargets.Children .Where((i) => !SelectedChildren .Contains(i.ID)); var keepVisibleItems = keepItems.SelectMany(c => c.VisiblePaths()).ToList(); if (removeVisibleItems.Any() && keepVisibleItems.Any()) { var totalOperations = removeVisibleItems.Count * keepVisibleItems.Count; double amountPerOperation = 1.0 / totalOperations; double percentCompleted = 0; var progressStatus = new ProgressStatus { Status = "Do Subtract" }; bool first = true; foreach (var keep in keepVisibleItems) { var resultsVertexSource = (keep as IPathObject).VertexSource.Transform(keep.Matrix); foreach (var remove in removeVisibleItems) { resultsVertexSource = resultsVertexSource.MergePaths(((IPathObject)remove).VertexSource.Transform(remove.Matrix), ClipperLib.ClipType.ctDifference); // report our progress percentCompleted += amountPerOperation; progressStatus.Progress0To1 = percentCompleted; reporter?.Report(progressStatus); } if (first) { this.VertexSource = resultsVertexSource; first = false; } else { this.VertexSource.MergePaths(resultsVertexSource, ClipperLib.ClipType.ctUnion); } } // this.VertexSource = this.VertexSource.Transform(Matrix.Inverted); first = true; foreach (var child in Children) { if (first) { // hide the source item child.Visible = false; first = false; } else { child.Visible = true; } } } }
private void Subtract(CancellationToken cancellationToken, IProgress <ProgressStatus> reporter) { SourceContainer.Visible = true; RemoveAllButSource(); var parentOfSubtractTargets = SourceContainer.DescendantsAndSelfMultipleChildrenFirstOrSelf(); if (parentOfSubtractTargets.Children.Count() < 2) { if (parentOfSubtractTargets.Children.Count() == 1) { this.Children.Add(SourceContainer.Clone()); SourceContainer.Visible = false; } return; } CleanUpSelectedChildrenNames(this); var removeVisibleItems = parentOfSubtractTargets.Children .Where((i) => SelectedChildren .Contains(i.Name)) .SelectMany(c => c.VisibleMeshes()) .ToList(); var keepItems = parentOfSubtractTargets.Children .Where((i) => !SelectedChildren .Contains(i.Name)); var keepVisibleItems = keepItems.SelectMany(c => c.VisibleMeshes()).ToList(); if (removeVisibleItems.Any() && keepVisibleItems.Any()) { var totalOperations = removeVisibleItems.Count * keepVisibleItems.Count; double amountPerOperation = 1.0 / totalOperations; double percentCompleted = 0; ProgressStatus progressStatus = new ProgressStatus(); progressStatus.Status = "Do CSG"; foreach (var keep in keepVisibleItems) { var resultsMesh = keep.Mesh; var keepWorldMatrix = keep.WorldMatrix(SourceContainer); foreach (var remove in removeVisibleItems) { resultsMesh = BooleanProcessing.Do(resultsMesh, keepWorldMatrix, remove.Mesh, remove.WorldMatrix(SourceContainer), 1, reporter, amountPerOperation, percentCompleted, progressStatus, cancellationToken); // after the first time we get a result the results mesh is in the right coordinate space keepWorldMatrix = Matrix4X4.Identity; // report our progress percentCompleted += amountPerOperation; progressStatus.Progress0To1 = percentCompleted; reporter?.Report(progressStatus); } // store our results mesh var resultsItem = new Object3D() { Mesh = resultsMesh, Visible = false }; // copy all the properties but the matrix resultsItem.CopyWorldProperties(keep, SourceContainer, Object3DPropertyFlags.All & (~(Object3DPropertyFlags.Matrix | Object3DPropertyFlags.Visible))); // and add it to this this.Children.Add(resultsItem); } bool first = true; foreach (var child in Children) { if (first) { // hid the source item child.Visible = false; first = false; } else { child.Visible = true; } } } }
private void Subtract(CancellationToken cancellationToken, IProgress <ProgressStatus> reporter) { SourceContainer.Visible = true; RemoveAllButSource(); var parentOfSubtractTargets = SourceContainer.DescendantsAndSelfMultipleChildrenFirstOrSelf(); if (parentOfSubtractTargets.Children.Count() < 2) { if (parentOfSubtractTargets.Children.Count() == 1) { this.Children.Add(SourceContainer.Clone()); SourceContainer.Visible = false; } return; } CleanUpSelectedChildrenNames(this); var removeVisibleItems = parentOfSubtractTargets.Children .Where((i) => SelectedChildren .Contains(i.ID)) .SelectMany(c => c.VisibleMeshes()) .ToList(); var keepItems = parentOfSubtractTargets.Children .Where((i) => !SelectedChildren .Contains(i.ID)); var keepVisibleItems = keepItems.SelectMany(c => c.VisibleMeshes()).ToList(); if (removeVisibleItems.Any() && keepVisibleItems.Any()) { foreach (var keep in keepVisibleItems) { #if false var items = removeVisibleItems.Select(i => (i.Mesh, i.WorldMatrix(SourceContainer))).ToList(); items.Insert(0, (keep.Mesh, keep.Matrix)); var resultsMesh = BooleanProcessing.DoArray(items, CsgModes.Subtract, Processing, InputResolution, OutputResolution, reporter, cancellationToken); #else var totalOperations = removeVisibleItems.Count * keepVisibleItems.Count; double amountPerOperation = 1.0 / totalOperations; double ratioCompleted = 0; var progressStatus = new ProgressStatus { Status = "Do CSG" }; var resultsMesh = keep.Mesh; var keepWorldMatrix = keep.WorldMatrix(SourceContainer); foreach (var remove in removeVisibleItems) { resultsMesh = BooleanProcessing.Do(resultsMesh, keepWorldMatrix, // other mesh remove.Mesh, remove.WorldMatrix(SourceContainer), // operation type CsgModes.Subtract, Processing, InputResolution, OutputResolution, // reporting reporter, amountPerOperation, ratioCompleted, progressStatus, cancellationToken); // after the first time we get a result the results mesh is in the right coordinate space keepWorldMatrix = Matrix4X4.Identity; // report our progress ratioCompleted += amountPerOperation; progressStatus.Progress0To1 = ratioCompleted; reporter?.Report(progressStatus); } #endif // store our results mesh var resultsItem = new Object3D() { Mesh = resultsMesh, Visible = false, OwnerID = keep.ID }; // copy all the properties but the matrix resultsItem.CopyWorldProperties(keep, SourceContainer, Object3DPropertyFlags.All & (~(Object3DPropertyFlags.Matrix | Object3DPropertyFlags.Visible))); // and add it to this this.Children.Add(resultsItem); if (!RemoveSubtractObjects) { this.Children.Modify((list) => { foreach (var item in removeVisibleItems) { var newObject = new Object3D() { Mesh = item.Mesh }; newObject.CopyWorldProperties(item, SourceContainer, Object3DPropertyFlags.All & (~Object3DPropertyFlags.Visible)); list.Add(newObject); } }); } } bool first = true; foreach (var child in Children) { if (first) { // hide the source item child.Visible = false; first = false; } else { child.Visible = true; } } } }