Added a Translate command

Made Rotate and FitToBounds Apply and Remove
refactoring
This commit is contained in:
LarsBrubaker 2018-07-06 07:10:39 -07:00
parent 0783f975a8
commit 72ce9b86de
8 changed files with 331 additions and 211 deletions

View file

@ -723,6 +723,23 @@ namespace MatterHackers.MatterControl
},
iconCollector: () => AggContext.StaticData.LoadIcon("noun_479927.png", ApplicationController.Instance.MenuTheme.InvertIcons));
this.Graph.RegisterOperation(
typeof(IObject3D),
"Translate".Localize(),
(sceneItem, scene) =>
{
var selectedItem = scene.SelectedItem;
scene.SelectedItem = null;
var translate = TranslateObject3D.Create(selectedItem.Clone());
translate.MakeNameNonColliding();
scene.UndoBuffer.AddAndDo(new ReplaceCommand(new List<IObject3D> { selectedItem }, new List<IObject3D> { translate }));
scene.SelectedItem = translate;
return Task.CompletedTask;
},
iconCollector: () => AggContext.StaticData.LoadIcon(Path.Combine("ViewTransformControls", "translate.png"), ApplicationController.Instance.MenuTheme.InvertIcons));
this.Graph.RegisterOperation(
typeof(IObject3D),
"Rotate".Localize(),
@ -738,7 +755,7 @@ namespace MatterHackers.MatterControl
return Task.CompletedTask;
},
iconCollector: () => AggContext.StaticData.LoadIcon("icon_rotate_32x32.png", ApplicationController.Instance.MenuTheme.InvertIcons));
iconCollector: () => AggContext.StaticData.LoadIcon(Path.Combine("ViewTransformControls", "rotate.png"), ApplicationController.Instance.MenuTheme.InvertIcons));
this.Graph.RegisterOperation(
typeof(IPathObject),

View file

@ -32,10 +32,12 @@ using MatterHackers.DataConverters3D;
using MatterHackers.Localizations;
using MatterHackers.VectorMath;
using Newtonsoft.Json;
using System;
using System.ComponentModel;
namespace MatterHackers.MatterControl.DesignTools.Operations
{
[Obsolete("Not used anymore. Replaced with FitToBoundsObject3D_2", false)]
public class RotateObject3D : Object3D
{
[DisplayName("X")]

View file

@ -27,9 +27,6 @@ of the authors and should not be interpreted as representing official policies,
either expressed or implied, of the FreeBSD Project.
*/
using System;
using System.ComponentModel;
using System.Linq;
using MatterHackers.Agg;
using MatterHackers.Agg.UI;
using MatterHackers.DataConverters3D;
@ -38,22 +35,182 @@ using MatterHackers.MatterControl.PartPreviewWindow;
using MatterHackers.MeshVisualizer;
using MatterHackers.PolygonMesh;
using MatterHackers.VectorMath;
using System;
using System.ComponentModel;
using System.Linq;
namespace MatterHackers.MatterControl.DesignTools.Operations
{
public class FitToBoundsObject3D_2 : TransformWrapperObject3D, IEditorDraw
{
Vector3 boundsSize;
public double Width
private Vector3 boundsSize;
private AxisAlignedBoundingBox cacheAabb;
private Vector3 cacheBounds;
private Matrix4X4 cacheMatrix;
public FitToBoundsObject3D_2()
{
get => boundsSize.X;
set
Name = "Fit to Bounds".Localize();
}
public override bool CanApply => true;
public override bool CanRemove => true;
private IObject3D FitBounds => Children.Last();
public static FitToBoundsObject3D_2 Create(IObject3D itemToFit)
{
var fitToBounds = new FitToBoundsObject3D_2();
var aabb = itemToFit.GetAxisAlignedBoundingBox();
var bounds = new Object3D()
{
boundsSize.X = value;
UpdateBoundsItem();
Visible = false,
Color = new Color(Color.Red, 100),
Mesh = PlatonicSolids.CreateCube()
};
// add all the children
var scaleItem = new Object3D();
fitToBounds.Children.Add(scaleItem);
scaleItem.Children.Add(itemToFit);
fitToBounds.Children.Add(bounds);
fitToBounds.SizeX = aabb.XSize;
fitToBounds.SizeY = aabb.YSize;
fitToBounds.SizeZ = aabb.ZSize;
return fitToBounds;
}
public void DrawEditor(object sender, DrawEventArgs e)
{
if (sender is InteractionLayer layer
&& layer.Scene.SelectedItem != null
&& layer.Scene.SelectedItem.DescendantsAndSelf().Where((i) => i == this).Any())
{
var aabb = SourceItem.GetAxisAlignedBoundingBox();
var center = aabb.Center;
var worldMatrix = this.WorldMatrix();
var minXyz = center - new Vector3(SizeX / 2, SizeY / 2, SizeZ / 2);
var maxXyz = center + new Vector3(SizeX / 2, SizeY / 2, SizeZ / 2);
var bounds = new AxisAlignedBoundingBox(minXyz, maxXyz);
//var leftW = Vector3.Transform(, worldMatrix);
var right = Vector3.Transform(center + new Vector3(SizeX / 2, 0, 0), worldMatrix);
// layer.World.Render3DLine(left, right, Agg.Color.Red);
layer.World.RenderAabb(bounds, worldMatrix, Agg.Color.Red, 1, 1);
}
}
public override AxisAlignedBoundingBox GetAxisAlignedBoundingBox(Matrix4X4 matrix)
{
if (Children.Count == 2)
{
if (cacheMatrix != matrix
|| cacheBounds != boundsSize)
{
using (FitBounds.RebuildLock())
{
FitBounds.Visible = true;
cacheAabb = base.GetAxisAlignedBoundingBox(matrix);
FitBounds.Visible = false;
}
cacheMatrix = matrix;
cacheBounds = boundsSize;
}
return cacheAabb;
}
return base.GetAxisAlignedBoundingBox(matrix);
}
public override void OnInvalidate(InvalidateArgs invalidateType)
{
if ((invalidateType.InvalidateType == InvalidateType.Content
|| invalidateType.InvalidateType == InvalidateType.Matrix
|| invalidateType.InvalidateType == InvalidateType.Mesh)
&& invalidateType.Source != this
&& !RebuildLocked)
{
Rebuild(null);
}
else if (invalidateType.InvalidateType == InvalidateType.Properties
&& invalidateType.Source == this)
{
Rebuild(null);
}
else
{
base.OnInvalidate(invalidateType);
}
}
public void Rebuild(UndoBuffer undoBuffer)
{
this.DebugDepth("Rebuild");
using (RebuildLock())
{
UpdateBoundsItem();
var aabb = this.GetAxisAlignedBoundingBox();
AdjustChildSize(null, null);
if (aabb.ZSize > 0)
{
// If the part was already created and at a height, maintain the height.
PlatingHelper.PlaceMeshAtHeight(this, aabb.minXYZ.Z);
}
}
base.Invalidate(new InvalidateArgs(this, InvalidateType.Matrix));
}
private void AdjustChildSize(object sender, EventArgs e)
{
var aabb = SourceItem.GetAxisAlignedBoundingBox();
TransformItem.Matrix = Matrix4X4.Identity;
var scale = Vector3.One;
if (StretchX)
{
scale.X = SizeX / aabb.XSize;
}
if (StretchY)
{
scale.Y = SizeY / aabb.YSize;
}
if (StretchZ)
{
scale.Z = SizeZ / aabb.ZSize;
}
switch (MaintainRatio)
{
case MaintainRatio.None:
break;
case MaintainRatio.X_Y:
var minXy = Math.Min(scale.X, scale.Y);
scale.X = minXy;
scale.Y = minXy;
break;
case MaintainRatio.X_Y_Z:
var minXyz = Math.Min(Math.Min(scale.X, scale.Y), scale.Z);
scale.X = minXyz;
scale.Y = minXyz;
scale.Z = minXyz;
break;
}
TransformItem.Matrix = Object3DExtensions.ApplyAtPosition(TransformItem.Matrix, aabb.Center, Matrix4X4.CreateScale(scale));
}
private void UpdateBoundsItem()
{
if (Children.Count == 2)
@ -76,7 +233,24 @@ namespace MatterHackers.MatterControl.DesignTools.Operations
}
}
public double Depth
#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;
UpdateBoundsItem();
}
}
[DisplayName("Depth")]
public double SizeY
{
get => boundsSize.Y;
set
@ -85,7 +259,9 @@ namespace MatterHackers.MatterControl.DesignTools.Operations
UpdateBoundsItem();
}
}
public double Height
[DisplayName("Height")]
public double SizeZ
{
get => boundsSize.Z;
set
@ -95,172 +271,15 @@ namespace MatterHackers.MatterControl.DesignTools.Operations
}
}
private IObject3D FitBounds => Children.Last();
[Description("Set the rules for how to maintain the part while scaling.")]
public MaintainRatio MaintainRatio { get; set; } = MaintainRatio.X_Y;
[Description("Allows you turn turn on and off applying the fit to the x axis.")]
public bool StretchX { get; set; } = true;
[Description("Allows you turn turn on and off applying the fit to the y axis.")]
public bool StretchY { get; set; } = true;
[Description("Allows you turn turn on and off applying the fit to the z axis.")]
public bool StretchZ { get; set; } = true;
public FitToBoundsObject3D_2()
{
Name = "Fit to Bounds".Localize();
}
public override void OnInvalidate(InvalidateArgs invalidateType)
{
if ((invalidateType.InvalidateType == InvalidateType.Content
|| invalidateType.InvalidateType == InvalidateType.Matrix
|| invalidateType.InvalidateType == InvalidateType.Mesh)
&& invalidateType.Source != this
&& !RebuildLocked)
{
Rebuild(null);
}
else if (invalidateType.InvalidateType == InvalidateType.Properties
&& invalidateType.Source == this)
{
Rebuild(null);
}
else
{
base.OnInvalidate(invalidateType);
}
}
public static FitToBoundsObject3D_2 Create(IObject3D itemToFit)
{
var fitToBounds = new FitToBoundsObject3D_2();
var aabb = itemToFit.GetAxisAlignedBoundingBox();
var bounds = new Object3D()
{
Visible = false,
Color = new Color(Color.Red, 100),
Mesh = PlatonicSolids.CreateCube()
};
// add all the children
var scaleItem = new Object3D();
fitToBounds.Children.Add(scaleItem);
scaleItem.Children.Add(itemToFit);
fitToBounds.Children.Add(bounds);
fitToBounds.Width = aabb.XSize;
fitToBounds.Depth = aabb.YSize;
fitToBounds.Height = aabb.ZSize;
return fitToBounds;
}
public void Rebuild(UndoBuffer undoBuffer)
{
this.DebugDepth("Rebuild");
using (RebuildLock())
{
UpdateBoundsItem();
var aabb = this.GetAxisAlignedBoundingBox();
AdjustChildSize(null, null);
if (aabb.ZSize > 0)
{
// If the part was already created and at a height, maintain the height.
PlatingHelper.PlaceMeshAtHeight(this, aabb.minXYZ.Z);
}
}
base.Invalidate(new InvalidateArgs(this, InvalidateType.Matrix));
}
Matrix4X4 cacheMatrix;
Vector3 cacheBounds;
AxisAlignedBoundingBox cacheAabb;
public override AxisAlignedBoundingBox GetAxisAlignedBoundingBox(Matrix4X4 matrix)
{
if (Children.Count == 2)
{
if (cacheMatrix != matrix
|| cacheBounds != boundsSize)
{
using (FitBounds.RebuildLock())
{
FitBounds.Visible = true;
cacheAabb = base.GetAxisAlignedBoundingBox(matrix);
FitBounds.Visible = false;
}
cacheMatrix = matrix;
cacheBounds = boundsSize;
}
return cacheAabb;
}
return base.GetAxisAlignedBoundingBox(matrix);
}
private void AdjustChildSize(object sender, EventArgs e)
{
var aabb = SourceItem.GetAxisAlignedBoundingBox();
TransformItem.Matrix = Matrix4X4.Identity;
var scale = Vector3.One;
if (StretchX)
{
scale.X = Width / aabb.XSize;
}
if (StretchY)
{
scale.Y = Depth / aabb.YSize;
}
if (StretchZ)
{
scale.Z = Height / aabb.ZSize;
}
switch (MaintainRatio)
{
case MaintainRatio.None:
break;
case MaintainRatio.X_Y:
var minXy = Math.Min(scale.X, scale.Y);
scale.X = minXy;
scale.Y = minXy;
break;
case MaintainRatio.X_Y_Z:
var minXyz = Math.Min(Math.Min(scale.X, scale.Y), scale.Z);
scale.X = minXyz;
scale.Y = minXyz;
scale.Z = minXyz;
break;
}
TransformItem.Matrix = Object3DExtensions.ApplyAtPosition(TransformItem.Matrix, aabb.Center, Matrix4X4.CreateScale(scale));
}
public void DrawEditor(object sender, DrawEventArgs e)
{
if (sender is InteractionLayer layer
&& layer.Scene.SelectedItem != null
&& layer.Scene.SelectedItem.DescendantsAndSelf().Where((i) => i == this).Any())
{
var aabb = SourceItem.GetAxisAlignedBoundingBox();
var center = aabb.Center;
var worldMatrix = this.WorldMatrix();
var minXyz = center - new Vector3(Width / 2, Depth / 2, Height / 2);
var maxXyz = center + new Vector3(Width / 2, Depth / 2, Height / 2);
var bounds = new AxisAlignedBoundingBox(minXyz, maxXyz);
//var leftW = Vector3.Transform(, worldMatrix);
var right = Vector3.Transform(center + new Vector3(Width / 2, 0, 0), worldMatrix);
// layer.World.Render3DLine(left, right, Agg.Color.Red);
layer.World.RenderAabb(bounds, worldMatrix, Agg.Color.Red, 1, 1);
}
}
#endregion // editable properties
}
}

