Working on new circular fit to bounds

refactoring Transform Wrapper Object
This commit is contained in:
Lars Brubaker 2019-02-08 13:05:04 -08:00
parent e96f7c0fdf
commit d0430bed92
9 changed files with 136 additions and 109 deletions

View file

@ -42,7 +42,7 @@ using System.Threading.Tasks;
namespace MatterHackers.MatterControl.DesignTools.Operations namespace MatterHackers.MatterControl.DesignTools.Operations
{ {
public class FitToBoundsObject3D_2 : TransformWrapperObject3D, IEditorDraw public class FitToBoundsObject3D_2 : TransformWrapperObject3D, IEditorDraw, IPropertyGridModifier
{ {
private Vector3 boundsSize; private Vector3 boundsSize;
@ -60,6 +60,72 @@ namespace MatterHackers.MatterControl.DesignTools.Operations
private IObject3D FitBounds => Children.Last(); private IObject3D FitBounds => Children.Last();
#region // editable properties
[Description("Set the shape the part will be fit into.")]
public FitType FitType { get; set; } = FitType.Box;
[Description("Set the rules for how to maintain the part while scaling.")]
public MaintainRatio MaintainRatio { get; set; } = MaintainRatio.X_Y;
[Description("Normally the part is expanded to the cylinders. This will try to center the weight of the part in the cylinder.")]
public bool AlternateCentering { get; set; } = false;
[DisplayName("Width")]
public double SizeX
{
get => boundsSize.X;
set
{
boundsSize.X = value;
if (this.Children.Count() > 0)
{
Rebuild();
}
}
}
[DisplayName("Depth")]
public double SizeY
{
get => boundsSize.Y;
set
{
boundsSize.Y = value;
if (this.Children.Count() > 0)
{
Rebuild();
}
}
}
public double Diameter { get; set; }
[DisplayName("Height")]
public double SizeZ
{
get => boundsSize.Z;
set
{
boundsSize.Z = value;
if (this.Children.Count() > 0)
{
Rebuild();
}
}
}
[Description("Allows you turn on and off applying the fit to the x axis.")]
public bool StretchX { get; set; } = true;
[Description("Allows you turn on and off applying the fit to the y axis.")]
public bool StretchY { get; set; } = true;
[Description("Allows you turn on and off applying the fit to the z axis.")]
public bool StretchZ { get; set; } = true;
#endregion // editable properties
public static async Task<FitToBoundsObject3D_2> Create(IObject3D itemToFit) public static async Task<FitToBoundsObject3D_2> Create(IObject3D itemToFit)
{ {
var fitToBounds = new FitToBoundsObject3D_2(); var fitToBounds = new FitToBoundsObject3D_2();
@ -97,21 +163,41 @@ namespace MatterHackers.MatterControl.DesignTools.Operations
&& layer.Scene.SelectedItem != null && layer.Scene.SelectedItem != null
&& layer.Scene.SelectedItem.DescendantsAndSelf().Where((i) => i == this).Any()) && layer.Scene.SelectedItem.DescendantsAndSelf().Where((i) => i == this).Any())
{ {
var aabb = SourceItems.GetAxisAlignedBoundingBox(); var aabb = UntransformedChildren.GetAxisAlignedBoundingBox();
if (FitType == FitType.Box)
{
var center = aabb.Center;
var worldMatrix = this.WorldMatrix();
var center = aabb.Center; var minXyz = center - new Vector3(SizeX / 2, SizeY / 2, SizeZ / 2);
var worldMatrix = this.WorldMatrix(); var maxXyz = center + new Vector3(SizeX / 2, SizeY / 2, SizeZ / 2);
var bounds = new AxisAlignedBoundingBox(minXyz, maxXyz);
var minXyz = center - new Vector3(SizeX / 2, SizeY / 2, SizeZ / 2); //var leftW = Vector3Ex.Transform(, worldMatrix);
var maxXyz = center + new Vector3(SizeX / 2, SizeY / 2, SizeZ / 2); var right = Vector3Ex.Transform(center + new Vector3(SizeX / 2, 0, 0), worldMatrix);
var bounds = new AxisAlignedBoundingBox(minXyz, maxXyz); // layer.World.Render3DLine(left, right, Agg.Color.Red);
//var leftW = Vector3Ex.Transform(, worldMatrix); layer.World.RenderAabb(bounds, worldMatrix, Agg.Color.Red, 1, 1);
var right = Vector3Ex.Transform(center + new Vector3(SizeX / 2, 0, 0), worldMatrix); }
// layer.World.Render3DLine(left, right, Agg.Color.Red); else
layer.World.RenderAabb(bounds, worldMatrix, Agg.Color.Red, 1, 1); {
layer.World.RenderCylinderOutline(this.WorldMatrix(), aabb.Center, Diameter, aabb.ZSize, 30, Color.Red, 1, 1);
}
} }
} }
public void UpdateControls(PublicPropertyChange change)
{
// turn on/off the stuff for cylinder
change.SetRowVisible(nameof(Diameter), () => FitType == FitType.Cylinder);
change.SetRowVisible(nameof(AlternateCentering), () => FitType == FitType.Cylinder);
// turn on/off the stuff for box
change.SetRowVisible(nameof(SizeX), () => FitType == FitType.Box);
change.SetRowVisible(nameof(SizeY), () => FitType == FitType.Box);
change.SetRowVisible(nameof(MaintainRatio), () => FitType == FitType.Box);
change.SetRowVisible(nameof(StretchX), () => FitType == FitType.Box);
change.SetRowVisible(nameof(StretchY), () => FitType == FitType.Box);
}
public override AxisAlignedBoundingBox GetAxisAlignedBoundingBox(Matrix4X4 matrix) public override AxisAlignedBoundingBox GetAxisAlignedBoundingBox(Matrix4X4 matrix)
{ {
if (Children.Count == 2) if (Children.Count == 2)
@ -188,8 +274,8 @@ namespace MatterHackers.MatterControl.DesignTools.Operations
{ {
if (Children.Count > 0) if (Children.Count > 0)
{ {
var aabb = SourceItems.GetAxisAlignedBoundingBox(); var aabb = UntransformedChildren.GetAxisAlignedBoundingBox();
TransformItem.Matrix = Matrix4X4.Identity; ItemWithTransform.Matrix = Matrix4X4.Identity;
var scale = Vector3.One; var scale = Vector3.One;
if (StretchX) if (StretchX)
{ {
@ -223,7 +309,7 @@ namespace MatterHackers.MatterControl.DesignTools.Operations
break; break;
} }
TransformItem.Matrix = Object3DExtensions.ApplyAtPosition(TransformItem.Matrix, aabb.Center, Matrix4X4.CreateScale(scale)); ItemWithTransform.Matrix = Object3DExtensions.ApplyAtPosition(ItemWithTransform.Matrix, aabb.Center, Matrix4X4.CreateScale(scale));
} }
} }
@ -231,7 +317,7 @@ namespace MatterHackers.MatterControl.DesignTools.Operations
{ {
if (Children.Count == 2) if (Children.Count == 2)
{ {
var transformAabb = TransformItem.GetAxisAlignedBoundingBox(); var transformAabb = ItemWithTransform.GetAxisAlignedBoundingBox();
var fitAabb = FitBounds.GetAxisAlignedBoundingBox(); var fitAabb = FitBounds.GetAxisAlignedBoundingBox();
var fitSize = fitAabb.Size; var fitSize = fitAabb.Size;
if (boundsSize.X != 0 && boundsSize.Y != 0 && boundsSize.Z != 0 if (boundsSize.X != 0 && boundsSize.Y != 0 && boundsSize.Z != 0
@ -243,68 +329,9 @@ namespace MatterHackers.MatterControl.DesignTools.Operations
boundsSize.Y / fitSize.Y, boundsSize.Y / fitSize.Y,
boundsSize.Z / fitSize.Z); boundsSize.Z / fitSize.Z);
FitBounds.Matrix *= Matrix4X4.CreateTranslation( FitBounds.Matrix *= Matrix4X4.CreateTranslation(
transformAabb.Center transformAabb.Center - FitBounds.GetAxisAlignedBoundingBox().Center);
- FitBounds.GetAxisAlignedBoundingBox().Center);
} }
} }
} }
#region // editable properties
[Description("Set the rules for how to maintain the part while scaling.")]
public MaintainRatio MaintainRatio { get; set; } = MaintainRatio.X_Y;
[DisplayName("Width")]
public double SizeX
{
get => boundsSize.X;
set
{
boundsSize.X = value;
if (this.Children.Count() > 0)
{
Rebuild();
}
}
}
[DisplayName("Depth")]
public double SizeY
{
get => boundsSize.Y;
set
{
boundsSize.Y = value;
if (this.Children.Count() > 0)
{
Rebuild();
}
}
}
[DisplayName("Height")]
public double SizeZ
{
get => boundsSize.Z;
set
{
boundsSize.Z = value;
if (this.Children.Count() > 0)
{
Rebuild();
}
}
}
[Description("Allows you turn on and off applying the fit to the x axis.")]
public bool StretchX { get; set; } = true;
[Description("Allows you turn on and off applying the fit to the y axis.")]
public bool StretchY { get; set; } = true;
[Description("Allows you turn on and off applying the fit to the z axis.")]
public bool StretchZ { get; set; } = true;
#endregion // editable properties
} }
} }

