Working on adding hole support to Source Objects

This commit is contained in:
Lars Brubaker 2022-04-29 17:33:29 -07:00
parent 16af8dcdb2
commit ce9019884f
11 changed files with 599 additions and 125 deletions

View file

@ -79,7 +79,7 @@ namespace MatterHackers.MatterControl.PartPreviewWindow.View3D
var rebuildLocks = this.RebuilLockAll();
return ApplicationController.Instance.Tasks.Execute(
return ApplicationController.Instance.Tasks.Execute(
"Combine".Localize(),
null,
(reporter, cancellationTokenSource) =>
@ -105,10 +105,11 @@ namespace MatterHackers.MatterControl.PartPreviewWindow.View3D
this.cancellationToken = null;
UiThread.RunOnIdle(() =>
{
rebuildLocks.Dispose();
this.CancelAllParentBuilding();
Parent?.Invalidate(new InvalidateArgs(this, InvalidateType.Children));
rebuildLocks.Dispose();
this.CancelAllParentBuilding();
Parent?.Invalidate(new InvalidateArgs(this, InvalidateType.Children));
});
return Task.CompletedTask;
});
}

View file

@ -87,7 +87,7 @@ namespace MatterHackers.MatterControl.PartPreviewWindow.View3D
if (layer.Scene.SelectedItem != null
&& layer.Scene.SelectedItem == this)
{
var parentOfSubtractTargets = this.SourceContainer.DescendantsAndSelfMultipleChildrenFirstOrSelf();
var parentOfSubtractTargets = this.SourceContainer.FirstWithMultipleChildrenDescendantsAndSelf();
var removeObjects = parentOfSubtractTargets.Children
.Where(i => SelectedChildren.Contains(i.ID))
@ -195,7 +195,7 @@ namespace MatterHackers.MatterControl.PartPreviewWindow.View3D
SourceContainer.Visible = true;
RemoveAllButSource();
var parentOfPaintTargets = SourceContainer.DescendantsAndSelfMultipleChildrenFirstOrSelf();
var parentOfPaintTargets = SourceContainer.FirstWithMultipleChildrenDescendantsAndSelf();
if (parentOfPaintTargets.Children.Count() < 2)
{

View file

@ -86,7 +86,7 @@ namespace MatterHackers.MatterControl.PartPreviewWindow.View3D
if (layer.Scene.SelectedItem != null
&& layer.Scene.SelectedItem == this)
{
var parentOfSubtractTargets = this.SourceContainer.DescendantsAndSelfMultipleChildrenFirstOrSelf();
var parentOfSubtractTargets = this.SourceContainer.FirstWithMultipleChildrenDescendantsAndSelf();
var removeObjects = parentOfSubtractTargets.Children
.Where(i => SelectedChildren.Contains(i.ID))
@ -109,7 +109,7 @@ namespace MatterHackers.MatterControl.PartPreviewWindow.View3D
if (SelectedChildren.Count == 0)
{
SelectedChildren.Add(SourceContainer.DescendantsAndSelfMultipleChildrenFirstOrSelf().Children.Last().ID);
SelectedChildren.Add(SourceContainer.FirstWithMultipleChildrenDescendantsAndSelf().Children.Last().ID);
}
}
@ -212,28 +212,29 @@ namespace MatterHackers.MatterControl.PartPreviewWindow.View3D
Subtract(CancellationToken.None, null);
}
private (IEnumerable<IObject3D>, IEnumerable<IObject3D>) GetSubtractItems()
private static (IEnumerable<IObject3D>, IEnumerable<IObject3D>) GetSubtractItems(IObject3D source, SelectedChildren selectedChildren)
{
var parentOfSubtractTargets = SourceContainer.DescendantsAndSelfMultipleChildrenFirstOrSelf();
if (parentOfSubtractTargets.Children.Count() < 2)
{
if (parentOfSubtractTargets.Children.Count() == 1)
{
this.Children.Add(SourceContainer.Clone());
SourceContainer.Visible = false;
}
var parentOfSubtractTargets = source.FirstWithMultipleChildrenDescendantsAndSelf();
// if there are 0 results
if (parentOfSubtractTargets.Children.Count() == 0)
{
return (null, null);
}
// if there is only 1 result (regardless of it being a keep or remove) return it as a keep
if (parentOfSubtractTargets.Children.Count() == 1)
{
return (new IObject3D[] { source }, null);
}
var removeItems = parentOfSubtractTargets.Children
.Where((i) => SelectedChildren
.Where((i) => selectedChildren
.Contains(i.ID))
.SelectMany(c => c.VisibleMeshes());
var keepItems = parentOfSubtractTargets.Children
.Where((i) => !SelectedChildren
.Where((i) => !selectedChildren
.Contains(i.ID))
.SelectMany(c => c.VisibleMeshes());
@ -247,98 +248,45 @@ namespace MatterHackers.MatterControl.PartPreviewWindow.View3D
CleanUpSelectedChildrenIDs(this);
var (keepItems, removeItems) = GetSubtractItems();
var removeItemsCount = removeItems == null ? 0 : removeItems.Count();
var keepItemsCount = keepItems == null ? 0 : keepItems.Count();
var (keepItems, removeItems) = GetSubtractItems(SourceContainer, SelectedChildren);
if (removeItems?.Any() == true
&& keepItems?.Any() == true)
{
foreach (var keep in keepItems)
var resultItems = DoSubtract(SourceContainer,
keepItems,
removeItems,
reporter,
cancellationToken,
Processing,
InputResolution,
OutputResolution);
foreach(var resultsItem in resultItems)
{
this.Children.Add(resultsItem);
if (!RemoveSubtractObjects)
{
#if false
var items = removeItems.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 = removeItemsCount * keepItemsCount;
double amountPerOperation = 1.0 / totalOperations;
double ratioCompleted = 0;
var progressStatus = new ProgressStatus
this.Children.Modify((list) =>
{
Status = "Do CSG"
};
var resultsMesh = keep.Mesh;
var keepWorldMatrix = keep.WorldMatrix(SourceContainer);
foreach (var remove in removeItems)
{
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 removeItems)
{
foreach (var item in removeItems)
var newObject = new Object3D()
{
var newObject = new Object3D()
{
Mesh = item.Mesh
};
Mesh = item.Mesh
};
newObject.CopyWorldProperties(item, SourceContainer, Object3DPropertyFlags.All & (~Object3DPropertyFlags.Visible));
list.Add(newObject);
}
});
}
newObject.CopyWorldProperties(item, SourceContainer, Object3DPropertyFlags.All & (~Object3DPropertyFlags.Visible));
list.Add(newObject);
}
});
}
}
if (Children.Count == 1)
{
// we only have the source item, leave it visible
}
else // hide the source and show the children
{
bool first = true;
foreach (var child in Children)
{
@ -356,11 +304,98 @@ namespace MatterHackers.MatterControl.PartPreviewWindow.View3D
}
}
public static IEnumerable<IObject3D> DoSubtract(IObject3D sourceContainer,
IEnumerable<IObject3D> keepItems,
IEnumerable<IObject3D> removeItems,
IProgress<ProgressStatus> reporter,
CancellationToken cancellationToken,
ProcessingModes processingMode = ProcessingModes.Polygons,
ProcessingResolution inputResolution = ProcessingResolution._64,
ProcessingResolution outputResolution = ProcessingResolution._64)
{
var results = new List<IObject3D>();
if (keepItems?.Any() == true)
{
if (removeItems?.Any() == true)
{
foreach (var keep in keepItems)
{
#if false
var items = removeItems.Select(i => (i.Mesh, i.WorldMatrix(sourceContainer))).ToList();
items.Insert(0, (keep.Mesh, keep.Matrix));
var resultsMesh = BooleanProcessing.DoArray(items,
CsgModes.Subtract,
processingMode,
inputResolution,
outputResolution,
reporter,
cancellationToken);
#else
var totalOperations = removeItems.Count() * keepItems.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 removeItems)
{
resultsMesh = BooleanProcessing.Do(resultsMesh,
keepWorldMatrix,
// other mesh
remove.Mesh,
remove.WorldMatrix(sourceContainer),
// operation type
CsgModes.Subtract,
processingMode,
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
results.Add(resultsItem);
}
}
}
return results;
}
public static void CleanUpSelectedChildrenIDs(OperationSourceContainerObject3D item)
{
if (item is ISelectableChildContainer selectableChildContainer)
{
var parentOfSubtractTargets = item.SourceContainer.DescendantsAndSelfMultipleChildrenFirstOrSelf();
var parentOfSubtractTargets = item.SourceContainer.FirstWithMultipleChildrenDescendantsAndSelf();
var allVisibleIDs = parentOfSubtractTargets.Children.Select(i => i.ID);
// remove any names from SelectedChildren that are not a child we can select
@ -384,7 +419,7 @@ namespace MatterHackers.MatterControl.PartPreviewWindow.View3D
public override string NameFromChildren()
{
var (keepItems, removeItems) = GetSubtractItems();
var (keepItems, removeItems) = GetSubtractItems(SourceContainer, SelectedChildren);
return CalculateName(keepItems, ", ", " - ", removeItems, ", ");
}
}

View file

@ -156,7 +156,7 @@ namespace MatterHackers.MatterControl.PartPreviewWindow.View3D
SourceContainer.Visible = true;
RemoveAllButSource();
var parentOfSubtractTargets = SourceContainer.DescendantsAndSelfMultipleChildrenFirstOrSelf();
var parentOfSubtractTargets = SourceContainer.FirstWithMultipleChildrenDescendantsAndSelf();
if (parentOfSubtractTargets.Children.Count() < 2)
{
@ -243,7 +243,7 @@ namespace MatterHackers.MatterControl.PartPreviewWindow.View3D
{
if (item is ISelectableChildContainer selectableChildContainer)
{
var parentOfSubtractTargets = item.DescendantsAndSelfMultipleChildrenFirstOrSelf();
var parentOfSubtractTargets = item.FirstWithMultipleChildrenDescendantsAndSelf();
var allVisibleNames = parentOfSubtractTargets.Children.Select(i => i.ID);
// remove any names from SelectedChildren that are not a child we can select