View file

@ -30,30 +30,25 @@ either expressed or implied, of the FreeBSD Project.
using MatterHackers.Agg.UI;
using MatterHackers.DataConverters3D;
using MatterHackers.Localizations;
using MatterHackers.MatterControl.DesignTools.EditableTypes;
using MatterHackers.MatterControl.PartPreviewWindow;
using MatterHackers.MeshVisualizer;
using MatterHackers.RenderOpenGl.OpenGl;
using MatterHackers.VectorMath;
using Newtonsoft.Json;
using System.ComponentModel;
using System.Linq;
using MatterHackers.MatterControl.DesignTools.EditableTypes;
using System;
namespace MatterHackers.MatterControl.DesignTools.Operations
{
public class RotateObject3D_2 : TransformWrapperObject3D, IEditorDraw
{
public DirectionAxis RotateAbout { get; set; } = new DirectionAxis() { Origin = Vector3.NegativeInfinity, Normal = Vector3.UnitZ };
[DisplayName("Angle")]
public double AngleDegrees { get; set; } = 0;
public RotateObject3D_2()
{
Name = "Rotate".Localize();
}
public RotateObject3D_2(IObject3D item, double xRadians = 0, double yRadians = 0, double zRadians = 0, string name = "")
: this()
{
Children.Add(item.Clone());
@ -65,6 +60,15 @@ namespace MatterHackers.MatterControl.DesignTools.Operations
{
}
public override bool CanApply => true;
public override bool CanRemove => true;
#region // editable properties
public DirectionAxis RotateAbout { get; set; } = new DirectionAxis() { Origin = Vector3.NegativeInfinity, Normal = Vector3.UnitZ };
[DisplayName("Angle")]
public double AngleDegrees { get; set; } = 0;
#endregion
[JsonIgnore]
public Matrix4X4 RotationMatrix
{
@ -79,17 +83,28 @@ namespace MatterHackers.MatterControl.DesignTools.Operations
}
}
private void Rebuild(UndoBuffer undoBuffer)
public static RotateObject3D_2 Create(IObject3D itemToRotate)
{
this.DebugDepth("Rebuild");
var rotate = new RotateObject3D_2();
var aabb = itemToRotate.GetAxisAlignedBoundingBox();
using (RebuildLock())
rotate.RotateAbout.Origin = aabb.Center;
var rotateItem = new Object3D();
rotate.Children.Add(rotateItem);
rotateItem.Children.Add(itemToRotate);
return rotate;
}
public void DrawEditor(object sender, DrawEventArgs e)
{
if (sender is InteractionLayer layer
&& layer.Scene.SelectedItem != null
&& layer.Scene.SelectedItem.DescendantsAndSelf().Where((i) => i == this).Any())
{
// set the matrix for the inner object
TransformItem.Matrix = RotationMatrix;
layer.World.RenderDirectionAxis(RotateAbout, this.WorldMatrix(), 30);
}
Invalidate(new InvalidateArgs(this, InvalidateType.Matrix, null));
}
public override void OnInvalidate(InvalidateArgs invalidateType)
@ -126,28 +141,17 @@ namespace MatterHackers.MatterControl.DesignTools.Operations
}
}
public void DrawEditor(object sender, DrawEventArgs e)
private void Rebuild(UndoBuffer undoBuffer)
{
if (sender is InteractionLayer layer
&& layer.Scene.SelectedItem != null
&& layer.Scene.SelectedItem.DescendantsAndSelf().Where((i) => i == this).Any())
this.DebugDepth("Rebuild");
using (RebuildLock())
{
layer.World.RenderDirectionAxis(RotateAbout, this.WorldMatrix(), 30);
// set the matrix for the inner object
TransformItem.Matrix = RotationMatrix;
}
}
public static RotateObject3D_2 Create(IObject3D itemToRotate)
{
var rotate = new RotateObject3D_2();
var aabb = itemToRotate.GetAxisAlignedBoundingBox();
rotate.RotateAbout.Origin = aabb.Center;
var rotateItem = new Object3D();
rotate.Children.Add(rotateItem);
rotateItem.Children.Add(itemToRotate);
return rotate;
Invalidate(new InvalidateArgs(this, InvalidateType.Matrix, null));
}
}
}