View file

@ -76,8 +76,8 @@ namespace MatterHackers.MatterControl.DesignTools.Operations
{ {
base.WrapItems(items, undoBuffer); base.WrapItems(items, undoBuffer);
// use source item as the wrape may have cloned it // use source item as the wraper may have cloned it
var aabb = SourceItems.GetAxisAlignedBoundingBox(); var aabb = UntransformedChildren.GetAxisAlignedBoundingBox();
this.RotateAbout.Origin = aabb.Center; this.RotateAbout.Origin = aabb.Center;
} }
@ -135,7 +135,7 @@ namespace MatterHackers.MatterControl.DesignTools.Operations
using (RebuildLock()) using (RebuildLock())
{ {
// set the matrix for the inner object // set the matrix for the inner object
TransformItem.Matrix = RotationMatrix; ItemWithTransform.Matrix = RotationMatrix;
} }
Invalidate(InvalidateType.Matrix); Invalidate(InvalidateType.Matrix);

View file

@ -70,9 +70,9 @@ namespace MatterHackers.MatterControl.DesignTools.Operations
base.WrapItems(items, undoBuffer); base.WrapItems(items, undoBuffer);
// use source item as it may be a copy of item by the time we have wrapped it // use source item as it may be a copy of item by the time we have wrapped it
var aabb = SourceItems.GetAxisAlignedBoundingBox(); var aabb = UntransformedChildren.GetAxisAlignedBoundingBox();
var newCenter = new Vector3(aabb.Center.X, aabb.Center.Y, aabb.MinXYZ.Z); var newCenter = new Vector3(aabb.Center.X, aabb.Center.Y, aabb.MinXYZ.Z);
SourceItems.Translate(-newCenter); UntransformedChildren.Translate(-newCenter);
this.Translate(newCenter); this.Translate(newCenter);
} }
@ -93,7 +93,7 @@ namespace MatterHackers.MatterControl.DesignTools.Operations
return ScaleRatio.X * 100; return ScaleRatio.X * 100;
} }
return ScaleRatio.X * SourceItems.GetAxisAlignedBoundingBox().XSize; return ScaleRatio.X * UntransformedChildren.GetAxisAlignedBoundingBox().XSize;
} }
set set
@ -104,7 +104,7 @@ namespace MatterHackers.MatterControl.DesignTools.Operations
} }
else else
{ {
ScaleRatio.X = value / SourceItems.GetAxisAlignedBoundingBox().XSize; ScaleRatio.X = value / UntransformedChildren.GetAxisAlignedBoundingBox().XSize;
} }
} }
} }
@ -120,7 +120,7 @@ namespace MatterHackers.MatterControl.DesignTools.Operations
return ScaleRatio.Y * 100; return ScaleRatio.Y * 100;
} }
return ScaleRatio.Y * SourceItems.GetAxisAlignedBoundingBox().YSize; return ScaleRatio.Y * UntransformedChildren.GetAxisAlignedBoundingBox().YSize;
} }
set set
@ -131,7 +131,7 @@ namespace MatterHackers.MatterControl.DesignTools.Operations
} }
else else
{ {
ScaleRatio.Y = value / SourceItems.GetAxisAlignedBoundingBox().YSize; ScaleRatio.Y = value / UntransformedChildren.GetAxisAlignedBoundingBox().YSize;
} }
} }
} }
@ -147,7 +147,7 @@ namespace MatterHackers.MatterControl.DesignTools.Operations
return ScaleRatio.Z * 100; return ScaleRatio.Z * 100;
} }
return ScaleRatio.Z * SourceItems.GetAxisAlignedBoundingBox().ZSize; return ScaleRatio.Z * UntransformedChildren.GetAxisAlignedBoundingBox().ZSize;
} }
set set
@ -158,7 +158,7 @@ namespace MatterHackers.MatterControl.DesignTools.Operations
} }
else else
{ {
ScaleRatio.Z = value / SourceItems.GetAxisAlignedBoundingBox().ZSize; ScaleRatio.Z = value / UntransformedChildren.GetAxisAlignedBoundingBox().ZSize;
} }
} }
} }
@ -213,10 +213,10 @@ namespace MatterHackers.MatterControl.DesignTools.Operations
using (RebuildLock()) using (RebuildLock())
{ {
// set the matrix for the transform object // set the matrix for the transform object
TransformItem.Matrix = Matrix4X4.Identity; ItemWithTransform.Matrix = Matrix4X4.Identity;
TransformItem.Matrix *= Matrix4X4.CreateTranslation(-ScaleAbout); ItemWithTransform.Matrix *= Matrix4X4.CreateTranslation(-ScaleAbout);
TransformItem.Matrix *= Matrix4X4.CreateScale(ScaleRatio); ItemWithTransform.Matrix *= Matrix4X4.CreateScale(ScaleRatio);
TransformItem.Matrix *= Matrix4X4.CreateTranslation(ScaleAbout); ItemWithTransform.Matrix *= Matrix4X4.CreateTranslation(ScaleAbout);
} }
Invalidate(InvalidateType.Matrix); Invalidate(InvalidateType.Matrix);

