commit
edafb8168a
9 changed files with 1003 additions and 679 deletions
|
|
@ -549,10 +549,6 @@
|
|||
<Project>{9B062971-A88E-4A3D-B3C9-12B78D15FA66}</Project>
|
||||
<Name>clipper_library</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="Submodules\agg-sharp\Csg\Csg.csproj">
|
||||
<Project>{7E61A5BD-E78F-4B80-88C9-3821B4FA062E}</Project>
|
||||
<Name>Csg</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="Submodules\agg-sharp\DataConverters3D\DataConverters3D.csproj">
|
||||
<Project>{04667764-DC7B-4B95-AEF6-B4E6C87A54E9}</Project>
|
||||
<Name>DataConverters3D</Name>
|
||||
|
|
|
|||
|
|
@ -184,55 +184,66 @@ namespace MatterHackers.MatterControl.PartPreviewWindow.View3D
|
|||
var removeObjects = participants.Where((obj) => obj.OutputType == PrintOutputTypes.Hole).ToList();
|
||||
var keepObjects = participants.Where((obj) => obj.OutputType != PrintOutputTypes.Hole).ToList();
|
||||
|
||||
if (removeObjects.Any()
|
||||
&& keepObjects.Any())
|
||||
{
|
||||
var totalOperations = removeObjects.Count * keepObjects.Count;
|
||||
double amountPerOperation = 1.0 / totalOperations;
|
||||
double percentCompleted = 0;
|
||||
|
||||
foreach (var remove in removeObjects)
|
||||
{
|
||||
foreach (var keep in keepObjects)
|
||||
{
|
||||
progressStatus.Status = "Copy Remove";
|
||||
reporter.Report(progressStatus);
|
||||
var transformedRemove = Mesh.Copy(remove.Mesh, CancellationToken.None);
|
||||
transformedRemove.Transform(remove.WorldMatrix(null));
|
||||
|
||||
progressStatus.Status = "Copy Keep";
|
||||
reporter.Report(progressStatus);
|
||||
var transformedKeep = Mesh.Copy(keep.Mesh, CancellationToken.None);
|
||||
transformedKeep.Transform(keep.WorldMatrix(null));
|
||||
|
||||
progressStatus.Status = "Do CSG";
|
||||
reporter.Report(progressStatus);
|
||||
transformedKeep = PolygonMesh.Csg.CsgOperations.Subtract(transformedKeep, transformedRemove, (status, progress0To1) =>
|
||||
{
|
||||
// Abort if flagged
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
progressStatus.Status = status;
|
||||
progressStatus.Progress0To1 = percentCompleted + amountPerOperation * progress0To1;
|
||||
reporter.Report(progressStatus);
|
||||
}, cancellationToken);
|
||||
var inverse = keep.WorldMatrix(null);
|
||||
inverse.Invert();
|
||||
transformedKeep.Transform(inverse);
|
||||
|
||||
keep.Mesh = transformedKeep;
|
||||
view3DWidget.Invalidate();
|
||||
|
||||
percentCompleted += amountPerOperation;
|
||||
progressStatus.Progress0To1 = percentCompleted;
|
||||
reporter.Report(progressStatus);
|
||||
}
|
||||
|
||||
remove.Visible = false;
|
||||
}
|
||||
}
|
||||
Subtract(keepObjects, removeObjects, cancellationToken, reporter);
|
||||
return Task.CompletedTask;
|
||||
});
|
||||
}
|
||||
|
||||
public static void Subtract(List<IObject3D> keepObjects, List<IObject3D> removeObjects)
|
||||
{
|
||||
Subtract(keepObjects, removeObjects, CancellationToken.None, null);
|
||||
}
|
||||
|
||||
public static void Subtract(List<IObject3D> keepObjects, List<IObject3D> removeObjects, CancellationToken cancellationToken, IProgress<ProgressStatus> reporter)
|
||||
{
|
||||
if (removeObjects.Any()
|
||||
&& keepObjects.Any())
|
||||
{
|
||||
var totalOperations = removeObjects.Count * keepObjects.Count;
|
||||
double amountPerOperation = 1.0 / totalOperations;
|
||||
double percentCompleted = 0;
|
||||
|
||||
ProgressStatus progressStatus = new ProgressStatus();
|
||||
foreach (var remove in removeObjects)
|
||||
{
|
||||
foreach (var keep in keepObjects)
|
||||
{
|
||||
progressStatus.Status = "Copy Remove";
|
||||
reporter?.Report(progressStatus);
|
||||
var transformedRemove = Mesh.Copy(remove.Mesh, CancellationToken.None);
|
||||
transformedRemove.Transform(remove.WorldMatrix(null));
|
||||
|
||||
progressStatus.Status = "Copy Keep";
|
||||
reporter?.Report(progressStatus);
|
||||
var transformedKeep = Mesh.Copy(keep.Mesh, CancellationToken.None);
|
||||
transformedKeep.Transform(keep.WorldMatrix(null));
|
||||
|
||||
progressStatus.Status = "Do CSG";
|
||||
reporter?.Report(progressStatus);
|
||||
transformedKeep = PolygonMesh.Csg.CsgOperations.Subtract(transformedKeep, transformedRemove, (status, progress0To1) =>
|
||||
{
|
||||
// Abort if flagged
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
progressStatus.Status = status;
|
||||
progressStatus.Progress0To1 = percentCompleted + amountPerOperation * progress0To1;
|
||||
reporter?.Report(progressStatus);
|
||||
}, cancellationToken);
|
||||
var inverse = keep.WorldMatrix(null);
|
||||
inverse.Invert();
|
||||
transformedKeep.Transform(inverse);
|
||||
|
||||
keep.Mesh = transformedKeep;
|
||||
keep.Invalidate();
|
||||
|
||||
percentCompleted += amountPerOperation;
|
||||
progressStatus.Progress0To1 = percentCompleted;
|
||||
reporter?.Report(progressStatus);
|
||||
}
|
||||
|
||||
remove.Visible = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -854,6 +854,11 @@ namespace MatterHackers.MatterControl.PartPreviewWindow
|
|||
activeButtonBeforeMouseOverride = viewControls3D.ActiveButton;
|
||||
viewControls3D.ActiveButton = ViewControls3DButtons.Translate;
|
||||
}
|
||||
else if(Keyboard.IsKeyDown(Keys.Alt))
|
||||
{
|
||||
activeButtonBeforeMouseOverride = viewControls3D.ActiveButton;
|
||||
viewControls3D.ActiveButton = ViewControls3DButtons.Scale;
|
||||
}
|
||||
else
|
||||
{
|
||||
activeButtonBeforeMouseOverride = viewControls3D.ActiveButton;
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
Subproject commit d826d929111ca15c045bedb64b9dee560824ea3f
|
||||
Subproject commit 8f747f76300429070c357dc37c5f0b3f0fe79703
|
||||
|
|
@ -41,7 +41,6 @@ namespace MatterControl.Tests
|
|||
string knownAssemblies = @"MatterHackers.VectorMath.dll
|
||||
AGG.dll
|
||||
MatterHackers.PolygonMesh.dll
|
||||
MatterHackers.Csg.dll
|
||||
clipper_library.dll
|
||||
MatterHackers.Agg.UI.dll
|
||||
Tesselate.dll
|
||||
|
|
|
|||
|
|
@ -1,621 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Threading;
|
||||
using MatterHackers.Agg;
|
||||
using MatterHackers.Agg.Font;
|
||||
using MatterHackers.Agg.Platform;
|
||||
using MatterHackers.Agg.UI;
|
||||
using MatterHackers.Csg;
|
||||
using MatterHackers.Csg.Solids;
|
||||
using MatterHackers.Csg.Transform;
|
||||
using MatterHackers.DataConverters3D;
|
||||
using MatterHackers.Localizations;
|
||||
using MatterHackers.MatterControl.CustomWidgets;
|
||||
using MatterHackers.MatterControl.PartPreviewWindow;
|
||||
using MatterHackers.RenderOpenGl;
|
||||
using MatterHackers.VectorMath;
|
||||
|
||||
namespace MatterHackers.MatterControl.SimplePartScripting
|
||||
{
|
||||
public abstract class MatterCadObject3D : Object3D
|
||||
{
|
||||
public override string ActiveEditor { get; set; } = "MatterCadEditor";
|
||||
|
||||
public abstract void RebuildMeshes();
|
||||
}
|
||||
|
||||
public class MatterCadEditor : IObject3DEditor
|
||||
{
|
||||
private View3DWidget view3DWidget;
|
||||
private IObject3D item;
|
||||
|
||||
public string Name => "MatterCad";
|
||||
|
||||
public bool Unlocked { get; } = true;
|
||||
|
||||
public IEnumerable<Type> SupportedTypes() => new Type[]
|
||||
{
|
||||
typeof(MatterCadObject3D),
|
||||
};
|
||||
|
||||
public GuiWidget Create(IObject3D item, View3DWidget view3DWidget, ThemeConfig theme)
|
||||
{
|
||||
this.view3DWidget = view3DWidget;
|
||||
this.item = item;
|
||||
|
||||
var mainContainer = new FlowLayoutWidget(FlowDirection.TopToBottom)
|
||||
{
|
||||
HAnchor = HAnchor.Stretch
|
||||
};
|
||||
|
||||
if (item is MatterCadObject3D)
|
||||
{
|
||||
ModifyCadObject(view3DWidget, mainContainer, theme);
|
||||
}
|
||||
|
||||
mainContainer.MinimumSize = new Vector2(250, 0);
|
||||
return mainContainer;
|
||||
}
|
||||
|
||||
private void ModifyCadObject(View3DWidget view3DWidget, FlowLayoutWidget tabContainer, ThemeConfig theme)
|
||||
{
|
||||
var allowedTypes = new Type[] { typeof(double), typeof(string), typeof(bool) };
|
||||
|
||||
var ownedPropertiesOnly = System.Reflection.BindingFlags.Public
|
||||
| System.Reflection.BindingFlags.Instance
|
||||
| System.Reflection.BindingFlags.DeclaredOnly;
|
||||
|
||||
var editableProperties = this.item.GetType().GetProperties(ownedPropertiesOnly)
|
||||
.Where(pi => allowedTypes.Contains(pi.PropertyType)
|
||||
&& pi.GetGetMethod() != null)
|
||||
.Select(p => new
|
||||
{
|
||||
Value = p.GetGetMethod().Invoke(this.item, null),
|
||||
DisplayName = GetDisplayName(p),
|
||||
PropertyInfo = p
|
||||
});
|
||||
|
||||
foreach (var property in editableProperties)
|
||||
{
|
||||
// create a double editor
|
||||
if (property.Value is double doubleValue)
|
||||
{
|
||||
FlowLayoutWidget rowContainer = CreateSettingsRow(property.DisplayName.Localize());
|
||||
var doubleEditWidget = new MHNumberEdit(doubleValue, pixelWidth: 50 * GuiWidget.DeviceScale, allowNegatives: true, allowDecimals: true, increment: .05)
|
||||
{
|
||||
SelectAllOnFocus = true,
|
||||
VAnchor = VAnchor.Center
|
||||
};
|
||||
doubleEditWidget.ActuallNumberEdit.EditComplete += (s, e) =>
|
||||
{
|
||||
double editValue;
|
||||
if (double.TryParse(doubleEditWidget.Text, out editValue))
|
||||
{
|
||||
property.PropertyInfo.GetSetMethod().Invoke(this.item, new Object[] { editValue });
|
||||
}
|
||||
((MatterCadObject3D)item).RebuildMeshes();
|
||||
};
|
||||
rowContainer.AddChild(doubleEditWidget);
|
||||
tabContainer.AddChild(rowContainer);
|
||||
}
|
||||
// create a bool editor
|
||||
else if (property.Value is bool boolValue)
|
||||
{
|
||||
FlowLayoutWidget rowContainer = CreateSettingsRow(property.DisplayName.Localize());
|
||||
|
||||
var doubleEditWidget = new CheckBox("");
|
||||
doubleEditWidget.Checked = boolValue;
|
||||
doubleEditWidget.CheckedStateChanged += (s, e) =>
|
||||
{
|
||||
property.PropertyInfo.GetSetMethod().Invoke(this.item, new Object[] { doubleEditWidget.Checked });
|
||||
((MatterCadObject3D)item).RebuildMeshes();
|
||||
};
|
||||
rowContainer.AddChild(doubleEditWidget);
|
||||
tabContainer.AddChild(rowContainer);
|
||||
}
|
||||
// create a bool editor
|
||||
else if (property.Value is string stringValue)
|
||||
{
|
||||
FlowLayoutWidget rowContainer = CreateSettingsRow(property.DisplayName.Localize());
|
||||
var textEditWidget = new MHTextEditWidget(stringValue, pixelWidth: 150 * GuiWidget.DeviceScale)
|
||||
{
|
||||
SelectAllOnFocus = true,
|
||||
VAnchor = VAnchor.Center
|
||||
};
|
||||
textEditWidget.ActualTextEditWidget.EditComplete += (s, e) =>
|
||||
{
|
||||
property.PropertyInfo.GetSetMethod().Invoke(this.item, new Object[] { textEditWidget.Text });
|
||||
((MatterCadObject3D)item).RebuildMeshes();
|
||||
};
|
||||
rowContainer.AddChild(textEditWidget);
|
||||
tabContainer.AddChild(rowContainer);
|
||||
}
|
||||
}
|
||||
|
||||
var updateButton = theme.ButtonFactory.Generate("Update".Localize());
|
||||
updateButton.Margin = new BorderDouble(5);
|
||||
updateButton.HAnchor = HAnchor.Right;
|
||||
updateButton.Click += (s, e) =>
|
||||
{
|
||||
((MatterCadObject3D)item).RebuildMeshes();
|
||||
};
|
||||
tabContainer.AddChild(updateButton);
|
||||
}
|
||||
|
||||
private string GetDisplayName(PropertyInfo prop)
|
||||
{
|
||||
var nameAttribute = prop.GetCustomAttributes(true).OfType<DisplayNameAttribute>().FirstOrDefault();
|
||||
return nameAttribute?.DisplayName ?? prop.Name;
|
||||
}
|
||||
|
||||
private static FlowLayoutWidget CreateSettingsRow(string labelText)
|
||||
{
|
||||
var rowContainer = new FlowLayoutWidget(FlowDirection.LeftToRight)
|
||||
{
|
||||
HAnchor = HAnchor.Stretch,
|
||||
Padding = new BorderDouble(5)
|
||||
};
|
||||
|
||||
var label = new TextWidget(labelText + ":", textColor: ActiveTheme.Instance.PrimaryTextColor)
|
||||
{
|
||||
Margin = new BorderDouble(0, 0, 3, 0),
|
||||
VAnchor = VAnchor.Center
|
||||
};
|
||||
rowContainer.AddChild(label);
|
||||
|
||||
rowContainer.AddChild(new HorizontalSpacer());
|
||||
|
||||
return rowContainer;
|
||||
}
|
||||
}
|
||||
|
||||
public class TestPart : MatterCadObject3D
|
||||
{
|
||||
public double XOffset { get; set; } = -.4;
|
||||
|
||||
public TestPart()
|
||||
{
|
||||
RebuildMeshes();
|
||||
}
|
||||
|
||||
public override void RebuildMeshes()
|
||||
{
|
||||
CsgObject boxCombine = new Box(10, 10, 10);
|
||||
boxCombine -= new Translate(new Box(10, 10, 10), XOffset, -3, 2);
|
||||
this.Mesh = CsgToMesh.Convert(boxCombine);
|
||||
}
|
||||
}
|
||||
|
||||
public class BadSubtract : MatterCadObject3D
|
||||
{
|
||||
public double Sides { get; set; } = 4;
|
||||
|
||||
public BadSubtract()
|
||||
{
|
||||
RebuildMeshes();
|
||||
}
|
||||
|
||||
public override void RebuildMeshes()
|
||||
{
|
||||
int sides = 3;
|
||||
CsgObject keep = new Cylinder(20, 20, sides);
|
||||
CsgObject subtract = new Cylinder(10, 21, sides);
|
||||
subtract = new SetCenter(subtract, keep.GetCenter());
|
||||
CsgObject result = keep - subtract;
|
||||
this.Mesh = CsgToMesh.Convert(result);
|
||||
}
|
||||
}
|
||||
|
||||
public class CardHolder : MatterCadObject3D
|
||||
{
|
||||
[DisplayName("Name")]
|
||||
public string NameToWrite { get; set; } = "MatterHackers";
|
||||
|
||||
public CardHolder()
|
||||
{
|
||||
RebuildMeshes();
|
||||
}
|
||||
|
||||
public override void RebuildMeshes()
|
||||
{
|
||||
CsgObject plainCardHolder = new MeshContainer("PlainBusinessCardHolder.stl");
|
||||
|
||||
//TypeFace typeFace = TypeFace.LoadSVG("Viking_n.svg");
|
||||
|
||||
var letterPrinter = new TypeFacePrinter(NameToWrite);//, new StyledTypeFace(typeFace, 12));
|
||||
PolygonMesh.Mesh textMesh = VertexSourceToMesh.Extrude(letterPrinter, 5);
|
||||
|
||||
CsgObject nameMesh = new MeshContainer(textMesh);
|
||||
|
||||
AxisAlignedBoundingBox textBounds = textMesh.GetAxisAlignedBoundingBox();
|
||||
var textArea = new Vector2(85, 20);
|
||||
|
||||
// test the area that the names will go to
|
||||
//nameMesh = new Box(textArea.x, textArea.y, 5);
|
||||
|
||||
double scale = Math.Min(textArea.X / textBounds.XSize, textArea.Y / textBounds.YSize);
|
||||
nameMesh = new Scale(nameMesh, scale, scale, 1);
|
||||
nameMesh = new Align(nameMesh, Face.Top | Face.Front, plainCardHolder, Face.Bottom | Face.Front);
|
||||
nameMesh = new SetCenter(nameMesh, plainCardHolder.GetCenter(), true, false, false);
|
||||
|
||||
nameMesh = new Rotate(nameMesh, MathHelper.DegreesToRadians(18));
|
||||
nameMesh = new Translate(nameMesh, 0, 2, 16);
|
||||
|
||||
// output one combined mesh
|
||||
//plainCardHolder += nameMesh;
|
||||
//SetAndInvalidateMesh(CsgToMesh.Convert(plainCardHolder));
|
||||
|
||||
// output two meshes for card holder and text
|
||||
this.Children.Modify(list =>
|
||||
{
|
||||
list.Clear();
|
||||
list.AddRange(new[]
|
||||
{
|
||||
new Object3D()
|
||||
{
|
||||
Mesh = CsgToMesh.Convert(plainCardHolder)
|
||||
},
|
||||
new Object3D()
|
||||
{
|
||||
Mesh = CsgToMesh.Convert(nameMesh)
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
this.Mesh = null;
|
||||
}
|
||||
}
|
||||
|
||||
public class PvcT : MatterCadObject3D
|
||||
{
|
||||
[DisplayName("Outer Radius")]
|
||||
public double OuterDiameter { get; set; } = 20;
|
||||
|
||||
[DisplayName("Inner Radius")]
|
||||
public double InnerDiameter { get; set; } = 15;
|
||||
|
||||
public double BottomReach { get; set; } = 30;
|
||||
public double TopReach { get; set; } = 30;
|
||||
public double FrontReach { get; set; } = 25;
|
||||
|
||||
private int sides = 50;
|
||||
|
||||
public PvcT()
|
||||
{
|
||||
RebuildMeshes();
|
||||
}
|
||||
|
||||
public override void RebuildMeshes()
|
||||
{
|
||||
CsgObject topBottomConnect = new Cylinder(OuterDiameter/2, OuterDiameter, sides, Alignment.y);
|
||||
CsgObject frontConnect = new Cylinder(OuterDiameter/2, OuterDiameter/2, sides, Alignment.x);
|
||||
frontConnect = new Align(frontConnect, Face.Right, topBottomConnect, Face.Right);
|
||||
|
||||
CsgObject bottomReach = new Rotate(CreateReach(BottomReach), -MathHelper.Tau / 4);
|
||||
bottomReach = new Align(bottomReach, Face.Back, topBottomConnect, Face.Front, 0, 1);
|
||||
|
||||
CsgObject topReach = new Rotate(CreateReach(TopReach), MathHelper.Tau / 4);
|
||||
topReach = new Align(topReach, Face.Front, topBottomConnect, Face.Back, 0, -1);
|
||||
|
||||
CsgObject frontReach = new Rotate(CreateReach(FrontReach), 0, -MathHelper.Tau / 4);
|
||||
frontReach = new Align(frontReach, Face.Left, topBottomConnect, Face.Right, -1);
|
||||
|
||||
// output multiple meshes for pipe connector
|
||||
this.Children.Modify(list =>
|
||||
{
|
||||
list.Clear();
|
||||
list.AddRange(new[]
|
||||
{
|
||||
new Object3D()
|
||||
{
|
||||
Mesh = CsgToMesh.Convert(topBottomConnect),
|
||||
Color = Color.LightGray
|
||||
},
|
||||
new Object3D()
|
||||
{
|
||||
Mesh = CsgToMesh.Convert(frontConnect),
|
||||
Color = Color.LightGray
|
||||
},
|
||||
new Object3D()
|
||||
{
|
||||
Mesh = CsgToMesh.Convert(bottomReach),
|
||||
Color = Color.White
|
||||
},
|
||||
new Object3D()
|
||||
{
|
||||
Mesh = CsgToMesh.Convert(topReach),
|
||||
Color = Color.White
|
||||
},
|
||||
new Object3D()
|
||||
{
|
||||
Mesh = CsgToMesh.Convert(frontReach),
|
||||
Color = Color.White
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
this.Color = Color.Transparent;
|
||||
this.Mesh = null;
|
||||
}
|
||||
|
||||
private CsgObject CreateReach(double reach)
|
||||
{
|
||||
var finWidth = 4.0;
|
||||
var finLength = InnerDiameter;
|
||||
var fin1 = new Box(finWidth, finLength, reach);
|
||||
fin1.ChamferEdge(Face.Top | Face.Back, finLength / 8);
|
||||
fin1.ChamferEdge(Face.Top | Face.Front, finLength / 8);
|
||||
CsgObject fin2 = new Rotate(fin1, 0, 0, MathHelper.Tau / 4);
|
||||
|
||||
return fin1 + fin2;
|
||||
}
|
||||
}
|
||||
|
||||
public class RibonWithName : MatterCadObject3D
|
||||
{
|
||||
[DisplayName("Name")]
|
||||
public string NameToWrite { get; set; } = "MatterHackers";
|
||||
|
||||
static TypeFace typeFace = null;
|
||||
|
||||
public RibonWithName()
|
||||
{
|
||||
RebuildMeshes();
|
||||
}
|
||||
|
||||
public override void RebuildMeshes()
|
||||
{
|
||||
CsgObject cancerRibonStl = new MeshContainer("Cancer_Ribbon.stl");
|
||||
|
||||
cancerRibonStl = new Rotate(cancerRibonStl, MathHelper.DegreesToRadians(90));
|
||||
|
||||
if (typeFace == null)
|
||||
{
|
||||
typeFace = TypeFace.LoadFrom(AggContext.StaticData.ReadAllText(Path.Combine("Fonts", "TitilliumWeb-Black.svg")));
|
||||
}
|
||||
|
||||
var letterPrinter = new TypeFacePrinter(NameToWrite.ToUpper(), new StyledTypeFace(typeFace, 12));
|
||||
PolygonMesh.Mesh textMesh = VertexSourceToMesh.Extrude(letterPrinter, 5);
|
||||
|
||||
CsgObject nameMesh = new MeshContainer(textMesh);
|
||||
|
||||
AxisAlignedBoundingBox textBounds = textMesh.GetAxisAlignedBoundingBox();
|
||||
var textArea = new Vector2(25, 6);
|
||||
|
||||
double scale = Math.Min(textArea.X / textBounds.XSize, textArea.Y / textBounds.YSize);
|
||||
nameMesh = new Scale(nameMesh, scale, scale, 2 / textBounds.ZSize);
|
||||
nameMesh = new Align(nameMesh, Face.Bottom | Face.Front, cancerRibonStl, Face.Top | Face.Front, 0, 0, -1);
|
||||
nameMesh = new SetCenter(nameMesh, cancerRibonStl.GetCenter(), true, false, false);
|
||||
|
||||
nameMesh = new Rotate(nameMesh, 0, 0, MathHelper.DegreesToRadians(50));
|
||||
nameMesh = new Translate(nameMesh, -37, -14, -1);
|
||||
|
||||
// output two meshes
|
||||
|
||||
this.Children.Modify(list =>
|
||||
{
|
||||
list.Clear();
|
||||
list.AddRange(new[]
|
||||
{
|
||||
new Object3D()
|
||||
{
|
||||
Mesh = CsgToMesh.Convert(cancerRibonStl)
|
||||
},
|
||||
new Object3D()
|
||||
{
|
||||
Mesh = CsgToMesh.Convert(nameMesh)
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
this.Mesh = null;
|
||||
}
|
||||
}
|
||||
|
||||
public class PinchTest : MatterCadObject3D
|
||||
{
|
||||
[DisplayName("Back Ratio")]
|
||||
public double PinchRatio { get; set; } = 1;
|
||||
PolygonMesh.Mesh inputMesh;
|
||||
PolygonMesh.Mesh transformedMesh;
|
||||
|
||||
public PinchTest()
|
||||
{
|
||||
var letterPrinter = new TypeFacePrinter("MatterHackers");
|
||||
inputMesh = VertexSourceToMesh.Extrude(letterPrinter, 5);
|
||||
transformedMesh = PolygonMesh.Mesh.Copy(inputMesh, CancellationToken.None);
|
||||
|
||||
RebuildMeshes();
|
||||
}
|
||||
|
||||
public override void RebuildMeshes()
|
||||
{
|
||||
var aabb = inputMesh.GetAxisAlignedBoundingBox();
|
||||
for(int i=0; i< transformedMesh.Vertices.Count; i++)
|
||||
{
|
||||
var pos = inputMesh.Vertices[i].Position;
|
||||
|
||||
var ratioToApply = PinchRatio;
|
||||
|
||||
var distFromCenter = pos.X - aabb.Center.X;
|
||||
var distanceToPinch = distFromCenter * (1-PinchRatio);
|
||||
var delta = (aabb.Center.X + distFromCenter * ratioToApply) - pos.X;
|
||||
|
||||
// find out how much to pinch based on y position
|
||||
var amountOfRatio = (pos.Y - aabb.minXYZ.Y) / aabb.YSize;
|
||||
transformedMesh.Vertices[i].Position = new Vector3(pos.X + delta * amountOfRatio, pos.Y, pos.Z);
|
||||
}
|
||||
|
||||
transformedMesh.MarkAsChanged();
|
||||
transformedMesh.CalculateNormals();
|
||||
|
||||
this.Mesh = transformedMesh;
|
||||
}
|
||||
}
|
||||
|
||||
public class CurveTest : MatterCadObject3D
|
||||
{
|
||||
[DisplayName("Bend Up")]
|
||||
public bool BendCW { get; set; } = true;
|
||||
|
||||
[DisplayName("Angle")]
|
||||
public double AngleDegrees { get; set; } = 0;
|
||||
PolygonMesh.Mesh inputMesh;
|
||||
PolygonMesh.Mesh transformedMesh;
|
||||
|
||||
public CurveTest()
|
||||
{
|
||||
var letterPrinter = new TypeFacePrinter("MatterHackers");
|
||||
inputMesh = VertexSourceToMesh.Extrude(letterPrinter, 5);
|
||||
transformedMesh = PolygonMesh.Mesh.Copy(inputMesh, CancellationToken.None);
|
||||
|
||||
RebuildMeshes();
|
||||
}
|
||||
|
||||
public override void RebuildMeshes()
|
||||
{
|
||||
if(AngleDegrees > 0)
|
||||
{
|
||||
var aabb = inputMesh.GetAxisAlignedBoundingBox();
|
||||
|
||||
// find the radius that will make the x-size sweep out the requested angle
|
||||
// c = Tr ; r = c/T
|
||||
var angleRadians = MathHelper.DegreesToRadians(AngleDegrees);
|
||||
var circumference = aabb.XSize * MathHelper.Tau / angleRadians;
|
||||
var radius = circumference / MathHelper.Tau;
|
||||
|
||||
var rotateXyPos = new Vector2(aabb.minXYZ.X, BendCW ? aabb.maxXYZ.Y : aabb.minXYZ.Y);
|
||||
if(!BendCW)
|
||||
{
|
||||
angleRadians = -angleRadians;
|
||||
}
|
||||
|
||||
for (int i = 0; i < transformedMesh.Vertices.Count; i++)
|
||||
{
|
||||
var pos = inputMesh.Vertices[i].Position;
|
||||
var pos2D = new Vector2(pos);
|
||||
Vector2 rotateSpace = pos2D - rotateXyPos;
|
||||
var rotateRatio = rotateSpace.X / aabb.XSize;
|
||||
|
||||
rotateSpace.X = 0;
|
||||
rotateSpace.Y += BendCW ? -radius : radius;
|
||||
rotateSpace.Rotate(angleRadians * rotateRatio);
|
||||
rotateSpace.Y += BendCW ? radius : -radius; ;
|
||||
rotateSpace += rotateXyPos;
|
||||
|
||||
transformedMesh.Vertices[i].Position = new Vector3(rotateSpace.X, rotateSpace.Y, pos.Z);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < transformedMesh.Vertices.Count; i++)
|
||||
{
|
||||
transformedMesh.Vertices[i].Position = inputMesh.Vertices[i].Position;
|
||||
}
|
||||
}
|
||||
|
||||
transformedMesh.MarkAsChanged();
|
||||
transformedMesh.CalculateNormals();
|
||||
|
||||
this.Mesh = transformedMesh;
|
||||
}
|
||||
}
|
||||
|
||||
public class ChairFoot : MatterCadObject3D
|
||||
{
|
||||
// these are the public variables that would be edited
|
||||
[DisplayName("Final")]
|
||||
public bool FinalPart { get; set; } = true;
|
||||
|
||||
[DisplayName("Height")]
|
||||
public double HeightFromFloorToBottomOfLeg { get; set; } = 10;
|
||||
|
||||
[DisplayName("Outer Size")]
|
||||
public double OuterSize { get; set; } = 22;
|
||||
|
||||
[DisplayName("Inner Size")]
|
||||
public double InnerSize { get; set; } = 20;
|
||||
[DisplayName("Reach")]
|
||||
public double InsideReach { get; set; } = 10;
|
||||
|
||||
[DisplayName("Angle")]
|
||||
public double AngleDegrees { get; set; } = 3;
|
||||
|
||||
public ChairFoot()
|
||||
{
|
||||
RebuildMeshes();
|
||||
}
|
||||
|
||||
public override void RebuildMeshes()
|
||||
{
|
||||
// This would be better expressed as the desired offset height (height from ground to bottom of chair leg).
|
||||
double angleRadians = MathHelper.DegreesToRadians(AngleDegrees);
|
||||
double extraHeightForRotation = Math.Sinh(angleRadians) * OuterSize; // get the distance to clip off the extra bottom
|
||||
double unclippedFootHeight = HeightFromFloorToBottomOfLeg + extraHeightForRotation;
|
||||
|
||||
if(FinalPart)
|
||||
{
|
||||
Box chairFootBox = new Box(OuterSize, OuterSize, unclippedFootHeight);
|
||||
//chairFootBox.BevelEdge(Edge.LeftBack, 2);
|
||||
//chairFootBox.BevelEdge(Edge.LeftFront, 2);
|
||||
//chairFootBox.BevelEdge(Edge.RightBack, 2);
|
||||
//chairFootBox.BevelEdge(Edge.RightFront, 2);
|
||||
CsgObject chairFoot = chairFootBox;
|
||||
|
||||
CsgObject ring = new Cylinder(InnerSize / 2 - 1, InsideReach, 30);
|
||||
ring -= new Cylinder(ring.XSize / 2 - 2, ring.ZSize + 1, 30);
|
||||
|
||||
CsgObject fins = new Box(3, 1, ring.ZSize);
|
||||
fins = new Translate(fins, 0, 1) + new Translate(fins, 0, -1);
|
||||
fins -= new Align(new Rotate(new Box(5, 5, 5), 0, MathHelper.DegreesToRadians(45)), Face.Bottom | Face.Left, fins, Face.Top | Face.Left, 0, 0, -fins.XSize);
|
||||
fins = new Translate(fins, InnerSize / 2 - .1);
|
||||
|
||||
ring += new Rotate(fins, 0, 0, MathHelper.DegreesToRadians(45));
|
||||
ring += new Rotate(fins, 0, 0, MathHelper.DegreesToRadians(45 + 90));
|
||||
ring += new Rotate(fins, 0, 0, MathHelper.DegreesToRadians(45 + 180));
|
||||
ring += new Rotate(fins, 0, 0, MathHelper.DegreesToRadians(45 - 90));
|
||||
|
||||
chairFoot += new Align(ring, Face.Bottom, chairFoot, Face.Top, 0, 0, -.1);
|
||||
|
||||
chairFoot = new Rotate(chairFoot, 0, angleRadians, 0);
|
||||
CsgObject clipBox = new Align(new Box(OuterSize * 2, OuterSize * 2, unclippedFootHeight), Face.Top, chairFoot, Face.Bottom, 0, 0, extraHeightForRotation);
|
||||
chairFoot -= clipBox;
|
||||
chairFoot = new Translate(chairFoot, 0, 0, clipBox.GetAxisAlignedBoundingBox().maxXYZ.Z);
|
||||
|
||||
this.Mesh = CsgToMesh.Convert(chairFoot);
|
||||
}
|
||||
else // fit part
|
||||
{
|
||||
double baseHeight = 3;
|
||||
double insideHeight = 4;
|
||||
Box chairFootBox = new Box(OuterSize, OuterSize, baseHeight);
|
||||
chairFootBox.BevelEdge(Edge.LeftBack, 2);
|
||||
chairFootBox.BevelEdge(Edge.LeftFront, 2);
|
||||
chairFootBox.BevelEdge(Edge.RightBack, 2);
|
||||
chairFootBox.BevelEdge(Edge.RightFront, 2);
|
||||
CsgObject chairFoot = chairFootBox;
|
||||
|
||||
CsgObject ring = new Cylinder(InnerSize / 2 - 1, insideHeight, 30);
|
||||
ring -= new Cylinder(ring.XSize / 2 - 2, ring.ZSize + 1, 30);
|
||||
|
||||
CsgObject fins = new Box(3, 1, ring.ZSize);
|
||||
fins = new Translate(fins, 0, 1) + new Translate(fins, 0, -1);
|
||||
fins -= new Align(new Rotate(new Box(5, 5, 5), 0, MathHelper.DegreesToRadians(45)), Face.Bottom | Face.Left, fins, Face.Top | Face.Left, 0, 0, -fins.XSize);
|
||||
fins = new Translate(fins, InnerSize / 2 - .1);
|
||||
|
||||
ring += new Rotate(fins, 0, 0, MathHelper.DegreesToRadians(45));
|
||||
ring += new Rotate(fins, 0, 0, MathHelper.DegreesToRadians(45 + 90));
|
||||
ring += new Rotate(fins, 0, 0, MathHelper.DegreesToRadians(45 + 180));
|
||||
ring += new Rotate(fins, 0, 0, MathHelper.DegreesToRadians(45 - 90));
|
||||
|
||||
chairFoot += new Align(ring, Face.Bottom, chairFoot, Face.Top, 0, 0, -.1);
|
||||
|
||||
this.Mesh = CsgToMesh.Convert(chairFoot);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
166
TextCreator/CardHolderTool/MatterCadEditor.cs
Normal file
166
TextCreator/CardHolderTool/MatterCadEditor.cs
Normal file
|
|
@ -0,0 +1,166 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using MatterHackers.Agg;
|
||||
using MatterHackers.Agg.UI;
|
||||
using MatterHackers.DataConverters3D;
|
||||
using MatterHackers.Localizations;
|
||||
using MatterHackers.MatterControl.CustomWidgets;
|
||||
using MatterHackers.MatterControl.PartPreviewWindow;
|
||||
using MatterHackers.VectorMath;
|
||||
|
||||
namespace MatterHackers.MatterControl.MatterCad
|
||||
{
|
||||
public class MatterCadEditor : IObject3DEditor
|
||||
{
|
||||
private IObject3D item;
|
||||
private View3DWidget view3DWidget;
|
||||
public string Name => "MatterCad";
|
||||
|
||||
public bool Unlocked { get; } = true;
|
||||
|
||||
public GuiWidget Create(IObject3D item, View3DWidget view3DWidget, ThemeConfig theme)
|
||||
{
|
||||
this.view3DWidget = view3DWidget;
|
||||
this.item = item;
|
||||
|
||||
var mainContainer = new FlowLayoutWidget(FlowDirection.TopToBottom)
|
||||
{
|
||||
HAnchor = HAnchor.Stretch
|
||||
};
|
||||
|
||||
if (item is MatterCadObject3D)
|
||||
{
|
||||
ModifyCadObject(view3DWidget, mainContainer, theme);
|
||||
}
|
||||
|
||||
mainContainer.MinimumSize = new Vector2(250, 0);
|
||||
return mainContainer;
|
||||
}
|
||||
|
||||
public IEnumerable<Type> SupportedTypes() => new Type[]
|
||||
{
|
||||
typeof(MatterCadObject3D),
|
||||
};
|
||||
|
||||
private static FlowLayoutWidget CreateSettingsRow(string labelText)
|
||||
{
|
||||
var rowContainer = new FlowLayoutWidget(FlowDirection.LeftToRight)
|
||||
{
|
||||
HAnchor = HAnchor.Stretch,
|
||||
Padding = new BorderDouble(5)
|
||||
};
|
||||
|
||||
var label = new TextWidget(labelText + ":", textColor: ActiveTheme.Instance.PrimaryTextColor)
|
||||
{
|
||||
Margin = new BorderDouble(0, 0, 3, 0),
|
||||
VAnchor = VAnchor.Center
|
||||
};
|
||||
rowContainer.AddChild(label);
|
||||
|
||||
rowContainer.AddChild(new HorizontalSpacer());
|
||||
|
||||
return rowContainer;
|
||||
}
|
||||
|
||||
private string GetDisplayName(PropertyInfo prop)
|
||||
{
|
||||
var nameAttribute = prop.GetCustomAttributes(true).OfType<DisplayNameAttribute>().FirstOrDefault();
|
||||
return nameAttribute?.DisplayName ?? prop.Name;
|
||||
}
|
||||
|
||||
private void ModifyCadObject(View3DWidget view3DWidget, FlowLayoutWidget tabContainer, ThemeConfig theme)
|
||||
{
|
||||
var allowedTypes = new Type[] { typeof(double), typeof(string), typeof(bool) };
|
||||
|
||||
var ownedPropertiesOnly = System.Reflection.BindingFlags.Public
|
||||
| System.Reflection.BindingFlags.Instance
|
||||
| System.Reflection.BindingFlags.DeclaredOnly;
|
||||
|
||||
var editableProperties = this.item.GetType().GetProperties(ownedPropertiesOnly)
|
||||
.Where(pi => allowedTypes.Contains(pi.PropertyType)
|
||||
&& pi.GetGetMethod() != null)
|
||||
.Select(p => new
|
||||
{
|
||||
Value = p.GetGetMethod().Invoke(this.item, null),
|
||||
DisplayName = GetDisplayName(p),
|
||||
PropertyInfo = p
|
||||
});
|
||||
|
||||
foreach (var property in editableProperties)
|
||||
{
|
||||
// create a double editor
|
||||
if (property.Value is double doubleValue)
|
||||
{
|
||||
FlowLayoutWidget rowContainer = CreateSettingsRow(property.DisplayName.Localize());
|
||||
var doubleEditWidget = new MHNumberEdit(doubleValue, pixelWidth: 50 * GuiWidget.DeviceScale, allowNegatives: true, allowDecimals: true, increment: .05)
|
||||
{
|
||||
SelectAllOnFocus = true,
|
||||
VAnchor = VAnchor.Center
|
||||
};
|
||||
doubleEditWidget.ActuallNumberEdit.EditComplete += (s, e) =>
|
||||
{
|
||||
double editValue;
|
||||
if (double.TryParse(doubleEditWidget.Text, out editValue))
|
||||
{
|
||||
property.PropertyInfo.GetSetMethod().Invoke(this.item, new Object[] { editValue });
|
||||
}
|
||||
((MatterCadObject3D)item).RebuildMeshes();
|
||||
};
|
||||
rowContainer.AddChild(doubleEditWidget);
|
||||
tabContainer.AddChild(rowContainer);
|
||||
}
|
||||
// create a bool editor
|
||||
else if (property.Value is bool boolValue)
|
||||
{
|
||||
FlowLayoutWidget rowContainer = CreateSettingsRow(property.DisplayName.Localize());
|
||||
|
||||
var doubleEditWidget = new CheckBox("");
|
||||
doubleEditWidget.Checked = boolValue;
|
||||
doubleEditWidget.CheckedStateChanged += (s, e) =>
|
||||
{
|
||||
property.PropertyInfo.GetSetMethod().Invoke(this.item, new Object[] { doubleEditWidget.Checked });
|
||||
((MatterCadObject3D)item).RebuildMeshes();
|
||||
};
|
||||
rowContainer.AddChild(doubleEditWidget);
|
||||
tabContainer.AddChild(rowContainer);
|
||||
}
|
||||
// create a bool editor
|
||||
else if (property.Value is string stringValue)
|
||||
{
|
||||
FlowLayoutWidget rowContainer = CreateSettingsRow(property.DisplayName.Localize());
|
||||
var textEditWidget = new MHTextEditWidget(stringValue, pixelWidth: 150 * GuiWidget.DeviceScale)
|
||||
{
|
||||
SelectAllOnFocus = true,
|
||||
VAnchor = VAnchor.Center
|
||||
};
|
||||
textEditWidget.ActualTextEditWidget.EditComplete += (s, e) =>
|
||||
{
|
||||
property.PropertyInfo.GetSetMethod().Invoke(this.item, new Object[] { textEditWidget.Text });
|
||||
((MatterCadObject3D)item).RebuildMeshes();
|
||||
};
|
||||
rowContainer.AddChild(textEditWidget);
|
||||
tabContainer.AddChild(rowContainer);
|
||||
}
|
||||
}
|
||||
|
||||
var updateButton = theme.ButtonFactory.Generate("Update".Localize());
|
||||
updateButton.Margin = new BorderDouble(5);
|
||||
updateButton.HAnchor = HAnchor.Right;
|
||||
updateButton.Click += (s, e) =>
|
||||
{
|
||||
((MatterCadObject3D)item).RebuildMeshes();
|
||||
};
|
||||
tabContainer.AddChild(updateButton);
|
||||
}
|
||||
}
|
||||
|
||||
public abstract class MatterCadObject3D : Object3D
|
||||
{
|
||||
public override string ActiveEditor { get; set; } = "MatterCadEditor";
|
||||
|
||||
public abstract void RebuildMeshes();
|
||||
}
|
||||
}
|
||||
771
TextCreator/CardHolderTool/MeshObjects.cs
Normal file
771
TextCreator/CardHolderTool/MeshObjects.cs
Normal file
|
|
@ -0,0 +1,771 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using MatterHackers.Agg;
|
||||
using MatterHackers.Agg.Font;
|
||||
using MatterHackers.Agg.Platform;
|
||||
using MatterHackers.Agg.VertexSource;
|
||||
using MatterHackers.DataConverters3D;
|
||||
using MatterHackers.MatterControl.MatterCad;
|
||||
using MatterHackers.MatterControl.PartPreviewWindow.View3D;
|
||||
using MatterHackers.PolygonMesh;
|
||||
using MatterHackers.RenderOpenGl;
|
||||
using MatterHackers.VectorMath;
|
||||
|
||||
namespace MatterHackers.MatterControl.MeshObjects
|
||||
{
|
||||
public enum Alignment { X, Y, Z, negX, negY, negZ };
|
||||
|
||||
[Flags]
|
||||
public enum Face
|
||||
{
|
||||
Left = 0x01,
|
||||
Right = 0x02,
|
||||
Front = 0x04,
|
||||
Back = 0x08,
|
||||
Bottom = 0x10,
|
||||
Top = 0x20,
|
||||
};
|
||||
|
||||
[Flags]
|
||||
public enum Edge
|
||||
{
|
||||
LeftFront = Face.Left | Face.Front,
|
||||
LeftBack = Face.Left | Face.Back,
|
||||
LeftBottom = Face.Left | Face.Bottom,
|
||||
LeftTop = Face.Left | Face.Top,
|
||||
RightFront = Face.Right | Face.Front,
|
||||
RightBack = Face.Right | Face.Back,
|
||||
RightBottom = Face.Right | Face.Bottom,
|
||||
RightTop = Face.Right | Face.Top,
|
||||
FrontBottom = Face.Front | Face.Bottom,
|
||||
FrontTop = Face.Front | Face.Top,
|
||||
BackBottom = Face.Back | Face.Bottom,
|
||||
BackTop = Face.Back | Face.Top
|
||||
}
|
||||
|
||||
public class BadSubtract : MatterCadObject3D
|
||||
{
|
||||
public BadSubtract()
|
||||
{
|
||||
RebuildMeshes();
|
||||
}
|
||||
|
||||
public double Sides { get; set; } = 4;
|
||||
|
||||
public override void RebuildMeshes()
|
||||
{
|
||||
int sides = 3;
|
||||
IObject3D keep = new Cylinder(20, 20, sides);
|
||||
IObject3D subtract = new Cylinder(10, 21, sides);
|
||||
subtract = new SetCenter(subtract, keep.GetCenter());
|
||||
IObject3D result = keep.Minus(subtract);
|
||||
this.SetChildren(result);
|
||||
}
|
||||
}
|
||||
|
||||
public class SetCenter : Object3D
|
||||
{
|
||||
public SetCenter()
|
||||
{
|
||||
}
|
||||
|
||||
public SetCenter(IObject3D item, Vector3 position)
|
||||
{
|
||||
Matrix *= Matrix4X4.CreateTranslation(position - item.GetCenter());
|
||||
Children.Add(item.Clone());
|
||||
}
|
||||
|
||||
public SetCenter(IObject3D item, double x, double y, double z)
|
||||
: this(item, new Vector3(x, y, z))
|
||||
{
|
||||
}
|
||||
|
||||
public SetCenter(IObject3D item, Vector3 offset, bool onX = true, bool onY = true, bool onZ = true)
|
||||
{
|
||||
var center = item.GetAxisAlignedBoundingBox(Matrix4X4.Identity).Center;
|
||||
|
||||
Vector3 consideredOffset = Vector3.Zero; // zero out anything we don't want
|
||||
if (onX)
|
||||
{
|
||||
consideredOffset.X = offset.X - center.X;
|
||||
}
|
||||
if (onY)
|
||||
{
|
||||
consideredOffset.Y = offset.Y - center.Y;
|
||||
}
|
||||
if (onZ)
|
||||
{
|
||||
consideredOffset.Z = offset.Z - center.Z;
|
||||
}
|
||||
|
||||
Matrix *= Matrix4X4.CreateTranslation(consideredOffset);
|
||||
Children.Add(item.Clone());
|
||||
}
|
||||
}
|
||||
|
||||
public class Cylinder : Object3D
|
||||
{
|
||||
public Cylinder()
|
||||
{
|
||||
}
|
||||
|
||||
public Cylinder(double radius, double height, int sides, Alignment alignment = Alignment.Z)
|
||||
: this(radius, radius, height, sides, alignment)
|
||||
{
|
||||
}
|
||||
|
||||
public Cylinder(double radiusBottom, double radiusTop, double height, int sides, Alignment alignment = Alignment.Z)
|
||||
{
|
||||
var path = new VertexStorage();
|
||||
path.MoveTo(0, -height/2);
|
||||
path.LineTo(radiusBottom, -height/2);
|
||||
path.LineTo(radiusTop, height/2);
|
||||
path.LineTo(0, height/2);
|
||||
|
||||
Mesh = VertexSourceToMesh.Revolve(path, sides);
|
||||
switch (alignment)
|
||||
{
|
||||
case Alignment.X:
|
||||
Matrix = Matrix4X4.CreateRotationY(MathHelper.Tau / 4);
|
||||
break;
|
||||
case Alignment.Y:
|
||||
Matrix = Matrix4X4.CreateRotationX(MathHelper.Tau / 4);
|
||||
break;
|
||||
case Alignment.Z:
|
||||
// This is the natural case (how it was modled)
|
||||
break;
|
||||
case Alignment.negX:
|
||||
Matrix = Matrix4X4.CreateRotationY(-MathHelper.Tau / 4);
|
||||
break;
|
||||
case Alignment.negY:
|
||||
Matrix = Matrix4X4.CreateRotationX(-MathHelper.Tau / 4);
|
||||
break;
|
||||
case Alignment.negZ:
|
||||
Matrix = Matrix4X4.CreateRotationX(MathHelper.Tau / 2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class CardHolder : MatterCadObject3D
|
||||
{
|
||||
public CardHolder()
|
||||
{
|
||||
RebuildMeshes();
|
||||
}
|
||||
|
||||
[DisplayName("Name")]
|
||||
public string NameToWrite { get; set; } = "MatterHackers";
|
||||
|
||||
public override void RebuildMeshes()
|
||||
{
|
||||
IObject3D plainCardHolder = Object3D.Load("C:/Temp/CardHolder.stl");
|
||||
|
||||
//TypeFace typeFace = TypeFace.LoadSVG("Viking_n.svg");
|
||||
|
||||
var letterPrinter = new TypeFacePrinter(NameToWrite);//, new StyledTypeFace(typeFace, 12));
|
||||
|
||||
IObject3D nameMesh = new Object3D()
|
||||
{
|
||||
Mesh = VertexSourceToMesh.Extrude(letterPrinter, 5)
|
||||
};
|
||||
|
||||
AxisAlignedBoundingBox textBounds = nameMesh.GetAxisAlignedBoundingBox(Matrix4X4.Identity);
|
||||
var textArea = new Vector2(90, 20);
|
||||
|
||||
// test the area that the names will go to
|
||||
// nameMesh = new Box(textArea.X, textArea.Y, 5);
|
||||
|
||||
double scale = Math.Min(textArea.X / textBounds.XSize, textArea.Y / textBounds.YSize);
|
||||
nameMesh = new Scale(nameMesh, scale, scale, 1);
|
||||
nameMesh = new Align(nameMesh, Face.Bottom | Face.Front, plainCardHolder, Face.Bottom | Face.Front);
|
||||
nameMesh = new SetCenter(nameMesh, plainCardHolder.GetCenter(), true, false, false);
|
||||
|
||||
nameMesh = new Rotate(nameMesh, MathHelper.DegreesToRadians(-16));
|
||||
nameMesh = new Translate(nameMesh, 0, 4, 2);
|
||||
|
||||
// output two meshes for card holder and text
|
||||
this.Children.Modify(list =>
|
||||
{
|
||||
list.Clear();
|
||||
list.Add(plainCardHolder);
|
||||
list.Add(nameMesh);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
public class ChairFoot2 : MatterCadObject3D
|
||||
{
|
||||
public ChairFoot()
|
||||
{
|
||||
RebuildMeshes();
|
||||
}
|
||||
|
||||
[DisplayName("Angle")]
|
||||
public double AngleDegrees { get; set; } = 3;
|
||||
|
||||
// these are the public variables that would be edited
|
||||
[DisplayName("Final")]
|
||||
public bool FinalPart { get; set; } = true;
|
||||
|
||||
[DisplayName("Height")]
|
||||
public double HeightFromFloorToBottomOfLeg { get; set; } = 10;
|
||||
|
||||
[DisplayName("Inner Size")]
|
||||
public double InnerSize { get; set; } = 20;
|
||||
|
||||
[DisplayName("Reach")]
|
||||
public double InsideReach { get; set; } = 10;
|
||||
|
||||
[DisplayName("Outer Size")]
|
||||
public double OuterSize { get; set; } = 22;
|
||||
|
||||
public override void RebuildMeshes()
|
||||
{
|
||||
// This would be better expressed as the desired offset height (height from ground to bottom of chair leg).
|
||||
double angleRadians = MathHelper.DegreesToRadians(AngleDegrees);
|
||||
double extraHeightForRotation = Math.Sinh(angleRadians) * OuterSize; // get the distance to clip off the extra bottom
|
||||
double unclippedFootHeight = HeightFromFloorToBottomOfLeg + extraHeightForRotation;
|
||||
|
||||
if (FinalPart)
|
||||
{
|
||||
Box chairFootBox = new Box(OuterSize, OuterSize, unclippedFootHeight);
|
||||
//chairFootBox.BevelEdge(Edge.LeftBack, 2);
|
||||
//chairFootBox.BevelEdge(Edge.LeftFront, 2);
|
||||
//chairFootBox.BevelEdge(Edge.RightBack, 2);
|
||||
//chairFootBox.BevelEdge(Edge.RightFront, 2);
|
||||
IObject3D chairFoot = chairFootBox;
|
||||
|
||||
IObject3D ring = new Cylinder(InnerSize / 2 - 1, InsideReach, 30);
|
||||
ring -= new Cylinder(ring.XSize / 2 - 2, ring.ZSize + 1, 30);
|
||||
|
||||
IObject3D fins = new Box(3, 1, ring.ZSize);
|
||||
fins = new Translate(fins, 0, 1) + new Translate(fins, 0, -1);
|
||||
fins -= new Align(new Rotate(new Box(5, 5, 5), 0, MathHelper.DegreesToRadians(45)), Face.Bottom | Face.Left, fins, Face.Top | Face.Left, 0, 0, -fins.XSize);
|
||||
fins = new Translate(fins, InnerSize / 2 - .1);
|
||||
|
||||
ring += new Rotate(fins, 0, 0, MathHelper.DegreesToRadians(45));
|
||||
ring += new Rotate(fins, 0, 0, MathHelper.DegreesToRadians(45 + 90));
|
||||
ring += new Rotate(fins, 0, 0, MathHelper.DegreesToRadians(45 + 180));
|
||||
ring += new Rotate(fins, 0, 0, MathHelper.DegreesToRadians(45 - 90));
|
||||
|
||||
chairFoot += new Align(ring, Face.Bottom, chairFoot, Face.Top, 0, 0, -.1);
|
||||
|
||||
chairFoot = new Rotate(chairFoot, 0, angleRadians, 0);
|
||||
IObject3D clipBox = new Align(new Box(OuterSize * 2, OuterSize * 2, unclippedFootHeight), Face.Top, chairFoot, Face.Bottom, 0, 0, extraHeightForRotation);
|
||||
chairFoot -= clipBox;
|
||||
chairFoot = new Translate(chairFoot, 0, 0, clipBox.GetAxisAlignedBoundingBox().maxXYZ.Z);
|
||||
|
||||
this.Mesh = CsgToMesh.Convert(chairFoot);
|
||||
}
|
||||
else // fit part
|
||||
{
|
||||
double baseHeight = 3;
|
||||
double insideHeight = 4;
|
||||
Box chairFootBox = new Box(OuterSize, OuterSize, baseHeight);
|
||||
chairFootBox.BevelEdge(Edge.LeftBack, 2);
|
||||
chairFootBox.BevelEdge(Edge.LeftFront, 2);
|
||||
chairFootBox.BevelEdge(Edge.RightBack, 2);
|
||||
chairFootBox.BevelEdge(Edge.RightFront, 2);
|
||||
IObject3D chairFoot = chairFootBox;
|
||||
|
||||
IObject3D ring = new Cylinder(InnerSize / 2 - 1, insideHeight, 30);
|
||||
ring -= new Cylinder(ring.XSize / 2 - 2, ring.ZSize + 1, 30);
|
||||
|
||||
IObject3D fins = new Box(3, 1, ring.ZSize);
|
||||
fins = new Translate(fins, 0, 1) + new Translate(fins, 0, -1);
|
||||
fins -= new Align(new Rotate(new Box(5, 5, 5), 0, MathHelper.DegreesToRadians(45)), Face.Bottom | Face.Left, fins, Face.Top | Face.Left, 0, 0, -fins.XSize);
|
||||
fins = new Translate(fins, InnerSize / 2 - .1);
|
||||
|
||||
ring += new Rotate(fins, 0, 0, MathHelper.DegreesToRadians(45));
|
||||
ring += new Rotate(fins, 0, 0, MathHelper.DegreesToRadians(45 + 90));
|
||||
ring += new Rotate(fins, 0, 0, MathHelper.DegreesToRadians(45 + 180));
|
||||
ring += new Rotate(fins, 0, 0, MathHelper.DegreesToRadians(45 - 90));
|
||||
|
||||
chairFoot += new Align(ring, Face.Bottom, chairFoot, Face.Top, 0, 0, -.1);
|
||||
|
||||
this.Mesh = CsgToMesh.Convert(chairFoot);
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
public class CurveTest : MatterCadObject3D
|
||||
{
|
||||
private PolygonMesh.Mesh inputMesh;
|
||||
|
||||
private PolygonMesh.Mesh transformedMesh;
|
||||
|
||||
public CurveTest()
|
||||
{
|
||||
var letterPrinter = new TypeFacePrinter("MatterHackers");
|
||||
inputMesh = VertexSourceToMesh.Extrude(letterPrinter, 5);
|
||||
transformedMesh = PolygonMesh.Mesh.Copy(inputMesh, CancellationToken.None);
|
||||
|
||||
RebuildMeshes();
|
||||
}
|
||||
|
||||
[DisplayName("Angle")]
|
||||
public double AngleDegrees { get; set; } = 0;
|
||||
|
||||
[DisplayName("Bend Up")]
|
||||
public bool BendCW { get; set; } = true;
|
||||
|
||||
public override void RebuildMeshes()
|
||||
{
|
||||
if (AngleDegrees > 0)
|
||||
{
|
||||
var aabb = inputMesh.GetAxisAlignedBoundingBox();
|
||||
|
||||
// find the radius that will make the x-size sweep out the requested angle
|
||||
// c = Tr ; r = c/T
|
||||
var angleRadians = MathHelper.DegreesToRadians(AngleDegrees);
|
||||
var circumference = aabb.XSize * MathHelper.Tau / angleRadians;
|
||||
var radius = circumference / MathHelper.Tau;
|
||||
|
||||
var rotateXyPos = new Vector2(aabb.minXYZ.X, BendCW ? aabb.maxXYZ.Y : aabb.minXYZ.Y);
|
||||
if (!BendCW)
|
||||
{
|
||||
angleRadians = -angleRadians;
|
||||
}
|
||||
|
||||
for (int i = 0; i < transformedMesh.Vertices.Count; i++)
|
||||
{
|
||||
var pos = inputMesh.Vertices[i].Position;
|
||||
var pos2D = new Vector2(pos);
|
||||
Vector2 rotateSpace = pos2D - rotateXyPos;
|
||||
var rotateRatio = rotateSpace.X / aabb.XSize;
|
||||
|
||||
rotateSpace.X = 0;
|
||||
rotateSpace.Y += BendCW ? -radius : radius;
|
||||
rotateSpace.Rotate(angleRadians * rotateRatio);
|
||||
rotateSpace.Y += BendCW ? radius : -radius; ;
|
||||
rotateSpace += rotateXyPos;
|
||||
|
||||
transformedMesh.Vertices[i].Position = new Vector3(rotateSpace.X, rotateSpace.Y, pos.Z);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < transformedMesh.Vertices.Count; i++)
|
||||
{
|
||||
transformedMesh.Vertices[i].Position = inputMesh.Vertices[i].Position;
|
||||
}
|
||||
}
|
||||
|
||||
transformedMesh.MarkAsChanged();
|
||||
transformedMesh.CalculateNormals();
|
||||
|
||||
this.Mesh = transformedMesh;
|
||||
}
|
||||
}
|
||||
|
||||
public class PinchTest : MatterCadObject3D
|
||||
{
|
||||
private PolygonMesh.Mesh inputMesh;
|
||||
|
||||
private PolygonMesh.Mesh transformedMesh;
|
||||
|
||||
public PinchTest()
|
||||
{
|
||||
var letterPrinter = new TypeFacePrinter("MatterHackers");
|
||||
inputMesh = VertexSourceToMesh.Extrude(letterPrinter, 5);
|
||||
transformedMesh = PolygonMesh.Mesh.Copy(inputMesh, CancellationToken.None);
|
||||
|
||||
RebuildMeshes();
|
||||
}
|
||||
|
||||
[DisplayName("Back Ratio")]
|
||||
public double PinchRatio { get; set; } = 1;
|
||||
|
||||
public override void RebuildMeshes()
|
||||
{
|
||||
var aabb = inputMesh.GetAxisAlignedBoundingBox();
|
||||
for (int i = 0; i < transformedMesh.Vertices.Count; i++)
|
||||
{
|
||||
var pos = inputMesh.Vertices[i].Position;
|
||||
|
||||
var ratioToApply = PinchRatio;
|
||||
|
||||
var distFromCenter = pos.X - aabb.Center.X;
|
||||
var distanceToPinch = distFromCenter * (1 - PinchRatio);
|
||||
var delta = (aabb.Center.X + distFromCenter * ratioToApply) - pos.X;
|
||||
|
||||
// find out how much to pinch based on y position
|
||||
var amountOfRatio = (pos.Y - aabb.minXYZ.Y) / aabb.YSize;
|
||||
transformedMesh.Vertices[i].Position = new Vector3(pos.X + delta * amountOfRatio, pos.Y, pos.Z);
|
||||
}
|
||||
|
||||
transformedMesh.MarkAsChanged();
|
||||
transformedMesh.CalculateNormals();
|
||||
|
||||
this.Mesh = transformedMesh;
|
||||
}
|
||||
}
|
||||
|
||||
public class PvcT : MatterCadObject3D
|
||||
{
|
||||
private int sides = 50;
|
||||
|
||||
public PvcT()
|
||||
{
|
||||
RebuildMeshes();
|
||||
}
|
||||
|
||||
[DisplayName("Inner Radius")]
|
||||
public double InnerDiameter { get; set; } = 15;
|
||||
|
||||
[DisplayName("Outer Radius")]
|
||||
public double OuterDiameter { get; set; } = 20;
|
||||
|
||||
public double BottomReach { get; set; } = 30;
|
||||
|
||||
public double FrontReach { get; set; } = 25;
|
||||
|
||||
public double TopReach { get; set; } = 30;
|
||||
|
||||
public override void RebuildMeshes()
|
||||
{
|
||||
IObject3D topBottomConnect = new Cylinder(OuterDiameter / 2, OuterDiameter, sides, Alignment.Y);
|
||||
IObject3D frontConnect = new Cylinder(OuterDiameter / 2, OuterDiameter / 2, sides, Alignment.X);
|
||||
frontConnect = new Align(frontConnect, Face.Right, topBottomConnect, Face.Right);
|
||||
|
||||
IObject3D bottomReach = new Rotate(CreateReach(BottomReach), -MathHelper.Tau / 4);
|
||||
bottomReach = new Align(bottomReach, Face.Back, topBottomConnect, Face.Front, 0, .1);
|
||||
|
||||
IObject3D topReach = new Rotate(CreateReach(TopReach), MathHelper.Tau / 4);
|
||||
topReach = new Align(topReach, Face.Front, topBottomConnect, Face.Back, 0, -.1);
|
||||
|
||||
IObject3D frontReach = new Rotate(CreateReach(FrontReach), 0, -MathHelper.Tau / 4);
|
||||
frontReach = new Align(frontReach, Face.Left, topBottomConnect, Face.Right, -.1);
|
||||
|
||||
// output multiple meshes for pipe connector
|
||||
this.Children.Modify(list =>
|
||||
{
|
||||
list.Clear();
|
||||
list.Add(topBottomConnect);
|
||||
list.Add(frontConnect);
|
||||
list.Add(bottomReach);
|
||||
list.Add(topReach);
|
||||
list.Add(frontReach);
|
||||
});
|
||||
|
||||
this.Color = Color.Transparent;
|
||||
this.Mesh = null;
|
||||
}
|
||||
|
||||
private IObject3D CreateReach(double reach)
|
||||
{
|
||||
var finWidth = 4.0;
|
||||
var finLength = InnerDiameter;
|
||||
|
||||
var pattern = new VertexStorage();
|
||||
pattern.MoveTo(0, 0);
|
||||
pattern.LineTo(finLength/2, 0);
|
||||
pattern.LineTo(finLength/2, reach - finLength / 8);
|
||||
pattern.LineTo(finLength/2 - finLength / 8, reach);
|
||||
pattern.LineTo(-finLength/2 + finLength / 8, reach);
|
||||
pattern.LineTo(-finLength/2, reach - finLength / 8);
|
||||
pattern.LineTo(-finLength/2, 0);
|
||||
|
||||
var fin1 = new Object3D()
|
||||
{
|
||||
Mesh = VertexSourceToMesh.Extrude(pattern, finWidth)
|
||||
};
|
||||
fin1 = new Translate(fin1, 0, 0, -finWidth / 2);
|
||||
//fin1.ChamferEdge(Face.Top | Face.Back, finLength / 8);
|
||||
//fin1.ChamferEdge(Face.Top | Face.Front, finLength / 8);
|
||||
fin1 = new Rotate(fin1, -MathHelper.Tau / 4);
|
||||
var fin2 = new SetCenter(new Rotate(fin1, 0, 0, MathHelper.Tau / 4), fin1.GetCenter());
|
||||
|
||||
return new Object3D().SetChildren(new List<IObject3D>() { fin1, fin2 });
|
||||
}
|
||||
}
|
||||
|
||||
public class RibonWithName : MatterCadObject3D
|
||||
{
|
||||
private static TypeFace typeFace = null;
|
||||
|
||||
public RibonWithName()
|
||||
{
|
||||
RebuildMeshes();
|
||||
}
|
||||
|
||||
[DisplayName("Name")]
|
||||
public string NameToWrite { get; set; } = "MatterHackers";
|
||||
|
||||
public override void RebuildMeshes()
|
||||
{
|
||||
IObject3D cancerRibonStl = Object3D.Load("Cancer_Ribbon.stl", CancellationToken.None);
|
||||
|
||||
cancerRibonStl = new Rotate(cancerRibonStl, MathHelper.DegreesToRadians(90));
|
||||
|
||||
if (typeFace == null)
|
||||
{
|
||||
typeFace = TypeFace.LoadFrom(AggContext.StaticData.ReadAllText(Path.Combine("Fonts", "TitilliumWeb-Black.svg")));
|
||||
}
|
||||
|
||||
var letterPrinter = new TypeFacePrinter(NameToWrite.ToUpper(), new StyledTypeFace(typeFace, 12));
|
||||
|
||||
IObject3D nameMesh = new Object3D()
|
||||
{
|
||||
Mesh = VertexSourceToMesh.Extrude(letterPrinter, 5)
|
||||
};
|
||||
|
||||
AxisAlignedBoundingBox textBounds = nameMesh.GetAxisAlignedBoundingBox();
|
||||
var textArea = new Vector2(25, 6);
|
||||
|
||||
double scale = Math.Min(textArea.X / textBounds.XSize, textArea.Y / textBounds.YSize);
|
||||
nameMesh = new Scale(nameMesh, scale, scale, 2 / textBounds.ZSize);
|
||||
nameMesh = new Align(nameMesh, Face.Bottom | Face.Front, cancerRibonStl, Face.Top | Face.Front, 0, 0, -1);
|
||||
nameMesh = new SetCenter(nameMesh, cancerRibonStl.GetCenter(), true, false, false);
|
||||
|
||||
nameMesh = new Rotate(nameMesh, 0, 0, MathHelper.DegreesToRadians(50));
|
||||
nameMesh = new Translate(nameMesh, -37, -14, -1);
|
||||
|
||||
// output two meshes for card holder and text
|
||||
this.Children.Modify(list =>
|
||||
{
|
||||
list.Clear();
|
||||
list.Add(cancerRibonStl);
|
||||
list.Add(nameMesh);
|
||||
});
|
||||
|
||||
this.Mesh = null;
|
||||
}
|
||||
}
|
||||
|
||||
public class Box : Object3D
|
||||
{
|
||||
public Box(double x, double y, double z)
|
||||
{
|
||||
Mesh = PlatonicSolids.CreateCube(x, y, z);
|
||||
Mesh.CleanAndMergMesh(CancellationToken.None);
|
||||
}
|
||||
}
|
||||
|
||||
public static class Object3DExtensions
|
||||
{
|
||||
public static IObject3D Translate(this IObject3D objectToTranslate, double x = 0, double y = 0, double z = 0, string name = "")
|
||||
{
|
||||
return objectToTranslate.Translate(new Vector3(x, y, z), name);
|
||||
}
|
||||
|
||||
public static IObject3D Translate(this IObject3D objectToTranslate, Vector3 translation, string name = "")
|
||||
{
|
||||
objectToTranslate.Matrix *= Matrix4X4.CreateTranslation(translation);
|
||||
return objectToTranslate;
|
||||
}
|
||||
|
||||
public static IObject3D Minus(this IObject3D a, IObject3D b)
|
||||
{
|
||||
var resultsA = a.Clone();
|
||||
SubtractEditor.Subtract(resultsA.VisibleMeshes().ToList(), b.VisibleMeshes().ToList());
|
||||
return resultsA;
|
||||
}
|
||||
|
||||
public static Vector3 GetCenter(this IObject3D item)
|
||||
{
|
||||
return item.GetAxisAlignedBoundingBox(Matrix4X4.Identity).Center;
|
||||
}
|
||||
|
||||
public static IObject3D SetChildren(this IObject3D parent, IEnumerable<IObject3D> newChildren)
|
||||
{
|
||||
parent.Children.Modify((list) =>
|
||||
{
|
||||
list.Clear();
|
||||
list.AddRange(newChildren);
|
||||
});
|
||||
|
||||
return parent;
|
||||
}
|
||||
|
||||
public static void SetChildren(this IObject3D parent, IObject3D newChild)
|
||||
{
|
||||
parent.Children.Modify((list) =>
|
||||
{
|
||||
list.Clear();
|
||||
list.Add(newChild);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public class Translate : Object3D
|
||||
{
|
||||
public Translate()
|
||||
{ }
|
||||
|
||||
public Translate(IObject3D item, double x = 0, double y = 0, double z = 0)
|
||||
: this(item, new Vector3(x, y, z))
|
||||
{
|
||||
}
|
||||
|
||||
public Translate(IObject3D item, Vector3 translation)
|
||||
{
|
||||
Matrix *= Matrix4X4.CreateTranslation(translation);
|
||||
Children.Add(item.Clone());
|
||||
}
|
||||
}
|
||||
|
||||
public class Align : Object3D
|
||||
{
|
||||
public Align()
|
||||
{
|
||||
}
|
||||
|
||||
public Align(IObject3D objectToAlign, Face boundingFacesToAlign, IObject3D objectToAlignTo, Face boundingFacesToAlignTo, double offsetX = 0, double offsetY = 0, double offsetZ = 0, string name = "")
|
||||
: this(objectToAlign, boundingFacesToAlign, GetPositionToAlignTo(objectToAlignTo, boundingFacesToAlignTo, new Vector3(offsetX, offsetY, offsetZ)), name)
|
||||
{
|
||||
if (objectToAlign == objectToAlignTo)
|
||||
{
|
||||
throw new Exception("You cannot align an object ot itself.");
|
||||
}
|
||||
}
|
||||
|
||||
public Align(IObject3D objectToAlign, Face boundingFacesToAlign, double offsetX = 0, double offsetY = 0, double offsetZ = 0, string name = "")
|
||||
: this(objectToAlign, boundingFacesToAlign, new Vector3(offsetX, offsetY, offsetZ), name)
|
||||
{
|
||||
}
|
||||
|
||||
public Align(IObject3D objectToAlign, Face boundingFacesToAlign, Vector3 positionToAlignTo, double offsetX, double offsetY, double offsetZ, string name = "")
|
||||
: this(objectToAlign, boundingFacesToAlign, positionToAlignTo + new Vector3(offsetX, offsetY, offsetZ), name)
|
||||
{
|
||||
}
|
||||
|
||||
public Align(IObject3D item, Face boundingFacesToAlign, Vector3 positionToAlignTo, string name = "")
|
||||
{
|
||||
AxisAlignedBoundingBox bounds = item.GetAxisAlignedBoundingBox();
|
||||
|
||||
if (IsSet(boundingFacesToAlign, Face.Left, Face.Right))
|
||||
{
|
||||
positionToAlignTo.X = positionToAlignTo.X - bounds.minXYZ.X;
|
||||
}
|
||||
if (IsSet(boundingFacesToAlign, Face.Right, Face.Left))
|
||||
{
|
||||
positionToAlignTo.X = positionToAlignTo.X - bounds.minXYZ.X - (bounds.maxXYZ.X - bounds.minXYZ.X);
|
||||
}
|
||||
if (IsSet(boundingFacesToAlign, Face.Front, Face.Back))
|
||||
{
|
||||
positionToAlignTo.Y = positionToAlignTo.Y - bounds.minXYZ.Y;
|
||||
}
|
||||
if (IsSet(boundingFacesToAlign, Face.Back, Face.Front))
|
||||
{
|
||||
positionToAlignTo.Y = positionToAlignTo.Y - bounds.minXYZ.Y - (bounds.maxXYZ.Y - bounds.minXYZ.Y);
|
||||
}
|
||||
if (IsSet(boundingFacesToAlign, Face.Bottom, Face.Top))
|
||||
{
|
||||
positionToAlignTo.Z = positionToAlignTo.Z - bounds.minXYZ.Z;
|
||||
}
|
||||
if (IsSet(boundingFacesToAlign, Face.Top, Face.Bottom))
|
||||
{
|
||||
positionToAlignTo.Z = positionToAlignTo.Z - bounds.minXYZ.Z - (bounds.maxXYZ.Z - bounds.minXYZ.Z);
|
||||
}
|
||||
|
||||
Matrix *= Matrix4X4.CreateTranslation(positionToAlignTo);
|
||||
Children.Add(item.Clone());
|
||||
}
|
||||
|
||||
public static Vector3 GetPositionToAlignTo(IObject3D objectToAlignTo, Face boundingFacesToAlignTo, Vector3 extraOffset)
|
||||
{
|
||||
Vector3 positionToAlignTo = new Vector3();
|
||||
if (IsSet(boundingFacesToAlignTo, Face.Left, Face.Right))
|
||||
{
|
||||
positionToAlignTo.X = objectToAlignTo.GetAxisAlignedBoundingBox().minXYZ.X;
|
||||
}
|
||||
if (IsSet(boundingFacesToAlignTo, Face.Right, Face.Left))
|
||||
{
|
||||
positionToAlignTo.X = objectToAlignTo.GetAxisAlignedBoundingBox().maxXYZ.X;
|
||||
}
|
||||
if (IsSet(boundingFacesToAlignTo, Face.Front, Face.Back))
|
||||
{
|
||||
positionToAlignTo.Y = objectToAlignTo.GetAxisAlignedBoundingBox().minXYZ.Y;
|
||||
}
|
||||
if (IsSet(boundingFacesToAlignTo, Face.Back, Face.Front))
|
||||
{
|
||||
positionToAlignTo.Y = objectToAlignTo.GetAxisAlignedBoundingBox().maxXYZ.Y;
|
||||
}
|
||||
if (IsSet(boundingFacesToAlignTo, Face.Bottom, Face.Top))
|
||||
{
|
||||
positionToAlignTo.Z = objectToAlignTo.GetAxisAlignedBoundingBox().minXYZ.Z;
|
||||
}
|
||||
if (IsSet(boundingFacesToAlignTo, Face.Top, Face.Bottom))
|
||||
{
|
||||
positionToAlignTo.Z = objectToAlignTo.GetAxisAlignedBoundingBox().maxXYZ.Z;
|
||||
}
|
||||
return positionToAlignTo + extraOffset;
|
||||
}
|
||||
|
||||
private static bool IsSet(Face variableToCheck, Face faceToCheckFor, Face faceToAssertNot)
|
||||
{
|
||||
if ((variableToCheck & faceToCheckFor) != 0)
|
||||
{
|
||||
if ((variableToCheck & faceToAssertNot) != 0)
|
||||
{
|
||||
throw new Exception("You cannot have both " + faceToCheckFor.ToString() + " and " + faceToAssertNot.ToString() + " set when calling Align. The are mutually exclusive.");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public class Rotate : Object3D
|
||||
{
|
||||
public Rotate()
|
||||
{
|
||||
}
|
||||
|
||||
public Rotate(IObject3D item, double x = 0, double y = 0, double z = 0, string name = "")
|
||||
: this(item, new Vector3(x, y, z), name)
|
||||
{
|
||||
}
|
||||
|
||||
public Rotate(IObject3D item, Vector3 translation, string name = "")
|
||||
{
|
||||
Matrix *= Matrix4X4.CreateRotation(translation);
|
||||
Children.Add(item.Clone());
|
||||
}
|
||||
}
|
||||
|
||||
public class Scale : Object3D
|
||||
{
|
||||
public Scale()
|
||||
{
|
||||
}
|
||||
|
||||
public Scale(IObject3D item, double x = 0, double y = 0, double z = 0, string name = "")
|
||||
: this(item, new Vector3(x, y, z), name)
|
||||
{
|
||||
}
|
||||
|
||||
public Scale(IObject3D item, Vector3 translation, string name = "")
|
||||
{
|
||||
Matrix *= Matrix4X4.CreateScale(translation);
|
||||
Children.Add(item.Clone());
|
||||
}
|
||||
}
|
||||
|
||||
public class TestPart : MatterCadObject3D
|
||||
{
|
||||
public TestPart()
|
||||
{
|
||||
RebuildMeshes();
|
||||
}
|
||||
|
||||
public double XOffset { get; set; } = -.4;
|
||||
|
||||
public override void RebuildMeshes()
|
||||
{
|
||||
IObject3D boxCombine = new Box(10, 10, 10);
|
||||
boxCombine = boxCombine.Minus(new Translate(new Box(10, 10, 10), XOffset, -3, 2));
|
||||
this.SetChildren(boxCombine);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -56,7 +56,8 @@
|
|||
<Compile Include="Braille\BrailleEditor.cs" />
|
||||
<Compile Include="Braille\BrailleGrade2.cs" />
|
||||
<Compile Include="Braille\BrailleGrade2Mapping.cs" />
|
||||
<Compile Include="CardHolderTool\CardHolder.cs" />
|
||||
<Compile Include="CardHolderTool\MatterCadEditor.cs" />
|
||||
<Compile Include="CardHolderTool\MeshObjects.cs" />
|
||||
<Compile Include="TextCreatorPlugin.cs" />
|
||||
<Compile Include="Text\TextGenerator.cs" />
|
||||
<Compile Include="Text\TextEditor.cs" />
|
||||
|
|
@ -70,10 +71,6 @@
|
|||
<Project>{9B062971-A88E-4A3D-B3C9-12B78D15FA66}</Project>
|
||||
<Name>clipper_library</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\Submodules\agg-sharp\Csg\Csg.csproj">
|
||||
<Project>{7E61A5BD-E78F-4B80-88C9-3821B4FA062E}</Project>
|
||||
<Name>Csg</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\Submodules\agg-sharp\DataConverters2D\DataConverters2D.csproj">
|
||||
<Project>{94838988-523C-4B11-AD82-8B9B76F23A31}</Project>
|
||||
<Name>DataConverters2D</Name>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue