Beispiel #1
0
        /// <summary>
        /// Joins vertex to the cheapest neighbour.
        /// </summary>
        /// <param name="vertex">The vertex to join.</param>
        /// <param name="type">The type of position join method.</param>
        /// <returns></returns>
        public bool JoinToNearestByCost(Vertex vertex, JoinPositionType type = JoinPositionType.Middle)
        {
            Debug.Assert(vertex != null);

            Vertex nearest = vertex.Neighbors.Min();

            if (nearest != null)
            {
                Vector3 position;
                switch (type)
                {
                case JoinPositionType.Source:
                {
                    position = vertex.Position;
                    break;
                }

                case JoinPositionType.Target:
                {
                    position = nearest.Position;
                    break;
                }

                default:
                case JoinPositionType.Middle:
                {
                    position = Vector3Extension.Mean(vertex.Position, nearest.Position);
                    break;
                }
                }

                return(JoinVertices(vertex, nearest, position));
            }
            return(false);
        }
Beispiel #2
0
        /// <summary>
        /// Optimizes edge target.
        /// </summary>
        /// <param name="v1">The source edge vertex.</param>
        /// <param name="v2">The target edge vertex.</param>
        /// <param name="edge">The edge additional params.</param>
        /// <param name="policy">The used policy.</param>
        private void OptimizeEdgeTarget(ref Vertex v1, ref Vertex v2, ref Triangle.Edge edge, WeightPolicy policy)
        {
            ErrorMetric Q = (ErrorMetric)edge.Tag;

            double  min_cost = double.MaxValue;
            Vector3 best;

            if (policy.HasFlag(WeightPolicy.Optmized) && Q.Optimize(out best))
            {
                Q.ProposedPoint = best;
                min_cost        = Q.VertexError(best);
            }
            else
            {
                double min1 = Q.VertexError(v1.Position);
                double min2 = Q.VertexError(v2.Position);

                if (min1 < min2)
                {
                    min_cost = min1;
                    best     = v1.Position;
                }
                else
                {
                    min_cost = min2;
                    best     = v2.Position;
                }

                if (policy.HasFlag(WeightPolicy.MiddlePoint))
                {
                    Vector3 middle      = Vector3Extension.Mean(v1.Position, v2.Position);
                    double  cost_middle = Q.VertexError(middle);

                    if (cost_middle < min_cost)
                    {
                        min_cost = cost_middle;
                        best     = middle;
                    }
                }
            }

            if (policy.HasFlag(WeightPolicy.AverageTriangleArea))
            {
                min_cost /= Q.Area;
            }

            edge.Cost       = -min_cost;
            Q.ProposedPoint = best;
            edge.Tag        = (object)Q;
        }
Beispiel #3
0
        /// <summary>
        /// Joins vertex to the closest neighbour.
        /// </summary>
        /// <param name="vertex">The vertex to join.</param>
        /// /// <param name="type">The type of position join method.</param>
        /// <returns>true when successful, false otherwise.</returns>
        public bool JoinToNearestByDistance(Vertex vertex, JoinPositionType type = JoinPositionType.Middle)
        {
            Debug.Assert(vertex != null);

            Vertex nearest     = null;
            float  minDistance = float.MaxValue;

            var neighbors = vertex.Neighbors.ToList();

            foreach (var neighbor in neighbors)
            {
                float distance = Vector3.Distance(vertex.Position, neighbor.Position);

                if (distance < minDistance)
                {
                    minDistance = distance;
                    nearest     = neighbor;
                }
            }

            if (nearest != null)
            {
                Vector3 position;
                switch (type)
                {
                case JoinPositionType.Source:
                {
                    position = vertex.Position;
                    break;
                }

                case JoinPositionType.Target:
                {
                    position = nearest.Position;
                    break;
                }

                default:
                case JoinPositionType.Middle:
                {
                    position = Vector3Extension.Mean(vertex.Position, nearest.Position);
                    break;
                }
                }

                return(JoinVertices(vertex, nearest, position));
            }
            return(false);
        }