View file

@ -27,15 +27,19 @@ of the authors and should not be interpreted as representing official policies,
either expressed or implied, of the FreeBSD Project.
*/
using MatterHackers.Agg.UI;
using MatterHackers.DataConverters3D;
using MatterHackers.Localizations;
using MatterHackers.VectorMath;
using System.Linq;
namespace MatterHackers.MatterControl.DesignTools.Operations
{
public class TranslateObject3D : Object3D
public class TranslateObject3D : TransformWrapperObject3D
{
public TranslateObject3D()
{
Name = "Translate".Localize();
}
public TranslateObject3D(IObject3D item, double x = 0, double y = 0, double z = 0)
@ -43,10 +47,84 @@ namespace MatterHackers.MatterControl.DesignTools.Operations
{
}
public TranslateObject3D(IObject3D item, Vector3 translation)
public TranslateObject3D(IObject3D itemToTranslate, Vector3 translation)
: this()
{
Matrix *= Matrix4X4.CreateTranslation(translation);
Children.Add(item.Clone());
var translate = this;
var aabb = itemToTranslate.GetAxisAlignedBoundingBox();
var translateItem = new Object3D();
translate.Children.Add(translateItem);
translateItem.Children.Add(itemToTranslate);
}
public override bool CanApply => true;
public override bool CanRemove => true;
public static TranslateObject3D Create(IObject3D itemToTranslate)
{
var translate = new TranslateObject3D();
var aabb = itemToTranslate.GetAxisAlignedBoundingBox();
var translateItem = new Object3D();
translate.Children.Add(translateItem);
translateItem.Children.Add(itemToTranslate);
return translate;
}
#region // editable properties
public Vector3 Translation { get; set; } = Vector3.Zero;
#endregion // editable properties
public override void OnInvalidate(InvalidateArgs invalidateType)
{
if ((invalidateType.InvalidateType == InvalidateType.Content
|| invalidateType.InvalidateType == InvalidateType.Matrix
|| invalidateType.InvalidateType == InvalidateType.Mesh)
&& invalidateType.Source != this
&& !RebuildLocked)
{
Rebuild(null);
}
else if (invalidateType.InvalidateType == InvalidateType.Color)
{
var sourceItem = OperationSourceObject3D.GetOrCreateSourceContainer(this).Children.FirstOrDefault();
foreach (var item in Children)
{
if (item != sourceItem)
{
item.Color = sourceItem.Color;
}
}
base.OnInvalidate(invalidateType);
}
else if (invalidateType.InvalidateType == InvalidateType.Properties
&& invalidateType.Source == this)
{
Rebuild(null);
}
else
{
base.OnInvalidate(invalidateType);
}
}
private void Rebuild(UndoBuffer undoBuffer)
{
this.DebugDepth("Rebuild");
using (RebuildLock())
{
// set the matrix for the inner object
TransformItem.Matrix = Matrix4X4.CreateTranslation(Translation);
}
Invalidate(new InvalidateArgs(this, InvalidateType.Matrix, null));
}
}
}