View file

@ -50,20 +50,20 @@ namespace MatterHackers.MatterControl.DesignTools.Operations
public override bool CanFlatten => true; public override bool CanFlatten => true;
[JsonIgnore] [JsonIgnore]
public SafeList<IObject3D> SourceItems public SafeList<IObject3D> UntransformedChildren
{ {
get get
{ {
if (TransformItem?.Children.Count > 0) if (ItemWithTransform?.Children.Count > 0)
{ {
return TransformItem.Children; return ItemWithTransform.Children;
} }
return null; return null;
} }
} }
protected IObject3D TransformItem protected IObject3D ItemWithTransform
{ {
get get
{ {
@ -87,16 +87,16 @@ namespace MatterHackers.MatterControl.DesignTools.Operations
} }
// push child into children // push child into children
foreach (var item in SourceItems) foreach (var item in UntransformedChildren)
{ {
item.Matrix *= TransformItem.Matrix; item.Matrix *= ItemWithTransform.Matrix;
} }
// add our children to our parent and remove from parent // add our children to our parent and remove from parent
this.Parent.Children.Modify(list => this.Parent.Children.Modify(list =>
{ {
list.Remove(this); list.Remove(this);
list.AddRange(TransformItem.Children); list.AddRange(ItemWithTransform.Children);
}); });
} }
Invalidate(InvalidateType.Children); Invalidate(InvalidateType.Children);
@ -107,7 +107,7 @@ namespace MatterHackers.MatterControl.DesignTools.Operations
using (RebuildLock()) using (RebuildLock())
{ {
// push our matrix into inner children // push our matrix into inner children
foreach (var child in TransformItem.Children) foreach (var child in ItemWithTransform.Children)
{ {
child.Matrix *= this.Matrix; child.Matrix *= this.Matrix;
} }
@ -116,7 +116,7 @@ namespace MatterHackers.MatterControl.DesignTools.Operations
this.Parent.Children.Modify(list => this.Parent.Children.Modify(list =>
{ {
list.Remove(this); list.Remove(this);
list.AddRange(TransformItem.Children); list.AddRange(ItemWithTransform.Children);
}); });
} }

