Merge pull request #4 from Exolun/Refactor/BindingRefactor

Refactor/binding refactor
This commit is contained in:
Michael Smith 2016-03-23 21:26:16 -07:00
commit b4feff07ec
72 changed files with 9417 additions and 1352 deletions

1
.gitignore vendored
View File

@ -210,3 +210,4 @@ FakesAssemblies/
GeneratedArtifacts/
_Pvt_Extensions/
ModelManifest.xml
OSCADSharp/NDependOut/

View File

@ -1,29 +1,82 @@

using OSCADSharp.DataBinding;
using OSCADSharp.Solids;
using OSCADSharp.Spatial;
using OSCADSharp.Utility;
namespace OSCADSharp.ConsoleTests
{
class Program
{
private static OSCADObject getEndCover(OSCADObject outer)
{
var bounds = outer.Bounds();
var endCover = new Cube(Inches.Sixteenth, bounds.Width, bounds.Height, true);
var choppedOut = endCover.Clone().Scale(2, (bounds.Width-Inches.Quarter)/ bounds.Width, (bounds.Height - Inches.Half) / bounds.Height);
choppedOut = choppedOut.Translate(0, Inches.Quarter, 0);
return endCover - choppedOut;
}
private static void makeBracket()
{
OSCADObject cube = new Cube(new Vector3(Inches.ToMillimeters(2.75), Inches.One, Inches.ToMillimeters(1.25)), true);
var outside = cube.Clone();
((Cube)outside).Size.X += Inches.Sixteenth;
((Cube)outside).Size.Z += Inches.Sixteenth;
cube = cube.Scale(2, 1, 1).Translate(0, Inches.Sixteenth, 0);
var obj = outside - cube;
var bounds = obj.Bounds();
obj = obj + getEndCover(outside).Translate(bounds.XMax, 0, 0);
obj = obj + getEndCover(outside).Translate(-bounds.XMax, 0, 0);
obj.ToFile("leftBracket").Open();
}
private static void makePeg()
{
Variables.Global.Add("$fn", 30);
OSCADObject flatInnerPortion = new Cylinder(Inches.Quarter, Inches.Eigth, true);
OSCADObject shaft = new Cylinder(Inches.Eigth, Inches.Half, true);
flatInnerPortion = flatInnerPortion.Translate(0, 0, shaft.Bounds().ZMax);
OSCADObject pegShaft = new Cylinder(Inches.Quarter, Inches.Half - Inches.Eigth, true)
.Translate(0, 0, -Inches.Eigth);
OSCADObject bottomBall = new Sphere(Inches.Quarter* 1.1)
.Translate(0, 0, pegShaft.Bounds().ZMin);
var obj = flatInnerPortion + shaft + pegShaft + bottomBall;
obj = obj.Rotate(0, 180, 0).Translate(0, 0, obj.Bounds().ZMax);
obj.ToFile("peg");
}
static void Main(string[] args)
{
var diam = new Variable("mainColumn", Inches.Half);
var height = new Variable("overallHeight", Inches.Quarter);
Variables.Global.Add(diam);
Variables.Global.Add(height);
makePeg();
var cyl = new Cylinder(diam, diam, height);
//var diam = new Variable("mainColumn", Inches.Half);
//var height = new Variable("overallHeight", Inches.Quarter);
//Variables.Global.Add(diam);
//Variables.Global.Add(height);
var pos = cyl.Position();
var cyl1 = new Cylinder(1, 100, true).Translate(pos);
var cyl2 = new Cylinder(1, 100, true).Rotate(0, 90, 0).Translate(pos);
var cyl3 = new Cylinder(1, 100, true).Rotate(90, 0, 0).Translate(pos);
var axisHelper = cyl1.Union(cyl2, cyl3).Color("Red");
//var cyl = new Cylinder(diam, diam, height);
//var topCorner = new Sphere().Translate(obj.Bounds().TopRight);
//var botCorner = new Sphere().Translate(obj.Bounds().BottomLeft);
(cyl + axisHelper).ToFile("test.scad").Open();
//var pos = cyl.Position();
//var cyl1 = new Cylinder(1, 100, true).Translate(pos);
//var cyl2 = new Cylinder(1, 100, true).Rotate(0, 90, 0).Translate(pos);
//var cyl3 = new Cylinder(1, 100, true).Rotate(90, 0, 0).Translate(pos);
//var axisHelper = cyl1.Union(cyl2, cyl3).Color("Red");
////var topCorner = new Sphere().Translate(obj.Bounds().TopRight);
////var botCorner = new Sphere().Translate(obj.Bounds().BottomLeft);
//(cyl + axisHelper).ToFile("test.scad").Open();
//Console.ReadKey();
}
}

View File

@ -1,6 +1,8 @@
using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Linq;
using OSCADSharp.DataBinding;
using OSCADSharp.Solids;
namespace OSCADSharp.UnitTests
{

View File

@ -1,5 +1,6 @@
using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using OSCADSharp.Solids;
namespace OSCADSharp.UnitTests
{

View File

@ -1,4 +1,5 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using OSCADSharp.Solids;
using System;
using System.Collections.Generic;
using System.Linq;

View File

@ -1,4 +1,6 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using OSCADSharp.Solids;
using OSCADSharp.Spatial;
using System;
using System.Collections.Generic;
using System.Linq;

View File

@ -1,7 +1,9 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using OSCADSharp.Files;
using OSCADSharp.Scripting;
using OSCADSharp.DataBinding;
using OSCADSharp.IO;
using OSCADSharp.Solids;
using OSCADSharp.Utility;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
@ -80,7 +82,7 @@ namespace OSCADSharp.UnitTests
.Translate(0, 5, 10).Rotate(0, 90, 0)
.Translate(0, 0, 10).Scale(1, 1, 2);
List<uint> ids = obj.Children().Select(child => child.Id).ToList();
List<int> ids = obj.Children().Select(child => child.Id).ToList();
ids.Add(obj.Id);
Assert.AreEqual(ids.Count, ids.Distinct().Count());
@ -147,11 +149,11 @@ namespace OSCADSharp.UnitTests
var mock = new Mock<IFileWriter>();
mock.Setup(_wrtr => _wrtr.WriteAllLines(It.IsAny<string>(), It.IsAny<string[]>()))
.Callback<string, string[]>((path, contents) => { output = contents; });
Dependencies.FileWriter = mock.Object;
Dependencies.SetFileWriter(mock.Object);
cube.ToFile("myFile");
Assert.AreEqual(Settings.OSCADSharpHeader, output[0]);
Assert.AreEqual(OutputSettings.OSCADSharpHeader, output[0]);
}
[TestMethod]
@ -164,7 +166,7 @@ namespace OSCADSharp.UnitTests
var mock = new Mock<IFileWriter>();
mock.Setup(_wrtr => _wrtr.WriteAllLines(It.IsAny<string>(), It.IsAny<string[]>()))
.Callback<string, string[]>((path, contents) => { output = contents; });
Dependencies.FileWriter = mock.Object;
Dependencies.SetFileWriter(mock.Object);
cube.ToFile("myFile");

View File

@ -1,4 +1,6 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using OSCADSharp.DataBinding;
using OSCADSharp.Utility;
using System;
using System.Collections.Generic;
using System.Linq;
@ -24,7 +26,7 @@ namespace OSCADSharp.UnitTests.Scripting
var compound = new Variable("x", 5) / 12;
string type = compound.GetType().ToString();
Assert.AreEqual("OSCADSharp.Scripting.CompoundVariable", type);
Assert.AreEqual("OSCADSharp.DataBinding.Variable+CompoundVariable", type);
}
}
}

View File

@ -1,7 +1,9 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using OSCADSharp.Files;
using OSCADSharp.Scripting;
using OSCADSharp.DataBinding;
using OSCADSharp.IO;
using OSCADSharp.Solids;
using OSCADSharp.Utility;
using System;
using System.Collections.Generic;
using System.Linq;
@ -23,7 +25,7 @@ namespace OSCADSharp.UnitTests
var mock = new Mock<IFileWriter>();
mock.Setup(_wrtr => _wrtr.WriteAllLines(It.IsAny<string>(), It.IsAny<string[]>()))
.Callback<string, string[]>((path, contents) => { output = contents; });
Dependencies.FileWriter = mock.Object;
Dependencies.SetFileWriter(mock.Object);
cube.ToFile("myFile");
@ -34,14 +36,14 @@ namespace OSCADSharp.UnitTests
[ExpectedException(typeof(InvalidOperationException))]
public void Settings_NullOpenSCADPathThrowsError()
{
Settings.OpenSCADPath = null;
OutputSettings.OpenSCADPath = null;
var cube = new Cube();
var mock = new Mock<IFileWriter>();
mock.Setup(_wrtr => _wrtr.WriteAllLines(It.IsAny<string>(), It.IsAny<string[]>()))
.Callback<string, string[]>((path, contents) => { });
Dependencies.FileWriter = mock.Object;
Dependencies.SetFileWriter(mock.Object);
cube.ToFile("test").Open();
}

View File

@ -2,7 +2,10 @@
using System.Text;
using System.Collections.Generic;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using OSCADSharp.Scripting;
using OSCADSharp.Utility;
using OSCADSharp.Spatial;
using OSCADSharp.DataBinding;
using OSCADSharp.Solids;
namespace OSCADSharp.UnitTests
{
@ -191,5 +194,15 @@ namespace OSCADSharp.UnitTests
Assert.IsTrue(script.Contains("translate(v = [xOffset"));
Assert.IsTrue(script.Contains("size = [15, 5, myHeight]"));
}
[TestMethod]
public void Cube_LengthWidthHeightAppearsInScriptOutput()
{
var cube = new Cube(15, 5, 12);
string script = cube.ToString();
Assert.IsTrue(script.Contains("size = [15, 5, 12]"));
}
}
}

View File

@ -1,5 +1,8 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using OSCADSharp.Scripting;
using OSCADSharp.DataBinding;
using OSCADSharp.Solids;
using OSCADSharp.Spatial;
using OSCADSharp.Utility;
using System;
using System.Collections.Generic;
using System.Linq;

View File

