Beispiel #1
0
        // find distance x0 is from triangle x1-x2-x3
        static float point_triangle_distance(ref Vector3f x0, ref Vector3f x1, ref Vector3f x2, ref Vector3f x3)
        {
            // first find barycentric coordinates of closest point on infinite plane
            Vector3f x13 = (x1 - x3);
            Vector3f x23 = (x2 - x3);
            Vector3f x03 = (x0 - x3);
            float    m13 = x13.LengthSquared, m23 = x23.LengthSquared, d = x13.Dot(x23);
            float    invdet = 1.0f / Math.Max(m13 * m23 - d * d, 1e-30f);
            float    a = x13.Dot(x03), b = x23.Dot(x03);
            // the barycentric coordinates themselves
            float w23 = invdet * (m23 * a - d * b);
            float w31 = invdet * (m13 * b - d * a);
            float w12 = 1 - w23 - w31;

            if (w23 >= 0 && w31 >= 0 && w12 >= 0)   // if we're inside the triangle
            {
                return(x0.Distance(w23 * x1 + w31 * x2 + w12 * x3));
            }
            else             // we have to clamp to one of the edges
            {
                if (w23 > 0) // this rules out edge 2-3 for us
                {
                    return(Math.Min(point_segment_distance(ref x0, ref x1, ref x2), point_segment_distance(ref x0, ref x1, ref x3)));
                }
                else if (w31 > 0) // this rules out edge 1-3
                {
                    return(Math.Min(point_segment_distance(ref x0, ref x1, ref x2), point_segment_distance(ref x0, ref x2, ref x3)));
                }
                else // w12 must be >0, ruling out edge 1-2
                {
                    return(Math.Min(point_segment_distance(ref x0, ref x1, ref x3), point_segment_distance(ref x0, ref x2, ref x3)));
                }
            }
        }
Beispiel #2
0
        void update_neighbours_sparse(GraphNode parent)
        {
            Vector3f parentPos  = PositionF(parent.id);
            float    parentDist = parent.graph_distance;

            foreach (int nbr_id in NeighboursF(parent.id))
            {
                GraphNode nbr = get_node(nbr_id);
                if (nbr.frozen)
                {
                    continue;
                }

                float nbr_dist = parentDist + parentPos.Distance(PositionF(nbr_id));
                if (SparseQueue.Contains(nbr))
                {
                    if (nbr_dist < nbr.priority)
                    {
                        nbr.parent         = parent;
                        nbr.graph_distance = nbr_dist;
                        SparseQueue.Update(nbr, nbr.graph_distance);
                    }
                }
                else
                {
                    nbr.parent         = parent;
                    nbr.graph_distance = nbr_dist;
                    SparseQueue.Enqueue(nbr, nbr.graph_distance);
                }
            }
        }
Beispiel #3
0
        // find distance x0 is from segment x1-x2
        static float point_segment_distance(ref Vector3f x0, ref Vector3f x1, ref Vector3f x2)
        {
            Vector3f dx = x2 - x1;
            float    m2 = dx.LengthSquared;
            // find parameter value of closest point on segment
            float s12 = (dx.Dot(x2 - x0) / m2);

            if (s12 < 0)
            {
                s12 = 0;
            }
            else if (s12 > 1)
            {
                s12 = 1;
            }
            // and find the distance
            return(x0.Distance(s12 * x1 + (1 - s12) * x2));
        }
Beispiel #4
0
        protected virtual DMesh3 BuildMesh_TolerantWeld(STLSolid solid, double weld_tolerance)
        {
            var builder = new DMesh3Builder();

            builder.AppendNewMesh(false, false, false, false);

            DVectorArray3f vertices = solid.Vertices;
            int            N        = vertices.Count;

            int[] mapV = new int[N];


            AxisAlignedBox3d bounds = AxisAlignedBox3d.Empty;

            for (int i = 0; i < N; ++i)
            {
                bounds.Contain(vertices[i]);
            }

            // [RMS] because we are only searching within tiny radius, there is really no downside to
            // using lots of bins here, except memory usage. If we don't, and the mesh has a ton of triangles
            // very close together (happens all the time on big meshes!), then this step can start
            // to take an *extremely* long time!
            int num_bins = 256;

            if (N > 100000)
            {
                num_bins = 512;
            }

            if (N > 1000000)
            {
                num_bins = 1024;
            }

            if (N > 2000000)
            {
                num_bins = 2048;
            }

            if (N > 5000000)
            {
                num_bins = 4096;
            }

            var uniqueV = new PointHashGrid3d <int>(bounds.MaxDim / (float)num_bins, -1);
            var pos     = new Vector3f[N];

            for (int vi = 0; vi < N; ++vi)
            {
                Vector3f v = vertices[vi];

                var pair = uniqueV.FindNearestInRadius(v, weld_tolerance, (vid) =>
                {
                    return(v.Distance(pos[vid]));
                });
                if (pair.Key == -1)
                {
                    int vid = builder.AppendVertex(v.x, v.y, v.z);
                    uniqueV.InsertPoint(vid, v);
                    mapV[vi] = vid;
                    pos[vid] = v;
                }
                else
                {
                    mapV[vi] = pair.Key;
                }
            }

            append_mapped_triangles(solid, builder, mapV);
            return(builder.Meshes[0]);
        }