コード例 #1
0
        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);
        }
コード例 #2
0
        /// <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);
        }
コード例 #3
0
        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);
        }