Exemple #1
0
 /// <summary>
 /// Copy constructor.
 /// </summary>
 public UnitCell Duplicate()
 {
     var dup = new UnitCell();
     foreach (Point3d node in Nodes)
     {
         dup.Nodes.Add(node);
     }
     foreach (IndexPair nodePair in NodePairs)
     {
         dup.NodePairs.Add(nodePair);
     }
     foreach (int[] nodePath in NodePaths)
     {
         dup.NodePaths.Add(new int[4] { nodePath[0], nodePath[1], nodePath[2], nodePath[3] });
     }
     return dup;
 }
Exemple #2
0
        /// <summary>
        /// Maps cell topology to UVWi node map (linear struts).
        /// </summary>
        public void ConformMapping(UnitCell cell, float[] N)
        {
            for (int u = 0; u <= N[0]; u++)
            {
                for (int v = 0; v <= N[1]; v++)
                {
                    for (int w = 0; w <= N[2]; w++)
                    {
                        // We're inside a unit cell
                        // Loop through all pairs of nodes that make up struts
                        foreach (IndexPair nodePair in cell.NodePairs)
                        {
                            // Prepare the path of the nodes (path in tree)
                            // First, get relative paths of nodes (with respect to current unit cell)
                            int[] IRel = cell.NodePaths[nodePair.I];
                            int[] JRel = cell.NodePaths[nodePair.J];
                            // Next, compute absolute paths
                            GH_Path IPath = new GH_Path(u + IRel[0], v + IRel[1], w + IRel[2]);
                            GH_Path JPath = new GH_Path(u + JRel[0], v + JRel[1], w + JRel[2]);

                            // Make sure the cell exists
                            // No cells exist beyond the boundary + 1
                            if (Nodes.PathExists(IPath) && Nodes.PathExists(JPath))
                            {
                                LatticeNode node1 = Nodes[IPath, IRel[3]];
                                LatticeNode node2 = Nodes[JPath, JRel[3]];
                                // Make sure both nodes exist:
                                // Null nodes either belong to other cells, or are beyond the upper uvw boundary
                                if (node1 != null && node2 != null)
                                {
                                    LineCurve curve = new LineCurve(node1.Point3d, node2.Point3d);
                                    if (curve != null && curve.IsValid)
                                    {
                                        Struts.Add(curve);
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
        /// <summary>
        /// Copy constructor.
        /// </summary>
        public UnitCell Duplicate()
        {
            var dup = new UnitCell();

            foreach (Point3d node in Nodes)
            {
                dup.Nodes.Add(node);
            }
            foreach (IndexPair nodePair in NodePairs)
            {
                dup.NodePairs.Add(nodePair);
            }
            foreach (int[] nodePath in NodePaths)
            {
                dup.NodePaths.Add(new int[4] {
                    nodePath[0], nodePath[1], nodePath[2], nodePath[3]
                });
            }
            return(dup);
        }
        /// <summary>
        /// This is the method that actually does the work.
        /// </summary>
        /// <param name="DA">The DA object is used to retrieve from inputs and store in outputs.</param>
        protected override void SolveInstance(IGH_DataAccess DA)
        {
            // 1. Retrieve/validate input
            var curves = new List<Curve>();
            if (!DA.GetDataList(0, curves)) { return; }

            // 2. Convert curve input to line input
            var lines = new List<Line>();
            foreach (Curve curve in curves)
            {
                // Make sure the curve is linear, if not, return error and abort.
                if (!curve.IsLinear())
                {
                    AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "All struts must be linear.");
                    return;
                }
                // Convert curve to line
                lines.Add(new Line(curve.PointAtStart, curve.PointAtEnd));
            }
    
            // 3. Instantiate UnitCell object.
            UnitCell cell = new UnitCell(lines);
            
            // 4. CheckValidity instance method to check the unit cell. Use the return value to output useful error message.
            switch (cell.CheckValidity())
            {
                case -1:
                    AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Invalid cell - opposing faces must be identical.");
                    return;
                case 0:
                    AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Invalid cell - each face needs at least one node lying on it.");
                    return;
                case 1:
                    AddRuntimeMessage(GH_RuntimeMessageLevel.Blank, "Your cell is valid!");
                    break;
            }

            // 5. Set output
            DA.SetData(0, new UnitCellGoo(cell));

        }
        /// <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 is used to retrieve from inputs and store in outputs.</param>
        protected override void SolveInstance(IGH_DataAccess DA)
        {
            // 0. Generate input menu list
            Component = this;
            GrasshopperDocument = this.OnPingDocument();
            // Only generate it if the input has no source
            if (Component.Params.Input[0].SourceCount == 0)
            {
                InputTools.TopoSelect(ref Component, ref GrasshopperDocument, 0, 11);
            }

            // 1. Retrieve input
            int cellType = 0;
            if (!DA.GetData(0, ref cellType)) { return; }

            // 2. Instantiate line list
            var lines = new List<Line>();

            // 3. Set cell size
            double d = 5;

            // 4. Switch statement for the different cell types
            switch (cellType)
            {
                // "GRID"
                case 0:
                    lines = GridLines(d);
                    break;
                // "X"
                case 1:
                    lines = XLines(d);
                    break;
                // "STAR"
                case 2:
                    lines = StarLines(d);
                    break;
                // "CROSS"
                case 3:
                    lines = CrossLines(d);                        
                    break;
                // "TESSERACT"
                case 4:
                    lines = TesseractLines(d);
                    break;
                // "VINTILES"
                case 5:
                    lines = VintileLines(d);
                    break;
                // "OCTET"
                case 6:
                    lines = OctetLines(d);
                    break;
                // "DIAMOND"
                case 7:
                    lines = DiamondLines(d);
                    break;
                // "HONEYCOMB"
                case 8:
                    lines = Honeycomb(d);
                    break;
                // "AUXETIC HONEYCOMB"
                case 9:
                    lines = AuxeticHoneycomb(d);
                    break;
            }

            // 5. Instantiate UnitCell object and check validity.
            var cell = new UnitCell(lines);
            if (!cell.isValid)
            {
                AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Invalid cell - this is embarassing.");
            }

            // 6. Construct normalized cell lines (for optional output)
            var lines2 = new List<Line>();
            foreach (IndexPair nodePair in cell.NodePairs)
            {
                lines2.Add(new Line(cell.Nodes[nodePair.I], cell.Nodes[nodePair.J]));
            }

            // 7. Set output (as LatticeCellGoo)
            DA.SetData(0, new UnitCellGoo(cell));
            DA.SetDataList(1, lines2);
        }
Exemple #7
0
        /// <summary>
        /// Maps cell topology to the node grid and trims to the design space.
        /// </summary>
        public void UniformMapping(UnitCell cell, GeometryBase designSpace, int spaceType, float[] N, double minStrutLength, double maxStrutLength)
        {
            double tol = RhinoDoc.ActiveDoc.ModelAbsoluteTolerance;

            for (int u = 0; u <= N[0]; u++)
            {
                for (int v = 0; v <= N[1]; v++)
                {
                    for (int w = 0; w <= N[2]; w++)
                    {
                        // We're inside a unit cell
                        // Loop through all pairs of nodes that make up struts
                        foreach (IndexPair nodePair in cell.NodePairs)
                        {
                            // Prepare the path of the nodes (path in tree)
                            // First, get relative paths of nodes (with respect to current unit cell)
                            int[] IRel = cell.NodePaths[nodePair.I];
                            int[] JRel = cell.NodePaths[nodePair.J];
                            // Next, compute absolute paths
                            GH_Path IPath = new GH_Path(u + IRel[0], v + IRel[1], w + IRel[2]);
                            GH_Path JPath = new GH_Path(u + JRel[0], v + JRel[1], w + JRel[2]);

                            // Make sure the cell exists
                            if (Nodes.PathExists(IPath) && Nodes.PathExists(JPath))
                            {
                                LatticeNode node1 = Nodes[IPath, IRel[3]];
                                LatticeNode node2 = Nodes[JPath, JRel[3]];
                                // Make sure both nodes exist:
                                // Null nodes either belong to other cells, or are beyond the upper uvw boundary
                                if (node1 != null && node2 != null)
                                {
                                    Curve fullCurve = new LineCurve(node1.Point3d, node2.Point3d);

                                    // If both nodes are inside, add full strut
                                    if (node1.IsInside && node2.IsInside)
                                    {
                                        Struts.Add(fullCurve);
                                    }
                                    // If neither node is inside, skip to next loop
                                    else if (!node1.IsInside && !node2.IsInside)
                                    {
                                        continue;
                                    }
                                    // Else, strut requires trimming
                                    else
                                    {
                                        // We are going to find the intersection point with the design space
                                        Point3d[] intersectionPts = null;
                                        Curve[]   overlapCurves   = null;
                                        LineCurve strutToTrim     = null;

                                        switch (spaceType)
                                        {
                                        // Brep design space
                                        case 1:
                                            strutToTrim = new LineCurve(node1.Point3d, node2.Point3d);
                                            // Find intersection point
                                            Intersection.CurveBrep(strutToTrim, (Brep)designSpace, tol, out overlapCurves, out intersectionPts);
                                            break;

                                        // Mesh design space
                                        case 2:
                                            // Dummy faceIds variable for MeshLine call
                                            int[] faceIds;
                                            strutToTrim = new LineCurve(node1.Point3d, node2.Point3d);
                                            // Find intersection point
                                            intersectionPts = Intersection.MeshLine((Mesh)designSpace, strutToTrim.Line, out faceIds);
                                            break;

                                        // Solid surface design space
                                        case 3:
                                            // Dummy overlapCurves variable for CurveBrep call
                                            overlapCurves = null;
                                            strutToTrim   = new LineCurve(node1.Point3d, node2.Point3d);
                                            // Find intersection point
                                            Intersection.CurveBrep(strutToTrim, ((Surface)designSpace).ToBrep(), tol, out overlapCurves, out intersectionPts);
                                            break;
                                        }

                                        LineCurve testLine = null;
                                        // Now, if an intersection point was found, trim the strut
                                        if (intersectionPts.Length > 0)
                                        {
                                            testLine = AddTrimmedStrut(node1, node2, intersectionPts[0], minStrutLength, maxStrutLength);
                                            // If the strut was succesfully trimmed, add it to the list
                                            if (testLine != null)
                                            {
                                                Struts.Add(testLine);
                                            }
                                        }
                                        else if (overlapCurves != null && overlapCurves.Length > 0)
                                        {
                                            Struts.Add(overlapCurves[0]);
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
Exemple #8
0
        /// <summary>
        /// Morphs cell topology to UVWI node map (morphed struts).
        /// </summary>
        public void MorphMapping(UnitCell cell, DataTree <GeometryBase> spaceTree, float[] N)
        {
            for (int u = 0; u <= N[0]; u++)
            {
                for (int v = 0; v <= N[1]; v++)
                {
                    for (int w = 0; w <= N[2]; w++)
                    {
                        // We're inside a unit cell
                        // Loop through all pairs of nodes that make up struts
                        foreach (IndexPair nodePair in cell.NodePairs)
                        {
                            // Prepare the path of the nodes (path in tree)
                            // First, get relative paths of nodes (with respect to current unit cell)
                            int[] IRel = cell.NodePaths[nodePair.I];
                            int[] JRel = cell.NodePaths[nodePair.J];
                            // Next, compute absolute paths
                            GH_Path IPath = new GH_Path(u + IRel[0], v + IRel[1], w + IRel[2]);
                            GH_Path JPath = new GH_Path(u + JRel[0], v + JRel[1], w + JRel[2]);

                            // Make sure the cell exists
                            // No cells exist beyond the boundary + 1
                            if (Nodes.PathExists(IPath) && Nodes.PathExists(JPath))
                            {
                                LatticeNode node1 = Nodes[IPath, IRel[3]];
                                LatticeNode node2 = Nodes[JPath, JRel[3]];
                                // Make sure both nodes exist:
                                // Null nodes either belong to other cells, or are beyond the upper uvw boundary.
                                if (node1 != null && node2 != null)
                                {
                                    GH_Path spacePath;

                                    // If strut is along boundary, we must use the previous morph space
                                    // Since one does not exist beyond the boundary)
                                    if (u == N[0] && v == N[1])
                                    {
                                        spacePath = new GH_Path(u - 1, v - 1);
                                    }
                                    else if (u == N[0])
                                    {
                                        spacePath = new GH_Path(u - 1, v);
                                    }
                                    else if (v == N[1])
                                    {
                                        spacePath = new GH_Path(u, v - 1);
                                    }
                                    else
                                    {
                                        spacePath = new GH_Path(u, v);
                                    }

                                    // Retrieve uv cell space (will be casted in the tempPt loop)
                                    GeometryBase ss1 = spaceTree[spacePath, 0];
                                    GeometryBase ss2 = spaceTree[spacePath, 1];

                                    // Discretize the unit cell line for morph mapping
                                    int ptCount = 16;
                                    // Template points are unitized cell points (x,y of these points are u,v of sub-surface)
                                    var  templatePts  = new List <Point3d>();
                                    Line templateLine = new Line(cell.Nodes[nodePair.I], cell.Nodes[nodePair.J]);
                                    for (int ptIndex = 0; ptIndex <= ptCount; ptIndex++)
                                    {
                                        templatePts.Add(templateLine.PointAt(ptIndex / (double)ptCount));
                                    }

                                    // We will map the lines' points to its uvw cell-space
                                    // Control points are the interpolation points in space
                                    var controlPoints = new List <Point3d>();

                                    foreach (Point3d tempPt in templatePts)
                                    {
                                        Point3d    surfPt;
                                        Vector3d[] surfDerivs;
                                        // UV params on unitized sub-surface are simply the xy coordinate of the template point
                                        double uParam = tempPt.X;
                                        double vParam = tempPt.Y;
                                        // If at boundary, we're using a previous morph space, so reverse the parameter(s)
                                        if (u == N[0])
                                        {
                                            uParam = 1 - uParam;
                                        }
                                        if (v == N[1])
                                        {
                                            vParam = 1 - vParam;
                                        }

                                        // Now, we will map the template point to the uvw-space
                                        ((Surface)ss1).Evaluate(uParam, vParam, 0, out surfPt, out surfDerivs);
                                        Vector3d wVect = Vector3d.Unset;
                                        switch (ss2.ObjectType)
                                        {
                                        case ObjectType.Point:
                                            wVect = ((Point)ss2).Location - surfPt;;
                                            break;

                                        case ObjectType.Curve:
                                            wVect = ((Curve)ss2).PointAt(uParam) - surfPt;
                                            break;

                                        case ObjectType.Surface:
                                            Point3d    surfPt2;
                                            Vector3d[] surfDerivs2;
                                            ((Surface)ss2).Evaluate(uParam, vParam, 0, out surfPt2, out surfDerivs2);
                                            wVect = surfPt2 - surfPt;
                                            break;
                                        }
                                        // The mapped point
                                        Point3d uvwPt = surfPt + wVect * (w + tempPt.Z) / N[2];
                                        controlPoints.Add(uvwPt);
                                    }

                                    // Now create interpolated curve based on control points
                                    Curve curve = Curve.CreateInterpolatedCurve(controlPoints, 3);

                                    if (curve != null && curve.IsValid)
                                    {
                                        Struts.Add(curve);
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
        /// <summary>
        /// This is the method that actually does the work.
        /// </summary>
        /// <param name="DA">The DA object is used to retrieve from inputs and store in outputs.</param>
        protected override void SolveInstance(IGH_DataAccess DA)
        {
            // 1. Retrieve and validate data
            var cell = new UnitCell();
            GeometryBase designSpace = null;
            Plane orientationPlane = Plane.Unset;
            double xCellSize = 0;
            double yCellSize = 0;
            double zCellSize = 0;
            double minLength = 0; // the trim tolerance (i.e. minimum strut length)
            double maxLength = 0;
            bool strictlyIn = false;

            if (!DA.GetData(0, ref cell)) { return; }
            if (!DA.GetData(1, ref designSpace)) { return; }
            if (!DA.GetData(2, ref orientationPlane)) { return; }
            if (!DA.GetData(3, ref xCellSize)) { return; }
            if (!DA.GetData(4, ref yCellSize)) { return; }
            if (!DA.GetData(5, ref zCellSize)) { return; }
            if (!DA.GetData(6, ref minLength)) { return; }
            if (!DA.GetData(7, ref maxLength)) { return; }
            if (!DA.GetData(8, ref strictlyIn)) { return; }

            if (!cell.isValid) { return; }
            if (!designSpace.IsValid) { return; }
            if (!orientationPlane.IsValid) { return; }
            if (xCellSize == 0) { return; } 
            if (yCellSize == 0) { return; }
            if (zCellSize == 0) { return; }
            if (minLength>=xCellSize || minLength>=yCellSize || minLength>=zCellSize)
            {
                AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Tolerance parameter cannot be larger than the unit cell dimensions.");
                return;
            }
            // 2. Validate the design space
            int spaceType = FrameTools.ValidateSpace(ref designSpace);
            if (spaceType == 0)
            {
                AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Design space must be a closed Brep, Mesh or Surface");
                return;
            }

            double tol = RhinoDoc.ActiveDoc.ModelAbsoluteTolerance;
                
            // 3. Compute oriented bounding box and its corner points
            Box bBox = new Box();
            designSpace.GetBoundingBox(orientationPlane, out bBox);
            Point3d[] bBoxCorners = bBox.GetCorners();
            //    Set basePlane based on the bounding box
            Plane basePlane = new Plane(bBoxCorners[0], bBoxCorners[1], bBoxCorners[3]);

            // 4. Determine number of iterations required to fill the box, and package into array
            double xLength = bBoxCorners[0].DistanceTo(bBoxCorners[1]);
            double yLength = bBoxCorners[0].DistanceTo(bBoxCorners[3]);
            double zLength = bBoxCorners[0].DistanceTo(bBoxCorners[4]);
            int nX = (int)Math.Ceiling(xLength / xCellSize); // Roundup to next integer if non-integer
            int nY = (int)Math.Ceiling(yLength / yCellSize);
            int nZ = (int)Math.Ceiling(zLength / zCellSize);
            float[] N = new float[3] { nX, nY, nZ };

            // 5. Initialize nodeTree
            var lattice = new Lattice();

            // 6. Prepare cell (this is a UnitCell object)
            cell = cell.Duplicate();
            cell.FormatTopology();

            // 7. Define iteration vectors in each direction (accounting for Cell Size)
            Vector3d vectorU = xCellSize * basePlane.XAxis;
            Vector3d vectorV = yCellSize * basePlane.YAxis;
            Vector3d vectorW = zCellSize * basePlane.ZAxis;

            // 8. 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] * vectorU + uvw[1] * vectorV + uvw[2] * vectorW;
                                var newNode = new LatticeNode(basePlane.Origin + V);

                                // Check if point is inside - use unstrict tolerance, meaning it can be outside the surface by the specified tolerance
                                bool isInside = FrameTools.IsPointInside(designSpace, newNode.Point3d, spaceType, tol, strictlyIn);

                                // Set the node state (it's location wrt the design space)
                                if (isInside)
                                {
                                    newNode.State = LatticeNodeState.Inside;
                                }
                                else
                                {
                                    newNode.State = LatticeNodeState.Outside;
                                }

                                // Add node to tree
                                nodeList.Add(newNode);
                            }
                        }
                    }
                }
            }

            // 9. Map struts to the node tree
            lattice.UniformMapping(cell, designSpace, spaceType, N, minLength, maxLength);
                
            // 10. 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. 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);            
        }
Exemple #11
0
        /// <summary>
        /// Maps cell topology to UVWi node map (linear struts).         
        /// </summary>
        public void ConformMapping(UnitCell cell, float[] N)
        {
            for (int u = 0; u <= N[0]; u++)
            {
                for (int v = 0; v <= N[1]; v++)
                {
                    for (int w = 0; w <= N[2]; w++)
                    {
                        // We're inside a unit cell
                        // Loop through all pairs of nodes that make up struts
                        foreach (IndexPair nodePair in cell.NodePairs)
                        {
                            // Prepare the path of the nodes (path in tree)
                            // First, get relative paths of nodes (with respect to current unit cell)
                            int[] IRel = cell.NodePaths[nodePair.I];
                            int[] JRel = cell.NodePaths[nodePair.J];
                            // Next, compute absolute paths
                            GH_Path IPath = new GH_Path(u + IRel[0], v + IRel[1], w + IRel[2]);
                            GH_Path JPath = new GH_Path(u + JRel[0], v + JRel[1], w + JRel[2]);

                            // Make sure the cell exists
                            // No cells exist beyond the boundary + 1
                            if (Nodes.PathExists(IPath) && Nodes.PathExists(JPath))
                            {
                                LatticeNode node1 = Nodes[IPath, IRel[3]];
                                LatticeNode node2 = Nodes[JPath, JRel[3]];
                                // Make sure both nodes exist:
                                // Null nodes either belong to other cells, or are beyond the upper uvw boundary
                                if (node1 != null && node2 != null)
                                {
                                    LineCurve curve = new LineCurve(node1.Point3d, node2.Point3d);
                                    if (curve != null && curve.IsValid)
                                    {
                                        Struts.Add(curve);
                                    }
                                }
                            }
                            
                        }
                    }
                }
            }
        }
Exemple #12
0
        /// <summary>
        /// Maps cell topology to the node grid and trims to the design space.
        /// </summary>
        public void UniformMapping(UnitCell cell, GeometryBase designSpace, int spaceType, float[] N, double minStrutLength, double maxStrutLength)
        {
            double tol = RhinoDoc.ActiveDoc.ModelAbsoluteTolerance;

            for (int u = 0; u <= N[0]; u++)
            {
                for (int v = 0; v <= N[1]; v++)
                {
                    for (int w = 0; w <= N[2]; w++)
                    {
                        // We're inside a unit cell
                        // Loop through all pairs of nodes that make up struts
                        foreach (IndexPair nodePair in cell.NodePairs)
                        {
                            // Prepare the path of the nodes (path in tree)
                            // First, get relative paths of nodes (with respect to current unit cell)
                            int[] IRel = cell.NodePaths[nodePair.I];
                            int[] JRel = cell.NodePaths[nodePair.J];
                            // Next, compute absolute paths
                            GH_Path IPath = new GH_Path(u + IRel[0], v + IRel[1], w + IRel[2]);
                            GH_Path JPath = new GH_Path(u + JRel[0], v + JRel[1], w + JRel[2]);

                            // Make sure the cell exists
                            if (Nodes.PathExists(IPath) && Nodes.PathExists(JPath))
                            {
                                LatticeNode node1 = Nodes[IPath, IRel[3]];
                                LatticeNode node2 = Nodes[JPath, JRel[3]];
                                // Make sure both nodes exist:
                                // Null nodes either belong to other cells, or are beyond the upper uvw boundary
                                if (node1 != null && node2 != null)
                                {
                                    Curve fullCurve = new LineCurve(node1.Point3d, node2.Point3d);

                                    // If both nodes are inside, add full strut
                                    if (node1.IsInside && node2.IsInside)
                                    {
                                        Struts.Add(fullCurve);
                                    }
                                    // If neither node is inside, skip to next loop
                                    else if (!node1.IsInside && !node2.IsInside)
                                    {
                                        continue;
                                    }
                                    // Else, strut requires trimming
                                    else
                                    {
                                        // We are going to find the intersection point with the design space
                                        Point3d[] intersectionPts = null;
                                        Curve[] overlapCurves = null;
                                        LineCurve strutToTrim = null;

                                        switch (spaceType)
                                        {
                                            // Brep design space
                                            case 1:
                                                strutToTrim = new LineCurve(node1.Point3d, node2.Point3d);
                                                // Find intersection point
                                                Intersection.CurveBrep(strutToTrim, (Brep)designSpace, tol, out overlapCurves, out intersectionPts);
                                                break;
                                            // Mesh design space
                                            case 2:
                                                // Dummy faceIds variable for MeshLine call
                                                int[] faceIds;
                                                strutToTrim = new LineCurve(node1.Point3d, node2.Point3d);
                                                // Find intersection point
                                                intersectionPts = Intersection.MeshLine((Mesh)designSpace, strutToTrim.Line, out faceIds);
                                                break;
                                            // Solid surface design space
                                            case 3:
                                                // Dummy overlapCurves variable for CurveBrep call
                                                overlapCurves = null;
                                                strutToTrim = new LineCurve(node1.Point3d, node2.Point3d);
                                                // Find intersection point
                                                Intersection.CurveBrep(strutToTrim, ((Surface)designSpace).ToBrep(), tol, out overlapCurves, out intersectionPts);
                                                break;
                                        }

                                        LineCurve testLine = null;
                                        // Now, if an intersection point was found, trim the strut
                                        if (intersectionPts.Length > 0)
                                        {
                                            testLine = AddTrimmedStrut(node1, node2, intersectionPts[0], minStrutLength, maxStrutLength);
                                            // If the strut was succesfully trimmed, add it to the list
                                            if (testLine != null)
                                            {
                                                Struts.Add(testLine);
                                            }
                                        }
                                        else if (overlapCurves != null && overlapCurves.Length > 0)
                                        {
                                            Struts.Add(overlapCurves[0]);
                                        }

                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
Exemple #13
0
        /// <summary>
        /// Morphs cell topology to UVWI node map (morphed struts).
        /// </summary>
        public void MorphMapping(UnitCell cell, DataTree<GeometryBase> spaceTree, float[] N)
        {
            for (int u = 0; u <= N[0]; u++)
            {
                for (int v = 0; v <= N[1]; v++)
                {
                    for (int w = 0; w <= N[2]; w++)
                    {
                        // We're inside a unit cell
                        // Loop through all pairs of nodes that make up struts
                        foreach (IndexPair nodePair in cell.NodePairs)
                        {
                            // Prepare the path of the nodes (path in tree)
                            // First, get relative paths of nodes (with respect to current unit cell)
                            int[] IRel = cell.NodePaths[nodePair.I];
                            int[] JRel = cell.NodePaths[nodePair.J];
                            // Next, compute absolute paths
                            GH_Path IPath = new GH_Path(u + IRel[0], v + IRel[1], w + IRel[2]);
                            GH_Path JPath = new GH_Path(u + JRel[0], v + JRel[1], w + JRel[2]);

                            // Make sure the cell exists
                            // No cells exist beyond the boundary + 1
                            if (Nodes.PathExists(IPath) && Nodes.PathExists(JPath))
                            {
                                LatticeNode node1 = Nodes[IPath, IRel[3]];
                                LatticeNode node2 = Nodes[JPath, JRel[3]];
                                // Make sure both nodes exist:
                                // Null nodes either belong to other cells, or are beyond the upper uvw boundary.
                                if (node1 != null && node2 != null)
                                {
                                    GH_Path spacePath;

                                    // If strut is along boundary, we must use the previous morph space 
                                    // Since one does not exist beyond the boundary) 
                                    if (u == N[0] && v == N[1])
                                    {
                                        spacePath = new GH_Path(u - 1, v - 1);
                                    }
                                    else if (u == N[0])
                                    {
                                        spacePath = new GH_Path(u - 1, v);
                                    }
                                    else if (v == N[1])
                                    {
                                        spacePath = new GH_Path(u, v - 1);
                                    }                                        
                                    else
                                    {
                                        spacePath = new GH_Path(u, v);
                                    }

                                    // Retrieve uv cell space (will be casted in the tempPt loop)
                                    GeometryBase ss1 = spaceTree[spacePath, 0];
                                    GeometryBase ss2 = spaceTree[spacePath, 1];

                                    // Discretize the unit cell line for morph mapping
                                    int ptCount = 16;
                                    // Template points are unitized cell points (x,y of these points are u,v of sub-surface)
                                    var templatePts = new List<Point3d>();  
                                    Line templateLine = new Line(cell.Nodes[nodePair.I], cell.Nodes[nodePair.J]);
                                    for (int ptIndex = 0; ptIndex <= ptCount; ptIndex++)
                                    {
                                        templatePts.Add(templateLine.PointAt(ptIndex / (double)ptCount));
                                    }

                                    // We will map the lines' points to its uvw cell-space
                                    // Control points are the interpolation points in space
                                    var controlPoints = new List<Point3d>();

                                    foreach (Point3d tempPt in templatePts)
                                    {
                                        Point3d surfPt;
                                        Vector3d[] surfDerivs;
                                        // UV params on unitized sub-surface are simply the xy coordinate of the template point
                                        double uParam = tempPt.X;
                                        double vParam = tempPt.Y;
                                        // If at boundary, we're using a previous morph space, so reverse the parameter(s)
                                        if (u == N[0])
                                        {
                                            uParam = 1 - uParam;
                                        }
                                        if (v == N[1])
                                        {
                                            vParam = 1 - vParam;
                                        }

                                        // Now, we will map the template point to the uvw-space
                                        ((Surface)ss1).Evaluate(uParam, vParam, 0, out surfPt, out surfDerivs);
                                        Vector3d wVect = Vector3d.Unset;
                                        switch (ss2.ObjectType)
                                        {
                                            case ObjectType.Point:
                                                wVect = ((Point)ss2).Location - surfPt; ;
                                                break;
                                            case ObjectType.Curve:
                                                wVect = ((Curve)ss2).PointAt(uParam) - surfPt;
                                                break;
                                            case ObjectType.Surface: 
                                                Point3d surfPt2;
                                                Vector3d[] surfDerivs2;
                                                ((Surface)ss2).Evaluate(uParam, vParam, 0, out surfPt2, out surfDerivs2);
                                                wVect = surfPt2 - surfPt;
                                                break;
                                        }
                                        // The mapped point
                                        Point3d uvwPt = surfPt + wVect * (w + tempPt.Z) / N[2];
                                        controlPoints.Add(uvwPt);

                                    }

                                    // Now create interpolated curve based on control points
                                    Curve curve = Curve.CreateInterpolatedCurve(controlPoints, 3);

                                    if (curve != null && curve.IsValid)
                                    {
                                        Struts.Add(curve);
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
        /// <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);            
        }