Exemplo n.º 1
0
        /// <summary>
        /// Calculates the area of the Triangle formed by the three given points.
        /// The points shouldn't be colinear.
        /// </summary>
        /// <param name="A">Corner of the Triangle</param>
        /// <param name="B">Corner of the Triangle</param>
        /// <param name="C">Corner of the Triangle</param>
        /// <returns>Area of the Triangle</returns>
        public static double GetAreaOf(Vector A, Vector B, Vector C)
        {
            Vector cb = B - C;
            Vector ca = A - C;

            double a = cb.Length();
            double b = ca.Length();

            return(0.5 * a * b * Math.Sin(Vertex.Angle(cb, ca)));
        }
Exemplo n.º 2
0
        /// <summary>
        /// Fills the intial arrays, sets the extrema, the center and the scale.
        /// Sets the incident Triangles and the Neighborhood of each Vertex.
        /// Fills the Edge list. Calculates the Triangle normals.
        /// Sets the local coordinate system and the rotation matrix for each Triangle.
        /// Determines the area nearest each Vertex of a Triangle and the area of the entire Triangle.
        /// Calculates the angles of the Triangles.
        /// </summary>
        /// <param name="triNormals">If true, the Triangle normals and the centroid are calculated.
        /// If False, they are not calculated.</param>
        public void Finish(bool triNormals)
        {
            double oldMinLength = 0;

            if (edges.Count != 0)
            {
                oldMinLength = edges.Values[0].Length;
            }
            ClearRelations();

            Edge   edge;
            double edgeLength;

            float[] min = new float[3] {
                0.0f, 0.0f, 0.0f
            };
            float[] max = new float[3] {
                0.0f, 0.0f, 0.0f
            };

            // Calculates the minimum and maximum coordinates of every Triangle.
            for (int i = 0; i < this.Count; i++)
            {
                for (int j = 0; j < 3; j++)
                {
                    if (this[i, 1][j] <= this[i, 0][j])
                    {
                        this[i].Min[j] = (float)this[i, 1][j];
                        this[i].Max[j] = (float)this[i, 0][j];
                    }
                    else
                    {
                        this[i].Min[j] = (float)this[i, 0][j];
                        this[i].Max[j] = (float)this[i, 1][j];
                    }

                    if (this[i, 2][j] < this[i].Min[j])
                    {
                        this[i].Min[j] = (float)this[i, 2][j];
                    }
                    if (this[i, 2][j] > this[i].Max[j])
                    {
                        this[i].Max[j] = (float)this[i, 2][j];
                    }
                }
            }

            // Initializes maximum and minimum with the values of the first Triangle.
            for (int h = 0; h < 3; h++)
            {
                if (this.Count > 0)
                {
                    min[h] = this[0].Min[h];
                    max[h] = this[0].Max[h];
                }
                else
                {
                    min[h] = 0;
                    max[h] = 1;
                }
            }

            for (int i = 0; i < this.Count; i++)
            {
                if (triNormals)
                {
                    // Sets the Centroid for each Triangle.
                    this[i].Centroid = ((vertices[this[i][0]] + vertices[this[i][1]] + vertices[this[i][2]]) / 3).ToVertex();
                    // Sets the Normal for each Triangle.
                    this[i].Centroid.Normal = Triangle.GetNormalOf(this[i, 0], this[i, 1], this[i, 2]);
                }

                for (int j = 0; j < 3; j++)
                {
                    if (this[i].Min[j] < min[j])
                    {
                        min[j] = this[i].Min[j];
                    }
                    if (this[i].Max[j] > max[j])
                    {
                        max[j] = this[i].Max[j];
                    }

                    // Sets the incident Triangles.
                    this[i, j].AddIncidentTriangle(i);
                    // Sets the Neighborhood.
                    this[i, j].Neighborhood.AddNeighbors(this[i][(j + 1) % 3], this[i][(j + 2) % 3]);
                    // Fills the Edge list.
                    edgeLength = Vertex.Distance(this[i, j], this[i, (j + 1) % 3]);
                    edge       = new Edge(this[i][j], this[i][(j + 1) % 3], edgeLength);
                    this[i].Edges.Add(edge);
                    if (!edges.ContainsKey(edge.Key))
                    {
                        edge.Triangles.Add(i);
                        edges.Add(edge.Key, edge);
                    }
                    else
                    {
                        edges[edge.Key].Triangles.Add(i);
                    }
                }

                // Sets the areas closest to each corner of a Triangle.
                // This was adapted from Szymon Rusinkiewicz C++ library trimesh2 (http://www.cs.princeton.edu/gfx/proj/trimesh2/).
                Vector[] e = new Vector[3] {
                    this[i, 2] - this[i, 1], this[i, 0] - this[i, 2], this[i, 1] - this[i, 0]
                };
                double   area = 0.5 * (e[0] % e[1]).Length();
                double[] l2   = new double[3] {
                    e[0].SquaredLength(), e[1].SquaredLength(), e[2].SquaredLength()
                };
                double[] ew = new double[3] {
                    l2[0] * (l2[1] + l2[2] - l2[0]), l2[1] * (l2[2] + l2[0] - l2[1]), l2[2] * (l2[0] + l2[1] - l2[2])
                };

                if (ew[0] <= 0.0f)
                {
                    this[i].CornerAreas[1] = -0.25 * l2[2] * area / (e[0].Dot(e[2]));
                    this[i].CornerAreas[2] = -0.25 * l2[1] * area / (e[0].Dot(e[1]));
                    this[i].CornerAreas[0] = area - this[i].CornerAreas[1] - this[i].CornerAreas[2];
                }
                else if (ew[1] <= 0.0f)
                {
                    this[i].CornerAreas[2] = -0.25 * l2[0] * area / (e[1].Dot(e[0]));
                    this[i].CornerAreas[0] = -0.25 * l2[2] * area / (e[1].Dot(e[2]));
                    this[i].CornerAreas[1] = area - this[i].CornerAreas[2] - this[i].CornerAreas[0];
                }
                else if (ew[2] <= 0.0f)
                {
                    this[i].CornerAreas[0] = -0.25 * l2[1] * area / (e[2].Dot(e[1]));
                    this[i].CornerAreas[1] = -0.25 * l2[0] * area / (e[2].Dot(e[0]));
                    this[i].CornerAreas[2] = area - this[i].CornerAreas[0] - this[i].CornerAreas[1];
                }
                else
                {
                    double ewscale = 0.5 * area / (ew[0] + ew[1] + ew[2]);
                    for (int j = 0; j < 3; j++)
                    {
                        this[i].CornerAreas[j] = ewscale * (ew[(j + 1) % 3] + ew[(j + 2) % 3]);
                    }
                }
                // The Voronoi area of a Vertex is caclulated by summing up the calculated corner areas.
                this[i, 0].Area += this[i].CornerAreas[0];
                this[i, 1].Area += this[i].CornerAreas[1];
                this[i, 2].Area += this[i].CornerAreas[2];

                // Calculates the area for each Triangle.
                double a = this[i, 0].DistanceFrom(this[i, 1]);
                double b = this[i, 1].DistanceFrom(this[i, 2]);
                double c = this[i, 2].DistanceFrom(this[i, 0]);
                double s = 0.5 * (a + b + c);
                this[i].Area = Math.Sqrt(s * (s - a) * (s - b) * (s - c));

                // Calculates the angles of each Triangle.
                Vector ab = this[i, 1] - this[i, 0];
                Vector ac = this[i, 2] - this[i, 0];
                Vector ba = this[i, 0] - this[i, 1];
                Vector bc = this[i, 2] - this[i, 1];
                Vector cb = this[i, 1] - this[i, 2];
                Vector ca = this[i, 0] - this[i, 2];

                this[i].Angles[0] = Vertex.Angle(ab, ac);
                this[i].Angles[1] = Vertex.Angle(ba, bc);
                this[i].Angles[2] = Vertex.Angle(cb, ca);
            }
            if (edges.Count != 0)
            {
                if ((oldMinLength != edges.Values[0].Length) && (MinEdgeLengthChanged != null))
                {
                    MinEdgeLengthChanged(edges.Values[0].Length);
                }
            }
            else
            {
                if (MinEdgeLengthChanged != null)
                {
                    MinEdgeLengthChanged(0);
                }
            }

            // The center is calculated.
            for (int i = 0; i < 3; i++)
            {
                center[i] = 0.5 * (max[i] + min[i]);
            }

            // The scale is the maximum size in one coordinate direction. It is used for drawing.
            float oldScale = scale;

            scale = max[0] - min[0];
            if (max[1] - min[1] > scale)
            {
                scale = max[1] - min[1];
            }
            if (max[2] - min[2] > scale)
            {
                scale = max[2] - min[2];
            }
            if ((oldScale != scale) && (ScaleChanged != null))
            {
                ScaleChanged();
            }

            // The colorDist is used to space the picking colors.
            int temp = 256 * 256 * 256;

            vertexColorDist   = temp / (vertices.Count + 2);
            edgeColorDist     = temp / (edges.Count + 2);
            triangleColorDist = temp / (this.Count + 2);
        }