Example #1
0
        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;
                    }
                }
            }
        }