/// <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. Declare placeholder variables and assign initial invalid data. // This way, if the input parameters fail to supply valid data, we know when to abort var cell = new UnitCell(); double xCellSize = 0; double yCellSize = 0; double zCellSize = 0; int nX = 0; int nY = 0; int nZ = 0; // 2. Retrieve input data. if (!DA.GetData(0, ref cell)) { return; } if (!DA.GetData(1, ref xCellSize)) { return; } if (!DA.GetData(2, ref yCellSize)) { return; } if (!DA.GetData(3, ref zCellSize)) { return; } if (!DA.GetData(4, ref nX)) { return; } if (!DA.GetData(5, ref nY)) { return; } if (!DA.GetData(6, ref nZ)) { return; } // 3. If data is invalid, we need to abort. if (!cell.isValid) { return; } if (xCellSize == 0) { return; } if (yCellSize == 0) { return; } if (zCellSize == 0) { return; } if (nX == 0) { return; } if (nY == 0) { return; } if (nZ == 0) { return; } // 4. Initialise the lattice object var lattice = new Lattice(); // 5. Prepare cell (this is a UnitCell object) cell = cell.Duplicate(); cell.FormatTopology(); // 6. Define BasePlane and directional iteration vectors Plane basePlane = Plane.WorldXY; Vector3d vectorX = xCellSize * basePlane.XAxis; Vector3d vectorY = yCellSize * basePlane.YAxis; Vector3d vectorZ = zCellSize * basePlane.ZAxis; float[] N = new float[3] { nX, nY, nZ }; // 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 in the cell 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 { // Compute position vector Vector3d V = uvw[0] * vectorX + uvw[1] * vectorY + uvw[2] * vectorZ; // Instantiate new node var newNode = new LatticeNode(basePlane.Origin + V); // Add new node to tree nodeList.Add(newNode); } } } } } // 8. Map struts to the node tree lattice.ConformMapping(cell, N); // 9. Set output DA.SetDataList(0, lattice.Struts); }
/// <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 inputs var cell = new UnitCell(); Surface s1 = null; Surface s2 = null; int nU = 0; int nV = 0; int nW = 0; bool morphed = false; if (!DA.GetData(0, ref cell)) { return; } if (!DA.GetData(1, ref s1)) { return; } if (!DA.GetData(2, ref s2)) { 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 (!s1.IsValid) { return; } if (!s2.IsValid) { 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) var spaceTree = new DataTree<GeometryBase>(); // 3. Package the number of cells in each direction into an array float[] N = new float[3] { nU, nV, nW }; // 4. Normalize the UV-domain Interval unitDomain = new Interval(0,1); s1.SetDomain(0, unitDomain); // s1 u-direction s1.SetDomain(1, unitDomain); // s1 v-direction s2.SetDomain(0, unitDomain); // s2 u-direction s2.SetDomain(1, unitDomain); // s2 v-direction // 5. Prepare cell (this is a UnitCell object) cell = cell.Duplicate(); cell.FormatTopology(); // 6. 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 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 { // Initialize for surface 1 Point3d pt1; Vector3d[] derivatives1; // Initialize for surface 2 Point3d pt2; Vector3d[] derivatives2; // Evaluate point on both surfaces s1.Evaluate(uvw[0] / N[0], uvw[1] / N[1], 2, out pt1, out derivatives1); s2.Evaluate(uvw[0] / N[0], uvw[1] / N[1], 2, out pt2, out derivatives2); // Create vector joining the two points (this is our w-range) Vector3d wVect = pt2 - pt1; // Create the node, accounting for the position along the w-direction var newNode = new LatticeNode(pt1 + wVect * uvw[2] / N[2]); // Add node to tree nodeList.Add(newNode); } } } // Define the uv space 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-surfaces Surface ss1 = s1.Trim(uInterval, vInterval); Surface ss2 = s2.Trim(uInterval, vInterval); // Unitize domain ss1.SetDomain(0, unitDomain); ss1.SetDomain(1, unitDomain); ss2.SetDomain(0, unitDomain); ss2.SetDomain(1, unitDomain); // Save to the space tree spaceTree.Add(ss1, spacePath); spaceTree.Add(ss2, spacePath); } } } // 7. Map struts to the node tree if (morphed) lattice.MorphMapping(cell, spaceTree, N); else lattice.ConformMapping(cell, N); // 8. Set output DA.SetDataList(0, lattice.Struts); }
/// <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); }