From 6f42a89e03c4d7d3e3e648e3544ebdd6e7871c92 Mon Sep 17 00:00:00 2001 From: Mishael Nuh Date: Tue, 24 Dec 2019 12:51:37 -0500 Subject: [PATCH 1/8] Reduce number of collision checks which were unnecessary --- RodSteward/Generator.cs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/RodSteward/Generator.cs b/RodSteward/Generator.cs index 87d3fec..74e0b17 100644 --- a/RodSteward/Generator.cs +++ b/RodSteward/Generator.cs @@ -399,6 +399,9 @@ private Tuple>, List> FindMeshCollision(Dictionary 0) { @@ -412,6 +415,9 @@ private Tuple>, List> FindMeshCollision(Dictionary>, List> FindMeshCollision(Dictionary Date: Tue, 24 Dec 2019 14:49:42 -0500 Subject: [PATCH 2/8] Refactor model into separate class --- RodSteward/Generator.cs | 604 ++--------------------------------- RodSteward/Model.cs | 534 +++++++++++++++++++++++++++++++ RodSteward/RodSteward.csproj | 1 + 3 files changed, 558 insertions(+), 581 deletions(-) create mode 100644 RodSteward/Model.cs diff --git a/RodSteward/Generator.cs b/RodSteward/Generator.cs index 74e0b17..1b8735f 100644 --- a/RodSteward/Generator.cs +++ b/RodSteward/Generator.cs @@ -16,13 +16,7 @@ namespace RodSteward { public class Generator : GH_Component { - public bool SkipMeshBoolean { get; set; } = true; - - private Dictionary, Mesh> rodMeshes = new Dictionary, Mesh>(); - private Dictionary, Curve> rodCentrelines = new Dictionary, Curve>(); - private Dictionary> jointMeshes = new Dictionary>(); - private List> clashedRods = new List>(); - private List clashedJoints = new List(); + private Model model; public Generator() : base("Generator", "RSGenerator", @@ -50,6 +44,7 @@ protected override void RegisterInputParams(GH_InputParamManager pManager) protected override void RegisterOutputParams(GH_OutputParamManager pManager) { + pManager.AddGenericParameter("Model", "M", "Model object", GH_ParamAccess.item); pManager.AddMeshParameter("Joints", "J", "Joint meshes for structure", GH_ParamAccess.tree); pManager.AddMeshParameter("Rods", "R", "Rod meshes for structure", GH_ParamAccess.list); pManager.AddCurveParameter("Rod Curves", "RC", "Rod centreline curves", GH_ParamAccess.list); @@ -57,6 +52,7 @@ protected override void RegisterOutputParams(GH_OutputParamManager pManager) ((IGH_PreviewObject)pManager[0]).Hidden = true; ((IGH_PreviewObject)pManager[1]).Hidden = true; ((IGH_PreviewObject)pManager[2]).Hidden = true; + ((IGH_PreviewObject)pManager[3]).Hidden = true; } public override void DrawViewportMeshes(IGH_PreviewArgs args) @@ -65,15 +61,15 @@ public override void DrawViewportMeshes(IGH_PreviewArgs args) var rodMaterial = new Rhino.Display.DisplayMaterial(System.Drawing.Color.BurlyWood, 0.3); var jointMaterial = new Rhino.Display.DisplayMaterial(System.Drawing.Color.Black, 0.3); - foreach (var kvp in rodMeshes) + foreach (var kvp in model.RodMeshes) { - args.Display.DrawMeshShaded(kvp.Value, clashedRods.Contains(kvp.Key) ? errorMaterial : rodMaterial); + args.Display.DrawMeshShaded(kvp.Value, model.ClashedRods.Contains(kvp.Key) ? errorMaterial : rodMaterial); } - foreach (var kvp in jointMeshes) + foreach (var kvp in model.JointMeshes) { foreach (var b in kvp.Value) - args.Display.DrawMeshShaded(b, clashedJoints.Contains(kvp.Key) ? errorMaterial : jointMaterial); + args.Display.DrawMeshShaded(b, model.ClashedJoints.Contains(kvp.Key) ? errorMaterial : jointMaterial); } } @@ -86,7 +82,7 @@ protected override void SolveInstance(IGH_DataAccess DA) double jointThickness = 0; double jointLength = 0; double tolerance = 0; - + if (!DA.GetDataList(0, edges)) { return; } if (!DA.GetDataList(1, vertices)) { return; } if (!DA.GetData(2, ref sides)) { return; } @@ -98,523 +94,24 @@ protected override void SolveInstance(IGH_DataAccess DA) if (edges == null || vertices == null) { return; } if (radius <= 0 || sides <= 2 || jointThickness < 0 || jointLength < 0 || tolerance < 0) { throw new Exception("Invalid input."); } - var offsets = GetRodOffsets(edges, vertices, jointThickness, radius, tolerance); - - var rods = GetRodMeshes(edges, vertices, offsets, radius, (int)Math.Floor(sides)); - rodMeshes = rods.Item1; - rodCentrelines = rods.Item2; - - jointMeshes = GetJointMeshes(rodMeshes, edges, vertices, offsets, radius, (int)Math.Floor(sides), jointLength, jointThickness, tolerance); - - var collisions = FindMeshCollision(rodMeshes, jointMeshes); - clashedRods = collisions.Item1; - clashedJoints = collisions.Item2; - - var jointMeshTree = new DataTree(); - - foreach(var kvp in jointMeshes) - { - var path = new Grasshopper.Kernel.Data.GH_Path(kvp.Key); - jointMeshTree.AddRange(kvp.Value, path); - } - - DA.SetDataTree(0, jointMeshTree); - DA.SetDataList(1, rodMeshes.Values.ToList()); - DA.SetDataList(2, rodCentrelines.Values.ToList()); - } - - private Dictionary, double> GetRodOffsets(List> edges, List vertices, double jointThickness, double radius, double tolerance) - { - var offsets = new Dictionary, double>(); - - var jointRadius = radius + jointThickness + tolerance; - var innerRadius = radius + tolerance; - - for (int vStart = 0; vStart < vertices.Count; vStart++) - { - var connectedVertices = edges.Where(e => e.Item1 == vStart).Select(e => e.Item2).ToList(); - connectedVertices.AddRange(edges.Where(e => e.Item2 == vStart).Select(e => e.Item1).ToList()); - - if (connectedVertices.Count == 1) - { - var key = Tuple.Create(vStart, connectedVertices[0]); - - if (offsets.ContainsKey(key)) - offsets[key] = Math.Max(radius/2, offsets[key]); - else - offsets[key] = radius/2; - } - else - { - for (int vEnd = 0; vEnd < connectedVertices.Count; vEnd++) - { - for (int vCompare = vEnd + 1; vCompare < connectedVertices.Count; vCompare++) - { - var key1 = Tuple.Create(vStart, connectedVertices[vEnd]); - var key2 = Tuple.Create(vStart, connectedVertices[vCompare]); - - // Calculate angle - // Use procedure from: https://people.eecs.berkeley.edu/~wkahan/Triangle.pdf - // to minimize error for small angles - - var vec1 = vertices[connectedVertices[vEnd]] - vertices[vStart]; - var vec2 = vertices[connectedVertices[vCompare]] - vertices[vStart]; - var vec3 = Vector3d.Subtract(vec1, vec2); - var mag1 = vec1.Length; - var mag2 = vec2.Length; - var mag3 = vec3.Length; - - if (mag2 > mag1) - { - var t = mag2; - mag2 = mag1; - mag1 = t; - } - - double mu = 0; - if (mag2 >= mag3) - mu = mag3 - (mag1 - mag2); - else - mu = mag2 - (mag1 - mag3); - - var t1 = ((mag1 - mag2) + mag3) * mu; - var t2 = (mag1 + (mag2 + mag3)) * ((mag1 - mag3) + mag2); - - double divParam = 0; - double offset = 0; - if (Math.Abs(t2) <= 1e-6) - offset = jointRadius; - else - { - divParam = Math.Sqrt(t1 / t2); - offset = Math.Max(jointRadius / divParam, jointRadius); - } - - if (offsets.ContainsKey(key1)) - offsets[key1] = Math.Max(offset, offsets[key1]); - else - offsets[key1] = offset; - - if (offsets.ContainsKey(key2)) - offsets[key2] = Math.Max(offset, offsets[key2]); - else - offsets[key2] = offset; - } - } - } - } - - return offsets; - } - - private Tuple, Mesh>, Dictionary, Curve>> GetRodMeshes(List> edges, - List vertices, Dictionary, double> offsets, double radius, int sides) - { - var rodMeshes = new Dictionary, Mesh>(); - var rodCentrelines = new Dictionary, Curve>(); - - foreach (Tuple e in edges) + model = new Model() { - Curve centreline = new LineCurve(vertices[e.Item1], vertices[e.Item2]); - try - { - var o1 = offsets[e]; - var o2 = offsets[Tuple.Create(e.Item2, e.Item1)]; - if (o1 > 0) - { - centreline = centreline.Trim(CurveEnd.Start, o1); - } - if (o2 > 0) - { - centreline = centreline.Trim(CurveEnd.End, o2); - } - - if (centreline == null) - throw new Exception(); - } - catch - { - this.AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Rod not created. Radius and tolerance too large for edge lengths. Try reducing either or increase the edge lengths."); - continue; - } + Edges = edges, + Vertices = vertices, + Sides = (int)Math.Floor(sides), + Radius = radius, + JointThickness = jointThickness, + JointLength = jointLength, + Tolerance = tolerance, + }; - rodCentrelines[e] = centreline; - - rodMeshes[e] = Mesh.CreateFromCurvePipe(centreline, radius, sides, 0, MeshPipeCapStyle.Flat, false); - } + model.Generate(); + model.CalculateClashes(); - return Tuple.Create(rodMeshes, rodCentrelines); - } - - private Dictionary> GetJointMeshes(Dictionary, Mesh> rodMeshes, List> edges, - List vertices, Dictionary, double> offsets, double radius, int sides, - double jointLength, double jointThickness, double tolerance) - { - var jointMeshes = new Dictionary>(); - var separateJointMeshes = new Dictionary>(); - - var jointArmCounter = new Dictionary(); - - var jointCorePoints = new Dictionary>(); - - double jointRadius = radius + jointThickness + tolerance; - double innerRadius = radius + tolerance; - - for (int v = 0; v < vertices.Count; v++) - { - separateJointMeshes[v] = new List(); - jointCorePoints[v] = new List(); - jointArmCounter[v] = 1; - } - - foreach(Tuple e in edges) - { - if (!rodMeshes.ContainsKey(e)) - continue; - - Curve c = new LineCurve(vertices[e.Item1], vertices[e.Item2]); - - double len = c.GetLength(); - - if (len == 0) - { - this.AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Joint not created. Joint lengths greater than rod length. Try reducing joint lengths or radius."); - continue; - } - - Curve startCurve; - Curve endCurve; - - try - { - startCurve = c.Trim(CurveEnd.End, len - (offsets[e] + jointLength + tolerance)); - endCurve = c.Trim(CurveEnd.Start, len - (offsets[Tuple.Create(e.Item2, e.Item1)] + jointLength + tolerance)); - - if (startCurve == null || endCurve == null) - throw new Exception(); - } - catch - { - this.AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Joint not created. Joint lengths greater than rod length. Try reducing joint lengths or radius."); - continue; - } - - // Convex hull points - var vector = Point3d.Subtract(vertices[e.Item2], vertices[e.Item1]); - vector.Unitize(); - - Polyline outerPoly; - var outerProfile = GetProfile(jointRadius, sides, vector); - outerProfile.TryGetPolyline(out outerPoly); - - foreach (var l in outerPoly.Skip(1)) - { - jointCorePoints[e.Item1].Add(new double[] { l.X + vertices[e.Item1].X, l.Y + vertices[e.Item1].Y, l.Z + vertices[e.Item1].Z }); - jointCorePoints[e.Item2].Add(new double[] { l.X + vertices[e.Item2].X, l.Y + vertices[e.Item2].Y, l.Z + vertices[e.Item2].Z }); - } - - // Create hollow joint arms - var startMesh = CreateJointArm(vertices[e.Item1], vector, startCurve.GetLength(), offsets[e], innerRadius, jointRadius, sides); - var endMesh = CreateJointArm(vertices[e.Item2], vector, -endCurve.GetLength(), -offsets[Tuple.Create(e.Item2, e.Item1)], innerRadius, jointRadius, sides); - - separateJointMeshes[e.Item1].Add(startMesh); - separateJointMeshes[e.Item2].Add(endMesh); - - // Create joint label - var startLabel = CreateJointArmLabel(vertices[e.Item1], vector, e.Item1.ToString() + ((char)(jointArmCounter[e.Item1] + 64)).ToString(), startCurve.GetLength(), innerRadius, jointRadius, sides); - var endLabel = CreateJointArmLabel(vertices[e.Item2], vector, e.Item2.ToString() + ((char)(jointArmCounter[e.Item2] + 64)).ToString(), -endCurve.GetLength(), innerRadius, jointRadius, sides); - - jointArmCounter[e.Item1]++; - jointArmCounter[e.Item2]++; - - if (startLabel != null) - separateJointMeshes[e.Item1].Add(startLabel); - if (endLabel != null) - separateJointMeshes[e.Item2].Add(endLabel); - } - - foreach (KeyValuePair> kvp in jointCorePoints) - { - try - { - var convHullRes = ConvexHull.Create(kvp.Value, DocumentTolerance()); - var hullPoints = convHullRes.Result.Points.ToList(); - var hullFaces = convHullRes.Result.Faces.ToList(); - - var newMesh = new Mesh(); - newMesh.Vertices.AddVertices(hullPoints.Select(p => new Point3d(p.Position[0], p.Position[1], p.Position[2]))); - newMesh.Faces.AddFaces(hullFaces.Select(f => new MeshFace(hullPoints.IndexOf(f.Vertices[0]), hullPoints.IndexOf(f.Vertices[1]), hullPoints.IndexOf(f.Vertices[2])))); - newMesh.Normals.ComputeNormals(); - newMesh.UnifyNormals(); - newMesh.Normals.ComputeNormals(); - newMesh.Compact(); - separateJointMeshes[kvp.Key].Insert(0,newMesh); // Add conv hull to beginning - } - catch { } - } - - if (SkipMeshBoolean) - { - foreach (KeyValuePair> kvp in separateJointMeshes) - { - if (kvp.Value.Count > 0) - { - var mesh = kvp.Value.First(); - foreach (var m in kvp.Value.Skip(1)) - { - mesh.Append(m); - } - mesh.Weld(DocumentAngleTolerance()); - jointMeshes[kvp.Key] = new List() { mesh }; - } - } - } - else - { - foreach (KeyValuePair> kvp in separateJointMeshes) - { - var rhMesh = Mesh.CreateBooleanUnion(kvp.Value); - - if (rhMesh.Count() == 1) - jointMeshes[kvp.Key] = rhMesh.ToList(); - else - this.AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Mesh boolean failed. As usual..."); - } - } - - return jointMeshes; - } - - private Tuple>, List> FindMeshCollision(Dictionary, Mesh> rodMeshes, Dictionary> jointMeshes) - { - var clashedRods = new List>(); - var clashedJoints = new List(); - - var rodKeys = rodMeshes.Keys.ToList(); - var rodVals = rodMeshes.Values.ToList(); - var jointKeys = jointMeshes.Keys.ToList(); - var jointVals = jointMeshes.Values.ToList(); - - for (int i = 0; i < rodKeys.Count; i++) - { - for (int j = i + 1; j < rodKeys.Count; j++) - { - if (clashedRods.Contains(rodKeys[i]) && clashedRods.Contains(rodKeys[j])) - continue; - - var intersect = Rhino.Geometry.Intersect.Intersection.MeshMeshFast(rodVals[i], rodVals[j]); - if (intersect != null && intersect.Length > 0) - { - clashedRods.Add(rodKeys[i]); - clashedRods.Add(rodKeys[j]); - } - } - - for (int j = 0; j < jointKeys.Count; j++) - { - if (rodKeys[i].Item1 == jointKeys[j] || rodKeys[i].Item2 == jointKeys[j]) - continue; - - if (clashedRods.Contains(rodKeys[i]) && clashedJoints.Contains(jointKeys[j])) - continue; - - foreach (var jv in jointVals[j]) - { - var intersect = Rhino.Geometry.Intersect.Intersection.MeshMeshFast(rodVals[i], jv); - if (intersect != null && intersect.Length > 0) - { - clashedRods.Add(rodKeys[i]); - clashedJoints.Add(jointKeys[j]); - break; - } - } - } - } - - var hit = false; - for (int i = 0; i < jointKeys.Count; i++) - { - for (int j = i + 1; j < jointKeys.Count; j++) - { - if (clashedJoints.Contains(jointKeys[i]) && clashedJoints.Contains(jointKeys[j])) - continue; - - foreach (var iv in jointVals[i]) - { - foreach (var jv in jointVals[j]) - { - var intersect = Rhino.Geometry.Intersect.Intersection.MeshMeshFast(iv, jv); - if (intersect != null && intersect.Length > 0) - { - clashedJoints.Add(jointKeys[i]); - clashedJoints.Add(jointKeys[j]); - hit = true; - break; - } - } - if (hit) - { - hit = false; - break; - } - } - } - } - - return Tuple.Create(clashedRods, clashedJoints); - } - - private Curve GetProfile(double radius, int sides, Vector3d normal) - { - var profilePlane = new Plane(new Point3d(0, 0, 0), normal); - var circle = new Circle(profilePlane, radius); - return Polyline.CreateInscribedPolygon(circle, sides).ToPolylineCurve(); - } - - private Mesh CreateJointArm(Point3d origin, Vector3d direction, double length, double offset, double radius, double jointRadius, int sides) - { - var mesh = new Mesh(); - - Polyline outerPoly; - Polyline innerPoly; - var outerProfile = GetProfile(jointRadius, sides, direction); - var innerProfile = GetProfile(radius, sides, direction); - outerProfile.TryGetPolyline(out outerPoly); - innerProfile.TryGetPolyline(out innerPoly); - - Vector3d startLength = direction * length; - Vector3d startOffsetLength = direction * offset; - - // V - mesh.Vertices.Add(origin); - mesh.Vertices.Add(Point3d.Add(origin, startOffsetLength)); - foreach (var p in outerPoly.Skip(1)) - mesh.Vertices.Add(Point3d.Add(p, origin)); - foreach (var p in outerPoly.Skip(1)) - mesh.Vertices.Add(Point3d.Add(Point3d.Add(p, origin), startLength)); - foreach (var p in innerPoly.Skip(1)) - mesh.Vertices.Add(Point3d.Add(Point3d.Add(p, origin), startOffsetLength)); - foreach (var p in innerPoly.Skip(1)) - mesh.Vertices.Add(Point3d.Add(Point3d.Add(p, origin), startLength)); - - // F - for (int i = 2; i < sides + 1; i++) - mesh.Faces.AddFace(0, i, i + 1); - mesh.Faces.AddFace(0, sides + 1, 2); - - for (int i = 2 * sides + 2; i < 3 * sides + 1; i++) - mesh.Faces.AddFace(1, i, i + 1); - mesh.Faces.AddFace(1, 3 * sides + 1, 2 * sides + 2); - - for (int i = 0; i < sides; i++) - { - if (i < sides - 1) - { - mesh.Faces.AddFace(3 * sides + 2 + i, sides + 2 + i, sides + 3 + i); - mesh.Faces.AddFace(3 * sides + 2 + i, sides + 3 + i, 3 * sides + 3 + i); - } - else - { - mesh.Faces.AddFace(3 * sides + 2 + i, sides + 2 + i, sides + 2); - mesh.Faces.AddFace(3 * sides + 2 + i, sides + 2, 3 * sides + 2); - } - } - - for (int i = 0; i < sides; i++) - { - if (i < sides - 1) - { - mesh.Faces.AddFace(2 * sides + 2 + i, 3 * sides + 2 + i, 3 * sides + 3 + i); - mesh.Faces.AddFace(2 * sides + 2 + i, 3 * sides + 3 + i, 2 * sides + 3 + i); - } - else - { - mesh.Faces.AddFace(2 * sides + 2 + i, 3 * sides + 2 + i, 3 * sides + 2); - mesh.Faces.AddFace(2 * sides + 2 + i, 3 * sides + 2, 2 * sides + 2); - } - } - - for (int i = 0; i < sides; i++) - { - if (i < sides - 1) - { - mesh.Faces.AddFace(2 + i, sides + 2 + i, sides + 3 + i); - mesh.Faces.AddFace(2 + i, sides + 3 + i, 3 + i); - } - else - { - mesh.Faces.AddFace(2 + i, sides + 2 + i, sides + 2); - mesh.Faces.AddFace(2 + i, sides + 2, 2); - } - } - mesh.Normals.ComputeNormals(); - mesh.UnifyNormals(); - mesh.Normals.ComputeNormals(); - - return mesh; - } - - private Mesh CreateJointArmLabel(Point3d origin, Vector3d direction, string label, double length, double radius, double jointRadius, int sides) - { - Polyline innerPoly; - var innerProfile = GetProfile(radius, sides, direction); - innerProfile.TryGetPolyline(out innerPoly); - - var pSideMid = (innerPoly[1] + innerPoly[0]) / 2 + origin; - - Vector3d dir1 = length < 0 ? direction : -direction; - Vector3d dir3 = pSideMid - origin; - Vector3d dir2 = Vector3d.CrossProduct(dir3, dir1); - dir1.Unitize(); - dir2.Unitize(); - dir3.Unitize(); - - var textHeight = Math.Sqrt(jointRadius * jointRadius - radius * radius) / 1.5; - var embossHeight = (jointRadius - radius) * 1.2; - - Vector3d startTextOffset = (length < 0 ? -direction : direction) * (Math.Abs(length) - (jointRadius - radius)); - - Point3d planeOrigin = Point3d.Add(origin, startTextOffset); - planeOrigin = Point3d.Add(planeOrigin, dir3 * (pSideMid - origin).Length); - - var plane = new Plane(planeOrigin, dir1, dir2); - plane.UpdateEquation(); - - var style = new Rhino.DocObjects.DimensionStyle(); - style.TextHorizontalAlignment = Rhino.DocObjects.TextHorizontalAlignment.Left; - style.TextVerticalAlignment = Rhino.DocObjects.TextVerticalAlignment.Middle; - style.TextHeight = textHeight; - var prefFont = Rhino.DocObjects.Font.InstalledFonts("Lucida Console"); - if (prefFont.Length > 0) - style.Font = prefFont.First(); - - var writingPlane = new Plane(planeOrigin, new Vector3d(0, 0, 1)); // Must write to flat plane for some reason - - TextEntity textEnt = TextEntity.Create(label, writingPlane, style, false, Math.Abs(length), 0); - textEnt.SetBold(true); - - var meshes = textEnt.CreateExtrusions(style, embossHeight) - .Where(b => b != null) - .SelectMany(b => Mesh.CreateFromBrep(b.ToBrep(), MeshingParameters.FastRenderMesh)); - - var trans = Transform.PlaneToPlane(writingPlane, plane); - - if (meshes.Count() > 0) - { - var mesh = meshes.First(); - foreach (var m in meshes.Skip(1)) - { - mesh.Append(m); - } - mesh.Weld(DocumentAngleTolerance()); - mesh.Normals.ComputeNormals(); - mesh.UnifyNormals(); - mesh.Normals.ComputeNormals(); - mesh.Transform(trans); - return mesh; - } - - return null; + DA.SetData(0, model); + DA.SetDataTree(1, model.JointMeshTree); + DA.SetDataList(2, model.RodMeshes.Values.ToList()); + DA.SetDataList(3, model.RodCentrelines.Values.ToList()); } protected override System.Drawing.Bitmap Icon @@ -633,69 +130,14 @@ public GeneratorAttribute(GH_Component owner) : base(owner) { } protected override void Layout() { base.Layout(); - - System.Drawing.Rectangle rec0 = GH_Convert.ToRectangle(Bounds); - rec0.Height += 22 * 2; - - System.Drawing.Rectangle rec1 = rec0; - rec1.Y = rec1.Bottom - 22 * 2; - rec1.Height = 22; - rec1.Inflate(-2, -2); - - System.Drawing.Rectangle rec2 = rec0; - rec2.Y = rec2.Bottom - 22; - rec2.Height = 22; - rec2.Inflate(-2, -2); - - Bounds = rec0; - ButtonBounds1 = rec1; - ButtonBounds2 = rec2; } - private System.Drawing.Rectangle ButtonBounds1 { get; set; } - private System.Drawing.Rectangle ButtonBounds2 { get; set; } protected override void Render(GH_Canvas canvas, System.Drawing.Graphics graphics, GH_CanvasChannel channel) { base.Render(canvas, graphics, channel); - - if (channel == GH_CanvasChannel.Objects) - { - var component = Owner as Generator; - GH_Capsule button1 = GH_Capsule.CreateTextCapsule(ButtonBounds1, ButtonBounds1, component.SkipMeshBoolean ? GH_Palette.Black : GH_Palette.Grey, "Stable", 2, 0); - GH_Capsule button2 = GH_Capsule.CreateTextCapsule(ButtonBounds2, ButtonBounds2, !component.SkipMeshBoolean ? GH_Palette.Black : GH_Palette.Grey, "M.Boolean", 2, 0); - button1.Render(graphics, Selected, Owner.Locked, false); - button1.Dispose(); - button2.Render(graphics, Selected, Owner.Locked, false); - button2.Dispose(); - } } public override GH_ObjectResponse RespondToMouseDown(GH_Canvas sender, GH_CanvasMouseEvent e) { - if (e.Button == System.Windows.Forms.MouseButtons.Left) - { - System.Drawing.RectangleF rec1 = ButtonBounds1; - System.Drawing.RectangleF rec2 = ButtonBounds2; - if (rec1.Contains(e.CanvasLocation)) - { - var component = Owner as Generator; - if (component.SkipMeshBoolean != true) - { - component.SkipMeshBoolean = true; - component.ExpireSolution(true); - } - return GH_ObjectResponse.Handled; - } - else if (rec2.Contains(e.CanvasLocation)) - { - var component = Owner as Generator; - if (component.SkipMeshBoolean != false) - { - component.SkipMeshBoolean = false; - component.ExpireSolution(true); - } - return GH_ObjectResponse.Handled; - } - } return base.RespondToMouseDown(sender, e); } } diff --git a/RodSteward/Model.cs b/RodSteward/Model.cs new file mode 100644 index 0000000..80eee53 --- /dev/null +++ b/RodSteward/Model.cs @@ -0,0 +1,534 @@ +using Rhino.Geometry; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Grasshopper; +using MIConvexHull; + +namespace RodSteward +{ + public class Model + { + public int Sides { get; set; } = 50; + public double Radius { get; set; } = 6.35; + public double JointThickness { get; set; } = 3.0; + public double JointLength { get; set; } = 38; + public double Tolerance { get; set; } = 0.1; + + public double InnerWallRadius { get { return Radius + Tolerance; } } + public double OuterWallRadius { get { return Radius + JointThickness + Tolerance; } } + public DataTree JointMeshTree { + get + { + var jointMeshTree = new DataTree(); + + foreach (var kvp in JointMeshes) + { + var path = new Grasshopper.Kernel.Data.GH_Path(kvp.Key); + jointMeshTree.AddRange(kvp.Value, path); + } + + return jointMeshTree; + } + } + + public List> Edges { get; set; } + public List Vertices { get; set; } + + public Dictionary, double> Offsets { get; set; } + + public Dictionary, Mesh> RodMeshes { get; set; } + public Dictionary, Curve> RodCentrelines { get; set; } + public Dictionary> JointMeshes { get; set; } + + public List> ClashedRods { get; set; } + public List ClashedJoints { get; set; } + + public Model() + { + Edges = new List>(); + Vertices = new List(); + Offsets = new Dictionary, double>(); + RodMeshes = new Dictionary, Mesh>(); + RodCentrelines = new Dictionary, Curve>(); + JointMeshes = new Dictionary>(); + ClashedRods = new List>(); + ClashedJoints = new List(); + } + + public void Generate() + { + CalculateRodOffsets(); + GenerateRodMeshes(); + GenerateJointMeshes(); + } + + public Dictionary, double> CalculateRodOffsets() + { + Offsets.Clear(); + + for (int vStart = 0; vStart < Vertices.Count; vStart++) + { + var connectedVertices = Edges.Where(e => e.Item1 == vStart).Select(e => e.Item2).ToList(); + connectedVertices.AddRange(Edges.Where(e => e.Item2 == vStart).Select(e => e.Item1).ToList()); + + if (connectedVertices.Count == 1) + { + var key = Tuple.Create(vStart, connectedVertices[0]); + + if (Offsets.ContainsKey(key)) + Offsets[key] = Math.Max(Radius / 2, Offsets[key]); + else + Offsets[key] = Radius / 2; + } + else + { + for (int vEnd = 0; vEnd < connectedVertices.Count; vEnd++) + { + for (int vCompare = vEnd + 1; vCompare < connectedVertices.Count; vCompare++) + { + var key1 = Tuple.Create(vStart, connectedVertices[vEnd]); + var key2 = Tuple.Create(vStart, connectedVertices[vCompare]); + + // Calculate angle + // Use procedure from: https://people.eecs.berkeley.edu/~wkahan/Triangle.pdf + // to minimize error for small angles + + var vec1 = Vertices[connectedVertices[vEnd]] - Vertices[vStart]; + var vec2 = Vertices[connectedVertices[vCompare]] - Vertices[vStart]; + var vec3 = Vector3d.Subtract(vec1, vec2); + var mag1 = vec1.Length; + var mag2 = vec2.Length; + var mag3 = vec3.Length; + + if (mag2 > mag1) + { + var t = mag2; + mag2 = mag1; + mag1 = t; + } + + double mu = 0; + if (mag2 >= mag3) + mu = mag3 - (mag1 - mag2); + else + mu = mag2 - (mag1 - mag3); + + var t1 = ((mag1 - mag2) + mag3) * mu; + var t2 = (mag1 + (mag2 + mag3)) * ((mag1 - mag3) + mag2); + + double divParam = 0; + double offset = 0; + if (Math.Abs(t2) <= 1e-6) + offset = OuterWallRadius; + else + { + divParam = Math.Sqrt(t1 / t2); + offset = Math.Max(OuterWallRadius / divParam, OuterWallRadius); + } + + if (Offsets.ContainsKey(key1)) + Offsets[key1] = Math.Max(offset, Offsets[key1]); + else + Offsets[key1] = offset; + + if (Offsets.ContainsKey(key2)) + Offsets[key2] = Math.Max(offset, Offsets[key2]); + else + Offsets[key2] = offset; + } + } + } + } + + return Offsets; + } + + public Tuple>, List> CalculateClashes() + { + ClashedRods.Clear(); + ClashedJoints.Clear(); + + var rodKeys = RodMeshes.Keys.ToList(); + var rodVals = RodMeshes.Values.ToList(); + var jointKeys = JointMeshes.Keys.ToList(); + var jointVals = JointMeshes.Values.ToList(); + + for (int i = 0; i < rodKeys.Count; i++) + { + for (int j = i + 1; j < rodKeys.Count; j++) + { + if (ClashedRods.Contains(rodKeys[i]) && ClashedRods.Contains(rodKeys[j])) + continue; + + var intersect = Rhino.Geometry.Intersect.Intersection.MeshMeshFast(rodVals[i], rodVals[j]); + if (intersect != null && intersect.Length > 0) + { + ClashedRods.Add(rodKeys[i]); + ClashedRods.Add(rodKeys[j]); + } + } + + for (int j = 0; j < jointKeys.Count; j++) + { + if (rodKeys[i].Item1 == jointKeys[j] || rodKeys[i].Item2 == jointKeys[j]) + continue; + + if (ClashedRods.Contains(rodKeys[i]) && ClashedJoints.Contains(jointKeys[j])) + continue; + + foreach (var jv in jointVals[j]) + { + var intersect = Rhino.Geometry.Intersect.Intersection.MeshMeshFast(rodVals[i], jv); + if (intersect != null && intersect.Length > 0) + { + ClashedRods.Add(rodKeys[i]); + ClashedJoints.Add(jointKeys[j]); + break; + } + } + } + } + + var hit = false; + for (int i = 0; i < jointKeys.Count; i++) + { + for (int j = i + 1; j < jointKeys.Count; j++) + { + if (ClashedJoints.Contains(jointKeys[i]) && ClashedJoints.Contains(jointKeys[j])) + continue; + + foreach (var iv in jointVals[i]) + { + foreach (var jv in jointVals[j]) + { + var intersect = Rhino.Geometry.Intersect.Intersection.MeshMeshFast(iv, jv); + if (intersect != null && intersect.Length > 0) + { + ClashedJoints.Add(jointKeys[i]); + ClashedJoints.Add(jointKeys[j]); + hit = true; + break; + } + } + if (hit) + { + hit = false; + break; + } + } + } + } + + return Tuple.Create(ClashedRods, ClashedJoints); + } + + public Dictionary, Mesh> GenerateRodMeshes() + { + RodMeshes.Clear(); + RodCentrelines.Clear(); + + foreach (Tuple e in Edges) + { + Curve centreline = new LineCurve(Vertices[e.Item1], Vertices[e.Item2]); + try + { + var o1 = Offsets[e]; + var o2 = Offsets[Tuple.Create(e.Item2, e.Item1)]; + if (o1 > 0) + { + centreline = centreline.Trim(CurveEnd.Start, o1); + } + if (o2 > 0) + { + centreline = centreline.Trim(CurveEnd.End, o2); + } + + if (centreline == null) + throw new Exception(); + } + catch + { + throw new Exception("Rod not created. Radius and tolerance too large for edge lengths. Try reducing either or increase the edge lengths."); + } + + RodCentrelines[e] = centreline; + + RodMeshes[e] = Mesh.CreateFromCurvePipe(centreline, Radius, Sides, 0, MeshPipeCapStyle.Flat, false); + } + + return RodMeshes; + } + + public Dictionary> GenerateJointMeshes() + { + var separateJointMeshes = new Dictionary>(); + + var jointArmCounter = new Dictionary(); + + var jointCorePoints = new Dictionary>(); + + for (int v = 0; v < Vertices.Count; v++) + { + separateJointMeshes[v] = new List(); + jointCorePoints[v] = new List(); + jointArmCounter[v] = 1; + } + + foreach (Tuple e in Edges) + { + if (!RodMeshes.ContainsKey(e)) + continue; + + Curve c = new LineCurve(Vertices[e.Item1], Vertices[e.Item2]); + + double len = c.GetLength(); + + if (len == 0) + { + throw new Exception("Joint not created. Joint lengths greater than rod length. Try reducing joint lengths or radius."); + } + + Curve startCurve; + Curve endCurve; + + try + { + startCurve = c.Trim(CurveEnd.End, len - (Offsets[e] + JointLength + Tolerance)); + endCurve = c.Trim(CurveEnd.Start, len - (Offsets[Tuple.Create(e.Item2, e.Item1)] + JointLength + Tolerance)); + + if (startCurve == null || endCurve == null) + throw new Exception(); + } + catch + { + throw new Exception("Joint not created. Joint lengths greater than rod length. Try reducing joint lengths or radius."); + } + + // Convex hull points + var vector = Point3d.Subtract(Vertices[e.Item2], Vertices[e.Item1]); + vector.Unitize(); + + Polyline outerPoly; + var outerProfile = GetProfile(OuterWallRadius, vector); + outerProfile.TryGetPolyline(out outerPoly); + + foreach (var l in outerPoly.Skip(1)) + { + jointCorePoints[e.Item1].Add(new double[] { l.X + Vertices[e.Item1].X, l.Y + Vertices[e.Item1].Y, l.Z + Vertices[e.Item1].Z }); + jointCorePoints[e.Item2].Add(new double[] { l.X + Vertices[e.Item2].X, l.Y + Vertices[e.Item2].Y, l.Z + Vertices[e.Item2].Z }); + } + + // Create hollow joint arms + var startMesh = GenerateJointArm(Vertices[e.Item1], vector, startCurve.GetLength(), Offsets[e]); + var endMesh = GenerateJointArm(Vertices[e.Item2], vector, -endCurve.GetLength(), -Offsets[Tuple.Create(e.Item2, e.Item1)]); + + separateJointMeshes[e.Item1].Add(startMesh); + separateJointMeshes[e.Item2].Add(endMesh); + + // Create joint label + var startLabel = GenerateJointArmLabel(Vertices[e.Item1], vector, e.Item1.ToString() + ((char)(jointArmCounter[e.Item1] + 64)).ToString(), startCurve.GetLength()); + var endLabel = GenerateJointArmLabel(Vertices[e.Item2], vector, e.Item2.ToString() + ((char)(jointArmCounter[e.Item2] + 64)).ToString(), -endCurve.GetLength()); + + jointArmCounter[e.Item1]++; + jointArmCounter[e.Item2]++; + + if (startLabel != null) + separateJointMeshes[e.Item1].Add(startLabel); + if (endLabel != null) + separateJointMeshes[e.Item2].Add(endLabel); + } + + foreach (KeyValuePair> kvp in jointCorePoints) + { + try + { + var convHullRes = ConvexHull.Create(kvp.Value, Tolerance); + var hullPoints = convHullRes.Result.Points.ToList(); + var hullFaces = convHullRes.Result.Faces.ToList(); + + var newMesh = new Mesh(); + newMesh.Vertices.AddVertices(hullPoints.Select(p => new Point3d(p.Position[0], p.Position[1], p.Position[2]))); + newMesh.Faces.AddFaces(hullFaces.Select(f => new MeshFace(hullPoints.IndexOf(f.Vertices[0]), hullPoints.IndexOf(f.Vertices[1]), hullPoints.IndexOf(f.Vertices[2])))); + newMesh.Normals.ComputeNormals(); + newMesh.UnifyNormals(); + newMesh.Normals.ComputeNormals(); + newMesh.Compact(); + separateJointMeshes[kvp.Key].Insert(0, newMesh); // Add conv hull to beginning + } + catch { } + } + + foreach (KeyValuePair> kvp in separateJointMeshes) + { + if (kvp.Value.Count > 0) + { + var mesh = kvp.Value.First(); + foreach (var m in kvp.Value.Skip(1)) + { + mesh.Append(m); + } + mesh.Weld(Tolerance); + JointMeshes[kvp.Key] = new List() { mesh }; + } + } + + return JointMeshes; + } + + private Curve GetProfile(double radius, Vector3d normal) + { + var profilePlane = new Plane(new Point3d(0, 0, 0), normal); + var circle = new Circle(profilePlane, radius); + return Polyline.CreateInscribedPolygon(circle, Sides).ToPolylineCurve(); + } + + private Mesh GenerateJointArm(Point3d origin, Vector3d direction, double length, double offset) + { + var mesh = new Mesh(); + + Polyline outerPoly; + Polyline innerPoly; + var outerProfile = GetProfile(OuterWallRadius, direction); + var innerProfile = GetProfile(InnerWallRadius, direction); + outerProfile.TryGetPolyline(out outerPoly); + innerProfile.TryGetPolyline(out innerPoly); + + Vector3d startLength = direction * length; + Vector3d startOffsetLength = direction * offset; + + // V + mesh.Vertices.Add(origin); + mesh.Vertices.Add(Point3d.Add(origin, startOffsetLength)); + foreach (var p in outerPoly.Skip(1)) + mesh.Vertices.Add(Point3d.Add(p, origin)); + foreach (var p in outerPoly.Skip(1)) + mesh.Vertices.Add(Point3d.Add(Point3d.Add(p, origin), startLength)); + foreach (var p in innerPoly.Skip(1)) + mesh.Vertices.Add(Point3d.Add(Point3d.Add(p, origin), startOffsetLength)); + foreach (var p in innerPoly.Skip(1)) + mesh.Vertices.Add(Point3d.Add(Point3d.Add(p, origin), startLength)); + + // F + for (int i = 2; i < Sides + 1; i++) + mesh.Faces.AddFace(0, i, i + 1); + mesh.Faces.AddFace(0, Sides + 1, 2); + + for (int i = 2 * Sides + 2; i < 3 * Sides + 1; i++) + mesh.Faces.AddFace(1, i, i + 1); + mesh.Faces.AddFace(1, 3 * Sides + 1, 2 * Sides + 2); + + for (int i = 0; i < Sides; i++) + { + if (i < Sides - 1) + { + mesh.Faces.AddFace(3 * Sides + 2 + i, Sides + 2 + i, Sides + 3 + i); + mesh.Faces.AddFace(3 * Sides + 2 + i, Sides + 3 + i, 3 * Sides + 3 + i); + } + else + { + mesh.Faces.AddFace(3 * Sides + 2 + i, Sides + 2 + i, Sides + 2); + mesh.Faces.AddFace(3 * Sides + 2 + i, Sides + 2, 3 * Sides + 2); + } + } + + for (int i = 0; i < Sides; i++) + { + if (i < Sides - 1) + { + mesh.Faces.AddFace(2 * Sides + 2 + i, 3 * Sides + 2 + i, 3 * Sides + 3 + i); + mesh.Faces.AddFace(2 * Sides + 2 + i, 3 * Sides + 3 + i, 2 * Sides + 3 + i); + } + else + { + mesh.Faces.AddFace(2 * Sides + 2 + i, 3 * Sides + 2 + i, 3 * Sides + 2); + mesh.Faces.AddFace(2 * Sides + 2 + i, 3 * Sides + 2, 2 * Sides + 2); + } + } + + for (int i = 0; i < Sides; i++) + { + if (i < Sides - 1) + { + mesh.Faces.AddFace(2 + i, Sides + 2 + i, Sides + 3 + i); + mesh.Faces.AddFace(2 + i, Sides + 3 + i, 3 + i); + } + else + { + mesh.Faces.AddFace(2 + i, Sides + 2 + i, Sides + 2); + mesh.Faces.AddFace(2 + i, Sides + 2, 2); + } + } + mesh.Normals.ComputeNormals(); + mesh.UnifyNormals(); + mesh.Normals.ComputeNormals(); + + return mesh; + } + + private Mesh GenerateJointArmLabel(Point3d origin, Vector3d direction, string label, double length) + { + Polyline innerPoly; + var innerProfile = GetProfile(InnerWallRadius, direction); + innerProfile.TryGetPolyline(out innerPoly); + + var pSideMid = (innerPoly[1] + innerPoly[0]) / 2 + origin; + + Vector3d dir1 = length < 0 ? direction : -direction; + Vector3d dir3 = pSideMid - origin; + Vector3d dir2 = Vector3d.CrossProduct(dir3, dir1); + dir1.Unitize(); + dir2.Unitize(); + dir3.Unitize(); + + var textHeight = Math.Sqrt(OuterWallRadius * OuterWallRadius - InnerWallRadius * InnerWallRadius) / 1.5; + var embossHeight = (OuterWallRadius - InnerWallRadius) * 1.2; + + Vector3d startTextOffset = (length < 0 ? -direction : direction) * (Math.Abs(length) - (OuterWallRadius - InnerWallRadius)); + + Point3d planeOrigin = Point3d.Add(origin, startTextOffset); + planeOrigin = Point3d.Add(planeOrigin, dir3 * (pSideMid - origin).Length); + + var plane = new Plane(planeOrigin, dir1, dir2); + plane.UpdateEquation(); + + var style = new Rhino.DocObjects.DimensionStyle(); + style.TextHorizontalAlignment = Rhino.DocObjects.TextHorizontalAlignment.Left; + style.TextVerticalAlignment = Rhino.DocObjects.TextVerticalAlignment.Middle; + style.TextHeight = textHeight; + var prefFont = Rhino.DocObjects.Font.InstalledFonts("Lucida Console"); + if (prefFont.Length > 0) + style.Font = prefFont.First(); + + var writingPlane = new Plane(planeOrigin, new Vector3d(0, 0, 1)); // Must write to flat plane for some reason + + TextEntity textEnt = TextEntity.Create(label, writingPlane, style, false, Math.Abs(length), 0); + textEnt.SetBold(true); + + var meshes = textEnt.CreateExtrusions(style, embossHeight) + .Where(b => b != null) + .SelectMany(b => Mesh.CreateFromBrep(b.ToBrep(), MeshingParameters.FastRenderMesh)); + + var trans = Transform.PlaneToPlane(writingPlane, plane); + + if (meshes.Count() > 0) + { + var mesh = meshes.First(); + foreach (var m in meshes.Skip(1)) + { + mesh.Append(m); + } + mesh.Weld(Tolerance); + mesh.Normals.ComputeNormals(); + mesh.UnifyNormals(); + mesh.Normals.ComputeNormals(); + mesh.Transform(trans); + return mesh; + } + + return null; + } + } +} diff --git a/RodSteward/RodSteward.csproj b/RodSteward/RodSteward.csproj index 280dcec..9740000 100644 --- a/RodSteward/RodSteward.csproj +++ b/RodSteward/RodSteward.csproj @@ -73,6 +73,7 @@ + From 70d448b7f126947ed5b2f145d01314b52fa5e008 Mon Sep 17 00:00:00 2001 From: Mishael Nuh Date: Tue, 24 Dec 2019 14:52:01 -0500 Subject: [PATCH 3/8] Add default inputs for Generator component --- RodSteward/Generator.cs | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/RodSteward/Generator.cs b/RodSteward/Generator.cs index 1b8735f..97ec4f6 100644 --- a/RodSteward/Generator.cs +++ b/RodSteward/Generator.cs @@ -83,27 +83,26 @@ protected override void SolveInstance(IGH_DataAccess DA) double jointLength = 0; double tolerance = 0; + model = new Model(); + if (!DA.GetDataList(0, edges)) { return; } if (!DA.GetDataList(1, vertices)) { return; } - if (!DA.GetData(2, ref sides)) { return; } - if (!DA.GetData(3, ref radius)) { return; } - if (!DA.GetData(4, ref jointThickness)) { return; } - if (!DA.GetData(5, ref jointLength)) { return; } - if (!DA.GetData(6, ref tolerance)) { return; } + if (!DA.GetData(2, ref sides)) { sides = model.Sides; } + if (!DA.GetData(3, ref radius)) { radius = model.Radius; } + if (!DA.GetData(4, ref jointThickness)) { jointThickness = model.JointThickness; } + if (!DA.GetData(5, ref jointLength)) { jointLength = model.JointLength; } + if (!DA.GetData(6, ref tolerance)) { tolerance = model.Tolerance; } if (edges == null || vertices == null) { return; } if (radius <= 0 || sides <= 2 || jointThickness < 0 || jointLength < 0 || tolerance < 0) { throw new Exception("Invalid input."); } - model = new Model() - { - Edges = edges, - Vertices = vertices, - Sides = (int)Math.Floor(sides), - Radius = radius, - JointThickness = jointThickness, - JointLength = jointLength, - Tolerance = tolerance, - }; + model.Edges = edges; + model.Vertices = vertices; + model.Sides = (int)Math.Floor(sides); + model.Radius = radius; + model.JointThickness = jointThickness; + model.JointLength = jointLength; + model.Tolerance = tolerance; model.Generate(); model.CalculateClashes(); From 10d98d13301efb605411d3fae9fa57d5fbf05de6 Mon Sep 17 00:00:00 2001 From: Mishael Nuh Date: Tue, 24 Dec 2019 15:06:18 -0500 Subject: [PATCH 4/8] Remove unused libraries --- RodSteward/Generator.cs | 6 ------ RodSteward/Model.cs | 2 -- 2 files changed, 8 deletions(-) diff --git a/RodSteward/Generator.cs b/RodSteward/Generator.cs index 97ec4f6..8638b78 100644 --- a/RodSteward/Generator.cs +++ b/RodSteward/Generator.cs @@ -1,16 +1,10 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Text; -using System.Threading.Tasks; using Grasshopper.Kernel; using Grasshopper.GUI; using Grasshopper.GUI.Canvas; using Rhino.Geometry; -using MIConvexHull; -using System.Runtime.ExceptionServices; -using System.Security; -using Grasshopper; namespace RodSteward { diff --git a/RodSteward/Model.cs b/RodSteward/Model.cs index 80eee53..91ec0fb 100644 --- a/RodSteward/Model.cs +++ b/RodSteward/Model.cs @@ -2,8 +2,6 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Text; -using System.Threading.Tasks; using Grasshopper; using MIConvexHull; From 380a20d10a199f85a922619d7de86b4af6157564 Mon Sep 17 00:00:00 2001 From: Mishael Nuh Date: Tue, 24 Dec 2019 15:06:32 -0500 Subject: [PATCH 5/8] Change output components to use model object --- RodSteward/OutputJointSTL.cs | 23 ++++++++++++----------- RodSteward/OutputRodCutSVG.cs | 34 ++++++++++++++++------------------ 2 files changed, 28 insertions(+), 29 deletions(-) diff --git a/RodSteward/OutputJointSTL.cs b/RodSteward/OutputJointSTL.cs index 683805b..67dc625 100644 --- a/RodSteward/OutputJointSTL.cs +++ b/RodSteward/OutputJointSTL.cs @@ -29,7 +29,7 @@ public OutputJointSTL() protected override void RegisterInputParams(GH_InputParamManager pManager) { - pManager.AddMeshParameter("Joint", "J", "Joint meshes from Generator component", GH_ParamAccess.tree); + pManager.AddGenericParameter("Model", "M", "Model object", GH_ParamAccess.item); pManager.AddTextParameter("Directory", "D", "Output directory", GH_ParamAccess.item); pManager.AddBooleanParameter("Write Trigger", "T", "Triggers output", GH_ParamAccess.item); } @@ -41,11 +41,11 @@ protected override void RegisterOutputParams(GH_OutputParamManager pManager) protected override void SolveInstance(IGH_DataAccess DA) { - GH_Structure data = new GH_Structure(); + Model model = new Model(); string dir = null; bool trigger = false; - if (!DA.GetDataTree(0, out data)) { return; } + if (!DA.GetData(0, ref model)) { return; } if (!DA.GetData(1, ref dir)) { return; } if (!DA.GetData(2, ref trigger)) { return; } @@ -54,8 +54,7 @@ protected override void SolveInstance(IGH_DataAccess DA) return; } - if (data == null) { return; } - if (data.PathCount == 0) { return; } + if (model == null) { return; } if (!Directory.Exists(dir)) { @@ -69,15 +68,17 @@ protected override void SolveInstance(IGH_DataAccess DA) File.Delete(file); int fileCounter = 0; - for(int i = 0; i < data.Branches.Count(); i++) + + foreach(var kvp in model.JointMeshes) { var stlFile = new StlFile(); - stlFile.SolidName = "RS_Joint_Mesh_" + i.ToString(); - foreach(var m in data.Branches[i]) + stlFile.SolidName = "RS_Joint_Mesh_" + kvp.Key.ToString(); + + foreach(var m in kvp.Value) { - var vertices = m.Value.Vertices.Select(v => new StlVertex(v.X, v.Y, v.Z)).ToList(); - var faces = m.Value.Faces; - var normals = m.Value.FaceNormals.Select(n => new StlNormal(n.X, n.Y, n.Z)).ToList(); + var vertices = m.Vertices.Select(v => new StlVertex(v.X, v.Y, v.Z)).ToList(); + var faces = m.Faces; + var normals = m.FaceNormals.Select(n => new StlNormal(n.X, n.Y, n.Z)).ToList(); for(int f = 0; f < faces.Count(); f++) { diff --git a/RodSteward/OutputRodCutSVG.cs b/RodSteward/OutputRodCutSVG.cs index 1ad463f..606b604 100644 --- a/RodSteward/OutputRodCutSVG.cs +++ b/RodSteward/OutputRodCutSVG.cs @@ -33,9 +33,8 @@ public OutputRodCutSVG() protected override void RegisterInputParams(GH_InputParamManager pManager) { - pManager.AddCurveParameter("Rod Curves", "RC", "Joint meshes from Generator component", GH_ParamAccess.list); + pManager.AddGenericParameter("Model", "M", "Model object", GH_ParamAccess.item); pManager.AddNumberParameter("Stock Length", "SL", "Length of stock rods", GH_ParamAccess.item); - pManager.AddNumberParameter("Radius", "R", "Radius of rods", GH_ParamAccess.item); pManager.AddTextParameter("Directory", "D", "Output directory", GH_ParamAccess.item); pManager.AddBooleanParameter("Write Trigger", "T", "Triggers output", GH_ParamAccess.item); } @@ -48,35 +47,34 @@ protected override void RegisterOutputParams(GH_OutputParamManager pManager) protected override void SolveInstance(IGH_DataAccess DA) { - List data = new List(); + Model model = new Model(); double stockLength = 0; - double radius = 0; string dir = null; bool trigger = false; - if (!DA.GetDataList(0, data)) { return; } + if (!DA.GetData(0, ref model)) { return; } if (!DA.GetData(1, ref stockLength)) { return; } - if (!DA.GetData(2, ref radius)) { return; } - if (!DA.GetData(3, ref dir)) { return; } - if (!DA.GetData(4, ref trigger)) { return; } + if (!DA.GetData(2, ref dir)) { return; } + if (!DA.GetData(3, ref trigger)) { return; } - if (data == null) { return; } - if (data.Count == 0) { return; } + if (model == null) { return; } var binLengths = new List(); var binsTree = new DataTree(); - data = data.OrderByDescending(c => c.GetLength()).ToList(); + var lengths = model.RodCentrelines.Values + .Select(c => c.GetLength()) + .OrderByDescending(c => c) + .ToList(); - if (data.First().GetLength() > stockLength) + if (lengths.First() > stockLength) { this.AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Stock length less than longest member length."); return; } - foreach(var c in data) + foreach(var len in lengths) { - var len = c.GetLength(); bool added = false; for(int i = 0; i < binLengths.Count(); i++) { @@ -119,7 +117,7 @@ protected override void SolveInstance(IGH_DataAccess DA) var svgFile = new SvgDocument() { Width = new SvgUnit(SvgUnitType.None, (float)(stockLength + DOC_PADDING * 2)), - Height = new SvgUnit(SvgUnitType.None, (float)(radius * 2 * binLengths.Count() + ROD_PADDING * (binLengths.Count() - 1) + DOC_PADDING * 2)), + Height = new SvgUnit(SvgUnitType.None, (float)(model.Radius * 2 * binLengths.Count() + ROD_PADDING * (binLengths.Count() - 1) + DOC_PADDING * 2)), }; svgFile.ViewBox = new SvgViewBox(0, 0, svgFile.Width, svgFile.Height); @@ -132,7 +130,7 @@ protected override void SolveInstance(IGH_DataAccess DA) StartX = (float)(offset_x), EndX = (float)(offset_x), StartY = (float)(offset_y), - EndY = (float)(offset_y + radius * 2), + EndY = (float)(offset_y + model.Radius * 2), Stroke = new SvgColourServer(System.Drawing.Color.Red), StrokeWidth = 2, }); @@ -144,12 +142,12 @@ protected override void SolveInstance(IGH_DataAccess DA) StartX = (float)(offset_x), EndX = (float)(offset_x), StartY = (float)(offset_y), - EndY = (float)(offset_y + radius * 2), + EndY = (float)(offset_y + model.Radius * 2), Stroke = new SvgColourServer(System.Drawing.Color.Red), StrokeWidth = 2, }); } - offset_y += radius * 2 + ROD_PADDING; + offset_y += model.Radius * 2 + ROD_PADDING; } using (FileStream fs = File.Create(Path.Combine(dir, "RS_Laser_Cut_Plan.svg"))) From 94efa66009d7d1c3f02389e88b8d46fcab3a411d Mon Sep 17 00:00:00 2001 From: Mishael Nuh Date: Tue, 24 Dec 2019 15:28:52 -0500 Subject: [PATCH 6/8] Make inputs optional --- RodSteward/Generator.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/RodSteward/Generator.cs b/RodSteward/Generator.cs index 8638b78..d84db14 100644 --- a/RodSteward/Generator.cs +++ b/RodSteward/Generator.cs @@ -34,6 +34,12 @@ protected override void RegisterInputParams(GH_InputParamManager pManager) pManager.AddNumberParameter("Joint Thickness", "JT", "Thickness of Joint", GH_ParamAccess.item); pManager.AddNumberParameter("Joint Length", "JL", "Thickness of Joint", GH_ParamAccess.item); pManager.AddNumberParameter("Tolerance", "e", "Tolerance", GH_ParamAccess.item); + + pManager[2].Optional = true; + pManager[3].Optional = true; + pManager[4].Optional = true; + pManager[5].Optional = true; + pManager[6].Optional = true; } protected override void RegisterOutputParams(GH_OutputParamManager pManager) From eb5c89d4e02d2fa3c527859d74948022fc8467e5 Mon Sep 17 00:00:00 2001 From: Mishael Nuh Date: Tue, 24 Dec 2019 15:32:14 -0500 Subject: [PATCH 7/8] Prevent exception at instantiation. --- RodSteward/Generator.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/RodSteward/Generator.cs b/RodSteward/Generator.cs index d84db14..46ca4a8 100644 --- a/RodSteward/Generator.cs +++ b/RodSteward/Generator.cs @@ -57,6 +57,9 @@ protected override void RegisterOutputParams(GH_OutputParamManager pManager) public override void DrawViewportMeshes(IGH_PreviewArgs args) { + if (model == null) + return; + var errorMaterial = new Rhino.Display.DisplayMaterial(System.Drawing.Color.Red, 0.3); var rodMaterial = new Rhino.Display.DisplayMaterial(System.Drawing.Color.BurlyWood, 0.3); var jointMaterial = new Rhino.Display.DisplayMaterial(System.Drawing.Color.Black, 0.3); From 677cc29814e6633d4ecfc4e6d5a84c0ac71f8a4f Mon Sep 17 00:00:00 2001 From: Mishael Nuh Date: Tue, 24 Dec 2019 15:32:23 -0500 Subject: [PATCH 8/8] Update demo for refactor --- examples/Demo.gh | Bin 38372 -> 35897 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/examples/Demo.gh b/examples/Demo.gh index e5045a299a1fb0246a6a202a8e152fa2f3d95073..4493b4e048fb9846008d91038951ca954a8b4f7a 100644 GIT binary patch literal 35897 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%0AKD=I% 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 QPQJ!9xPiD{s^b{`KhgnpDgXcg