diff --git a/GHva3c/GHva3c/va3c_Scene.cs b/GHva3c/GHva3c/ComponentArchive/va3c_Scene_ARCHIVE_20141104.cs
similarity index 93%
rename from GHva3c/GHva3c/va3c_Scene.cs
rename to GHva3c/GHva3c/ComponentArchive/va3c_Scene_ARCHIVE_20141104.cs
index 7e41b67..3bbdcae 100644
--- a/GHva3c/GHva3c/va3c_Scene.cs
+++ b/GHva3c/GHva3c/ComponentArchive/va3c_Scene_ARCHIVE_20141104.cs
@@ -17,12 +17,20 @@
namespace GHva3c
{
- public class va3c_Scene : GH_Component
- {
+ public class va3c_Scene_ARCHIVE_20141104 : GH_Component
+ {
+ public override GH_Exposure Exposure
+ {
+ get
+ {
+ return GH_Exposure.hidden;
+ }
+ }
+
///
/// Initializes a new instance of the va3c_Scene class.
///
- public va3c_Scene()
+ public va3c_Scene_ARCHIVE_20141104()
: base("va3c_Scene", "va3c_Scene","va3c_Scene","va3c", "va3c")
{
}
@@ -260,31 +268,4 @@ private bool isJSONfile(string fileExtension)
}
}
}
-
- public class va3cGeometryCatcher
- {
- public string uuid;
- public string type;
- public object data;
- }
-
- public class va3cMaterialCatcher
- {
- public string uuid;
- public string type;
- public string color;
- public string ambient;
- public string emissive;
- public string specular;
- public double shininess;
- public double opacity;
- public bool transparent;
- public bool wireframe;
- public int side;
- }
-
- public class va3cAttributesCatcher
- {
- public object userData;
- }
}
\ No newline at end of file
diff --git a/GHva3c/GHva3c/GHva3c.csproj b/GHva3c/GHva3c/GHva3c.csproj
index 25831d1..116fad9 100644
--- a/GHva3c/GHva3c/GHva3c.csproj
+++ b/GHva3c/GHva3c/GHva3c.csproj
@@ -76,13 +76,16 @@
Resources.resx
+
-
+
Code
+
+
diff --git a/GHva3c/GHva3c/_Utilities.cs b/GHva3c/GHva3c/_Utilities.cs
new file mode 100644
index 0000000..24565b4
--- /dev/null
+++ b/GHva3c/GHva3c/_Utilities.cs
@@ -0,0 +1,78 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Grasshopper.Kernel;
+using Grasshopper.Kernel.Types;
+using Rhino.Geometry;
+
+namespace GHva3c
+{
+ ///
+ /// Contains utility functions to be called from GH component classes
+ ///
+ public class _Utilities
+ {
+ ///
+ /// Returns a string representation of a hex color given a GH_Colour object
+ ///
+ /// the grasshopper color to convert
+ /// a hex color string
+ public static string hexColor(GH_Colour ghColor)
+ {
+ string hexStr = "0x" + ghColor.Value.R.ToString("X2") +
+ ghColor.Value.G.ToString("X2") +
+ ghColor.Value.B.ToString("X2");
+
+ return hexStr;
+ }
+ }
+
+
+ //below are a number of Catcher classes which are used to deserialize JSON objects
+ //mostly called from the va3c_CompileScene component
+
+
+ public class va3cGeometryCatcher
+ {
+ public string uuid;
+ public string type;
+ public object data;
+ }
+
+ public class va3cMaterialCatcher
+ {
+ public string uuid;
+ public string type;
+ public string color;
+ public string ambient;
+ public string emissive;
+ public string specular;
+ public double shininess;
+ public double opacity;
+ public bool transparent;
+ public bool wireframe;
+ public int side;
+ }
+
+ public class va3cAttributesCatcher
+ {
+ public object userData;
+ }
+
+ public class va3cLineCatcher
+ {
+ public string uuid;
+ public string type;
+ public object data;
+ }
+
+ public class va3cLineBasicMaterialCatcher
+ {
+ public string uuid;
+ public string type;
+ public string color;
+ public double linewidth;
+ public double opacity;
+ }
+}
diff --git a/GHva3c/GHva3c/va3c_Line.cs b/GHva3c/GHva3c/va3c_Line.cs
index 6ce32db..74993c9 100644
--- a/GHva3c/GHva3c/va3c_Line.cs
+++ b/GHva3c/GHva3c/va3c_Line.cs
@@ -1,8 +1,16 @@
using System;
+using System.Dynamic;
using System.Collections.Generic;
+using System.Linq;
+using System.Windows.Forms;
+using System.Timers;
using Grasshopper.Kernel;
+using Grasshopper.Kernel.Types;
using Rhino.Geometry;
+using GHva3c.Properties;
+
+using Newtonsoft.Json;
namespace GHva3c
{
@@ -40,7 +48,52 @@ protected override void RegisterOutputParams(GH_Component.GH_OutputParamManager
/// The DA object is used to retrieve from inputs and store in outputs.
protected override void SolveInstance(IGH_DataAccess DA)
{
- DA.SetData(0, "BUILD ME!");
+ //local variables
+ GH_Line line = null;
+
+ //catch inputs and populate local variables
+ if (!DA.GetData(0, ref line))
+ {
+ return;
+ }
+
+ //create JSON from line
+ string outJSON = lineJSON(line.Value);
+
+ //output results
+ DA.SetData(0, outJSON);
+
+ }
+
+ private string lineJSON(Line line)
+ {
+ //create a dynamic object to populate
+ dynamic jason = new ExpandoObject();
+
+ //top level properties
+ jason.uuid = Guid.NewGuid();
+ jason.type = "Geometry";
+ jason.data = new ExpandoObject();
+
+ //populate data object properties
+ jason.data.vertices = new object[6];
+ jason.data.vertices[0] = line.FromX * -1.0;
+ jason.data.vertices[1] = line.FromZ;
+ jason.data.vertices[2] = line.FromY;
+ jason.data.vertices[3] = line.ToX * -1.0;
+ jason.data.vertices[4] = line.ToZ;
+ jason.data.vertices[5] = line.ToY;
+ jason.data.normals = new object[0];
+ jason.data.uvs = new object[0];
+ jason.data.faces = new object[0];
+ jason.data.scale = 1;
+ jason.data.visible = true;
+ jason.data.castShadow = true;
+ jason.data.receiveShadow = false;
+
+
+ //return
+ return JsonConvert.SerializeObject(jason);
}
///
diff --git a/GHva3c/GHva3c/va3c_LineBasicMaterial.cs b/GHva3c/GHva3c/va3c_LineBasicMaterial.cs
new file mode 100644
index 0000000..acad36a
--- /dev/null
+++ b/GHva3c/GHva3c/va3c_LineBasicMaterial.cs
@@ -0,0 +1,107 @@
+using System;
+using System.Collections.Generic;
+using System.Dynamic;
+
+using Grasshopper.Kernel;
+using Grasshopper.Kernel.Types;
+using Rhino.Geometry;
+
+using Newtonsoft.Json;
+using GHva3c.Properties;
+
+namespace GHva3c
+{
+ public class va3c_LineBasicMaterial : GH_Component
+ {
+ ///
+ /// Initializes a new instance of the va3c_LineBasicMaterial class.
+ ///
+ public va3c_LineBasicMaterial()
+ : base("va3c_LineBasicMaterial", "va3c_LineBasicMaterial",
+ "Creates a THREE.js Basic Line Material to use with line geometries",
+ "va3c", "materials")
+ {
+ }
+
+ ///
+ /// Registers all the input parameters for this component.
+ ///
+ protected override void RegisterInputParams(GH_Component.GH_InputParamManager pManager)
+ {
+ pManager.AddColourParameter("Color", "C", "Material Color", GH_ParamAccess.item);
+ pManager.AddNumberParameter("LineWeight", "LW", "The thickness, in pixels, of the line material", GH_ParamAccess.item, 1.0);
+ pManager[1].Optional = true;
+ }
+
+ ///
+ /// Registers all the output parameters for this component.
+ ///
+ protected override void RegisterOutputParams(GH_Component.GH_OutputParamManager pManager)
+ {
+ pManager.AddTextParameter("Material", "Mat", "Line Material", GH_ParamAccess.item);
+ }
+
+ ///
+ /// This is the method that actually does the work.
+ ///
+ /// The DA object is used to retrieve from inputs and store in outputs.
+ protected override void SolveInstance(IGH_DataAccess DA)
+ {
+ //loacl varaibles
+ GH_Colour inColor = null;
+ GH_Number inNumber = new GH_Number(1.0);
+
+ //get user data
+ if (!DA.GetData(0, ref inColor))
+ {
+ return;
+ }
+ DA.GetData(1, ref inNumber);
+
+ //spin up a JSON material from the inputs
+ string outJSON = ConstructMaterial(inColor, inNumber);
+
+ //output
+ DA.SetData(0, outJSON);
+
+
+ }
+
+ private string ConstructMaterial(GH_Colour inColor, GH_Number inNumber)
+ {
+ //json object to populate
+ dynamic jason = new ExpandoObject();
+
+ //JSON properties
+ jason.uuid = Guid.NewGuid();
+ jason.type = "LineBasicMaterial";
+ jason.color = _Utilities.hexColor(inColor);
+ jason.linewidth = inNumber.Value;
+ jason.opacity = 1;
+
+
+ return JsonConvert.SerializeObject(jason);
+ }
+
+ ///
+ /// Provides an Icon for the component.
+ ///
+ protected override System.Drawing.Bitmap Icon
+ {
+ get
+ {
+ //You can add image files to your project resources and access them like this:
+ // return Resources.IconForThisComponent;
+ return null;
+ }
+ }
+
+ ///
+ /// Gets the unique ID for this component. Do not change this ID after release.
+ ///
+ public override Guid ComponentGuid
+ {
+ get { return new Guid("{dc90f883-fc2f-4f0b-955b-b276fda72c70}"); }
+ }
+ }
+}
\ No newline at end of file
diff --git a/GHva3c/GHva3c/va3c_SceneCompiler.cs b/GHva3c/GHva3c/va3c_SceneCompiler.cs
new file mode 100644
index 0000000..1220029
--- /dev/null
+++ b/GHva3c/GHva3c/va3c_SceneCompiler.cs
@@ -0,0 +1,346 @@
+using System;
+using System.Dynamic;
+using System.Collections.Generic;
+using System.Linq;
+using System.Windows.Forms;
+using System.Timers;
+
+using Grasshopper.Kernel;
+using Grasshopper.Kernel.Types;
+using Rhino.Geometry;
+
+using Newtonsoft.Json;
+using System.IO;
+using System.Text.RegularExpressions;
+using GHva3c.Properties;
+
+
+namespace GHva3c
+{
+ public class va3c_SceneCompiler : GH_Component
+ {
+ ///
+ /// Initializes a new instance of the va3c_SceneCompiler class.
+ ///
+ public va3c_SceneCompiler()
+ : base("va3c_SceneCompiler", "va3c_SceneCompiler",
+ "Compiles va3c objects into a JSON representation of a THREE.js scene, which can be opened using the va3c viewer.",
+ "va3c", "va3c")
+ {
+ }
+
+ ///
+ /// Registers all the input parameters for this component.
+ ///
+ protected override void RegisterInputParams(GH_Component.GH_InputParamManager pManager)
+ {
+ pManager.AddBooleanParameter("write?", "W?", "Write the va3c JSON file to disk?", GH_ParamAccess.item);
+ pManager.AddTextParameter("filePath", "Fp", "Full filepath of the file you'd like to create. Files will be overwritten automatically.", GH_ParamAccess.item);
+ pManager.AddTextParameter("Meshes", "M", "va3c mesh JSON objects to add to the scene.", GH_ParamAccess.list);
+ pManager.AddTextParameter("Mesh Materials", "Mm", "va3c mesh materials to add to the scene. Input one material per mesh. If list lengths do not match we'll apply the last material to all subsequent meshses.", GH_ParamAccess.list);
+ pManager.AddTextParameter("Lines", "L", "va3c line JSON objects to add to the scene.", GH_ParamAccess.list);
+ pManager.AddTextParameter("Line Materials", "Lm", "va3c line materials to add to the scene. Input one material per line. If list lengths do not match we'll apply the last material to all subsequent lines.", GH_ParamAccess.list);
+ pManager[2].Optional = true;
+ pManager[3].Optional = true;
+ pManager[4].Optional = true;
+ pManager[5].Optional = true;
+ }
+
+ ///
+ /// Registers all the output parameters for this component.
+ ///
+ protected override void RegisterOutputParams(GH_Component.GH_OutputParamManager pManager)
+ {
+ pManager.AddTextParameter("Message", "Out", "Message", GH_ParamAccess.item);
+ pManager.AddTextParameter("Json Presentation of Scene", "J_Scene", "Json Presentation of Scene", GH_ParamAccess.item);
+ }
+
+ ///
+ /// This is the method that actually does the work.
+ ///
+ /// The DA object is used to retrieve from inputs and store in outputs.
+ protected override void SolveInstance(IGH_DataAccess DA)
+ {
+ bool write = false;
+ string myFilePath = null;
+ List inMeshGeometry = new List();
+ List inMeshMaterials = new List();
+ List inLineGeometry = new List();
+ List inLineMaterials = new List();
+
+ //get user inputs
+ //user should be able to create a scene contianing only lines, or only meshes, or both. All geo and material inputs will be optional, and we'll run some defense.
+ if (!DA.GetData(0, ref write)) return;
+ if (!DA.GetData(1, ref myFilePath)) return;
+ DA.GetDataList(2, inMeshGeometry);
+ DA.GetDataList(3, inMeshMaterials);
+ DA.GetDataList(4, inLineGeometry);
+ DA.GetDataList(5, inLineMaterials);
+
+ #region Input defense
+
+ //input some geometry
+ if (inMeshGeometry.Count < 1 && inLineGeometry.Count < 1)
+ {
+ string err = "The scene must contain at least one mesh or one line.";
+ AddRuntimeMessage(GH_RuntimeMessageLevel.Error, err);
+ DA.SetData(0, err);
+ return;
+ }
+
+ //make sure there are materials if there is geometry
+ if (inMeshGeometry.Count > 0 && inMeshMaterials.Count < 1)
+ {
+ string err = "You need at least one mesh material in order to create meshes.";
+ AddRuntimeMessage(GH_RuntimeMessageLevel.Error, err);
+ DA.SetData(0, err);
+ return;
+ }
+ if (inLineGeometry.Count > 0 && inLineMaterials.Count < 1)
+ {
+ string err = "You need at least one line material in order to create lines.";
+ AddRuntimeMessage(GH_RuntimeMessageLevel.Error, err);
+ DA.SetData(0, err);
+ return;
+ }
+
+ //if we are not told to run, return
+ if (!write)
+ {
+ string err = "Set the 'W?' input to true to write the JSON file to disk.";
+ AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, err);
+ DA.SetData(0, err);
+ return;
+ }
+
+ #endregion
+
+
+ #region file path defense
+
+ //check to see if the file path has any invalid characters
+ try
+ {
+ //FIRST check to see if there is more than one semicolon in the path
+ //or if there is a semiColon anywhere in there
+ string[] colonFrags = myFilePath.Split(':');
+ if (colonFrags.Length > 2 || myFilePath.Contains(";"))
+ {
+ throw new Exception();
+ }
+
+ //SECOND test the file name for invalid characters using regular expressions
+ //this method comes from the C# 4.0 in a nutshell book, p991
+ string inputFileName = Path.GetFileName(myFilePath);
+ char[] inValidChars = Path.GetInvalidFileNameChars();
+ string inValidString = Regex.Escape(new string(inValidChars));
+ string myNewValidFileName = Regex.Replace(inputFileName, "[" + inValidString + "]", "");
+
+ //if the replace worked, throw an error at the user.
+ if (inputFileName != myNewValidFileName)
+ {
+ throw new Exception();
+ }
+ }
+ catch (Exception)
+ {
+ //warn the user
+ AddRuntimeMessage(GH_RuntimeMessageLevel.Error,
+ "Your file name is invalid - check your input and try again.");
+ return;
+ }
+
+
+ //if neither the file or directory exist, throw a warning
+ if (!File.Exists(myFilePath) && !Directory.Exists(Path.GetDirectoryName(myFilePath)))
+ {
+ AddRuntimeMessage(GH_RuntimeMessageLevel.Error,
+ "The directory you specified does not exist. Please double check your input. No file path will be set.");
+ return;
+ }
+
+ //if the directory exists but the file type is not .xlsx, throw a warning and set pathString = noFIle
+ if (Directory.Exists(Path.GetDirectoryName(myFilePath)) && !isJSONfile(Path.GetExtension(myFilePath)))
+ {
+ AddRuntimeMessage(GH_RuntimeMessageLevel.Error,
+ "Please provide a file of type .js or .json. Something like: 'myExampleFile.json'.");
+ return;
+ }
+ #endregion
+
+
+
+ //compile geometry + materials into one JSON object with metadata etc.
+ //https://raw.githubusercontent.com/mrdoob/three.js/master/examples/obj/blenderscene/scene.js
+
+ try
+ {
+ //create json from lists of json:
+ string outJSON = sceneJSON(inMeshGeometry, inMeshMaterials, inLineGeometry, inLineMaterials);
+ outJSON = outJSON.Replace("OOO", "object");
+
+
+ //write the file to disk
+ File.WriteAllText(myFilePath, outJSON);
+
+ //report success
+ DA.SetData(0, "JSON file written successfully!");
+ DA.SetData(1, outJSON);
+ }
+ catch (Exception e)
+ {
+ AddRuntimeMessage(GH_RuntimeMessageLevel.Error,
+ "Something went wrong while trying to write the file to disk. Here's the error:\n\n"
+ + e.ToString());
+ return;
+ }
+ }
+
+ private string sceneJSON(List meshList, List meshMaterialList, List linesList, List linesMaterialList)
+ {
+ //create a dynamic object to populate
+ dynamic jason = new ExpandoObject();
+
+ //populate metadata object
+ jason.metadata = new ExpandoObject();
+ jason.metadata.version = 4.3;
+ jason.metadata.type = "Object";
+ jason.metadata.generator = "ObjectExporter";
+
+ //populate mesh geometries:
+ jason.geometries = new object[meshList.Count + linesList.Count]; //array for geometry - both lines and meshes
+ int meshCounter = 0;
+ jason.materials = new object[meshMaterialList.Count + linesMaterialList.Count]; //array for materials - both lines and meshes
+ int matCounter = 0;
+ Dictionary MeshDict = new Dictionary();
+ Dictionary attrDict = new Dictionary();
+ foreach (GH_String m in meshList)
+ {
+ //get the last material if the list lengths don't match
+ if (matCounter == meshMaterialList.Count)
+ {
+ matCounter = meshMaterialList.Count - 1;
+ }
+
+ //deserialize everything
+ va3cGeometryCatcher c = JsonConvert.DeserializeObject(m.Value);
+ va3cAttributesCatcher ac = JsonConvert.DeserializeObject(m.Value);
+ va3cMaterialCatcher mc = JsonConvert.DeserializeObject(meshMaterialList[matCounter].Value);
+
+ jason.geometries[meshCounter] = c;
+ jason.materials[matCounter] = mc;
+
+ //pull out an object from JSON and add to a local dict
+
+ MeshDict.Add(c.uuid, mc.uuid);
+ attrDict.Add(c.uuid, ac);
+
+ matCounter++;
+ meshCounter++;
+
+
+ }
+
+ //populate line geometries
+ int lineCounter = meshCounter;
+ int lineMaterialCounter = 0;
+ Dictionary LineDict = new Dictionary();
+ foreach (GH_String l in linesList)
+ {
+ //get the last material if the list lengths don't match
+ if (lineMaterialCounter == linesMaterialList.Count)
+ {
+ lineMaterialCounter = linesMaterialList.Count - 1;
+ }
+
+ //deserialize the line and the material
+ va3cLineCatcher lc = JsonConvert.DeserializeObject(l.Value);
+ va3cLineBasicMaterialCatcher lmc =
+ JsonConvert.DeserializeObject(linesMaterialList[lineMaterialCounter].Value);
+ //add the deserialized values to the jason object
+ jason.geometries[lineCounter] = lc;
+ jason.materials[matCounter + lineMaterialCounter] = lmc;
+
+ //populate dict to match up materials and lines
+ LineDict.Add(lc.uuid, lmc.uuid);
+
+ //increment counters
+ lineCounter++;
+ lineMaterialCounter++;
+ }
+
+
+ jason.OOO = new ExpandoObject();
+ //create scene:
+ jason.OOO.uuid = System.Guid.NewGuid();
+ jason.OOO.type = "Scene";
+ int[] numbers = new int[16] { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 };
+ jason.OOO.matrix = numbers;
+ jason.OOO.children = new object[meshList.Count + linesList.Count];
+
+ //create childern
+ //loop over meshes and lines
+ int i = 0;
+ foreach (var g in MeshDict.Keys) //meshes
+ {
+ jason.OOO.children[i] = new ExpandoObject();
+ jason.OOO.children[i].uuid = Guid.NewGuid();
+ jason.OOO.children[i].name = "mesh" + i.ToString();
+ jason.OOO.children[i].type = "Mesh";
+ jason.OOO.children[i].geometry = g;
+ jason.OOO.children[i].material = MeshDict[g];
+ jason.OOO.children[i].matrix = numbers;
+ jason.OOO.children[i].userData = attrDict[g].userData;
+ i++;
+ }
+ foreach (var l in LineDict.Keys)
+ {
+ jason.OOO.children[i] = new ExpandoObject();
+ jason.OOO.children[i].uuid = Guid.NewGuid();
+ jason.OOO.children[i].name = "line " + i.ToString();
+ jason.OOO.children[i].type = "Line";
+ jason.OOO.children[i].geometry = l;
+ jason.OOO.children[i].material = LineDict[l];
+ jason.OOO.children[i].matrix = numbers;
+ i++;
+ }
+
+
+ return JsonConvert.SerializeObject(jason);
+ }
+
+ private bool isJSONfile(string fileExtension)
+ {
+ if (fileExtension.ToLower() == ".js" ||
+ fileExtension.ToLower() == ".json")
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ ///
+ /// Provides an Icon for the component.
+ ///
+ protected override System.Drawing.Bitmap Icon
+ {
+ get
+ {
+ //You can add image files to your project resources and access them like this:
+ // return Resources.IconForThisComponent;
+ return null;
+ }
+ }
+
+ ///
+ /// Gets the unique ID for this component. Do not change this ID after release.
+ ///
+ public override Guid ComponentGuid
+ {
+ get { return new Guid("{065f9b89-44fd-4660-aba8-f4211e5e2ef9}"); }
+ }
+ }
+}
\ No newline at end of file
diff --git a/GHva3c/GHva3c/va3c_material.cs b/GHva3c/GHva3c/va3c_material.cs
index 4a40b2c..e416fb9 100644
--- a/GHva3c/GHva3c/va3c_material.cs
+++ b/GHva3c/GHva3c/va3c_material.cs
@@ -109,10 +109,10 @@ public string ConstructMaterial(GH_Colour Col, Double Opp, String Name)
JsonMat.uuid = Guid.NewGuid();
JsonMat.type = "MeshPhongMaterial";
- JsonMat.color = hexColor(Col);
- JsonMat.ambient = hexColor(Col);
- JsonMat.emissive = hexColor(new GH_Colour(System.Drawing.Color.Black));
- JsonMat.specular = hexColor(new GH_Colour(System.Drawing.Color.Gray));
+ JsonMat.color = _Utilities.hexColor(Col);
+ JsonMat.ambient = _Utilities.hexColor(Col);
+ JsonMat.emissive = _Utilities.hexColor(new GH_Colour(System.Drawing.Color.Black));
+ JsonMat.specular = _Utilities.hexColor(new GH_Colour(System.Drawing.Color.Gray));
JsonMat.shininess = 50;
JsonMat.opacity = Opp;
JsonMat.transparent = false;
@@ -120,16 +120,5 @@ public string ConstructMaterial(GH_Colour Col, Double Opp, String Name)
JsonMat.side = 2;
return JsonConvert.SerializeObject(JsonMat);
}
-
- //thanks platypus!
- public string hexColor(GH_Colour ghColor)
- {
- string hexStr = "0x" + ghColor.Value.R.ToString("X2") +
- ghColor.Value.G.ToString("X2") +
- ghColor.Value.B.ToString("X2");
- //dynamic hex = new ExpandoObject();
-
- return hexStr;
- }
}
}
\ No newline at end of file
diff --git a/SampleFiles/line tester.gh b/SampleFiles/line tester.gh
new file mode 100644
index 0000000..7109d6b
Binary files /dev/null and b/SampleFiles/line tester.gh differ
diff --git a/SampleFiles/mesh tester 2.gh b/SampleFiles/mesh tester 2.gh
index 1f47537..e6ce64e 100644
Binary files a/SampleFiles/mesh tester 2.gh and b/SampleFiles/mesh tester 2.gh differ