public Dictionary <Tuple <int, int>, Mesh> GenerateRodMeshes() { RodMeshes.Clear(); RodCentrelines.Clear(); foreach (Tuple <int, int> 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); }
/// <summary> /// This is the method that actually does the work. /// </summary> /// <param name="DA">The DA object can be used to retrieve data from input parameters and /// to store data in output parameters.</param> protected override void SolveInstance(IGH_DataAccess DA) { // 1. Retrieve and validate data var cell = new UnitCell(); double radius = 0; double height = 0; int nU = 0; int nV = 0; int nW = 0; bool morphed = false; if (!DA.GetData(0, ref cell)) { return; } if (!DA.GetData(1, ref radius)) { return; } if (!DA.GetData(2, ref height)) { return; } if (!DA.GetData(3, ref nU)) { return; } if (!DA.GetData(4, ref nV)) { return; } if (!DA.GetData(5, ref nW)) { return; } if (!DA.GetData(6, ref morphed)) { return; } if (!cell.isValid) { return; } if (radius == 0) { return; } if (height == 0) { return; } if (nU == 0) { return; } if (nV == 0) { return; } if (nW == 0) { return; } // 2. Initialize the lattice var lattice = new Lattice(); // Will contain the morphed uv spaces (as surface-surface, surface-axis or surface-point) var spaceTree = new DataTree <GeometryBase>(); // 3. Define cylinder Plane basePlane = Plane.WorldXY; Surface cylinder = (new Cylinder(new Circle(basePlane, radius), height)).ToNurbsSurface(); cylinder = cylinder.Transpose(); LineCurve axis = new LineCurve(basePlane.Origin, basePlane.Origin + height * basePlane.ZAxis); // 4. Package the number of cells in each direction into an array float[] N = new float[3] { nU, nV, nW }; // 5. Normalize the UV-domain Interval unitDomain = new Interval(0, 1); cylinder.SetDomain(0, unitDomain); // surface u-direction cylinder.SetDomain(1, unitDomain); // surface v-direction axis.Domain = unitDomain; // 6. Prepare cell (this is a UnitCell object) cell = cell.Duplicate(); cell.FormatTopology(); // 7. Map nodes to design space // Loop through the uvw cell grid for (int u = 0; u <= N[0]; u++) { for (int v = 0; v <= N[1]; v++) { for (int w = 0; w <= N[2]; w++) { // Construct cell path in tree GH_Path treePath = new GH_Path(u, v, w); // Fetch the list of nodes to append to, or initialise it var nodeList = lattice.Nodes.EnsurePath(treePath); // This loop maps each node index in the cell onto the UV-surface maps for (int i = 0; i < cell.Nodes.Count; i++) { double usub = cell.Nodes[i].X; // u-position within unit cell (local) double vsub = cell.Nodes[i].Y; // v-position within unit cell (local) double wsub = cell.Nodes[i].Z; // w-position within unit cell (local) double[] uvw = { u + usub, v + vsub, w + wsub }; // uvw-position (global) // Check if the node belongs to another cell (i.e. it's relative path points outside the current cell) bool isOutsideCell = (cell.NodePaths[i][0] > 0 || cell.NodePaths[i][1] > 0 || cell.NodePaths[i][2] > 0); // Check if current uvw-position is beyond the upper boundary bool isOutsideSpace = (uvw[0] > N[0] || uvw[1] > N[1] || uvw[2] > N[2]); if (isOutsideCell || isOutsideSpace) { nodeList.Add(null); } else { Point3d pt1, pt2; Vector3d[] derivatives; // Construct z-position vector Vector3d vectorZ = height * basePlane.ZAxis * uvw[0] / N[0]; // Compute pt1 (on axis) pt1 = basePlane.Origin + vectorZ; // Compute pt2 (on surface) cylinder.Evaluate(uvw[0] / N[0], uvw[1] / N[1], 2, out pt2, out derivatives); // Create vector joining these two points Vector3d wVect = pt2 - pt1; // Instantiate new node var newNode = new LatticeNode(pt1 + wVect * uvw[2] / N[2]); // Add new node to tree nodeList.Add(newNode); } } } // Define the uv space map tree (used for morphing) if (morphed && u < N[0] && v < N[1]) { GH_Path spacePath = new GH_Path(u, v); // Set trimming interval var uInterval = new Interval((u) / N[0], (u + 1) / N[0]); var vInterval = new Interval((v) / N[1], (v + 1) / N[1]); // Create sub-surface and sub axis Surface ss1 = cylinder.Trim(uInterval, vInterval); Curve ss2 = axis.Trim(uInterval); // Unitize domains ss1.SetDomain(0, unitDomain); ss1.SetDomain(1, unitDomain); ss2.Domain = unitDomain; // Save to the space tree spaceTree.Add(ss1, spacePath); spaceTree.Add(ss2, spacePath); } } } // 8. Map struts to the node tree if (morphed) { lattice.MorphMapping(cell, spaceTree, N); } else { lattice.ConformMapping(cell, N); } // 9. Set output DA.SetDataList(0, lattice.Struts); }
public Dictionary <int, List <Mesh> > GenerateJointMeshes(bool label = true) { JointMeshes.Clear(); JointArmLabel.Clear(); var separateJointMeshes = new Dictionary <int, List <Mesh> >(); var jointArmCounter = new Dictionary <int, int>(); var jointCorePoints = new Dictionary <int, List <double[]> >(); for (int v = 0; v < Vertices.Count; v++) { separateJointMeshes[v] = new List <Mesh>(); jointCorePoints[v] = new List <double[]>(); jointArmCounter[v] = 1; } foreach (Tuple <int, int> 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)); endCurve = c.Trim(CurveEnd.Start, len - (Offsets[Tuple.Create(e.Item2, e.Item1)] + JointLength)); 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); if (label) { // 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 <int, List <double[]> > kvp in jointCorePoints) { try { var scaling = Math.Floor(1000 / kvp.Value.SelectMany(p => p).Max()); var convHullRes = ConvexHull.Create(kvp.Value.Select(p => p.Select(pi => pi * scaling).ToArray()).ToList()); 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] / scaling, p.Position[1] / scaling, p.Position[2] / scaling))); 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 <int, List <Mesh> > 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>() { mesh }; } } return(JointMeshes); }