private void Combine(CancellationToken cancellationToken, IProgress <ProgressStatus> reporter) { SourceContainer.Visible = true; RemoveAllButSource(); var participants = SourceContainer.VisibleMeshes(); if (participants.Count() < 2) { if (participants.Count() == 1) { var newMesh = new Object3D(); newMesh.CopyProperties(participants.First(), Object3DPropertyFlags.All); newMesh.Mesh = participants.First().Mesh; this.Children.Add(newMesh); SourceContainer.Visible = false; } return; } var items = participants.Select(i => (i.Mesh, i.WorldMatrix(SourceContainer))); var resultsMesh = BooleanProcessing.DoArray(items, BooleanProcessing.CsgModes.Union, Processing, InputResolution, OutputResolution, reporter, cancellationToken); var resultsItem = new Object3D() { Mesh = resultsMesh }; resultsItem.CopyProperties(participants.First(), Object3DPropertyFlags.All & (~Object3DPropertyFlags.Matrix)); this.Children.Add(resultsItem); SourceContainer.Visible = false; }
private void Intersect(CancellationToken cancellationToken, IProgress <ProgressStatus> reporter) { SourceContainer.Visible = true; RemoveAllButSource(); var participants = SourceContainer.VisibleMeshes(); if (participants.Count() < 2) { if (participants.Count() == 1) { var newMesh = new Object3D(); newMesh.CopyProperties(participants.First(), Object3DPropertyFlags.All); newMesh.Mesh = participants.First().Mesh; this.Children.Add(newMesh); SourceContainer.Visible = false; } return; } var items = participants.Select(i => (i.Mesh, i.WorldMatrix(SourceContainer))); #if false var resultsMesh = BooleanProcessing.DoArray(items, CsgModes.Intersect, Processing, InputResolution, OutputResolution, reporter, cancellationToken); #else var totalOperations = items.Count() - 1; double amountPerOperation = 1.0 / totalOperations; double ratioCompleted = 0; var progressStatus = new ProgressStatus(); var resultsMesh = items.First().Item1; var keepWorldMatrix = items.First().Item2; bool first = true; foreach (var next in items) { if (first) { first = false; continue; } resultsMesh = BooleanProcessing.Do(resultsMesh, keepWorldMatrix, // other mesh next.Item1, next.Item2, // operation type CsgModes.Intersect, 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 if (resultsMesh != null) { var resultsItem = new Object3D() { Mesh = resultsMesh }; resultsItem.CopyProperties(participants.First(), Object3DPropertyFlags.All & (~Object3DPropertyFlags.Matrix)); this.Children.Add(resultsItem); 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.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; } } } }