View file

@ -97,7 +97,7 @@
<Compile Include="DesignTools\Operations\ArrayAdvancedObject3D.cs" />
<Compile Include="DesignTools\Operations\ArrayLinearObject3D.cs" />
<Compile Include="DesignTools\Operations\ArrayRadialObject3D.cs" />
<Compile Include="DesignTools\Operations\FitToBoundsObject3D.cs" />
<Compile Include="DesignTools\Obsolete\FitToBoundsObject3D.cs" />
<Compile Include="DesignTools\Operations\FitToBoundsObject3D_2.cs" />
<Compile Include="DesignTools\Operations\TransformWrapperObject3D.cs" />
<Compile Include="DesignTools\Operations\GroupObject3D.cs" />
@ -111,7 +111,7 @@
<Compile Include="DesignTools\Operations\OperationSourceObject3D.cs" />
<Compile Include="DesignTools\Operations\Path\SmoothPathObject3D.cs" />
<Compile Include="DesignTools\Operations\PinchObject3D.cs" />
<Compile Include="DesignTools\Operations\RotateObject3D.cs" />
<Compile Include="DesignTools\Obsolete\RotateObject3D.cs" />
<Compile Include="DesignTools\Operations\RotateObject3D_2.cs" />
<Compile Include="DesignTools\Operations\ScaleObject3D.cs" />
<Compile Include="DesignTools\Operations\SetCenterObject3D.cs" />

@ -1 +1 @@
Subproject commit 41db892c4b7790e3eb5c92896ed536cdfa722d2d
Subproject commit bb0881cd16ffb3498c8089cc6695d76629b3d332