View file

@ -104,7 +104,7 @@ namespace MatterHackers.MatterControl.DesignTools.Operations
using (RebuildLock()) using (RebuildLock())
{ {
// set the matrix for the inner object // set the matrix for the inner object
TransformItem.Matrix = Matrix4X4.CreateTranslation(Translation); ItemWithTransform.Matrix = Matrix4X4.CreateTranslation(Translation);
} }
Invalidate(InvalidateType.Matrix); Invalidate(InvalidateType.Matrix);

View file

@ -142,7 +142,7 @@ namespace MatterHackers.MatterControl.PartPreviewWindow
case TransformWrapperObject3D transformWrapperObject3D: case TransformWrapperObject3D transformWrapperObject3D:
return new ObjectView() return new ObjectView()
{ {
Children = transformWrapperObject3D.SourceItems, Children = transformWrapperObject3D.UntransformedChildren,
Name = item.Name, Name = item.Name,
Source = item Source = item
}; };

@ -1 +1 @@
Subproject commit 99e43459d04563a62fa721a9023d6f4c3e1748a2 Subproject commit 2572ad0b29d45fb647ef4d0d5d4dcc2e38e308e4

@ -1 +1 @@
Subproject commit a0c518cffc3fbfa781e582af0281a458c5e65903 Subproject commit b078d2a5e9d9981734096476de079b285a52efaf

