Fixed and improved Brairlle Object
Added Split Camel Case extension
This commit is contained in:
parent
94f6eebfe2
commit
d44207ea2a
19 changed files with 274 additions and 485 deletions
|
|
@ -1,187 +0,0 @@
|
|||
/*
|
||||
Copyright (c) 2017, Lars Brubaker, John Lewin
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
The views and conclusions contained in the software and documentation are those
|
||||
of the authors and should not be interpreted as representing official policies,
|
||||
either expressed or implied, of the FreeBSD Project.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using MatterHackers.Agg;
|
||||
using MatterHackers.Agg.UI;
|
||||
using MatterHackers.DataConverters3D;
|
||||
using MatterHackers.Localizations;
|
||||
using MatterHackers.MatterControl.PartPreviewWindow;
|
||||
using MatterHackers.MeshVisualizer;
|
||||
using MatterHackers.PolygonMesh;
|
||||
|
||||
namespace MatterHackers.MatterControl.Plugins.BrailleBuilder
|
||||
{
|
||||
public class BrailleEditor : IObject3DEditor
|
||||
{
|
||||
private MHTextEditWidget textToAddWidget;
|
||||
private CheckBox useGrade2;
|
||||
|
||||
private BrailleGenerator brailleGenerator;
|
||||
private View3DWidget view3DWidget;
|
||||
|
||||
private TextObject injectedItem = null;
|
||||
|
||||
public bool Unlocked { get; } = true;
|
||||
|
||||
public IEnumerable<Type> SupportedTypes() => new Type[] { typeof(TextObject) };
|
||||
|
||||
public GuiWidget Create(IObject3D item, View3DWidget parentView3D, ThemeConfig theme)
|
||||
{
|
||||
var scene = parentView3D.InteractionLayer.Scene;
|
||||
|
||||
injectedItem = scene?.SelectedItem as TextObject;
|
||||
|
||||
brailleGenerator = new BrailleGenerator();
|
||||
this.view3DWidget = parentView3D;
|
||||
|
||||
var container = new FlowLayoutWidget(FlowDirection.TopToBottom)
|
||||
{
|
||||
HAnchor = HAnchor.Stretch,
|
||||
};
|
||||
|
||||
textToAddWidget = new MHTextEditWidget("", pixelWidth: 300, messageWhenEmptyAndNotSelected: "Enter Text Here".Localize())
|
||||
{
|
||||
HAnchor = HAnchor.Stretch,
|
||||
Margin = new BorderDouble(5),
|
||||
Text = injectedItem.Text
|
||||
};
|
||||
textToAddWidget.ActualTextEditWidget.EnterPressed += (s, e) => RebuildText(textToAddWidget.Text);
|
||||
container.AddChild(textToAddWidget);
|
||||
|
||||
useGrade2 = new CheckBox(new CheckBoxViewText("Use Grade 2".Localize(), textColor: ActiveTheme.Instance.PrimaryTextColor));
|
||||
useGrade2.ToolTipText = "Experimental support for Braille grade 2 (contractions)".Localize();
|
||||
useGrade2.Checked = false;
|
||||
useGrade2.Margin = new BorderDouble(10, 5);
|
||||
useGrade2.HAnchor = HAnchor.Left;
|
||||
container.AddChild(useGrade2);
|
||||
useGrade2.CheckedStateChanged += (sender, e) =>
|
||||
{
|
||||
RebuildText(textToAddWidget.Text);
|
||||
};
|
||||
|
||||
Button updateButton = theme.ButtonFactory.Generate("Update".Localize());
|
||||
updateButton.Margin = new BorderDouble(5);
|
||||
updateButton.HAnchor = HAnchor.Right;
|
||||
updateButton.Click += (s, e) => RebuildText(textToAddWidget.Text);
|
||||
container.AddChild(updateButton);
|
||||
|
||||
// put in a link to the wikipedia article
|
||||
{
|
||||
LinkButtonFactory linkButtonFactory = new LinkButtonFactory();
|
||||
linkButtonFactory.fontSize = 10;
|
||||
linkButtonFactory.textColor = ActiveTheme.Instance.PrimaryTextColor;
|
||||
|
||||
Button moreAboutBrailleLink = linkButtonFactory.Generate("About Braille".Localize());
|
||||
moreAboutBrailleLink.Margin = new BorderDouble(10, 5);
|
||||
moreAboutBrailleLink.HAnchor = HAnchor.Left;
|
||||
moreAboutBrailleLink.Click += (sender, e) =>
|
||||
{
|
||||
UiThread.RunOnIdle(() =>
|
||||
{
|
||||
ApplicationController.Instance.LaunchBrowser("https://en.wikipedia.org/wiki/Braille");
|
||||
});
|
||||
};
|
||||
|
||||
container.AddChild(moreAboutBrailleLink);
|
||||
}
|
||||
|
||||
return container;
|
||||
}
|
||||
|
||||
public string Name { get; } = "Braille";
|
||||
|
||||
private async void RebuildText(string brailleText)
|
||||
{
|
||||
injectedItem.Text = brailleText;
|
||||
|
||||
if (brailleText.Length <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (useGrade2.Checked)
|
||||
{
|
||||
brailleText = BrailleGrade2.ConvertString(brailleText);
|
||||
}
|
||||
|
||||
brailleGenerator.ResetSettings();
|
||||
|
||||
var generatedItem = await Task.Run(() =>
|
||||
{
|
||||
Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture;
|
||||
|
||||
return brailleGenerator.CreateText(
|
||||
brailleText,
|
||||
1,
|
||||
1,
|
||||
injectedItem.Text);
|
||||
});
|
||||
|
||||
var scene = view3DWidget.InteractionLayer.Scene;
|
||||
scene.Children.Modify(list =>
|
||||
{
|
||||
// Find the injected item
|
||||
var item = list.Find(child => child == injectedItem);
|
||||
|
||||
// Clear and refresh its children
|
||||
item.Children.Modify(childList =>
|
||||
{
|
||||
childList.Clear();
|
||||
childList.AddRange(generatedItem.Children);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
private void RebuildBase()
|
||||
{
|
||||
var scene = view3DWidget.InteractionLayer.Scene;
|
||||
|
||||
if (scene.HasChildren() && injectedItem != null)
|
||||
{
|
||||
var newBaseplate = brailleGenerator.CreateBaseplate(injectedItem);
|
||||
if(newBaseplate == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Remove the old base and create and add a new one
|
||||
scene.Children.Modify(list =>
|
||||
{
|
||||
list.RemoveAll(child => child is BraileBasePlate);
|
||||
list.Add(newBaseplate);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,268 +0,0 @@
|
|||
/*
|
||||
Copyright (c) 2016, Lars Brubaker, John Lewin
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
The views and conclusions contained in the software and documentation are those
|
||||
of the authors and should not be interpreted as representing official policies,
|
||||
either expressed or implied, of the FreeBSD Project.
|
||||
*/
|
||||
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using MatterHackers.Agg;
|
||||
using MatterHackers.Agg.Font;
|
||||
using MatterHackers.Agg.Platform;
|
||||
using MatterHackers.Agg.VertexSource;
|
||||
using MatterHackers.DataConverters3D;
|
||||
using MatterHackers.DataConverters3D;
|
||||
using MatterHackers.PolygonMesh;
|
||||
using MatterHackers.VectorMath;
|
||||
|
||||
namespace MatterHackers.MatterControl.Plugins.BrailleBuilder
|
||||
{
|
||||
public class BrailleGenerator
|
||||
{
|
||||
private double lastHeightValue = 1;
|
||||
private double lastSizeValue = 1;
|
||||
|
||||
private TypeFace brailTypeFace;
|
||||
private TypeFace boldTypeFace;
|
||||
|
||||
private const double unscaledBaseHeight = 7;
|
||||
private const double unscaledLetterHeight = 3;
|
||||
|
||||
private Vector2[] characterSpacing;
|
||||
|
||||
public BrailleGenerator()
|
||||
{
|
||||
boldTypeFace = TypeFace.LoadFrom(AggContext.StaticData.ReadAllText(Path.Combine("Fonts", "LiberationMono.svg")));
|
||||
brailTypeFace = TypeFace.LoadFrom(AggContext.StaticData.ReadAllText(Path.Combine("Fonts", "Braille.svg")));
|
||||
}
|
||||
|
||||
public IObject3D CreateText(string brailleText, double wordSize, double wordHeight, string wordText = null)
|
||||
{
|
||||
var group = new TextObject
|
||||
{
|
||||
Text = wordText,
|
||||
ActiveEditor = "BrailleEditor"
|
||||
};
|
||||
|
||||
TypeFacePrinter brailPrinter = new TypeFacePrinter(brailleText, new StyledTypeFace(brailTypeFace, 12));
|
||||
|
||||
StyledTypeFace boldStyled = new StyledTypeFace(boldTypeFace, 12);
|
||||
|
||||
AddCharacterMeshes(group, brailleText, brailPrinter);
|
||||
Vector2 brailSize = brailPrinter.GetSize();
|
||||
|
||||
for (int i = 0; i < brailleText.Length; i++)
|
||||
{
|
||||
characterSpacing[i] += new Vector2(0, boldStyled.CapHeightInPixels * 1.5);
|
||||
}
|
||||
|
||||
IObject3D basePlate = CreateBaseplate(group);
|
||||
group.Children.Modify(list =>
|
||||
{
|
||||
list.Add(basePlate);
|
||||
|
||||
SetCharacterPositions(group);
|
||||
SetWordSize(group, wordSize);
|
||||
SetWordHeight(group, wordHeight);
|
||||
|
||||
// Remove the temporary baseplate added above and required by SetPositions/SetSize
|
||||
list.Remove(basePlate);
|
||||
|
||||
// Add the actual baseplate that can be correctly sized to its siblings bounds
|
||||
basePlate = CreateBaseplate(group);
|
||||
list.Add(basePlate);
|
||||
});
|
||||
|
||||
return group;
|
||||
}
|
||||
|
||||
private void AddCharacterMeshes(IObject3D group, string currentText, TypeFacePrinter printer)
|
||||
{
|
||||
StyledTypeFace typeFace = printer.TypeFaceStyle;
|
||||
|
||||
characterSpacing = new Vector2[currentText.Length];
|
||||
|
||||
for (int i = 0; i < currentText.Length; i++)
|
||||
{
|
||||
string letter = currentText[i].ToString();
|
||||
TypeFacePrinter letterPrinter = new TypeFacePrinter(letter, typeFace);
|
||||
|
||||
if (CharacterHasMesh(letterPrinter, letter))
|
||||
{
|
||||
#if true
|
||||
Mesh textMesh = VertexSourceToMesh.Extrude(letterPrinter, unscaledLetterHeight / 2);
|
||||
#else
|
||||
Mesh textMesh = VertexSourceToMesh.Extrude(letterPrinter, unscaledLetterHeight / 2);
|
||||
// this is the code to make rounded tops
|
||||
// convert the letterPrinter to clipper polygons
|
||||
List<List<IntPoint>> insetPoly = VertexSourceToPolygon.CreatePolygons(letterPrinter);
|
||||
// inset them
|
||||
ClipperOffset clipper = new ClipperOffset();
|
||||
clipper.AddPaths(insetPoly, JoinType.jtMiter, EndType.etClosedPolygon);
|
||||
List<List<IntPoint>> solution = new List<List<IntPoint>>();
|
||||
clipper.Execute(solution, 5.0);
|
||||
// convert them back into a vertex source
|
||||
// merge both the inset and original vertex sources together
|
||||
// convert the new vertex source into a mesh (triangulate them)
|
||||
// offset the inner loop in z
|
||||
// create the polygons from the inner loop to a center point so that there is the rest of an approximation of the bubble
|
||||
// make the mesh for the bottom
|
||||
// add the top and bottom together
|
||||
// done
|
||||
#endif
|
||||
var characterObject = new Object3D()
|
||||
{
|
||||
Mesh = textMesh
|
||||
};
|
||||
|
||||
characterSpacing[i] = printer.GetOffsetLeftOfCharacterIndex(i);
|
||||
characterObject.Matrix *= Matrix4X4.CreateTranslation(new Vector3(0, 0, unscaledLetterHeight / 2));
|
||||
|
||||
group.Children.Add(characterObject);
|
||||
}
|
||||
|
||||
//processingProgressControl.PercentComplete = ((i + 1) * 95 / currentText.Length);
|
||||
}
|
||||
}
|
||||
|
||||
private void SetCharacterPositions(IObject3D group)
|
||||
{
|
||||
if (group.HasChildren())
|
||||
{
|
||||
|
||||
int i = 0;
|
||||
|
||||
foreach(var child in group.Children)
|
||||
{
|
||||
Vector3 startPosition = Vector3.Transform(Vector3.Zero, child.Matrix);
|
||||
|
||||
var spacing = characterSpacing[i++];
|
||||
|
||||
double newX = spacing.X * lastSizeValue;
|
||||
double newY = spacing.Y * lastSizeValue;
|
||||
|
||||
child.Matrix *= Matrix4X4.CreateTranslation(new Vector3(newX, newY, startPosition.Z));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void SetWordHeight(IObject3D group, double newHeight)
|
||||
{
|
||||
if (group.HasChildren())
|
||||
{
|
||||
AxisAlignedBoundingBox baseBounds = group.Children.Last().GetAxisAlignedBoundingBox(Matrix4X4.Identity);
|
||||
|
||||
// Skip the base item
|
||||
foreach (var sceneItem in group.Children.Take(group.Children.Count - 1))
|
||||
{
|
||||
Vector3 startPosition = Vector3.Transform(Vector3.Zero, sceneItem.Matrix);
|
||||
|
||||
// take out the last scale
|
||||
double oldHeight = 1.0 / lastHeightValue;
|
||||
|
||||
// move the part to keep it in the same relative position
|
||||
sceneItem.Matrix *= Matrix4X4.CreateScale(new Vector3(1, 1, oldHeight));
|
||||
sceneItem.Matrix *= Matrix4X4.CreateScale(new Vector3(1, 1, newHeight));
|
||||
|
||||
sceneItem.Matrix *= Matrix4X4.CreateTranslation(new Vector3(0, 0, baseBounds.ZSize - startPosition.Z));
|
||||
}
|
||||
|
||||
lastHeightValue = newHeight;
|
||||
}
|
||||
}
|
||||
|
||||
public void SetWordSize(IObject3D group, double newSize)
|
||||
{
|
||||
if (group.HasChildren())
|
||||
{
|
||||
foreach (var object3D in group.Children)
|
||||
{
|
||||
Vector3 startPositionRelCenter = Vector3.Transform(Vector3.Zero, object3D.Matrix);
|
||||
|
||||
// take out the last scale
|
||||
double oldSize = 1.0 / lastSizeValue;
|
||||
Vector3 unscaledStartPositionRelCenter = startPositionRelCenter * oldSize;
|
||||
|
||||
Vector3 endPositionRelCenter = unscaledStartPositionRelCenter * newSize;
|
||||
|
||||
Vector3 deltaPosition = endPositionRelCenter - startPositionRelCenter;
|
||||
|
||||
// move the part to keep it in the same relative position
|
||||
object3D.Matrix *= Matrix4X4.CreateScale(new Vector3(oldSize, oldSize, oldSize));
|
||||
object3D.Matrix *= Matrix4X4.CreateScale(new Vector3(newSize, newSize, newSize));
|
||||
object3D.Matrix *= Matrix4X4.CreateTranslation(deltaPosition);
|
||||
}
|
||||
|
||||
lastSizeValue = newSize;
|
||||
}
|
||||
}
|
||||
private bool CharacterHasMesh(TypeFacePrinter letterPrinter, string letter)
|
||||
{
|
||||
return letterPrinter.LocalBounds.Width > 0
|
||||
&& letter != " "
|
||||
&& letter != "\n";
|
||||
}
|
||||
|
||||
public IObject3D CreateBaseplate(IObject3D group)
|
||||
{
|
||||
if (group.HasChildren())
|
||||
{
|
||||
AxisAlignedBoundingBox bounds = group.GetAxisAlignedBoundingBox(Matrix4X4.Identity);
|
||||
|
||||
double roundingScale = 20;
|
||||
RectangleDouble baseRect = new RectangleDouble(bounds.minXYZ.X, bounds.minXYZ.Y, bounds.maxXYZ.X, bounds.maxXYZ.Y);
|
||||
baseRect.Inflate(2);
|
||||
baseRect *= roundingScale;
|
||||
|
||||
RoundedRect baseRoundedRect = new RoundedRect(baseRect, 1 * roundingScale);
|
||||
Mesh baseMeshResult = VertexSourceToMesh.Extrude(baseRoundedRect, unscaledBaseHeight / 2 * roundingScale * lastHeightValue);
|
||||
baseMeshResult.Transform(Matrix4X4.CreateScale(1 / roundingScale));
|
||||
|
||||
var basePlateObject = new BraileBasePlate()
|
||||
{
|
||||
Mesh = baseMeshResult
|
||||
};
|
||||
|
||||
basePlateObject.Matrix *= Matrix4X4.CreateTranslation(new Vector3(0, 0, 0));
|
||||
|
||||
return basePlateObject;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public void ResetSettings()
|
||||
{
|
||||
lastHeightValue = 1;
|
||||
lastSizeValue = 1;
|
||||
}
|
||||
}
|
||||
|
||||
public class BraileBasePlate : Object3D
|
||||
{
|
||||
}
|
||||
|
||||
}
|
||||
173
TextCreator/Braille/BrailleObject3D.cs
Normal file
173
TextCreator/Braille/BrailleObject3D.cs
Normal file
|
|
@ -0,0 +1,173 @@
|
|||
/*
|
||||
Copyright (c) 2018, Lars Brubaker, John Lewin
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
The views and conclusions contained in the software and documentation are those
|
||||
of the authors and should not be interpreted as representing official policies,
|
||||
either expressed or implied, of the FreeBSD Project.
|
||||
*/
|
||||
|
||||
using System.ComponentModel;
|
||||
using System.IO;
|
||||
using MatterHackers.Agg.Font;
|
||||
using MatterHackers.Agg.Platform;
|
||||
using MatterHackers.Agg.Transform;
|
||||
using MatterHackers.Agg.UI;
|
||||
using MatterHackers.Agg.VertexSource;
|
||||
using MatterHackers.DataConverters3D;
|
||||
using MatterHackers.MatterControl.DesignTools.Operations;
|
||||
using MatterHackers.MatterControl.Plugins.BrailleBuilder;
|
||||
using MatterHackers.VectorMath;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Converters;
|
||||
|
||||
namespace MatterHackers.MatterControl.DesignTools
|
||||
{
|
||||
[WebPageLink("About Braille", "https://en.wikipedia.org/wiki/Braille")]
|
||||
public class BrailleObject3D : Object3D, IRebuildable
|
||||
{
|
||||
public BrailleObject3D()
|
||||
{
|
||||
}
|
||||
|
||||
public static BrailleObject3D Create()
|
||||
{
|
||||
var item = new BrailleObject3D();
|
||||
|
||||
item.Rebuild(null);
|
||||
return item;
|
||||
}
|
||||
|
||||
public override string ActiveEditor => "PublicPropertyEditor";
|
||||
|
||||
[DisplayName("Name")]
|
||||
public string TextToEncode { get; set; } = "Braille";
|
||||
|
||||
public double BaseHeight { get; set; } = 5;
|
||||
|
||||
[Description("Use Braille grade 2 (contractions)")]
|
||||
public bool UseGrade2 { get; set; }
|
||||
|
||||
public bool RenderAsBraille { get; set; } = true;
|
||||
|
||||
static TypeFace typeFace = TypeFace.LoadFrom(AggContext.StaticData.ReadAllText(Path.Combine("Fonts", "Braille.svg")));
|
||||
|
||||
|
||||
public void Rebuild(UndoBuffer undoBuffer)
|
||||
{
|
||||
var aabb = this.GetAxisAlignedBoundingBox();
|
||||
|
||||
this.Children.Modify(list =>
|
||||
{
|
||||
list.Clear();
|
||||
});
|
||||
|
||||
var brailleText = TextToEncode;
|
||||
if (UseGrade2)
|
||||
{
|
||||
brailleText = BrailleGrade2.ConvertString(brailleText);
|
||||
}
|
||||
|
||||
int pointSize = 28;
|
||||
double pointsToMm = 0.352778;
|
||||
IObject3D textObject = RenderAsBraille ? new Object3D() : this;
|
||||
var offest = 0.0;
|
||||
foreach (var letter in brailleText.ToCharArray())
|
||||
{
|
||||
IObject3D letterObject;
|
||||
TypeFacePrinter letterPrinter;
|
||||
if (RenderAsBraille)
|
||||
{
|
||||
letterPrinter = new TypeFacePrinter(letter.ToString(), new StyledTypeFace(typeFace, pointSize));
|
||||
var scalledLetterPrinter = new VertexSourceApplyTransform(letterPrinter, Affine.NewScaling(pointsToMm));
|
||||
|
||||
// add all the spheres to letterObject
|
||||
letterObject = new Object3D();
|
||||
|
||||
var vertexCount = 0;
|
||||
var positionSum = Vector2.Zero;
|
||||
var lastPosition = Vector2.Zero;
|
||||
// find each dot outline and get it's center and place a sphere there
|
||||
foreach (var vertex in scalledLetterPrinter.Vertices())
|
||||
{
|
||||
switch (vertex.command)
|
||||
{
|
||||
case Agg.ShapePath.FlagsAndCommand.CommandStop:
|
||||
case Agg.ShapePath.FlagsAndCommand.CommandEndPoly:
|
||||
case Agg.ShapePath.FlagsAndCommand.FlagClose:
|
||||
case Agg.ShapePath.FlagsAndCommand.CommandMoveTo:
|
||||
if(vertexCount > 0)
|
||||
{
|
||||
var center = positionSum / vertexCount;
|
||||
double radius = (center - lastPosition).Length;
|
||||
var sphere = new HalfSphereObject3D(radius * 2, 15);
|
||||
sphere.Translate(center.X, center.Y);
|
||||
letterObject.Children.Add(sphere);
|
||||
}
|
||||
vertexCount = 0;
|
||||
positionSum = Vector2.Zero;
|
||||
break;
|
||||
case Agg.ShapePath.FlagsAndCommand.CommandCurve3:
|
||||
case Agg.ShapePath.FlagsAndCommand.CommandCurve4:
|
||||
case Agg.ShapePath.FlagsAndCommand.CommandLineTo:
|
||||
vertexCount++;
|
||||
lastPosition = vertex.position;
|
||||
positionSum += lastPosition;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
letterPrinter = new TypeFacePrinter(letter.ToString(), pointSize);
|
||||
var scalledLetterPrinter = new VertexSourceApplyTransform(letterPrinter, Affine.NewScaling(pointsToMm));
|
||||
letterObject = new Object3D()
|
||||
{
|
||||
Mesh = VertexSourceToMesh.Extrude(scalledLetterPrinter, BaseHeight)
|
||||
};
|
||||
}
|
||||
|
||||
letterObject.Matrix = Matrix4X4.CreateTranslation(offest, 0, 0);
|
||||
textObject.Children.Add(letterObject);
|
||||
|
||||
offest += letterPrinter.GetSize(letter.ToString()).X * pointsToMm;
|
||||
}
|
||||
|
||||
if (RenderAsBraille)
|
||||
{
|
||||
// add the object that is the dots
|
||||
this.Children.Add(textObject);
|
||||
// add a plate under the dots
|
||||
IObject3D basePlate = new CubeObject3D(textObject.XSize() + pointSize * pointsToMm / 2, textObject.YSize() + pointSize * pointsToMm / 2, BaseHeight);
|
||||
basePlate = new SetCenter(basePlate, textObject.GetCenter() - new Vector3(0, 0, textObject.ZSize() / 2 + basePlate.ZSize() / 2));
|
||||
this.Children.Add(basePlate);
|
||||
}
|
||||
|
||||
if (aabb.ZSize > 0)
|
||||
{
|
||||
// If the part was already created and at a height, maintain the height.
|
||||
PlatingHelper.PlaceMeshAtHeight(this, aabb.minXYZ.Z);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue