public ConwayPoly Cylinderize(OpParams o)
        {
            var vertexPoints = new List <Vector3>();
            var faceIndices  = ListFacesByVertexIndices();

            for (var vertexIndex = 0; vertexIndex < Vertices.Count; vertexIndex++)
            {
                float amount = o.GetValueA(this, vertexIndex);
                var   vertex = Vertices[vertexIndex];
                if (IncludeVertex(vertexIndex, o.facesel, o.TagListFromString(), o.filterFunc))
                {
                    var normalized = new Vector2(vertex.Position.x, vertex.Position.z).normalized;
                    var result     = new Vector3(normalized.x, vertex.Position.y, normalized.y);
                    vertexPoints.Add(Vector3.LerpUnclamped(vertex.Position, result, amount));
                    VertexRoles[vertexIndex] = Roles.Existing;
                }
                else
                {
                    vertexPoints.Add(vertex.Position);
                    VertexRoles[vertexIndex] = Roles.Ignored;
                }
            }

            var conway = new ConwayPoly(vertexPoints, faceIndices, FaceRoles, VertexRoles, FaceTags);

            return(conway);
        }
        /**
         * Canonicalizes a polyhedron by adjusting its vertices iteratively.
         *
         * @param poly          The polyhedron whose vertices to adjust.
         * @param numIterations The number of iterations to adjust for.
         */
        public static void Adjust(ConwayPoly poly, int numIterations)
        {
            var dual = poly.Dual();

            for (int i = 0; i < numIterations; i++)
            {
                var newDualPositions = ReciprocalCenters(poly);
                dual.SetVertexPositions(newDualPositions);
                var newPositions = ReciprocalCenters(dual);
                poly.SetVertexPositions(newPositions);
            }
        }
        /**
         * A port of the "reciprocalC" function written by George Hart. Reflects
         * the centers of faces across the unit sphere.
         *
         * @param poly The polyhedron whose centers to invert.
         * @return The list of inverted face centers.
         */
        private static List <Vector3> ReciprocalCenters(ConwayPoly poly)
        {
            var faceCenters = new List <Vector3>();

            for (var i = 0; i < poly.Faces.Count; i++)
            {
                var newCenter = poly.Faces[i].Centroid;
                newCenter *= 1.0f / Mathf.Pow(newCenter.magnitude, 2);
                faceCenters.Add(newCenter);
            }

            return(faceCenters);
        }
        /**
         * A port of the "reciprocalN" function written by George Hart.
         *
         * @param poly The polyhedron to apply this canonicalization to.
         * @return A list of the new vertices of the dual polyhedron.
         */
        private static List <Vector3> ReciprocalVertices(ConwayPoly poly)
        {
            var newVertices = new List <Vector3>();

            foreach (var face in poly.Faces)
            {
                // Initialize values which will be updated in the loop below
                var    centroid        = face.Centroid;
                var    normalSum       = new Vector3();
                double avgEdgeDistance = 0.0;

                // Retrieve the indices of the vertices defining this face
                var faceVertices = face.GetVertices();

                // Keep track of the "previous" two vertices in CCW order
                var lastlastVertex = faceVertices[faceVertices.Count - 2];
                var lastVertex     = faceVertices[faceVertices.Count - 1];

                for (var i = 0; i < faceVertices.Count; i++)
                {
                    var vertex = faceVertices[i];
                    // Compute the normal of the plane defined by this vertex and
                    // the previous two
                    var v1 = lastlastVertex.Position;
                    v1 -= lastVertex.Position;
                    var v2 = vertex.Position;
                    v2 -= lastVertex.Position;
                    var normal = Vector3.Cross(v1, v2);
                    normalSum += normal;

                    // Compute distance from edge to origin
                    avgEdgeDistance += PointLineDist(new Vector3(), lastlastVertex.Position, lastVertex.Position);

                    // Update the previous vertices for the next iteration
                    lastlastVertex = lastVertex;
                    lastVertex     = vertex;
                }

                normalSum        = normalSum.normalized;
                avgEdgeDistance /= faceVertices.Count;

                var resultingVector = new Vector3();
                resultingVector  = Vector3.Dot(centroid, normalSum) * normalSum;
                resultingVector *= Mathf.Pow(1.0f / resultingVector.magnitude, 2);
                resultingVector *= (1.0f + (float)avgEdgeDistance) / 2.0f;
                newVertices.Add(resultingVector);
            }

            return(newVertices);
        }
        /**
         * A helper method for threshold-based termination in both planarizing and
         * adjusting. If a vertex moves by an unexpectedly large amount, or if the
         * new vertex position has an NaN component, the algorithm automatically
         * terminates.
         *
         * @param poly      The polyhedron to canonicalize.
         * @param threshold The threshold of vertex movement after an iteration.
         * @param planarize True if we are planarizing, false if we are adjusting.
         * @return The number of iterations that were executed.
         */
        private static int _Canonicalize(ConwayPoly poly, double threshold, bool planarize)
        {
            var dual             = poly.Dual();
            var currentPositions = poly.Vertices.Select(x => x.Position).ToList();

            int iterations = 0;

            while (true)
            {
                var newDualPositions = planarize ? ReciprocalVertices(poly) : ReciprocalCenters(poly);
                dual.SetVertexPositions(newDualPositions);
                var newPositions = planarize ? ReciprocalVertices(dual) : ReciprocalCenters(dual);

                double maxChange = 0.0;
                for (int i = 0; i < currentPositions.Count; i++)
                {
                    var newPos = poly.Vertices[i].Position;
                    var diff   = newPos - currentPositions[i];
                    maxChange = Math.Max(maxChange, diff.magnitude);
                }

                // Check if an error occurred in computation. If so, terminate
                // immediately
                if (Double.IsNaN(newPositions[0].x) || Double.IsNaN(newPositions[0].y) ||
                    Double.IsNaN(newPositions[0].z))
                {
                    break;
                }

                // Check if the position changed by a significant amount so as to
                // be erroneous. If so, terminate immediately
                if (planarize && maxChange > MAX_VERTEX_CHANGE)
                {
                    break;
                }

                poly.SetVertexPositions(newPositions);

                if (maxChange < threshold)
                {
                    break;
                }

                currentPositions = poly.Vertices.Select(x => x.Position).ToList();
                iterations++;
            }

            return(iterations);
        }
        /**
         * Canonicalizes this polyhedron until the change in position does not
         * exceed the given threshold. That is, the algorithm terminates when no vertex
         * moves more than the threshold after one iteration.
         *
         * @param thresholdAdjust    The threshold for change in one "adjust"
         *                           iteration.
         * @param thresholdPlanarize The threshold for change in one "planarize"
         *                           iteration.
         * @return The canonicalized version of this polyhedron.
         */
        public ConwayPoly Canonicalize(double thresholdAdjust, double thresholdPlanarize)
        {
            var        previousFaceRoles   = FaceRoles;
            var        previousVertexRoles = VertexRoles;
            ConwayPoly canonicalized       = Duplicate();

            if (thresholdAdjust > 0)
            {
                Adjust(canonicalized, thresholdAdjust);
            }
            if (thresholdPlanarize > 0)
            {
                Planarize(canonicalized, thresholdPlanarize);
            }
            canonicalized.FaceRoles   = previousFaceRoles;
            canonicalized.VertexRoles = previousVertexRoles;
            return(canonicalized);
        }
        /**
         * Modifies a polyhedron's vertices such that faces are closer to planar.
         * The more iterations, the closer the faces are to planar. If a vertex
         * moves by an unexpectedly large amount, or if the new vertex position
         * has an NaN component, the algorithm automatically terminates.
         *
         * @param poly          The polyhedron whose faces to planarize.
         * @param numIterations The number of iterations to planarize for.
         */
        public static void Planarize(ConwayPoly poly, int numIterations)
        {
            var dual = poly.Dual();

            for (int i = 0; i < numIterations; i++)
            {
                var newDualPositions = ReciprocalVertices(poly);
                dual.SetVertexPositions(newDualPositions);
                var newPositions = ReciprocalVertices(dual);

                double maxChange = 0.0;

                for (int j = 0; j < poly.Vertices.Count; j++)
                {
                    var newPos = poly.Vertices[j].Position;
                    var diff   = newPos - poly.Vertices[j].Position;
                    maxChange = Math.Max(maxChange, diff.magnitude);
                }

                // Check if an error occurred in computation. If so, terminate
                // immediately. This likely occurs when faces are already planar.
                if (Double.IsNaN(newPositions[0].x) || Double.IsNaN(newPositions[0].y) ||
                    Double.IsNaN(newPositions[0].z))
                {
                    break;
                }

                // Check if the position changed by a significant amount so as to
                // be erroneous. If so, terminate immediately
                if (maxChange > MAX_VERTEX_CHANGE)
                {
                    break;
                }

                poly.SetVertexPositions(newPositions);
            }
        }
 /**
  * Canonicalizes a polyhedron by adjusting its vertices iteratively. When
  * no vertex moves more than the given threshold, the algorithm terminates.
  *
  * @param poly      The polyhedron whose vertices to adjust.
  * @param threshold The threshold of vertex movement after an iteration.
  * @return The number of iterations that were executed.
  */
 public static int Adjust(ConwayPoly poly, double threshold)
 {
     return(_Canonicalize(poly, threshold, false));
 }
Exemple #9
0
 public MeshFaceList(ConwayPoly conwayPoly)
 {
     _mConwayPoly = conwayPoly;
 }
 /**
  * Modifies a polyhedron's vertices such that faces are closer to planar.
  * When no vertex moves more than the given threshold, the algorithm
  * terminates.
  *
  * @param poly      The polyhedron to canonicalize.
  * @param threshold The threshold of vertex movement after an iteration.
  * @return The number of iterations that were executed.
  */
 public static int Planarize(ConwayPoly poly, double threshold)
 {
     return(_Canonicalize(poly, threshold, true));
 }
 /// <summary>
 /// Convenience constructor, for use outside of the mesh class
 /// </summary>
 public MeshVertexList() : base()
 {
     _mConwayPoly = null;
 }
 /// <summary>
 /// Creates a vertex list that is aware of its parent mesh
 /// </summary>
 /// <param name="conwayPoly"></param>
 public MeshVertexList(ConwayPoly conwayPoly) : base()
 {
     _mConwayPoly = conwayPoly;
 }
Exemple #13
0
 /// <summary>
 /// Convenience constructor, for use outside of the mesh class
 /// </summary>
 public MeshHalfedgeList()
 {
     _mConwayPoly = null;
 }
Exemple #14
0
 /// <summary>
 /// Creates a halfedge list that is aware of its parent mesh
 /// </summary>
 /// <param name="conwayPoly"></param>
 public MeshHalfedgeList(ConwayPoly conwayPoly)
     : base()
 {
     _mConwayPoly = conwayPoly;
 }
Exemple #15
0
 public float GetValueB(ConwayPoly poly, int index) => funcB?.Invoke(new FilterParams(poly, index)) ?? valueB;