View file

@ -431,7 +431,7 @@ namespace MatterControl.Tests.MatterControl
Assert.IsTrue(preScaleAabb.Equals(postScaleAabb, .001)); Assert.IsTrue(preScaleAabb.Equals(postScaleAabb, .001));
Assert.AreNotEqual(cube, scaleObject.SourceItems.First(), "There is an undo buffer, there should have been a clone"); Assert.AreNotEqual(cube, scaleObject.UntransformedChildren.First(), "There is an undo buffer, there should have been a clone");
} }
// build cube with scale // build cube with scale
@ -454,7 +454,7 @@ namespace MatterControl.Tests.MatterControl
Assert.IsTrue(preScaleAabb.Equals(postScaleAabb, .001)); Assert.IsTrue(preScaleAabb.Equals(postScaleAabb, .001));
Assert.AreEqual(cube, scaleObject.SourceItems.First(), "There is no undo buffer, there should not have been a clone"); Assert.AreEqual(cube, scaleObject.UntransformedChildren.First(), "There is no undo buffer, there should not have been a clone");
} }
} }
@ -480,7 +480,7 @@ namespace MatterControl.Tests.MatterControl
Assert.IsTrue(preScaleAabb.Equals(postScaleAabb, .001)); Assert.IsTrue(preScaleAabb.Equals(postScaleAabb, .001));
Assert.AreEqual(cube, scaleObject.SourceItems.First(), "There is no undo buffer, there should not have been a clone"); Assert.AreEqual(cube, scaleObject.UntransformedChildren.First(), "There is no undo buffer, there should not have been a clone");
var rotateScaleObject = new RotateObject3D_2(cube); var rotateScaleObject = new RotateObject3D_2(cube);
// ensure that the object did not move // ensure that the object did not move
@ -489,7 +489,7 @@ namespace MatterControl.Tests.MatterControl
Assert.IsTrue(preScaleAabb.Equals(postRotateScaleAabb, .001)); Assert.IsTrue(preScaleAabb.Equals(postRotateScaleAabb, .001));
Assert.AreEqual(cube, rotateScaleObject.SourceItems.First(), "There is no undo buffer, there should not have been a clone"); Assert.AreEqual(cube, rotateScaleObject.UntransformedChildren.First(), "There is no undo buffer, there should not have been a clone");
} }
} }
@ -515,7 +515,7 @@ namespace MatterControl.Tests.MatterControl
Assert.IsTrue(preRotateAabb.Equals(postRotateAabb, .001)); Assert.IsTrue(preRotateAabb.Equals(postRotateAabb, .001));
Assert.AreEqual(cube, rotateObject.SourceItems.First(), "There is no undo buffer, there should not have been a clone"); Assert.AreEqual(cube, rotateObject.UntransformedChildren.First(), "There is no undo buffer, there should not have been a clone");
} }
} }