@ -1,6 +1,9 @@
using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using OSCADSharp.Scripting;
using OSCADSharp.Utility;
using OSCADSharp.Spatial;
using OSCADSharp.DataBinding;
using OSCADSharp.Solids;
namespace OSCADSharp.UnitTests
{

View File

@ -1,5 +1,7 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using OSCADSharp.Scripting;
using OSCADSharp.DataBinding;
using OSCADSharp.Solids;
using OSCADSharp.Spatial;
using System;
using System.Collections.Generic;
using System.Linq;

View File

@ -1,5 +1,6 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using OSCADSharp.Scripting;
using OSCADSharp.DataBinding;
using OSCADSharp.Solids;
using System;
using System.Collections.Generic;
using System.Linq;

View File

@ -1,4 +1,5 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using OSCADSharp.Solids;
using System;
using System.Collections.Generic;
using System.Linq;

View File

@ -1,5 +1,6 @@
using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using OSCADSharp.Solids;
namespace OSCADSharp.UnitTests
{

View File

@ -1,5 +1,7 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using OSCADSharp.Scripting;
using OSCADSharp.DataBinding;
using OSCADSharp.Solids;
using OSCADSharp.Spatial;
using System;
using System.Collections.Generic;
using System.Linq;

View File

@ -1,5 +1,7 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using OSCADSharp.Scripting;
using OSCADSharp.DataBinding;
using OSCADSharp.Solids;
using OSCADSharp.Spatial;
using System;
using System.Collections.Generic;
using System.Linq;

View File

@ -1,5 +1,7 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using OSCADSharp.Scripting;
using OSCADSharp.DataBinding;
using OSCADSharp.Solids;
using OSCADSharp.Spatial;
using System;
using System.Collections.Generic;
using System.Linq;

View File

@ -1,5 +1,7 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using OSCADSharp.Scripting;
using OSCADSharp.DataBinding;
using OSCADSharp.Solids;
using OSCADSharp.Spatial;
using System;
using System.Collections.Generic;
using System.Linq;

View File

@ -1,5 +1,8 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using OSCADSharp.Scripting;
using OSCADSharp.DataBinding;
using OSCADSharp.Solids;
using OSCADSharp.Spatial;
using OSCADSharp.Utility;
using System;
using System.Collections.Generic;
using System.Linq;

8101
OSCADSharp/OSCADSharp.ndproj Normal file

File diff suppressed because it is too large Load Diff

View File

@ -12,6 +12,7 @@ EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{C831DC9A-396A-43F9-AAC6-410A88485356}"
ProjectSection(SolutionItems) = preProject
..\LICENSE.txt = ..\LICENSE.txt
OSCADSharp\OSCADSharp.nuspec = OSCADSharp\OSCADSharp.nuspec
..\README.md = ..\README.md
EndProjectSection
EndProject

View File

@ -3,13 +3,12 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using OSCADSharp.Scripting;
namespace OSCADSharp.Bindings
namespace OSCADSharp.DataBinding
{
internal class BindableBoolean : IBindable
{
public string InnerValue
internal string InnerValue
{
get;
set;
@ -32,9 +31,9 @@ namespace OSCADSharp.Bindings
this.bindings.Synonym("innervalue", propertyName);
}
private string boundProperty = null;
private readonly string boundProperty = null;
public bool IsBound { get; set; } = false;
internal bool IsBound { get; set; } = false;
public void Bind(string property, Variable variable)
{
this.IsBound = true;
@ -42,17 +41,17 @@ namespace OSCADSharp.Bindings
this.bindings.Add<BindableBoolean>(this, property, stringifiedVar);
}
public BindableBoolean Clone()
public override string ToString()
{
return this.bindings.Get(this.boundProperty).BoundVariable.Text;
}
internal BindableBoolean Clone()
{
var clone = new BindableBoolean(this.boundProperty);
clone.bindings = this.bindings;
return clone;
}
public override string ToString()
{
return this.bindings.Get(this.boundProperty).BoundVariable.Text;
}
}
}

View File

@ -1,11 +1,11 @@
using System;
using OSCADSharp.Spatial;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using OSCADSharp.Scripting;
namespace OSCADSharp.Bindings
namespace OSCADSharp.DataBinding
{
internal class BindableVector : Vector3, IBindable
{
@ -16,11 +16,16 @@ namespace OSCADSharp.Bindings
{ "z", "z" }
});
public BindableVector(Vector3 vector, Dictionary<string, string> synonyms = null) : this(vector.X, vector.Y, vector.Z)
internal BindableVector(Vector3 vector, Dictionary<string, string> synonyms = null) : this(vector.X, vector.Y, vector.Z)
{
this.X = vector.X;
this.Y = vector.Y;
this.Z = vector.Z;
this.setSynonyms(synonyms);
}
public BindableVector(double x = 0, double y = 0, double z = 0, Dictionary<string, string> synonyms = null)
internal BindableVector(double x = 0, double y = 0, double z = 0, Dictionary<string, string> synonyms = null)
{
this.X = x;
this.Y = y;
@ -54,7 +59,7 @@ namespace OSCADSharp.Bindings
return String.Format("[{0}, {1}, {2}]", x, y, z);
}
public new BindableVector Clone()
internal new BindableVector Clone()
{
var clone = new BindableVector(base.Clone());
clone.bindings = this.bindings.Clone();

View File

@ -1,11 +1,10 @@
using OSCADSharp.Scripting;
using System;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace OSCADSharp.Bindings
namespace OSCADSharp.DataBinding
{
internal class Binding
{

View File

@ -1,28 +1,27 @@
using OSCADSharp.Scripting;
using System;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
namespace OSCADSharp.Bindings
namespace OSCADSharp.DataBinding
{
internal class Bindings
{
#region Fields
private Dictionary<string, Binding> bindings = new Dictionary<string, Binding>();
private Dictionary<string, string> propertyNametoOpenSCADFieldMappings = new Dictionary<string, string>();
private readonly Dictionary<string, string> propertyNametoOpenSCADFieldMappings = new Dictionary<string, string>();
private Dictionary<string, string> synonyms = new Dictionary<string, string>();
#endregion
#region Constructors
public Bindings()
internal Bindings()
{
this.propertyNametoOpenSCADFieldMappings = new Dictionary<string, string>();
}
public Bindings(Dictionary<string, string> mappings)
internal Bindings(Dictionary<string, string> mappings)
{
this.propertyNametoOpenSCADFieldMappings = mappings;
}

View File

@ -1,16 +1,15 @@
using OSCADSharp.Scripting;
using System;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace OSCADSharp
namespace OSCADSharp.DataBinding
{
/// <summary>
/// An object whose properties can be bound to variables
/// </summary>
public interface IBindable
internal interface IBindable
{
/// <summary>
/// Binds a variable to property of this object

View File

@ -1,11 +1,12 @@
using OSCADSharp.Scripting;
using OSCADSharp.Spatial;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
namespace OSCADSharp
namespace OSCADSharp.DataBinding
{
/// <summary>
/// A value for setting object properties in script output to
@ -229,5 +230,80 @@ namespace OSCADSharp
return applyMixedOperatorRight("/", left, right, VariableCalculator.Divide);
}
#endregion
#region CompoundVariable
private class CompoundVariable : Variable
{
internal CompoundVariable(string name, object value) : base(name, value, false)
{
}
}
#endregion
#region VariableCalculator
private static class VariableCalculator
{
internal static bool IsNumeric(object value)
{
return value is int || value is double || value is float || value is decimal;
}
internal static bool IsVector(object value)
{
return value is Vector3 || value is BindableVector;
}
private static object computeExpression(BinaryExpression expr, object left, object right)
{
object result = null;
if (IsNumeric(left) && IsNumeric(right))
result = Expression.Lambda<Func<double>>(expr).Compile()();
if (IsVector(left) || IsVector(right))
result = Expression.Lambda<Func<Vector3>>(expr).Compile()();
return result;
}
private static BinaryExpression makeExpression(Func<ConstantExpression, ConstantExpression, BinaryExpression> methodToUse,
object left, object right)
{
if (IsNumeric(left))
left = Convert.ToDouble(left);
if (IsNumeric(right))
right = Convert.ToDouble(right);
var leftExpr = Expression.Constant(left, left.GetType());
var rightExpr = Expression.Constant(right, right.GetType());
BinaryExpression expr = methodToUse(leftExpr, rightExpr);
return expr;
}
internal static object Add(object left, object right)
{
BinaryExpression expr = makeExpression(Expression.Add, left, right);
return computeExpression(expr, left, right);
}
internal static object Subtract(object left, object right)
{
BinaryExpression expr = makeExpression(Expression.Subtract, left, right);
return computeExpression(expr, left, right);
}
internal static object Multiply(object left, object right)
{
BinaryExpression expr = makeExpression(Expression.Multiply, left, right);
return computeExpression(expr, left, right);
}
internal static object Divide(object left, object right)
{
BinaryExpression expr = makeExpression(Expression.Divide, left, right);
return computeExpression(expr, left, right);
}
}
#endregion
}
}

View File

@ -5,7 +5,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace OSCADSharp
namespace OSCADSharp.DataBinding
{
/// <summary>
/// A collection of names/values for variables
@ -16,8 +16,8 @@ namespace OSCADSharp
/// Global variables that can be assigned for output at the
/// top of OpenSCAD scripts
/// </summary>
public static Variables Global = new Variables();
private ConcurrentDictionary<string, Variable> variables = new ConcurrentDictionary<string, Variable>();
public static Variables Global { get; set; } = new Variables();
private readonly ConcurrentDictionary<string, Variable> variables = new ConcurrentDictionary<string, Variable>();
/// <summary>
/// Adds a variable to the collection

View File

@ -1,16 +1,17 @@
using System;
using OSCADSharp.Utility;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace OSCADSharp.Files
namespace OSCADSharp.IO
{
internal class DefaultFileInvoker : IFileInvoker
{
private string filePath;
public DefaultFileInvoker(string filePath)
private readonly string filePath;
internal DefaultFileInvoker(string filePath)
{
this.filePath = filePath;
}
@ -19,7 +20,7 @@ namespace OSCADSharp.Files
{
try
{
Process.Start(Settings.OpenSCADPath, String.Format("-o {0} {1}", outputFile, this.filePath));
Process.Start(OutputSettings.OpenSCADPath, String.Format("-o {0} {1}", outputFile, this.filePath));
}
catch (InvalidOperationException)
{
@ -31,7 +32,7 @@ namespace OSCADSharp.Files
{
try
{
Process.Start(Settings.OpenSCADPath, String.Format("{0}", this.filePath));
Process.Start(OutputSettings.OpenSCADPath, String.Format("{0}", this.filePath));
}
catch (InvalidOperationException)
{

View File

@ -5,7 +5,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace OSCADSharp.Files
namespace OSCADSharp.IO
{
internal class DefaultFileWriter : IFileWriter
{

View File

@ -4,7 +4,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace OSCADSharp
namespace OSCADSharp.IO
{
/// <summary>
/// Invokes OpenSCAD actions on output files

View File

@ -4,7 +4,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace OSCADSharp
namespace OSCADSharp.IO
{
/// <summary>
/// A class that takes text and writes to file

View File

@ -0,0 +1,52 @@
using OSCADSharp.Utility;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace OSCADSharp.IO
{
/// <summary>
/// Settings for OpenSCAD scripts
/// </summary>
public static class OutputSettings
{
/// <summary>
/// Code-gen header
/// </summary>
public static string OSCADSharpHeader { get; private set; } = String.Format("/*Code Generated using OSCADSharp on {0}. {1}{2}For more information, please visit https://github.com/Exolun/OSCADSharp */{3}",
DateTime.Now.ToString(), Environment.NewLine, Environment.NewLine, Environment.NewLine);
/// <summary>
/// Path to the OpenSCAD executable for file invocation
/// (Default value is set the default install directory on Windows)
/// </summary>
public static string OpenSCADPath { get; set; } = new OpenSCADPathFinder().GetPath();
/// <summary>
/// Known where the default installation locations for OpenSCAD
/// are, and finds the right path for the current environment
/// </summary>
private class OpenSCADPathFinder
{
private readonly string[] possibleFilePaths = new string[]
{
@"C:\Program Files (x86)\OpenSCAD\openscad.exe",
@"C:\Program Files\OpenSCAD\openscad.exe"
};
internal string GetPath()
{
foreach (string path in possibleFilePaths)
{
if (File.Exists(path))
return path;
}
return null;
}
}
}
}

View File

@ -1,34 +0,0 @@
using OSCADSharp.Scripting;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using OSCADSharp.Spatial;
namespace OSCADSharp.Booleans
{
/// <summary>
/// Subtracts the 2nd (and all further) child nodes from the first one (logical and not).
/// </summary>
internal class Difference : MultiStatementObject
{
/// <summary>
/// Creates a subtraction of child nodes
/// </summary>
/// <param name="children"></param>
public Difference(IEnumerable<OSCADObject> children) : base("difference()", children)
{
}
public override Vector3 Position()
{
return children[0].Position();
}
public override Bounds Bounds()
{
return children[0].Bounds();
}
}
}

View File

@ -1,34 +0,0 @@
using OSCADSharp.Scripting;
using OSCADSharp.Spatial;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace OSCADSharp.Booleans
{
/// <summary>
/// Creates the intersection of all child nodes
/// </summary>
internal class Intersection : MultiStatementObject
{
/// <summary>
/// Creates the intersection of all child nodes
/// </summary>
/// <param name="children"></param>
public Intersection(IEnumerable<OSCADObject> children) : base("intersection()", children)
{
}
public override Vector3 Position()
{
throw new NotSupportedException("Position is not supported on Intersected objects.");
}
public override Bounds Bounds()
{
throw new NotSupportedException("Bounds is not supported on Intersected objects.");
}
}
}

View File

@ -1,23 +0,0 @@
using OSCADSharp.Scripting;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace OSCADSharp.Booleans
{
/// <summary>
/// A union of child nodes. This is the sum of all children (logical or).
/// </summary>
internal class Union : MultiStatementObject
{
/// <summary>
/// Create a union that is the combination of all children
/// </summary>
/// <param name="children">OSCADObjects to combine</param>
internal Union(IEnumerable<OSCADObject> children) : base("union()", children)
{
}
}
}

View File

@ -1,15 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace OSCADSharp.Scripting
{
internal class CompoundVariable : Variable
{
public CompoundVariable(string name, object value) : base(name, value, false)
{
}
}
}

View File

@ -1,104 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using OSCADSharp.Spatial;
namespace OSCADSharp.Scripting
{
/// <summary>
/// A statement that has multiple child nodes, whose ToString output
/// is more or less just an aggregate of the children
/// </summary>
internal class MultiStatementObject : OSCADObject
{
private string outerStatement;
internal MultiStatementObject(string outerStatement, IEnumerable<OSCADObject> children)
{
this.outerStatement = outerStatement;
this.children = children.ToList();
foreach (var child in children)
{
child.Parent = this;
}
}
public override string ToString()
{
StringBuilder sb = new StringBuilder();
foreach (var child in this.children)
{
sb.Append(child.ToString());
}
var formatter = new SingleBlockFormatter(this.outerStatement, sb.ToString());
return formatter.ToString();
}
public override OSCADObject Clone()
{
List<OSCADObject> childClones = new List<OSCADObject>();
foreach (var child in this.children)
{
childClones.Add(child.Clone());
}
return new MultiStatementObject(this.outerStatement, childClones)
{
Name = this.Name
};
}
public override Vector3 Position()
{
var positions = this.children.Select(child => child.Position());
return Vector3.Average(positions.ToArray());
}
public override Bounds Bounds()
{
var newBottomLeft = new Vector3();
var newTopRight = new Vector3();
foreach (var child in this.children)
{
var bounds = child.Bounds();
if (bounds.XMin < newBottomLeft.X)
{
newBottomLeft.X = bounds.XMin;
}
if (bounds.YMin < newBottomLeft.Y)
{
newBottomLeft.Y = bounds.YMin;
}
if (bounds.ZMin < newBottomLeft.Z)
{
newBottomLeft.Z = bounds.ZMin;
}
if (bounds.XMax > newTopRight.X)
{
newTopRight.X = bounds.XMax;
}
if (bounds.YMax> newTopRight.Y)
{
newTopRight.Y = bounds.YMax;
}
if (bounds.ZMax > newTopRight.Z)
{
newTopRight.Z = bounds.ZMax;
}
}
return new Bounds(newBottomLeft, newTopRight);
}
public override void Bind(string property, Variable variable)
{
throw new NotSupportedException("This object has no bindable properties.");
}
}
}

View File

@ -1,25 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using OSCADSharp.Spatial;
namespace OSCADSharp.Scripting
{
/// <summary>
/// A statement with just one nested child node
/// </summary>
internal abstract class SingleStatementObject : OSCADObject
{
protected OSCADObject obj;
public SingleStatementObject(OSCADObject obj)
{
this.obj = obj;
this.children.Add(obj);
obj.Parent = this;
}
}
}

View File

@ -1,73 +0,0 @@
using OSCADSharp.Bindings;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
namespace OSCADSharp
{
internal static class VariableCalculator
{
internal static bool IsNumeric(object value)
{
return value is int || value is double || value is float || value is decimal;
}
internal static bool IsVector(object value)
{
return value is Vector3 || value is BindableVector;
}
private static object computeExpression(BinaryExpression expr, object left, object right)
{
object result = null;
if (IsNumeric(left) && IsNumeric(right))
result = Expression.Lambda<Func<double>>(expr).Compile()();
if (IsVector(left) || IsVector(right))
result = Expression.Lambda<Func<Vector3>>(expr).Compile()();
return result;
}
private static BinaryExpression makeExpression(Func<ConstantExpression, ConstantExpression, BinaryExpression> methodToUse,
object left, object right)
{
if (IsNumeric(left))
left = Convert.ToDouble(left);
if (IsNumeric(right))
right = Convert.ToDouble(right);
var leftExpr = Expression.Constant(left, left.GetType());
var rightExpr = Expression.Constant(right, right.GetType());
BinaryExpression expr = methodToUse(leftExpr, rightExpr);
return expr;
}
internal static object Add(object left, object right)
{
BinaryExpression expr = makeExpression(Expression.Add, left, right);
return computeExpression(expr, left, right);
}
internal static object Subtract(object left, object right)
{
BinaryExpression expr = makeExpression(Expression.Subtract, left, right);
return computeExpression(expr, left, right);
}
internal static object Multiply(object left, object right)
{
BinaryExpression expr = makeExpression(Expression.Multiply, left, right);
return computeExpression(expr, left, right);
}
internal static object Divide(object left, object right)
{
BinaryExpression expr = makeExpression(Expression.Divide, left, right);
return computeExpression(expr, left, right);
}
}
}

View File

@ -1,34 +0,0 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace OSCADSharp
{
/// <summary>
/// Known where the default installation locations for OpenSCAD
/// are, and finds the right path for the current environment
/// </summary>
internal class OpenSCADPathFinder
{
private string[] possibleFilePaths = new string[]
{
@"C:\Program Files (x86)\OpenSCAD\openscad.exe",
@"C:\Program Files\OpenSCAD\openscad.exe"
};
internal string GetPath()
{
foreach (string path in possibleFilePaths)
{
if (File.Exists(path))
return path;
}
return null;
}
}
}

View File

@ -1,86 +0,0 @@
using OSCADSharp.Scripting;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using OSCADSharp.Spatial;
namespace OSCADSharp.Transforms
{
/// <summary>
/// An object that has color and/or opacity applied to it
/// </summary>
internal class ColoredObject : SingleStatementObject
{
#region Attributes
internal string ColorName { get; set; } = "Yellow";
internal double Opacity { get; set; } = 1.0;
#endregion
/// <summary>
/// Creates a colorized object
/// </summary>
/// <param name="obj">The object(s) to which color will be applied</param>
/// <param name="color">The string-wise name of the color to be applied</param>
/// <param name="opacity">Opacity from 0.0 to 1.0 </param>
internal ColoredObject(OSCADObject obj, string color = "Yellow", double opacity = 1.0) : base(obj)
{
this.ColorName = color;
this.Opacity = opacity;
}
/// <summary>
/// Creates a colorized object with predefined bindings
/// </summary>
/// <param name="obj">The object(s) to which color will be applied</param>
/// <param name="colorName"></param>
/// <param name="opacity"></param>
internal ColoredObject(OSCADObject obj, Variable colorName, Variable opacity) : base(obj)
{
this.Bind("color", colorName);
this.BindIfVariableNotNull("opacity", opacity);
}
public override string ToString()
{
string colorName = this.bindings.Contains("color") ? this.bindings.Get("color").BoundVariable.Text :
"\""+this.ColorName+"\"";
string opacity = this.bindings.Contains("opacity") ? this.bindings.Get("opacity").BoundVariable.Text
: this.Opacity.ToString();
string colorCommand = String.Format("color({0}, {1})", colorName, opacity);
var formatter = new SingleBlockFormatter(colorCommand, this.obj.ToString());
return formatter.ToString();
}
public override OSCADObject Clone()
{
return new ColoredObject(this.obj.Clone(), this.ColorName, this.Opacity)
{
Name = this.Name,
bindings = this.bindings.Clone()
};
}
public override Vector3 Position()
{
return this.obj.Position();
}
public override Bounds Bounds()
{
return this.obj.Bounds();
}
private Bindings.Bindings bindings = new Bindings.Bindings(new Dictionary<string, string>() {
{"color", "color" },
{"opacity", "opacity" }
});
public override void Bind(string property, Variable variable)
{
this.bindings.Add<ColoredObject>(this, property, variable);
}
}
}

View File

@ -1,19 +0,0 @@
using OSCADSharp.Scripting;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace OSCADSharp.Transforms
{
/// <summary>
/// Creates an object that's the convex hull of child objects
/// </summary>
internal class HulledObject : MultiStatementObject
{
public HulledObject(IEnumerable<OSCADObject> children) : base("hull()", children)
{
}
}
}

View File

@ -1,66 +0,0 @@
using OSCADSharp.Scripting;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using OSCADSharp.Spatial;
namespace OSCADSharp.Transforms
{
/// <summary>
/// Linear Extrusion is a modeling operation that takes a 2D polygon as input and extends it in the third dimension. This way a 3D shape is created.
///
/// This is a limited subset of the capabilities
/// </summary>
internal class LinearExtrudedObject : SingleStatementObject
{
/// <summary>
/// Height to extrude to
/// </summary>
public double Height { get; set; } = 1.0;
//TODO: Possibly implement everything else?
//linear_extrude(height = fanwidth, center = true, convexity = 10, twist = -fanrot, slices = 20, scale = 1.0) {...}
/// <summary>
/// An object that will be extruded from 2d to 3d
/// </summary>
/// <param name="obj"></param>
/// <param name="height"></param>
public LinearExtrudedObject(OSCADObject obj, double height) : base(obj)
{
this.Height = height;
}
public override OSCADObject Clone()
{
return new LinearExtrudedObject(this.obj.Clone(), this.Height)
{
Name = this.Name
};
}
public override string ToString()
{
string extrudeCommand = String.Format("linear_extrude(height = {0})", this.Height.ToString());
var formatter = new SingleBlockFormatter(extrudeCommand, this.obj.ToString());
return formatter.ToString();
}
public override Vector3 Position()
{
throw new NotSupportedException();
}
public override Bounds Bounds()
{
throw new NotImplementedException();
}
public override void Bind(string property, Variable variable)
{
throw new NotImplementedException();
}
}
}

View File

@ -1,31 +0,0 @@
using OSCADSharp.Scripting;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using OSCADSharp.Spatial;
namespace OSCADSharp.Transforms
{
/// <summary>
/// Creates an object that's the minkowski sum of child objects
/// </summary>
internal class MinkowskiedObject : MultiStatementObject
{
public MinkowskiedObject(IEnumerable<OSCADObject> children) : base("minkowski()", children)
{
}
public override Vector3 Position()
{
throw new NotSupportedException("Position is not supported on Minkowskied objects.");
}
public override Bounds Bounds()
{
throw new NotSupportedException("Bounds is not supported on Minkowskied objects.");
}
}
}

View File

@ -1,126 +0,0 @@
using OSCADSharp.Bindings;
using OSCADSharp.Scripting;
using OSCADSharp.Spatial;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace OSCADSharp.Transforms
{
/// <summary>
/// An object that's mirrored on a plane
/// </summary>
internal class MirroredObject : SingleStatementObject
{
/// <summary>
/// The normal vector of a plane intersecting the origin of the object,
/// through which to mirror it.
/// </summary>
internal Vector3 Normal { get; set; } = new BindableVector();
/// <summary>
/// Creates an object that's mirrored on a plane
/// </summary>
/// <param name="obj">The object(s) to be mirrored</param>
/// <param name="normal">The normal vector of the plane on the object's origin to mirror upon</param>
internal MirroredObject(OSCADObject obj, Vector3 normal) : base(obj)
{
this.Normal = new BindableVector(normal);
}
internal MirroredObject(OSCADObject obj, Variable normal) : base(obj)
{
this.Bind("normal", normal);
}
internal MirroredObject(OSCADObject obj, Vector3 normal, Variable x, Variable y, Variable z) : base(obj)
{
this.Normal = new BindableVector(normal);
this.BindIfVariableNotNull("x", x);
this.BindIfVariableNotNull("y", y);
this.BindIfVariableNotNull("z", z);
}
public override string ToString()
{
string normal = this.bindings.Contains("normal") ? this.bindings.Get("normal").BoundVariable.Text : this.Normal.ToString();
string mirrorCommand = String.Format("mirror({0})", normal);
var formatter = new SingleBlockFormatter(mirrorCommand, this.obj.ToString());
return formatter.ToString();
}
public override OSCADObject Clone()
{
return new MirroredObject(this.obj.Clone(), this.Normal)
{
Name = this.Name,
bindings = this.bindings.Clone()
};
}
// TODO: This will yield incorrect positions if mirroring on multiple axes
// fix mirrored positions for multiple-axis mirroring
public override Vector3 Position()
{
if (this.isMoreThanOneAxis())
{
throw new NotSupportedException("Getting the position of an object that's been mirrored on more than one axis is not currently supported.");
}
var pos = obj.Position();
double x = this.Normal.X != 0 ? pos.X * -1 : pos.X;
double y = this.Normal.Y != 0 ? pos.Y * -1 : pos.Y;
double z = this.Normal.Z != 0 ? pos.Z * -1 : pos.Z;
return new Vector3(x, y, z);
}
private bool isMoreThanOneAxis()
{
return (this.Normal.X != 0 && (this.Normal.Y != 0 || this.Normal.Z != 0)) ||
(this.Normal.Y != 0 && (this.Normal.X != 0 || this.Normal.Z != 0));
}
// TODO: As with Position, will yield incorrect positions if mirroring on multiple axes
// fix mirrored positions for multiple-axis mirroring
public override Bounds Bounds()
{
if (this.isMoreThanOneAxis())
{
throw new NotSupportedException("Getting the position of an object that's been mirrored on more than one axis is not currently supported.");
}
var oldBounds = this.obj.Bounds();
var newBottomLeft = new Vector3(this.Normal.X != 0 ? oldBounds.BottomLeft.X * -1 : oldBounds.BottomLeft.X,
this.Normal.Y != 0 ? oldBounds.BottomLeft.Y * -1 : oldBounds.BottomLeft.Y,
this.Normal.Z != 0 ? oldBounds.BottomLeft.Z * -1 : oldBounds.BottomLeft.Z);
var newTopRight = new Vector3(this.Normal.X != 0 ? oldBounds.TopRight.X * -1 : oldBounds.TopRight.X,
this.Normal.Y != 0 ? oldBounds.TopRight.Y * -1 : oldBounds.TopRight.Y,
this.Normal.Z != 0 ? oldBounds.TopRight.Z * -1 : oldBounds.TopRight.Z);
return new Bounds(newBottomLeft, newTopRight);
}
private Bindings.Bindings bindings = new Bindings.Bindings(new Dictionary<string, string>() {
{"normal", "normal"}
});
public override void Bind(string property, Variable variable)
{
var bindableVec = this.Normal as BindableVector;
if (bindableVec != null && property == "x" || property == "y" || property == "z")
{
bindableVec.Bind(property, variable);
}
else
{
this.bindings.Add<MirroredObject>(this, property, variable);
}
}
}
}

View File

@ -1,107 +0,0 @@
using OSCADSharp.Scripting;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using OSCADSharp.Spatial;
using OSCADSharp.Bindings;
namespace OSCADSharp.Transforms
{
/// <summary>
/// An object that's been resized to a specified set of X/Y/Z dimensions
/// </summary>
internal class ResizedObject : SingleStatementObject
{
/// <summary>
/// Size of the object in terms of X/Y/Z
/// </summary>
internal Vector3 Size { get; set; }
/// <summary>
/// Creates a resized object
/// </summary>
/// <param name="obj">The object(s) to be resized</param>
/// <param name="size">The size to resize to, in terms of x/y/z dimensions</param>
internal ResizedObject(OSCADObject obj, Vector3 size) : base(obj)
{
Size = new BindableVector(size);
}
internal ResizedObject(OSCADObject obj, Variable size) : base(obj)
{
this.Bind("size", size);
}
internal ResizedObject(OSCADObject obj, Vector3 size, Variable x, Variable y, Variable z) : base(obj)
{
this.Size = new BindableVector(size);
this.BindIfVariableNotNull("x", x);
this.BindIfVariableNotNull("y", y);
this.BindIfVariableNotNull("z", z);
}
internal ResizedObject(OSCADObject obj) : base(obj)
{
}
public override string ToString()
{
string size = this.bindings.Contains("size") ? this.bindings.Get("size").BoundVariable.Text : this.Size.ToString();
string resizeCommand = String.Format("resize({0})", size);
var formatter = new SingleBlockFormatter(resizeCommand, this.obj.ToString());
return formatter.ToString();
}
public override OSCADObject Clone()
{
var bndSize = this.Size as BindableVector;
return new ResizedObject(this.obj.Clone())
{
Name = this.Name,
bindings = this.bindings.Clone(),
Size = bndSize != null ? bndSize.Clone() : this.Size.Clone()
};
}
public override Vector3 Position()
{
var bounds = this.Bounds();
return Vector3.Average(bounds.BottomLeft, bounds.TopRight);
}
public override Bounds Bounds()
{
var oldBounds = obj.Bounds();
double xScaleFactor = this.Size.X > 0 ? this.Size.X / Math.Abs(oldBounds.XMax - oldBounds.XMin) : 1;
double yScaleFactor = this.Size.Y > 0 ? this.Size.Y / Math.Abs(oldBounds.YMax - oldBounds.YMin) : 1;
double zScaleFactor = this.Size.Z > 0 ? this.Size.Z / Math.Abs(oldBounds.ZMax - oldBounds.ZMin) : 1;
Vector3 scaleMultiplier = new Vector3(xScaleFactor, yScaleFactor, zScaleFactor);
return new Bounds(oldBounds.BottomLeft * scaleMultiplier, oldBounds.TopRight * scaleMultiplier);
}
private Bindings.Bindings bindings = new Bindings.Bindings(new Dictionary<string, string>() {
{ "size", "size" }
});
public override void Bind(string property, Variable variable)
{
var bindableVec = this.Size as BindableVector;
if(bindableVec != null && property == "x" || property == "y" || property == "z")
{
bindableVec.Bind(property, variable);
}
else
{
this.bindings.Add<ResizedObject>(this, property, variable);
}
}
}
}

View File

@ -1,93 +0,0 @@
using OSCADSharp.Bindings;
using OSCADSharp.Scripting;
using OSCADSharp.Spatial;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace OSCADSharp.Transforms
{
/// <summary>
/// An object with rotation applied
/// </summary>
internal class RotatedObject : SingleStatementObject
{
/// <summary>
/// The angle to rotate, in terms of X/Y/Z euler angles
/// </summary>
internal Vector3 Angle { get; set; } = new BindableVector();
/// <summary>
/// Creates an object with rotation applied
/// </summary>
/// <param name="obj">The object being rotated</param>
/// <param name="angle">The angle to rotate</param>
internal RotatedObject(OSCADObject obj, Vector3 angle) : base(obj)
{
this.Angle = new BindableVector(angle);
}
internal RotatedObject(OSCADObject obj, Variable normal) : base(obj)
{
this.Bind("angle", normal);
}
internal RotatedObject(OSCADObject obj, Vector3 angle, Variable x, Variable y, Variable z) : base(obj)
{
this.Angle = new BindableVector(angle);
this.BindIfVariableNotNull("x", x);
this.BindIfVariableNotNull("y", y);
this.BindIfVariableNotNull("z", z);
}
public override string ToString()
{
string angle = this.bindings.Contains("angle") ? this.bindings.Get("angle").BoundVariable.Text : this.Angle.ToString();
string rotateCommand = String.Format("rotate({0})", angle.ToString());
var formatter = new SingleBlockFormatter(rotateCommand, this.obj.ToString());
return formatter.ToString();
}
public override OSCADObject Clone()
{
return new RotatedObject(this.obj.Clone(), this.Angle)
{
Name = this.Name,
bindings = this.bindings.Clone()
};
}
public override Vector3 Position()
{
return Matrix.GetRotatedPoint(this.obj.Position(), this.Angle.X, this.Angle.Y, this.Angle.Z);
}
public override Bounds Bounds()
{
var oldBounds = obj.Bounds();
return new Bounds(Matrix.GetRotatedPoint(oldBounds.BottomLeft, this.Angle.X, this.Angle.Y, this.Angle.Z),
Matrix.GetRotatedPoint(oldBounds.TopRight, this.Angle.X, this.Angle.Y, this.Angle.Z));
}
private Bindings.Bindings bindings = new Bindings.Bindings(new Dictionary<string, string>() {
{ "angle", "angle" }
});
public override void Bind(string property, Variable variable)
{
var bindableVec = this.Angle as BindableVector;
if (bindableVec != null && property == "x" || property == "y" || property == "z")
{
bindableVec.Bind(property, variable);
}
else
{
this.bindings.Add<RotatedObject>(this, property, variable);
}
}
}
}

View File

@ -1,93 +0,0 @@
using OSCADSharp.Scripting;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using OSCADSharp.Spatial;
using OSCADSharp.Bindings;
namespace OSCADSharp.Transforms
{
/// <summary>
/// An object that's been rescaled
/// </summary>
internal class ScaledObject : SingleStatementObject
{
/// <summary>
/// The scale factor to be applied
/// </summary>
internal Vector3 ScaleFactor { get; set; } = new BindableVector(1, 1, 1);
/// <summary>
/// Creates a scaled object
/// </summary>
/// <param name="obj">Object(s) to be scaled</param>
/// <param name="scale">Scale factor in x/y/z components</param>
internal ScaledObject(OSCADObject obj, Vector3 scale) : base(obj)
{
this.ScaleFactor = new BindableVector(scale);
}
internal ScaledObject(OSCADObject obj, Variable normal) : base(obj)
{
this.Bind("scalefactor", normal);
}
internal ScaledObject(OSCADObject obj, Vector3 scale, Variable x, Variable y, Variable z) : base(obj)
{
this.ScaleFactor = new BindableVector(scale);
this.BindIfVariableNotNull("x", x);
this.BindIfVariableNotNull("y", y);
this.BindIfVariableNotNull("z", z);
}
public override string ToString()
{
string scale = this.bindings.Contains("scalefactor") ? this.bindings.Get("scalefactor").BoundVariable.Text : this.ScaleFactor.ToString();
string scaleCommand = String.Format("scale(v = {0})", scale);
var formatter = new SingleBlockFormatter(scaleCommand, this.obj.ToString());
return formatter.ToString();
}
public override OSCADObject Clone()
{
return new ScaledObject(this.obj.Clone(), this.ScaleFactor)
{
Name = this.Name,
bindings = this.bindings.Clone()
};
}
public override Vector3 Position()
{
return obj.Position() * this.ScaleFactor;
}
public override Bounds Bounds()
{
var oldBounds = obj.Bounds();
return new Bounds(oldBounds.BottomLeft * this.ScaleFactor, oldBounds.TopRight * this.ScaleFactor);
}
private Bindings.Bindings bindings = new Bindings.Bindings(new Dictionary<string, string>() {
{ "scalefactor", "scalefactor" }
});
public override void Bind(string property, Variable variable)
{
var bindableVec = this.ScaleFactor as BindableVector;
property = property == "scale" ? "scalefactor" : property;
if (bindableVec != null && property == "x" || property == "y" || property == "z")
{
bindableVec.Bind(property, variable);
}
else
{
this.bindings.Add<ScaledObject>(this, property, variable);
}
}
}
}

View File

@ -1,98 +0,0 @@
using OSCADSharp.Scripting;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using OSCADSharp.Spatial;
using OSCADSharp.Bindings;
namespace OSCADSharp.Transforms
{
/// <summary>
/// An object or objects that have been moved along the specified vector
/// </summary>
internal class TranslatedObject : SingleStatementObject
{
internal Vector3 Vector { get; set; }
/// <summary>
/// Creates a translated object
/// </summary>
/// <param name="obj">Object(s) to translate</param>
/// <param name="vector">Amount to translate by</param>
internal TranslatedObject(OSCADObject obj, Vector3 vector) : base(obj)
{
this.Vector = new BindableVector(vector);
}
internal TranslatedObject(OSCADObject obj, Variable normal) : base(obj)
{
this.Bind("vector", normal);
}
internal TranslatedObject(OSCADObject obj, Vector3 vector, Variable x, Variable y, Variable z) : base(obj)
{
this.Vector = new BindableVector(vector);
this.BindIfVariableNotNull("x", x);
this.BindIfVariableNotNull("y", y);
this.BindIfVariableNotNull("z", z);
}
internal TranslatedObject(OSCADObject obj) : base(obj)
{
}
public override string ToString()
{
string translation = this.bindings.Contains("vector") ? this.bindings.Get("vector").BoundVariable.Text : this.Vector.ToString();
string translateCommmand = String.Format("translate(v = {0})", translation);
var formatter = new SingleBlockFormatter(translateCommmand, this.obj.ToString());
return formatter.ToString();
}
public override OSCADObject Clone()
{
var bindableVec = this.Vector as BindableVector;
var clone = new TranslatedObject(this.obj.Clone())
{
Name = this.Name,
bindings = this.bindings.Clone(),
Vector = bindableVec != null ? bindableVec.Clone() : this.Vector.Clone()
};
return clone;
}
public override Vector3 Position()
{
return this.obj.Position() + this.Vector;
}
public override Bounds Bounds()
{
var oldBounds = obj.Bounds();
return new Bounds(oldBounds.BottomLeft + this.Vector, oldBounds.TopRight + this.Vector);
}
private Bindings.Bindings bindings = new Bindings.Bindings(new Dictionary<string, string>() {
{ "vector", "vector" }
});
public override void Bind(string property, Variable variable)
{
var bindableVec = this.Vector as BindableVector;
if (bindableVec != null && property == "x" || property == "y" || property == "z")
{
bindableVec.Bind(property, variable);
}
else
{
this.bindings.Add<TranslatedObject>(this, property, variable);
}
}
}
}

View File

@ -0,0 +1,167 @@
using OSCADSharp.DataBinding;
using OSCADSharp.Spatial;
using OSCADSharp.Utility;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace OSCADSharp
{
public abstract partial class OSCADObject
{
#region MirroredObject
/// <summary>
/// An object that's mirrored on a plane
/// </summary>
private class MirroredObject : SingleStatementObject
{
/// <summary>
/// The normal vector of a plane intersecting the origin of the object,
/// through which to mirror it.
/// </summary>
internal Vector3 Normal { get; set; } = new BindableVector();
/// <summary>
/// Creates an object that's mirrored on a plane
/// </summary>
/// <param name="obj">The object(s) to be mirrored</param>
/// <param name="normal">The normal vector of the plane on the object's origin to mirror upon</param>
internal MirroredObject(OSCADObject obj, Vector3 normal) : base(obj)
{
this.Normal = new BindableVector(normal);
}
internal MirroredObject(OSCADObject obj, Variable normal) : base(obj)
{
this.BindIfVariableNotNull("normal", normal);
}
internal MirroredObject(OSCADObject obj, Vector3 normal, Variable x, Variable y, Variable z) : base(obj)
{
this.Normal = new BindableVector(normal);
this.BindIfVariableNotNull("x", x);
this.BindIfVariableNotNull("y", y);
this.BindIfVariableNotNull("z", z);
}
public override string ToString()
{
string normal = this.bindings.Contains("normal") ? this.bindings.Get("normal").BoundVariable.Text : this.Normal.ToString();
string mirrorCommand = String.Format("mirror({0})", normal);
var formatter = new SingleBlockFormatter(mirrorCommand, this.obj.ToString());
return formatter.ToString();
}
public override OSCADObject Clone()
{
return new MirroredObject(this.obj.Clone(), this.Normal)
{
Name = this.Name,
bindings = this.bindings.Clone()
};
}
// TODO: This will yield incorrect positions if mirroring on multiple axes
// fix mirrored positions for multiple-axis mirroring
public override Vector3 Position()
{
if (this.isMoreThanOneAxis())
{
throw new NotSupportedException("Getting the position of an object that's been mirrored on more than one axis is not currently supported.");
}
var pos = obj.Position();
double x = this.Normal.X != 0 ? pos.X * -1 : pos.X;
double y = this.Normal.Y != 0 ? pos.Y * -1 : pos.Y;
double z = this.Normal.Z != 0 ? pos.Z * -1 : pos.Z;
return new Vector3(x, y, z);
}
private bool isMoreThanOneAxis()
{
return (this.Normal.X != 0 && (this.Normal.Y != 0 || this.Normal.Z != 0)) ||
(this.Normal.Y != 0 && (this.Normal.X != 0 || this.Normal.Z != 0));
}
// TODO: As with Position, will yield incorrect positions if mirroring on multiple axes
// fix mirrored positions for multiple-axis mirroring
public override Bounds Bounds()
{
if (this.isMoreThanOneAxis())
{
throw new NotSupportedException("Getting the position of an object that's been mirrored on more than one axis is not currently supported.");
}
var oldBounds = this.obj.Bounds();
var newBottomLeft = new Vector3(this.Normal.X != 0 ? oldBounds.BottomLeft.X * -1 : oldBounds.BottomLeft.X,
this.Normal.Y != 0 ? oldBounds.BottomLeft.Y * -1 : oldBounds.BottomLeft.Y,
this.Normal.Z != 0 ? oldBounds.BottomLeft.Z * -1 : oldBounds.BottomLeft.Z);
var newTopRight = new Vector3(this.Normal.X != 0 ? oldBounds.TopRight.X * -1 : oldBounds.TopRight.X,
this.Normal.Y != 0 ? oldBounds.TopRight.Y * -1 : oldBounds.TopRight.Y,
this.Normal.Z != 0 ? oldBounds.TopRight.Z * -1 : oldBounds.TopRight.Z);
return new Bounds(newBottomLeft, newTopRight);
}
private Bindings bindings = new Bindings(new Dictionary<string, string>() {
{"normal", "normal"}
});
public override void Bind(string property, Variable variable)
{
var bindableVec = this.Normal as BindableVector;
if (bindableVec != null && property == "x" || property == "y" || property == "z")
{
bindableVec.Bind(property, variable);
}
else
{
this.bindings.Add<MirroredObject>(this, property, variable);
}
}
}
#endregion
#region HulledObject
/// <summary>
/// Creates an object that's the convex hull of child objects
/// </summary>
private class HulledObject : MultiStatementObject
{
internal HulledObject(IEnumerable<OSCADObject> children) : base("hull()", children)
{
}
}
#endregion
#region MinkowskiedObject
/// <summary>
/// Creates an object that's the minkowski sum of child objects
/// </summary>
private class MinkowskiedObject : MultiStatementObject
{
internal MinkowskiedObject(IEnumerable<OSCADObject> children) : base("minkowski()", children)
{
}
public override Vector3 Position()
{
throw new NotSupportedException("Position is not supported on Minkowskied objects.");
}
public override Bounds Bounds()
{
throw new NotSupportedException("Bounds is not supported on Minkowskied objects.");
}
}
#endregion
}
}

View File

@ -0,0 +1,128 @@
using OSCADSharp.DataBinding;
using OSCADSharp.Spatial;
using OSCADSharp.Utility;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace OSCADSharp
{
public abstract partial class OSCADObject
{
#region MultiStatement
/// <summary>
/// A statement that has multiple child nodes, whose ToString output
/// is more or less just an aggregate of the children
/// </summary>
internal class MultiStatementObject : OSCADObject
{
private readonly string outerStatement;
internal MultiStatementObject(string outerStatement, IEnumerable<OSCADObject> children)
{
this.outerStatement = outerStatement;
this.m_children = children.ToList();
foreach (var child in children)
{
child.Parent = this;
}
}
public override string ToString()
{
StringBuilder sb = new StringBuilder();
foreach (var child in this.m_children)
{
sb.Append(child.ToString());
}
var formatter = new SingleBlockFormatter(this.outerStatement, sb.ToString());
return formatter.ToString();
}
public override OSCADObject Clone()
{
List<OSCADObject> childClones = new List<OSCADObject>();
foreach (var child in this.m_children)
{
childClones.Add(child.Clone());
}
return new MultiStatementObject(this.outerStatement, childClones)
{
Name = this.Name
};
}
public override Vector3 Position()
{
var positions = this.m_children.Select(child => child.Position());
return Vector3.Average(positions.ToArray());
}
public override Bounds Bounds()
{
var newBottomLeft = new Vector3();
var newTopRight = new Vector3();
foreach (var child in this.m_children)
{
var bounds = child.Bounds();
if (bounds.XMin < newBottomLeft.X)
{
newBottomLeft.X = bounds.XMin;
}
if (bounds.YMin < newBottomLeft.Y)
{
newBottomLeft.Y = bounds.YMin;
}
if (bounds.ZMin < newBottomLeft.Z)
{
newBottomLeft.Z = bounds.ZMin;
}
if (bounds.XMax > newTopRight.X)
{
newTopRight.X = bounds.XMax;
}
if (bounds.YMax > newTopRight.Y)
{
newTopRight.Y = bounds.YMax;
}
if (bounds.ZMax > newTopRight.Z)
{
newTopRight.Z = bounds.ZMax;
}
}
return new Bounds(newBottomLeft, newTopRight);
}
public override void Bind(string property, Variable variable)
{
throw new NotSupportedException("This object has no bindable properties.");
}
}
#endregion
#region SingleStatementObject
/// <summary>
/// A statement with just one nested child node
/// </summary>
internal abstract class SingleStatementObject : OSCADObject
{
protected OSCADObject obj { get; set; }
protected SingleStatementObject(OSCADObject obj)
{
this.obj = obj;
this.m_children.Add(obj);
obj.Parent = this;
}
}
#endregion
}
}

View File

@ -0,0 +1,453 @@
using OSCADSharp.DataBinding;
using OSCADSharp.Spatial;
using OSCADSharp.Utility;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace OSCADSharp
{
public abstract partial class OSCADObject
{
#region ColoredObject
/// <summary>
/// An OSCADObject that has color and/or opacity applied to it
/// </summary>
private class ColoredObject : SingleStatementObject
{
#region Attributes
internal string ColorName { get; set; } = "Yellow";
internal double Opacity { get; set; } = 1.0;
#endregion
/// <summary>
/// Creates a colorized object
/// </summary>
/// <param name="obj">The object(s) to which color will be applied</param>
/// <param name="color">The string-wise name of the color to be applied</param>
/// <param name="opacity">Opacity from 0.0 to 1.0 </param>
internal ColoredObject(OSCADObject obj, string color = "Yellow", double opacity = 1.0) : base(obj)
{
this.ColorName = color;
this.Opacity = opacity;
}
/// <summary>
/// Creates a colorized object with predefined bindings
/// </summary>
/// <param name="obj">The object(s) to which color will be applied</param>
/// <param name="colorName"></param>
/// <param name="opacity"></param>
internal ColoredObject(OSCADObject obj, Variable colorName, Variable opacity) : base(obj)
{
this.BindIfVariableNotNull("color", colorName);
this.BindIfVariableNotNull("opacity", opacity);
}
public override string ToString()
{
string colorName = this.bindings.Contains("color") ? this.bindings.Get("color").BoundVariable.Text :
"\"" + this.ColorName + "\"";
string opacity = this.bindings.Contains("opacity") ? this.bindings.Get("opacity").BoundVariable.Text
: this.Opacity.ToString();
string colorCommand = String.Format("color({0}, {1})", colorName, opacity);
var formatter = new SingleBlockFormatter(colorCommand, this.obj.ToString());
return formatter.ToString();
}
public override OSCADObject Clone()
{
return new ColoredObject(this.obj.Clone(), this.ColorName, this.Opacity)
{
Name = this.Name,
bindings = this.bindings.Clone()
};
}
public override Vector3 Position()
{
return this.obj.Position();
}
public override Bounds Bounds()
{
return this.obj.Bounds();
}
private Bindings bindings = new Bindings(new Dictionary<string, string>() {
{"color", "color" },
{"opacity", "opacity" }
});
public override void Bind(string property, Variable variable)
{
this.bindings.Add<ColoredObject>(this, property, variable);
}
}
#endregion
#region ResizedObject
/// <summary>
/// An OSCADObject that's been resized to a specified set of X/Y/Z dimensions
/// </summary>
private class ResizedObject : SingleStatementObject
{
/// <summary>
/// Size of the object in terms of X/Y/Z
/// </summary>
internal Vector3 Size { get; set; }
/// <summary>
/// Creates a resized object
/// </summary>
/// <param name="obj">The object(s) to be resized</param>
/// <param name="size">The size to resize to, in terms of x/y/z dimensions</param>
internal ResizedObject(OSCADObject obj, Vector3 size) : base(obj)
{
Size = new BindableVector(size);
}
internal ResizedObject(OSCADObject obj, Variable size) : base(obj)
{
this.BindIfVariableNotNull("size", size);
}
internal ResizedObject(OSCADObject obj, Vector3 size, Variable x, Variable y, Variable z) : base(obj)
{
this.Size = new BindableVector(size);
this.BindIfVariableNotNull("x", x);
this.BindIfVariableNotNull("y", y);
this.BindIfVariableNotNull("z", z);
}
internal ResizedObject(OSCADObject obj) : base(obj)
{
}
public override string ToString()
{
string size = this.bindings.Contains("size") ? this.bindings.Get("size").BoundVariable.Text : this.Size.ToString();
string resizeCommand = String.Format("resize({0})", size);
var formatter = new SingleBlockFormatter(resizeCommand, this.obj.ToString());
return formatter.ToString();
}
public override OSCADObject Clone()
{
var bndSize = this.Size as BindableVector;
return new ResizedObject(this.obj.Clone())
{
Name = this.Name,
bindings = this.bindings.Clone(),
Size = bndSize != null ? bndSize.Clone() : this.Size.Clone()
};
}
public override Vector3 Position()
{
var bounds = this.Bounds();
return Vector3.Average(bounds.BottomLeft, bounds.TopRight);
}
public override Bounds Bounds()
{
var oldBounds = obj.Bounds();
double xScaleFactor = this.Size.X > 0 ? this.Size.X / Math.Abs(oldBounds.XMax - oldBounds.XMin) : 1;
double yScaleFactor = this.Size.Y > 0 ? this.Size.Y / Math.Abs(oldBounds.YMax - oldBounds.YMin) : 1;
double zScaleFactor = this.Size.Z > 0 ? this.Size.Z / Math.Abs(oldBounds.ZMax - oldBounds.ZMin) : 1;
Vector3 scaleMultiplier = new Vector3(xScaleFactor, yScaleFactor, zScaleFactor);
return new Bounds(oldBounds.BottomLeft * scaleMultiplier, oldBounds.TopRight * scaleMultiplier);
}
private Bindings bindings = new Bindings(new Dictionary<string, string>() {
{ "size", "size" }
});
public override void Bind(string property, Variable variable)
{
var bindableVec = this.Size as BindableVector;
if (bindableVec != null && property == "x" || property == "y" || property == "z")
{
bindableVec.Bind(property, variable);
}
else
{
this.bindings.Add<ResizedObject>(this, property, variable);
}
}
}
#endregion
#region RotatedObject
/// <summary>
/// An OSCADObject with rotation applied
/// </summary>
private class RotatedObject : SingleStatementObject
{
/// <summary>
/// The angle to rotate, in terms of X/Y/Z euler angles
/// </summary>
internal Vector3 Angle { get; set; } = new BindableVector();
/// <summary>
/// Creates an object with rotation applied
/// </summary>
/// <param name="obj">The object being rotated</param>
/// <param name="angle">The angle to rotate</param>
internal RotatedObject(OSCADObject obj, Vector3 angle) : base(obj)
{
this.Angle = new BindableVector(angle);
}
internal RotatedObject(OSCADObject obj, Variable normal) : base(obj)
{
this.BindIfVariableNotNull("angle", normal);
}
internal RotatedObject(OSCADObject obj, Vector3 angle, Variable x, Variable y, Variable z) : base(obj)
{
this.Angle = new BindableVector(angle);
this.BindIfVariableNotNull("x", x);
this.BindIfVariableNotNull("y", y);
this.BindIfVariableNotNull("z", z);
}
public override string ToString()
{
string angle = this.bindings.Contains("angle") ? this.bindings.Get("angle").BoundVariable.Text : this.Angle.ToString();
string rotateCommand = String.Format("rotate({0})", angle.ToString());
var formatter = new SingleBlockFormatter(rotateCommand, this.obj.ToString());
return formatter.ToString();
}
public override OSCADObject Clone()
{
return new RotatedObject(this.obj.Clone(), this.Angle)
{
Name = this.Name,
bindings = this.bindings.Clone()
};
}
public override Vector3 Position()
{
return Matrix.GetRotatedPoint(this.obj.Position(), this.Angle.X, this.Angle.Y, this.Angle.Z);
}
public override Bounds Bounds()
{
var oldBounds = obj.Bounds();
return new Bounds(Matrix.GetRotatedPoint(oldBounds.BottomLeft, this.Angle.X, this.Angle.Y, this.Angle.Z),
Matrix.GetRotatedPoint(oldBounds.TopRight, this.Angle.X, this.Angle.Y, this.Angle.Z));
}
private Bindings bindings = new Bindings(new Dictionary<string, string>() {
{ "angle", "angle" }
});
public override void Bind(string property, Variable variable)
{
var bindableVec = this.Angle as BindableVector;
if (bindableVec != null && property == "x" || property == "y" || property == "z")
{
bindableVec.Bind(property, variable);
}
else
{
this.bindings.Add<RotatedObject>(this, property, variable);
}
}
}
#endregion
#region ScaledObject
/// <summary>
/// An object that's been rescaled
/// </summary>
private class ScaledObject : SingleStatementObject
{
/// <summary>
/// The scale factor to be applied
/// </summary>
internal Vector3 ScaleFactor { get; set; } = new BindableVector(1, 1, 1);
/// <summary>
/// Creates a scaled object
/// </summary>
/// <param name="obj">Object(s) to be scaled</param>
/// <param name="scale">Scale factor in x/y/z components</param>
internal ScaledObject(OSCADObject obj, Vector3 scale) : base(obj)
{
this.ScaleFactor = new BindableVector(scale);
}
internal ScaledObject(OSCADObject obj, Variable normal) : base(obj)
{
this.BindIfVariableNotNull("scalefactor", normal);
}
internal ScaledObject(OSCADObject obj, Vector3 scale, Variable x, Variable y, Variable z) : base(obj)
{
this.ScaleFactor = new BindableVector(scale);
this.BindIfVariableNotNull("x", x);
this.BindIfVariableNotNull("y", y);
this.BindIfVariableNotNull("z", z);
}
public override string ToString()
{
string scale = this.bindings.Contains("scalefactor") ? this.bindings.Get("scalefactor").BoundVariable.Text : this.ScaleFactor.ToString();
string scaleCommand = String.Format("scale(v = {0})", scale);
var formatter = new SingleBlockFormatter(scaleCommand, this.obj.ToString());
return formatter.ToString();
}
public override OSCADObject Clone()
{
return new ScaledObject(this.obj.Clone(), this.ScaleFactor)
{
Name = this.Name,
bindings = this.bindings.Clone()
};
}
public override Vector3 Position()
{
return obj.Position() * this.ScaleFactor;
}
public override Bounds Bounds()
{
var oldBounds = obj.Bounds();
return new Bounds(oldBounds.BottomLeft * this.ScaleFactor, oldBounds.TopRight * this.ScaleFactor);
}
private Bindings bindings = new Bindings(new Dictionary<string, string>() {
{ "scalefactor", "scalefactor" }
});
public override void Bind(string property, Variable variable)
{
var bindableVec = this.ScaleFactor as BindableVector;
property = property == "scale" ? "scalefactor" : property;
if (bindableVec != null && property == "x" || property == "y" || property == "z")
{
bindableVec.Bind(property, variable);
}
else
{
this.bindings.Add<ScaledObject>(this, property, variable);
}
}
}
#endregion
#region TranslatedObject
/// <summary>
/// An OSCADObject or objects that have been moved along the specified vector
/// </summary>
private class TranslatedObject : SingleStatementObject
{
internal Vector3 Vector { get; set; }
/// <summary>
/// Creates a translated object
/// </summary>
/// <param name="obj">Object(s) to translate</param>
/// <param name="vector">Amount to translate by</param>
internal TranslatedObject(OSCADObject obj, Vector3 vector) : base(obj)
{
this.Vector = new BindableVector(vector);
}
internal TranslatedObject(OSCADObject obj, Variable normal) : base(obj)
{
this.BindIfVariableNotNull("vector", normal);
}
internal TranslatedObject(OSCADObject obj, Vector3 vector, Variable x, Variable y, Variable z) : base(obj)
{
this.Vector = new BindableVector(vector);
this.BindIfVariableNotNull("x", x);
this.BindIfVariableNotNull("y", y);
this.BindIfVariableNotNull("z", z);
}
internal TranslatedObject(OSCADObject obj) : base(obj)
{
}
public override string ToString()
{
string translation = this.bindings.Contains("vector") ? this.bindings.Get("vector").BoundVariable.Text : this.Vector.ToString();
string translateCommmand = String.Format("translate(v = {0})", translation);
var formatter = new SingleBlockFormatter(translateCommmand, this.obj.ToString());
return formatter.ToString();
}
public override OSCADObject Clone()
{
var bindableVec = this.Vector as BindableVector;
var clone = new TranslatedObject(this.obj.Clone())
{
Name = this.Name,
bindings = this.bindings.Clone(),
Vector = bindableVec != null ? bindableVec.Clone() : this.Vector.Clone()
};
return clone;
}
public override Vector3 Position()
{
return this.obj.Position() + this.Vector;
}
public override Bounds Bounds()
{
var oldBounds = obj.Bounds();
return new Bounds(oldBounds.BottomLeft + this.Vector, oldBounds.TopRight + this.Vector);
}
private Bindings bindings = new Bindings(new Dictionary<string, string>() {
{ "vector", "vector" }
});
public override void Bind(string property, Variable variable)
{
var bindableVec = this.Vector as BindableVector;
if (bindableVec != null && property == "x" || property == "y" || property == "z")
{
bindableVec.Bind(property, variable);
}
else
{
this.bindings.Add<TranslatedObject>(this, property, variable);
}
}
}
#endregion
}
}

View File

@ -0,0 +1,80 @@
using OSCADSharp.Spatial;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace OSCADSharp
{
public abstract partial class OSCADObject
{
#region Difference
/// <summary>
/// Subtracts the 2nd (and all further) child nodes from the first one (logical and not).
/// </summary>
private class DifferencedObject : MultiStatementObject
{
/// <summary>
/// Creates a subtraction of child nodes
/// </summary>
/// <param name="children"></param>
internal DifferencedObject(IEnumerable<OSCADObject> children) : base("difference()", children)
{
}
public override Vector3 Position()
{
return m_children[0].Position();
}
public override Bounds Bounds()
{
return m_children[0].Bounds();
}
}
#endregion
#region Intersection
/// <summary>
/// Creates the intersection of all child nodes
/// </summary>
private class IntersectedObject : MultiStatementObject
{
/// <summary>
/// Creates the intersection of all child nodes
/// </summary>
/// <param name="children"></param>
internal IntersectedObject(IEnumerable<OSCADObject> children) : base("intersection()", children)
{
}
public override Vector3 Position()
{
throw new NotSupportedException("Position is not supported on Intersected objects.");
}
public override Bounds Bounds()
{
throw new NotSupportedException("Bounds is not supported on Intersected objects.");
}
}
#endregion
#region Union
/// <summary>
/// A union of child nodes. This is the sum of all children (logical or).
/// </summary>
private class UnionedObject : MultiStatementObject
{
/// <summary>
/// Create a union that is the combination of all children
/// </summary>
/// <param name="children">OSCADObjects to combine</param>
internal UnionedObject(IEnumerable<OSCADObject> children) : base("union()", children)
{
}
}
#endregion
}
}

View File

@ -1,9 +1,7 @@
using OSCADSharp.Bindings;
using OSCADSharp.Booleans;
using OSCADSharp.Files;
using OSCADSharp.Scripting;
using OSCADSharp.DataBinding;
using OSCADSharp.IO;
using OSCADSharp.Spatial;
using OSCADSharp.Transforms;
using OSCADSharp.Utility;
using System;
using System.Collections.Generic;
using System.IO;
@ -11,22 +9,24 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
[assembly: CLSCompliant(true)]
namespace OSCADSharp
{
/// <summary>
/// Represents any Object or collection of objects that becomes am
/// an OpenSCAD script when converted to a string.
/// </summary>
public abstract class OSCADObject : IBindable
public abstract partial class OSCADObject : IBindable
{
#region Attributes
private uint id = Ids.Get();
private readonly int id = Ids.Get();
/// <summary>
/// The unique Id of the object
/// these values auto-increment
/// </summary>
public uint Id { get { return this.id; } }
public int Id { get { return this.id; } }
/// <summary>
/// Name of this OSCADObject
@ -685,7 +685,7 @@ namespace OSCADSharp
/// <returns></returns>
public OSCADObject Union(params OSCADObject[] objects)
{
return doBlockStatement("Union", objects, (children) => { return new Union(children); });
return doBlockStatement("Union", objects, (children) => { return new UnionedObject(children); });
}
/// <summary>
@ -696,7 +696,7 @@ namespace OSCADSharp
/// <returns></returns>
public OSCADObject Difference(params OSCADObject[] objects)
{
return doBlockStatement("Difference", objects, (children) => { return new Difference(children); });
return doBlockStatement("Difference", objects, (children) => { return new DifferencedObject(children); });
}
/// <summary>
@ -708,7 +708,7 @@ namespace OSCADSharp
/// <returns></returns>
public OSCADObject Intersection(params OSCADObject[] objects)
{
return doBlockStatement("Intersection", objects, (children) => { return new Intersection(children); });
return doBlockStatement("Intersection", objects, (children) => { return new IntersectedObject(children); });
}
private OSCADObject doBlockStatement(string name, OSCADObject[] objects, Func<IEnumerable<OSCADObject>, OSCADObject> factory)
@ -781,7 +781,7 @@ namespace OSCADSharp
/// <summary>
/// Internal collection of children for this object
/// </summary>
protected List<OSCADObject> children = new List<OSCADObject>();
protected List<OSCADObject> m_children { get; set; } = new List<OSCADObject>();
/// <summary>
/// Returns all chidren of this OSCADObject
@ -792,12 +792,12 @@ namespace OSCADSharp
{
if(recursive == false)
{
return new List<OSCADObject>(this.children);
return new List<OSCADObject>(this.m_children);
}
// Initial children are reversed here because for objects with multiple children (such as boolean operations)
// the natural collection order would yield opposite the expected order in a stack (first child would be the last popped)
Stack<OSCADObject> toTraverse = new Stack<OSCADObject>(this.children.Reverse<OSCADObject>());
Stack<OSCADObject> toTraverse = new Stack<OSCADObject>(this.m_children.Reverse<OSCADObject>());
List<OSCADObject> allChildren = new List<OSCADObject>();
OSCADObject child = null;
@ -806,7 +806,7 @@ namespace OSCADSharp
child = toTraverse.Pop();
allChildren.Add(child);
foreach (var subChild in child.children)
foreach (var subChild in child.m_children)
{
toTraverse.Push(subChild);
}
@ -842,7 +842,7 @@ namespace OSCADSharp
Dependencies.FileWriter.WriteAllLines(path, new string[]
{
Settings.OSCADSharpHeader,
OutputSettings.OSCADSharpHeader,
Variables.Global.ToString(),
this.ToString()
});
@ -868,19 +868,19 @@ namespace OSCADSharp
/// <returns></returns>
public static OSCADObject operator +(OSCADObject left, OSCADObject right)
{
if(left.GetType() == typeof(Union))
if(left.GetType() == typeof(UnionedObject))
{
left.children.Add(right);
left.m_children.Add(right);
return left;
}
else if(right.GetType() == typeof(Union))
else if(right.GetType() == typeof(UnionedObject))
{
right.children.Add(left);
right.m_children.Add(left);
return right;
}
else
{
return new Union(new OSCADObject[] {left, right });
return new UnionedObject(new OSCADObject[] {left, right });
}
}
@ -892,19 +892,19 @@ namespace OSCADSharp
/// <returns></returns>
public static OSCADObject operator -(OSCADObject left, OSCADObject right)
{
if (left.GetType() == typeof(Difference))
if (left.GetType() == typeof(DifferencedObject))
{
left.children.Add(right);
left.m_children.Add(right);
return left;
}
else if (right.GetType() == typeof(Difference))
else if (right.GetType() == typeof(DifferencedObject))
{
right.children.Add(left);
right.m_children.Add(left);
return right;
}
else
{
return new Difference(new OSCADObject[] {left, right });
return new DifferencedObject(new OSCADObject[] {left, right });
}
}
#endregion

View File

@ -42,53 +42,38 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Internal\Bindings\BindableBoolean.cs" />
<Compile Include="Internal\Scripting\VariableCalculator.cs" />
<Compile Include="Internal\Scripting\CompoundVariable.cs" />
<Compile Include="Public\Settings\Dependencies.cs" />
<Compile Include="Internal\Files\DefaultFileInvoker.cs" />
<Compile Include="Internal\Files\DefaultFileWriter.cs" />
<Compile Include="Public\Files\IFileInvoker.cs" />
<Compile Include="Public\Files\IFileWriter.cs" />
<Compile Include="Internal\Settings\Ids.cs" />
<Compile Include="Internal\Settings\OpenSCADPathFinder.cs" />
<Compile Include="Internal\Bindings\Binding.cs" />
<Compile Include="Internal\Bindings\Bindings.cs" />
<Compile Include="Internal\Bindings\IBindable.cs" />
<Compile Include="Internal\Scripting\SingleStatementObject.cs" />
<Compile Include="Internal\Scripting\StatementBuilder.cs" />
<Compile Include="Public\Scripting\Variable.cs" />
<Compile Include="Public\Settings\Settings.cs" />
<Compile Include="Public\Inches.cs" />
<Compile Include="Internal\Bindings\BindableVector.cs" />
<Compile Include="Public\Spatial\Bounds.cs" />
<Compile Include="Internal\Spatial\Matrix.cs" />
<Compile Include="Internal\Transforms\HulledObject.cs" />
<Compile Include="Internal\Transforms\LinearExtrudedObject.cs" />
<Compile Include="Internal\Scripting\SingleBlockFormatter.cs" />
<Compile Include="Internal\Scripting\MultiStatementObject.cs" />
<Compile Include="Internal\Booleans\Difference.cs" />
<Compile Include="Internal\Booleans\Intersection.cs" />
<Compile Include="Internal\Booleans\Union.cs" />
<Compile Include="Public\OSCADObject.cs" />
<Compile Include="DataBinding\BindableBoolean.cs" />
<Compile Include="OSCADObject.AbstractTransforms.cs" />
<Compile Include="OSCADObject.BaseTransform.cs" />
<Compile Include="OSCADObject.BasicTransforms.cs" />
<Compile Include="OSCADObject.Booleans.cs" />
<Compile Include="Utility\Dependencies.cs" />
<Compile Include="IO\DefaultFileInvoker.cs" />
<Compile Include="IO\DefaultFileWriter.cs" />
<Compile Include="IO\IFileInvoker.cs" />
<Compile Include="IO\IFileWriter.cs" />
<Compile Include="Utility\Ids.cs" />
<Compile Include="DataBinding\Binding.cs" />
<Compile Include="DataBinding\Bindings.cs" />
<Compile Include="DataBinding\IBindable.cs" />
<Compile Include="Utility\StatementBuilder.cs" />
<Compile Include="DataBinding\Variable.cs" />
<Compile Include="IO\OutputSettings.cs" />
<Compile Include="Utility\Inches.cs" />
<Compile Include="DataBinding\BindableVector.cs" />
<Compile Include="Spatial\Bounds.cs" />
<Compile Include="Spatial\Matrix.cs" />
<Compile Include="Utility\SingleBlockFormatter.cs" />
<Compile Include="OSCADObject.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Public\Solids\Cube.cs" />
<Compile Include="Public\Solids\Cylinder.cs" />
<Compile Include="Public\Solids\Sphere.cs" />
<Compile Include="Public\Solids\Text3D.cs" />
<Compile Include="Internal\Transforms\ColoredObject.cs" />
<Compile Include="Internal\Transforms\MinkowskiedObject.cs" />
<Compile Include="Internal\Transforms\MirroredObject.cs" />
<Compile Include="Internal\Transforms\ResizedObject.cs" />
<Compile Include="Internal\Transforms\RotatedObject.cs" />
<Compile Include="Internal\Transforms\ScaledObject.cs" />
<Compile Include="Internal\Transforms\TranslatedObject.cs" />
<Compile Include="Public\Spatial\Vector3.cs" />
<Compile Include="Public\Scripting\Variables.cs" />
</ItemGroup>
<ItemGroup>
<None Include="OSCADSharp.nuspec" />
<Compile Include="Solids\Cube.cs" />
<Compile Include="Solids\Cylinder.cs" />
<Compile Include="Solids\Sphere.cs" />
<Compile Include="Solids\Text3D.cs" />
<Compile Include="Spatial\Vector3.cs" />
<Compile Include="DataBinding\Variables.cs" />
</ItemGroup>
<ItemGroup />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.

View File

@ -1,25 +0,0 @@
using OSCADSharp.Files;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace OSCADSharp
{
/// <summary>
/// Contains definitions for external APIs used by OSCADSharp
/// </summary>
public static class Dependencies
{
/// <summary>
/// Used to write scripts to file
/// </summary>
public static IFileWriter FileWriter = new DefaultFileWriter();
/// <summary>
/// Factory method to provide the class used to perform actions on output scripts
/// </summary>
public static Func<string, IFileInvoker> FileInvokerFactory = (path) => { return new DefaultFileInvoker(path); };
}
}

View File

@ -1,29 +0,0 @@
using OSCADSharp.Files;
using OSCADSharp.Scripting;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace OSCADSharp
{
/// <summary>
/// Settings for OpenSCAD scripts
/// </summary>
public static class Settings
{
/// <summary>
/// Code-gen header
/// </summary>
public static readonly string OSCADSharpHeader = String.Format("/*Code Generated using OSCADSharp on {0}. {1}{2}For more information, please visit https://github.com/Exolun/OSCADSharp */{3}",
DateTime.Now.ToString(), Environment.NewLine, Environment.NewLine, Environment.NewLine);
/// <summary>
/// Path to the OpenSCAD executable for file invocation
/// (Default value is set the default install directory on Windows)
/// </summary>
public static string OpenSCADPath = new OpenSCADPathFinder().GetPath();
}
}

View File

@ -1,13 +1,12 @@
using System;
using OSCADSharp.DataBinding;
using OSCADSharp.Spatial;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using OSCADSharp.Spatial;
using OSCADSharp.Bindings;
using OSCADSharp.Scripting;
namespace OSCADSharp
namespace OSCADSharp.Solids
{
/// <summary>
/// A Cube geometry
@ -103,8 +102,8 @@ namespace OSCADSharp
public override string ToString()
{
return String.Format("cube(size = {0}, center = {1}); {2}",
this.Size.ToString(),
this.centerBinding.IsBound ? this.centerBinding.ToString() : this.center.ToString().ToLower(),
this.Size.ToString(),
this.centerBinding.IsBound ? this.centerBinding.ToString() : this.center.ToString().ToLower(),
Environment.NewLine); ;
}
@ -137,7 +136,7 @@ namespace OSCADSharp
public override Vector3 Position()
{
Vector3 position;
if(this.Center == false)
if (this.Center == false)
{
position = new Vector3(this.Size.X / 2, this.Size.Y / 2, this.Size.Z / 2);
}
@ -155,18 +154,18 @@ namespace OSCADSharp
/// <returns></returns>
public override Bounds Bounds()
{
if(Center == false)
if (Center == false)
{
return new Bounds(new Vector3(), new Vector3(this.Size.X, this.Size.Y, this.Size.Z));
}
else
{
return new Bounds(new Vector3(-this.Size.X / 2, -this.Size.Y / 2, -this.Size.Z / 2),
return new Bounds(new Vector3(-this.Size.X / 2, -this.Size.Y / 2, -this.Size.Z / 2),
new Vector3(this.Size.X / 2, this.Size.Y / 2, this.Size.Z / 2));
}
}
private Bindings.Bindings bindings = new Bindings.Bindings();
private Bindings bindings = new Bindings();
private static readonly Dictionary<string, string> sizeSynonyms = new Dictionary<string, string>()
{
{"size.x", "x" },
@ -195,7 +194,7 @@ namespace OSCADSharp
vec.Bind(property, variable);
}
else if(property.ToLower() == "center")
else if (property.ToLower() == "center")
{
this.centerBinding.Bind(property, variable);
this.center = Convert.ToBoolean(variable.Value);

View File

@ -1,13 +1,13 @@
using System;
using OSCADSharp.DataBinding;
using OSCADSharp.Spatial;
using OSCADSharp.Utility;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using OSCADSharp.Spatial;
using OSCADSharp.Scripting;
using OSCADSharp.Bindings;
namespace OSCADSharp
namespace OSCADSharp.Solids
{
/// <summary>
/// A Cylinder geometry
@ -261,7 +261,7 @@ namespace OSCADSharp
}
}
private Bindings.Bindings bindings = new Bindings.Bindings(new Dictionary<string, string>()
private Bindings bindings = new Bindings(new Dictionary<string, string>()
{
{"radius", "r" },
{"radius1", "r1" },

View File

@ -3,13 +3,13 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using OSCADSharp.Spatial;
using OSCADSharp.Scripting;
using System.Collections.Concurrent;
using System.Reflection;
using OSCADSharp.Bindings;
using OSCADSharp.Spatial;
using OSCADSharp.DataBinding;
using OSCADSharp.Utility;
namespace OSCADSharp
namespace OSCADSharp.Solids
{
/// <summary>
/// A Sphere geometry
@ -25,11 +25,12 @@ namespace OSCADSharp
/// <summary>
/// This is the diameter of the sphere
/// </summary>
public double Diameter {
public double Diameter
{
get { return this.Radius * 2; }
set { this.Radius = value / 2; }
}
/// <summary>
/// Minimum angle (in degrees) of each cylinder fragment.
/// ($fa in OpenSCAD)
@ -143,11 +144,11 @@ namespace OSCADSharp
/// <returns></returns>
public override Bounds Bounds()
{
return new Bounds(new Vector3(-this.Radius, -this.Radius, -this.Radius),
return new Bounds(new Vector3(-this.Radius, -this.Radius, -this.Radius),
new Vector3(this.Radius, this.Radius, this.Radius));
}
private Bindings.Bindings bindings = new Bindings.Bindings(new Dictionary<string, string>()
private Bindings bindings = new Bindings(new Dictionary<string, string>()
{
{ "radius", "r" },
{ "minimumangle", "$fa" },

View File

@ -1,13 +1,13 @@
using OSCADSharp.Scripting;
using OSCADSharp.DataBinding;
using OSCADSharp.Spatial;
using OSCADSharp.Utility;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using OSCADSharp.Spatial;
using OSCADSharp.Bindings;
namespace OSCADSharp
namespace OSCADSharp.Solids
{
/// <summary>
/// Create text using fonts installed on the local system or provided as separate font file.
@ -170,7 +170,7 @@ namespace OSCADSharp
throw new NotSupportedException("Bounds are not supported for objects using Text3D");
}
private Bindings.Bindings bindings = new Bindings.Bindings(new Dictionary<string, string>()
private Bindings bindings = new Bindings(new Dictionary<string, string>()
{
{ "text", "text" },
{ "size", "size" },

View File

@ -1,10 +1,11 @@
using System;
using OSCADSharp.Spatial;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace OSCADSharp
namespace OSCADSharp.Spatial
{
/// <summary>
/// A set of boundaries

View File

@ -1,4 +1,5 @@
using System;
using OSCADSharp.Spatial;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
@ -13,7 +14,7 @@ namespace OSCADSharp.Spatial
internal class Matrix
{
#region Fields/Properties
private double[] values;
private readonly double[] values;
internal int ColumnCount { get; private set; }
internal int RowCount { get; private set; }
@ -78,13 +79,14 @@ namespace OSCADSharp.Spatial
return piOver180 * degrees;
}
private static readonly Matrix identity = new Matrix(new double[] {
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1
}, 4, 4);
internal static Matrix Identity { get { return identity; } }
internal static Matrix Identity()
{
return new Matrix(new double[] {
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1}, 4, 4); ;
}
/// <summary>
/// Gets a transformation matrix for performing rotations on the X-Axis
@ -95,7 +97,7 @@ namespace OSCADSharp.Spatial
internal static Matrix XRotation(double angle)
{
if (angle == 0)
return Identity;
return Identity();
double radAngle = toRadians(angle);
double[] rotationArr = new double[] {
@ -117,7 +119,7 @@ namespace OSCADSharp.Spatial
internal static Matrix YRotation(double angle)
{
if (angle == 0)
return Identity;
return Identity();
double radAngle = toRadians(angle);
double[] rotationArr = new double[] {
@ -139,7 +141,7 @@ namespace OSCADSharp.Spatial
internal static Matrix ZRotation(double angle)
{
if (angle == 0)
return Identity;
return Identity();
double radAngle = toRadians(angle);
double[] rotationArr = new double[] {

View File

@ -1,11 +1,10 @@
using OSCADSharp.Spatial;
using System;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace OSCADSharp
namespace OSCADSharp.Spatial
{
/// <summary>
/// A Three-Dimensional vector

View File

@ -0,0 +1,45 @@
using OSCADSharp.IO;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace OSCADSharp.Utility
{
/// <summary>
/// Contains definitions for external APIs used by OSCADSharp
/// </summary>
public static class Dependencies
{
/// <summary>
/// Used to write scripts to file
/// </summary>
public static IFileWriter FileWriter { get; private set; } = new DefaultFileWriter();
/// <summary>
/// Sets the filewriter for OSCADSharp to use
/// </summary>
/// <param name="writer"></param>
public static void SetFileWriter(IFileWriter writer)
{
FileWriter = writer;
}
/// <summary>
/// Factory method to provide the class used to perform actions on output scripts
/// </summary>
public static Func<string, IFileInvoker> FileInvokerFactory { get; private set; } = (path) => { return new DefaultFileInvoker(path); };
/// <summary>
/// Sets the factory method OSCADSharp will use to get
/// file invoker objects
/// </summary>
/// <param name="invokerFactoryMethod"></param>
public static void SetFileInvokerFactory(Func<string, IFileInvoker> invokerFactoryMethod)
{
FileInvokerFactory = invokerFactoryMethod;
}
}
}

View File

@ -4,21 +4,21 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace OSCADSharp
namespace OSCADSharp.Utility
{
/// <summary>
/// Responsible for creating identifiers for objects
/// </summary>
internal static class Ids
{
private static uint globalId = 0;
private static object idLockObject = new object();
private static int globalId = 0;
private readonly static object idLockObject = new object();
/// <summary>
/// Gets a unique auto-incrementing integer id
/// </summary>
/// <returns></returns>
internal static uint Get()
internal static int Get()
{
lock (idLockObject)
{

View File

@ -4,37 +4,37 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace OSCADSharp
namespace OSCADSharp.Utility
{
/// <summary>
/// Constants and conversions for units for us imperial-minded folks.
/// </summary>
public class Inches
public static class Inches
{
/// <summary>
/// One imperial inch
/// </summary>
public const double One = 25.4;
public static double One { get; private set; } = 25.4;
/// <summary>
/// Half of an imperial inch
/// </summary>
public const double Half = One / 2;
public static double Half { get; private set; } = One / 2;
/// <summary>
/// Quarter of an imperial inch
/// </summary>
public const double Quarter = Half / 2;
public static double Quarter { get; private set; } = Half / 2;
/// <summary>
/// Eigth of an imperial inch
/// </summary>
public const double Eigth = Quarter / 2;
public static double Eigth { get; private set; } = Quarter / 2;
/// <summary>
/// Sixteenth of an imperial inch
/// </summary>
public const double Sixteenth = Eigth / 2;
public static double Sixteenth { get; private set; } = Eigth / 2;
/// <summary>
/// Converts inches to millimeters

View File

@ -5,7 +5,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace OSCADSharp.Scripting
namespace OSCADSharp.Utility
{
/// <summary>
/// A class that creates blocks of curly-braced script with the
@ -13,9 +13,9 @@ namespace OSCADSharp.Scripting
/// </summary>
internal class SingleBlockFormatter
{
private string outerCode;
private string innerCode;
private string indentationAmount = " ";
private readonly string outerCode;
private readonly string innerCode;
private readonly string indentationAmount = " ";
internal SingleBlockFormatter(string outerCode, string innerCode)
{

View File

@ -1,10 +1,11 @@
using System;
using OSCADSharp.DataBinding;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace OSCADSharp.Scripting
namespace OSCADSharp.Utility
{
/// <summary>
/// Extends the capabilities of StringBuilder with domain-specific behavior
@ -13,25 +14,20 @@ namespace OSCADSharp.Scripting
internal class StatementBuilder
{
private StringBuilder SB { get; set; } = new StringBuilder();
private Bindings.Bindings bindings = null;
internal StatementBuilder()
{
}
internal StatementBuilder(Bindings.Bindings bindings)
private readonly Bindings bindings = null;
internal StatementBuilder(Bindings bindings)
{
this.bindings = bindings;
}
/// <summary>
/// Special append method for conditionally adding value-pairs
/// </summary>
/// <param name="name">The Name of the value-pair</param>
/// <param name="value">The value - if null this method does nothing</param>
/// <param name="prefixWithComma">(optional) Flag indicating whether a comma should be added before the value-pair</param>
public void AppendValuePairIfExists(string name, object value, bool prefixWithComma = false)
internal void AppendValuePairIfExists(string name, object value, bool prefixWithComma = false)
{
bool useBinding = this.shouldUseBinding(name);
@ -45,7 +41,7 @@ namespace OSCADSharp.Scripting
SB.Append(name);
SB.Append(" = ");
if(useBinding)
if (useBinding)
{
SB.Append(this.bindings.Get(name).BoundVariable.Text);
}
@ -65,20 +61,11 @@ namespace OSCADSharp.Scripting
/// Pass-through for StringBuilder.Append
/// </summary>
/// <param name="text"></param>
public void Append(string text)
internal void Append(string text)
{
SB.Append(text);
}
/// <summary>
/// Pass-through for StringBuilder.AppendLine
/// </summary>
/// <param name="text"></param>
public void AppendLine(string text)
{
SB.AppendLine(text);
}
/// <summary>
/// Gets this builder's full string
/// </summary>