Exemplo n.º 1
0
        /// <summary>
        /// Adds a plate to the node if it is a 'sharp' node, to improve convex hull shape.
        /// </summary>
        /// <param name="nodeIndex"> Index of the node we want to check/fix. </param>
        /// <param name="sides"> Number of sides on the sleeve meshes. </param>
        public void FixSharpNodes(int nodeIndex, int sides)
        {
            ExoHull node = this.Hulls[nodeIndex];

            // The extra plate is in the direction of the negative sum of all normals
            // We use the new plate normal to check if the node struts are contained
            // within a 180deg peripheral (i.e. the node is 'sharp')
            bool isSharp = true;
            // Sum of all normals
            Vector3d extraNormal = new Vector3d();

            foreach (int plateIndex in node.PlateIndices)
            {
                extraNormal += this.Plates[plateIndex].Normal;
            }
            foreach (int plateIndex in node.PlateIndices)
            {
                if (Vector3d.VectorAngle(-extraNormal, this.Plates[plateIndex].Normal) < Math.PI / 4)
                {
                    isSharp = false;
                }
            }

            //  If struts form a sharp corner, add an extra plate for a better convex hull shape
            if (isSharp)
            {
                // Plane offset from node slightly
                Plane plane = new Plane(node.Point3d - extraNormal * node.AvgRadius / node.PlateIndices.Count, -extraNormal);
                // Compute the vertices
                List <Point3d> Vtc = MeshTools.CreateKnuckle(plane, sides, node.AvgRadius, 0);
                // Add new plate and its vertices
                this.Plates.Add(new ExoPlate(nodeIndex, -extraNormal));
                int newPlateIndx = this.Plates.Count - 1;
                this.Plates[newPlateIndx].Vtc.AddRange(Vtc);
                node.PlateIndices.Add(newPlateIndx);
            }
        }
Exemplo n.º 2
0
        /// <summary>
        /// Generates sleeve mesh for the struts. The plate offsets should be set before you use this method.
        /// </summary>
        /// <param name="strutIndex">Index of the strut being thickened.</param>
        /// <param name="sides">Number of sides for the strut mesh.</param>
        /// <param name="sleeveMesh">The sleeve mesh</param>
        public Mesh MakeSleeve(int strutIndex, int sides)
        {
            Mesh      sleeveMesh = new Mesh();
            ExoSleeve strut      = this.Sleeves[strutIndex];
            // Plate for the start/end of the sleeve
            ExoPlate startPlate = this.Plates[strut.PlatePair.I];
            ExoPlate endPlate   = this.Plates[strut.PlatePair.J];
            // Param at the start/end of the sleeve
            double startParam, endParam;

            startParam = startPlate.Offset;
            endParam   = 1 - endPlate.Offset;

            // Set center point of start & end plates
            startPlate.Vtc.Add(strut.Curve.PointAt(startParam));
            endPlate.Vtc.Add(strut.Curve.PointAt(endParam));

            // Compute the number of sleeve divisions (must be even)
            double avgRadius = strut.AvgRadius;
            double length    = strut.Curve.GetLength(new Interval(startParam, endParam));
            double divisions = Math.Max((Math.Round(length * 0.5 / avgRadius) * 2), 2);

            // Generate sleeve vertices
            Vector3d normal = strut.Curve.TangentAtStart;

            // Loops along strut
            for (int j = 0; j <= divisions; j++)
            {
                Plane plane;
                // For linear struts
                if (strut.Curve.IsLinear())
                {
                    Point3d knucklePt = startPlate.Vtc[0] + (normal * (length * j / divisions));
                    plane = new Plane(knucklePt, normal);
                }
                // For curved struts, we compute a new perpendicular frame at every iteration
                else
                {
                    double  locParameter = startParam + (j / divisions) * (endParam - startParam);
                    Point3d knucklePt    = strut.Curve.PointAt(locParameter);
                    strut.Curve.PerpendicularFrameAt(locParameter, out plane);
                }
                // Compute varriable radius
                double R = strut.StartRadius - j * (strut.StartRadius - strut.EndRadius) / (double)divisions;
                // This angle twists the plate points along the strut, for triangulation
                double startAngle = j * Math.PI / sides;

                // Compute the vertices
                List <Point3d> Vtc = MeshTools.CreateKnuckle(plane, sides, R, startAngle);

                // If the vertices are hull points (plates that connect sleeves to node hulls), save them
                if (j == 0)
                {
                    startPlate.Vtc.AddRange(Vtc);
                }
                if (j == divisions)
                {
                    endPlate.Vtc.AddRange(Vtc);
                }

                sleeveMesh.Vertices.AddVertices(Vtc); // save vertices to sleeve mesh
            }

            // Generate sleeve mesh (stitch vertices)
            int V1, V2, V3, V4;

            for (int j = 0; j < divisions; j++)
            {
                for (int i = 0; i < sides; i++)
                {
                    V1 = (j * sides) + i;
                    V2 = (j * sides) + i + sides;
                    V3 = (j * sides) + sides + (i + 1) % (sides);
                    V4 = (j * sides) + (i + 1) % (sides);

                    sleeveMesh.Faces.AddFace(V1, V2, V4);
                    sleeveMesh.Faces.AddFace(V2, V3, V4);
                }
            }

            return(sleeveMesh);
        }