Beispiel #4
0
        public void Remesh(ref Mesh mesh, IProgressListener progress = null)
        {
            var triangles = mesh.Triangles;
            var vertices  = mesh.Vertices;

            // Compute K matrices for initial triangles.
            foreach (var t in triangles)
            {
                t.UpdateGeometricData();
                t.Tag = new ErrorMetric(t);
            }

            // Compute Q for intiial vertices.
            foreach (var v in vertices)
            {
                ComputeErrorMetricForVertex(v);
            }

            // Compute initial edge QEM-s
            foreach (var t in triangles)
            {
                ComputeErrorMetricForEdges(t);
            }

            foreach (var t in triangles)
            {
                ComputeEdgeCost(t);
            }

            foreach (var v in vertices)
            {
                v.Cost = 0.0;
                foreach (var t in v.Triangles)
                {
                    v.Cost += Math.Max(Math.Max(t.Edge12.Cost, t.Edge23.Cost), t.Edge31.Cost);
                }
            }

            // Compute number of triangles after we stop
            int toRemove      = (int)((m_Removed) * triangles.Count);
            int triangleLimit = triangles.Count - toRemove;

#if TRACE_NANS
            int nansCount = 0;
#endif
            int index = 0;
            for (int i = 0; (i < m_Removed) && (2 * m_Removed < triangles.Count); i += 2)
            {
                Vertex        v1, v2;
                Triangle.Edge edge;
                if (SearchBestCandidate(ref mesh, out v1, out v2, out edge))
                {
                    if (edge != null)
                    {
                        ErrorMetric em = (ErrorMetric)edge.Tag;
                        Vector3     v  = em.ProposedPoint;
#if false
                        if (v.IsNaN())
                        {
#if TRACE_NANS
                            ++nansCount;
#endif
                            v = Vector3Extension.Mean(v1.Position, v2.Position);
                        }
#endif
                        if (mesh.JoinVertices(v1, v2, v))
                        {
                            // V1, since v2 is removed from now.
                            UpdateVertexNeighbors(v1);
                        }

                        progress.OnProgress(index, toRemove);
                        index += 2;
                    }
                    else
                    {
                        Trace.WriteLine("If you see this message more than once per second, I can't find any matching edge");
                    }
                }
            }

#if TRACE_NANS
            Trace.WriteLine(string.Format("NaNs count: {0}", nansCount));
#endif
        }
Beispiel #5
0
        /// <summary>
        /// Computes edge cost for triangle.
        /// </summary>
        /// <param name="t">The triangle.</param>
        private void ComputeEdgeCost(Triangle t)
        {
#if false
            Vector3 P1 = E12.ComputePosition();
            Vector3 P2 = E23.ComputePosition();
            Vector3 P3 = E31.ComputePosition();

#if !DISABLE_QEM_COMPUTING
            double C12 = E12.Evaluate(P1);
            double C23 = E23.Evaluate(P2);
            double C31 = E31.Evaluate(P3);

            if (double.IsNaN(C12))
            {
#if DISABLE_MEAN_POINT
                E12.ProposedPoint = t.Vertex1.Position;
#else
                E12.ProposedPoint = Vector3Extension.Mean(
                    t.Vertex1.Position,
                    t.Vertex2.Position);
#endif
                C12 = E12.Evaluate(E12.ProposedPoint);
            }
            else
            {
                E12.ProposedPoint = P1;
            }

            if (double.IsNaN(C23))
            {
#if DISABLE_MEAN_POINT
                E23.ProposedPoint = t.Vertex2.Position;
#else
                E23.ProposedPoint = Vector3Extension.Mean(
                    t.Vertex2.Position,
                    t.Vertex3.Position);
                C23 = E23.Evaluate(E23.ProposedPoint);
#endif
            }
            else
            {
                E23.ProposedPoint = P2;
            }

            if (double.IsNaN(C31))
            {
#if DISABLE_MEAN_POINT
                E31.ProposedPoint = t.Vertex3.Position;
#else
                E31.ProposedPoint = Vector3Extension.Mean(
                    t.Vertex3.Position,
                    t.Vertex1.Position);
                C31 = E31.Evaluate(E31.ProposedPoint);
#endif
            }
            else
            {
                E31.ProposedPoint = P3;
            }
#else
            double C12 = E12.Evaluate(t.Vertex1.Position);
            double C23 = E23.Evaluate(t.Vertex2.Position);
            double C31 = E31.Evaluate(t.Vertex3.Position);
#endif

            t.Edge12.Cost = C12;
            t.Edge23.Cost = C23;
            t.Edge31.Cost = C31;
#else
            WeightPolicy policy = (WeightPolicy.Optmized | WeightPolicy.AverageTriangleArea);
            OptimizeEdgeTarget(ref t.m_Vertex1, ref t.m_Vertex2, ref t.m_Edge12, policy);
            OptimizeEdgeTarget(ref t.m_Vertex2, ref t.m_Vertex3, ref t.m_Edge23, policy);
            OptimizeEdgeTarget(ref t.m_Vertex3, ref t.m_Vertex1, ref t.m_Edge31, policy);
#endif
            t.Cost = Math.Min(t.Edge12.Cost, Math.Min(t.Edge23.Cost, t.Edge31.Cost));
        }