/// <summary>
        /// find squared distance from p to nearest segment on polyline
        /// </summary>
        public double DistanceSquared(Vector3d p, out int iNearSeg, out double fNearSegT)
        {
            iNearSeg  = -1;
            fNearSegT = double.MaxValue;
            double dist = double.MaxValue;
            int    N    = (Closed) ? vertices.Count : vertices.Count - 1;

            for (int vi = 0; vi < N; ++vi)
            {
                int       a   = vi;
                int       b   = (vi + 1) % vertices.Count;
                Segment3d seg = new Segment3d(vertices[a], vertices[b]);
                double    t   = (p - seg.Center).Dot(seg.Direction);
                double    d   = double.MaxValue;
                if (t >= seg.Extent)
                {
                    d = seg.P1.DistanceSquared(p);
                }
                else if (t <= -seg.Extent)
                {
                    d = seg.P0.DistanceSquared(p);
                }
                else
                {
                    d = (seg.PointAt(t) - p).LengthSquared;
                }
                if (d < dist)
                {
                    dist      = d;
                    iNearSeg  = vi;
                    fNearSegT = t;
                }
            }
            return(dist);
        }
Example #2
0
        public void AppendLine(Segment3d seg, float size)
        {
            Frame3f f = new Frame3f(seg.Center);

            f.AlignAxis(2, (Vector3f)seg.Direction);
            AppendBox(f, new Vector3f(size, size, seg.Extent));
        }
        static public double MinDistance(Ray3d r, Segment3d s)
        {
            double rayt, segt;
            double dsqr = SquaredDistance(ref r, ref s, out rayt, out segt);

            return(Math.Sqrt(dsqr));
        }
Example #4
0
 public Box3d(Segment3d seg)
 {
     Center = seg.Center;
     AxisZ  = seg.Direction;
     Vector3d.MakePerpVectors(ref AxisZ, out AxisX, out AxisY);
     Extent = new Vector3d(0, 0, seg.Extent);
 }
        static public double MinDistanceSegmentParam(Ray3d r, Segment3d s)
        {
            double rayt, segt;

            /*double dsqr = */ SquaredDistance(ref r, ref s, out rayt, out segt);
            return(segt);
        }
Example #6
0
        public static bool FindClosestRayIntersection(ISampledCurve3d c, double segRadius, Ray3d ray, out double minRayT)
        {
            minRayT = double.MaxValue;
            int nNearSegment = -1;

            int nSegs = c.SegmentCount;

            for (int i = 0; i < nSegs; ++i)
            {
                Segment3d seg = c.GetSegment(i);

                // raycast to line bounding-sphere first (is this going ot be faster??)
                double fSphereHitT;
                bool   bHitBoundSphere = RayIntersection.SphereSigned(ref ray.Origin, ref ray.Direction,
                                                                      ref seg.Center, seg.Extent + segRadius, out fSphereHitT);
                if (bHitBoundSphere == false)
                {
                    continue;
                }

                double rayt, segt;
                double dSqr = DistRay3Segment3.SquaredDistance(ref ray, ref seg, out rayt, out segt);
                if (dSqr < segRadius * segRadius)
                {
                    if (rayt < minRayT)
                    {
                        minRayT      = rayt;
                        nNearSegment = i;
                    }
                }
            }
            return(nNearSegment >= 0);
        }
Example #7
0
        protected bool is_on_edge(int eid, Vector3d v)
        {
            Index2i   ev  = Target.GetEdgeV(eid);
            Segment3d seg = new Segment3d(Target.GetVertex(ev.a), Target.GetVertex(ev.b));

            return(seg.DistanceSquared(v) < VertexSnapTol * VertexSnapTol);
        }
Example #8
0
        protected int on_edge(ref Triangle3d tri, ref Vector3d v)
        {
            var s01 = new Segment3d(tri.V0, tri.V1);

            if (s01.DistanceSquared(v) < VertexSnapTol * VertexSnapTol)
            {
                return(0);
            }

            var s12 = new Segment3d(tri.V1, tri.V2);

            if (s12.DistanceSquared(v) < VertexSnapTol * VertexSnapTol)
            {
                return(1);
            }

            var s20 = new Segment3d(tri.V2, tri.V0);

            if (s20.DistanceSquared(v) < VertexSnapTol * VertexSnapTol)
            {
                return(2);
            }

            return(-1);
        }
Example #9
0
        void find_min_distance(ref Ray3d ray, ref double min_dist, ref int min_dist_seg, ref double min_dist_segt, ref double min_dist_rayt, int bi, int iLayerStart, int iLayer)
        {
            // hit polygon layer, check segments
            if (iLayer == 0)
            {
                int       seg_i = 2 * bi;
                Segment3d seg_a = Curve.GetSegment(seg_i);
                double    segt, rayt;
                double    segdist_sqr = DistRay3Segment3.SquaredDistance(ref ray, ref seg_a, out rayt, out segt);
                double    segdist     = Math.Sqrt(segdist_sqr);
                if (segdist <= min_dist)
                {
                    min_dist      = segdist;
                    min_dist_seg  = seg_i;
                    min_dist_segt = segt;
                    min_dist_rayt = rayt;
                }
                if ((seg_i + 1) < Curve.SegmentCount)
                {
                    Segment3d seg_b = Curve.GetSegment(seg_i + 1);
                    segdist_sqr = DistRay3Segment3.SquaredDistance(ref ray, ref seg_b, out rayt, out segt);
                    segdist     = Math.Sqrt(segdist_sqr);
                    if (segdist <= min_dist)
                    {
                        min_dist      = segdist;
                        min_dist_seg  = seg_i + 1;
                        min_dist_segt = segt;
                        min_dist_rayt = rayt;
                    }
                }

                return;
            }

            // test both boxes and recurse
            // TODO: verify that this intersection strategy makes sense?
            int  prev_layer = iLayer - 1;
            int  prev_count = layer_counts[prev_layer];
            int  prev_start = iLayerStart - prev_count;
            int  prev_a     = prev_start + 2 * bi;
            bool intersects = IntrRay3Box3.Intersects(ref ray, ref boxes[prev_a], min_dist);

            if (intersects)
            {
                find_min_distance(ref ray, ref min_dist, ref min_dist_seg, ref min_dist_segt, ref min_dist_rayt, 2 * bi, prev_start, prev_layer);
            }
            if ((2 * bi + 1) >= prev_count)
            {
                return;
            }

            int  prev_b      = prev_a + 1;
            bool intersects2 = IntrRay3Box3.Intersects(ref ray, ref boxes[prev_b], min_dist);

            if (intersects2)
            {
                find_min_distance(ref ray, ref min_dist, ref min_dist_seg, ref min_dist_segt, ref min_dist_rayt, 2 * bi + 1, prev_start, prev_layer);
            }
        }
Example #10
0
        public static void AppendLine(DMesh3 mesh, Segment3d seg, float size)
        {
            Frame3f f = new Frame3f(seg.Center);

            f.AlignAxis(2, (Vector3f)seg.Direction);
            MeshEditor editor = new MeshEditor(mesh);

            editor.AppendBox(f, new Vector3f(size, size, seg.Extent));
        }
Example #11
0
        void find_min_distance(ref Vector3d pt, ref double min_dist, ref int min_dist_seg, ref double min_dist_segt, int bi, int iLayerStart, int iLayer)
        {
            // hit polygon layer, check segments
            if (iLayer == 0)
            {
                int       seg_i = 2 * bi;
                Segment3d seg_a = Curve.GetSegment(seg_i);
                double    segt;
                double    segdist = seg_a.DistanceSquared(pt, out segt);
                if (segdist <= min_dist)
                {
                    min_dist      = segdist;
                    min_dist_seg  = seg_i;
                    min_dist_segt = segt;
                }
                if ((seg_i + 1) < Curve.SegmentCount)
                {
                    Segment3d seg_b = Curve.GetSegment(seg_i + 1);
                    segdist = seg_b.DistanceSquared(pt, out segt);
                    if (segdist <= min_dist)
                    {
                        min_dist      = segdist;
                        min_dist_seg  = seg_i + 1;
                        min_dist_segt = segt;
                    }
                }

                return;
            }

            // test both boxes and recurse
            int    prev_layer = iLayer - 1;
            int    prev_count = layer_counts[prev_layer];
            int    prev_start = iLayerStart - prev_count;
            int    prev_a     = prev_start + 2 * bi;
            double dist       = boxes[prev_a].DistanceSquared(pt);

            if (dist <= min_dist)
            {
                find_min_distance(ref pt, ref min_dist, ref min_dist_seg, ref min_dist_segt, 2 * bi, prev_start, prev_layer);
            }
            if ((2 * bi + 1) >= prev_count)
            {
                return;
            }

            int    prev_b = prev_a + 1;
            double dist2  = boxes[prev_b].DistanceSquared(pt);

            if (dist2 <= min_dist)
            {
                find_min_distance(ref pt, ref min_dist, ref min_dist_seg, ref min_dist_segt, 2 * bi + 1, prev_start, prev_layer);
            }
        }
Example #12
0
 public void AppendSegments(double r)
 {
     foreach (var seg in Segments)
     {
         Segment3d s = new Segment3d(seg.v0.v, seg.v1.v);
         if (Target.FindEdge(seg.v0.vtx_id, seg.v1.vtx_id) == DMesh3.InvalidID)
         {
             MeshEditor.AppendLine(Target, s, (float)r);
         }
     }
 }
Example #13
0
        void find_closest_ray_intersction(ref Ray3d ray, double radius, ref int nearestSegment, ref double nearest_ray_t, int bi, int iLayerStart, int iLayer)
        {
            // hit polygon layer, check segments
            if (iLayer == 0)
            {
                int       seg_i = 2 * bi;
                Segment3d seg_a = Curve.GetSegment(seg_i);
                double    segt, rayt;
                double    segdist_sqr = DistRay3Segment3.SquaredDistance(ref ray, ref seg_a, out rayt, out segt);
                if (segdist_sqr <= radius * radius && rayt < nearest_ray_t)
                {
                    nearestSegment = seg_i;
                    nearest_ray_t  = rayt;
                }
                if ((seg_i + 1) < Curve.SegmentCount)
                {
                    Segment3d seg_b = Curve.GetSegment(seg_i + 1);
                    segdist_sqr = DistRay3Segment3.SquaredDistance(ref ray, ref seg_b, out rayt, out segt);
                    if (segdist_sqr <= radius * radius && rayt < nearest_ray_t)
                    {
                        nearestSegment = seg_i + 1;
                        nearest_ray_t  = rayt;
                    }
                }

                return;
            }

            // test both boxes and recurse
            // TODO: verify that this intersection strategy makes sense?
            int  prev_layer = iLayer - 1;
            int  prev_count = layer_counts[prev_layer];
            int  prev_start = iLayerStart - prev_count;
            int  prev_a     = prev_start + 2 * bi;
            bool intersects = IntrRay3Box3.Intersects(ref ray, ref boxes[prev_a], radius);

            if (intersects)
            {
                find_closest_ray_intersction(ref ray, radius, ref nearestSegment, ref nearest_ray_t, 2 * bi, prev_start, prev_layer);
            }
            if ((2 * bi + 1) >= prev_count)
            {
                return;
            }

            int  prev_b      = prev_a + 1;
            bool intersects2 = IntrRay3Box3.Intersects(ref ray, ref boxes[prev_b], radius);

            if (intersects2)
            {
                find_closest_ray_intersction(ref ray, radius, ref nearestSegment, ref nearest_ray_t, 2 * bi + 1, prev_start, prev_layer);
            }
        }
Example #14
0
        public Vector3d Project(Vector3d vPoint, int identifier = -1)
        {
            Vector3d vNearest    = Vector3d.Zero;
            double   fNearestSqr = double.MaxValue;

            int N = Curve.VertexCount;

            for (int i = 0; i < N; ++i)
            {
                Segment3d seg  = new Segment3d(Curve[i], Curve[(i + 1) % N]);
                Vector3d  pt   = seg.NearestPoint(vPoint);
                double    dsqr = pt.DistanceSquared(vPoint);
                if (dsqr < fNearestSqr)
                {
                    fNearestSqr = dsqr;
                    vNearest    = pt;
                }
            }

            return((fNearestSqr < double.MaxValue) ? vNearest : vPoint);
        }
 protected DMesh3 MakeDebugGraphMesh()
 {
     DMesh3 graphMesh = new DMesh3();
     graphMesh.EnableVertexColors(Vector3f.One);
     foreach (int vid in Graph.VertexIndices()) {
         if (TipVertices.Contains(vid)) {
             MeshEditor.AppendBox(graphMesh, Graph.GetVertex(vid), 0.3f, Colorf.Green);
         } else if (TipBaseVertices.Contains(vid)) {
             MeshEditor.AppendBox(graphMesh, Graph.GetVertex(vid), 0.225f, Colorf.Magenta);
         } else if (GroundVertices.Contains(vid)) {
             MeshEditor.AppendBox(graphMesh, Graph.GetVertex(vid), 0.35f, Colorf.Blue);
         } else {
             MeshEditor.AppendBox(graphMesh, Graph.GetVertex(vid), 0.15f, Colorf.White);
         }
     }
     foreach (int eid in Graph.EdgeIndices()) {
         Segment3d seg = Graph.GetEdgeSegment(eid);
         MeshEditor.AppendLine(graphMesh, seg, 0.1f);
     }
     return graphMesh;
 }
Example #16
0
        int find_nearest_edge(DMesh3 mesh, Vector3d v, HashSet <int> vertices)
        {
            int    near_eid = DMesh3.InvalidID;
            double nearSqr  = VertexSnapTol * VertexSnapTol;

            foreach (int eid in mesh.BoundaryEdgeIndices())
            {
                Index2i ev = mesh.GetEdgeV(eid);
                if (vertices.Contains(ev.a) == false || vertices.Contains(ev.b) == false)
                {
                    continue;
                }
                Segment3d seg  = new Segment3d(mesh.GetVertex(ev.a), mesh.GetVertex(ev.b));
                double    dSqr = seg.DistanceSquared(v);
                if (dSqr < nearSqr)
                {
                    near_eid = eid;
                    nearSqr  = dSqr;
                }
            }
            return(near_eid);
        }
Example #17
0
 static public double MinDistanceLineParam(Line3d line, Segment3d segment)
 {
     return(new DistLine3Segment3(line, segment).Compute().LineParameter);
 }
        public double GetSquared()
        {
            if (DistanceSquared >= 0)
            {
                return(DistanceSquared);
            }

            // Compare edges of triangle0 to the interior of triangle1.
            double sqrDist = Double.MaxValue, sqrDistTmp;
            var    edge = new Segment3d();
            double ratio;
            int    i0, i1;

            for (i0 = 2, i1 = 0; i1 < 3; i0 = i1++)
            {
                edge.SetEndpoints(triangle0[i0], triangle0[i1]);

                var queryST = new DistSegment3Triangle3(edge, triangle1);
                sqrDistTmp = queryST.GetSquared();
                if (sqrDistTmp < sqrDist)
                {
                    Triangle0Closest = queryST.SegmentClosest;
                    Triangle1Closest = queryST.TriangleClosest;
                    sqrDist          = sqrDistTmp;

                    ratio = queryST.SegmentParam / edge.Extent;
                    Triangle0BaryCoords              = Vector3d.Zero;
                    Triangle0BaryCoords[i0]          = (0.5) * (1 - ratio);
                    Triangle0BaryCoords[i1]          = 1 - Triangle0BaryCoords[i0];
                    Triangle0BaryCoords[3 - i0 - i1] = 0;
                    Triangle1BaryCoords              = queryST.TriangleBaryCoords;

                    if (sqrDist <= MathUtil.ZeroTolerance)
                    {
                        DistanceSquared = 0;
                        return(0);
                    }
                }
            }

            // Compare edges of triangle1 to the interior of triangle0.
            for (i0 = 2, i1 = 0; i1 < 3; i0 = i1++)
            {
                edge.SetEndpoints(triangle1[i0], triangle1[i1]);

                var queryST = new DistSegment3Triangle3(edge, triangle0);
                sqrDistTmp = queryST.GetSquared();
                if (sqrDistTmp < sqrDist)
                {
                    Triangle0Closest = queryST.SegmentClosest;
                    Triangle1Closest = queryST.TriangleClosest;
                    sqrDist          = sqrDistTmp;

                    ratio = queryST.SegmentParam / edge.Extent;
                    Triangle1BaryCoords              = Vector3d.Zero;
                    Triangle1BaryCoords[i0]          = (0.5) * (1 - ratio);
                    Triangle1BaryCoords[i1]          = 1 - Triangle1BaryCoords[i0];
                    Triangle1BaryCoords[3 - i0 - i1] = 0;
                    Triangle0BaryCoords              = queryST.TriangleBaryCoords;

                    if (sqrDist <= MathUtil.ZeroTolerance)
                    {
                        DistanceSquared = 0;
                        return(0);
                    }
                }
            }

            DistanceSquared = sqrDist;
            return(DistanceSquared);
        }
Example #19
0
        public double GetSquared()
        {
            if (DistanceSquared >= 0)
            {
                return(DistanceSquared);
            }

            // Test if line intersects triangle.  If so, the squared distance is zero.
            Vector3d edge0  = triangle.V1 - triangle.V0;
            Vector3d edge1  = triangle.V2 - triangle.V0;
            Vector3d normal = edge0.UnitCross(edge1);
            double   NdD    = normal.Dot(line.Direction);

            if (Math.Abs(NdD) > MathUtil.ZeroTolerance)
            {
                // The line and triangle are not parallel, so the line intersects
                // the plane of the triangle.
                Vector3d diff = line.Origin - triangle.V0;
                Vector3d U = Vector3d.Zero, V = Vector3d.Zero;
                Vector3d.GenerateComplementBasis(ref U, ref V, line.Direction);
                double UdE0   = U.Dot(edge0);
                double UdE1   = U.Dot(edge1);
                double UdDiff = U.Dot(diff);
                double VdE0   = V.Dot(edge0);
                double VdE1   = V.Dot(edge1);
                double VdDiff = V.Dot(diff);
                double invDet = (1) / (UdE0 * VdE1 - UdE1 * VdE0);

                // Barycentric coordinates for the point of intersection.
                double b1 = (VdE1 * UdDiff - UdE1 * VdDiff) * invDet;
                double b2 = (UdE0 * VdDiff - VdE0 * UdDiff) * invDet;
                double b0 = 1 - b1 - b2;

                if (b0 >= 0 && b1 >= 0 && b2 >= 0)
                {
                    // Line parameter for the point of intersection.
                    double DdE0   = line.Direction.Dot(edge0);
                    double DdE1   = line.Direction.Dot(edge1);
                    double DdDiff = line.Direction.Dot(diff);
                    LineParam = b1 * DdE0 + b2 * DdE1 - DdDiff;

                    // Barycentric coordinates for the point of intersection.
                    TriangleBaryCoords = new Vector3d(b0, b1, b2);

                    // The intersection point is inside or on the triangle.
                    LineClosest     = line.Origin + LineParam * line.Direction;
                    TriangleClosest = triangle.V0 + b1 * edge0 + b2 * edge1;
                    DistanceSquared = 0;
                    return(0);
                }
            }

            // Either (1) the line is not parallel to the triangle and the point of
            // intersection of the line and the plane of the triangle is outside the
            // triangle or (2) the line and triangle are parallel.  Regardless, the
            // closest point on the triangle is on an edge of the triangle.  Compare
            // the line to all three edges of the triangle.
            double sqrDist = double.MaxValue;

            for (int i0 = 2, i1 = 0; i1 < 3; i0 = i1++)
            {
                Segment3d         segment    = new Segment3d(triangle[i0], triangle[i1]);
                DistLine3Segment3 queryLS    = new DistLine3Segment3(line, segment);
                double            sqrDistTmp = queryLS.GetSquared();
                if (sqrDistTmp < sqrDist)
                {
                    LineClosest     = queryLS.LineClosest;
                    TriangleClosest = queryLS.SegmentClosest;
                    sqrDist         = sqrDistTmp;
                    LineParam       = queryLS.LineParameter;
                    double ratio = queryLS.SegmentParameter / segment.Extent;
                    TriangleBaryCoords              = Vector3d.Zero;
                    TriangleBaryCoords[i0]          = (0.5) * (1 - ratio);
                    TriangleBaryCoords[i1]          = 1 - TriangleBaryCoords[i0];
                    TriangleBaryCoords[3 - i0 - i1] = 0;
                }
            }

            DistanceSquared = sqrDist;
            return(DistanceSquared);
        }
Example #20
0
        // build tree of boxes as sequential array
        void build_sequential(DCurve3 curve)
        {
            int NV       = curve.VertexCount;
            int N        = NV;
            int boxCount = 0;

            layers       = 0;
            layer_counts = new List <int>();

            // count how many boxes in each layer, building up from initial segments
            int bi = 0;

            while (N > 1)
            {
                int layer_boxes = (N / 2) + (N % 2 == 0 ? 0 : 1);
                boxCount += layer_boxes;
                N         = layer_boxes;

                layer_counts.Add(layer_boxes);
                bi += layer_boxes;
                layers++;
            }


            boxes = new Box3d[boxCount];
            bi    = 0;

            // make first layer
            for (int si = 0; si < NV; si += 2)
            {
                Vector3d  v1   = curve[(si + 1) % NV];
                Segment3d seg1 = new Segment3d(curve[si], v1);
                Box3d     box  = new Box3d(seg1);
                if (si < NV - 1)
                {
                    Segment3d seg2 = new Segment3d(v1, curve[(si + 2) % NV]);
                    Box3d     box2 = new Box3d(seg2);
                    box = Box3d.Merge(ref box, ref box2);
                }
                boxes[bi++] = box;
            }

            // repeatedly build layers until we hit a single box
            N = bi;
            int  prev_layer_start = 0;
            bool done             = false;

            while (done == false)
            {
                int layer_start = bi;

                for (int k = 0; k < N; k += 2)
                {
                    Box3d mbox = Box3d.Merge(ref boxes[prev_layer_start + k], ref boxes[prev_layer_start + k + 1]);
                    boxes[bi++] = mbox;
                }

                N = (N / 2) + (N % 2 == 0 ? 0 : 1);
                prev_layer_start = layer_start;
                if (N == 1)
                {
                    done = true;
                }
            }
        }
Example #21
0
 // solidBox == false means fully contained segment does not intersect
 public IntrSegment3Box3(Segment3d s, Box3d b, bool solidBox)
 {
     segment = s; box = b; this.solid = solidBox;
 }
 public DistRay3Segment3(Ray3d rayIn, Segment3d segmentIn)
 {
     this.ray = rayIn; this.segment = segmentIn;
 }
 public DistSegment3Triangle3(Segment3d SegmentIn, Triangle3d TriangleIn)
 {
     this.triangle = TriangleIn; this.segment = SegmentIn;
 }
        public Vector3d PointAt(int iSegment, double fSegT)
        {
            Segment3d seg = new Segment3d(vertices[iSegment], vertices[(iSegment + 1) % vertices.Count]);

            return(seg.PointAt(fSegT));
        }
        /// <summary>
        /// compute w/o allocating temporaries/etc
        /// </summary>
        public static double SquaredDistance(ref Ray3d ray, ref Segment3d segment,
                                             out double rayT, out double segT)
        {
            Vector3d diff = ray.Origin - segment.Center;
            double   a01 = -ray.Direction.Dot(segment.Direction);
            double   b0 = diff.Dot(ray.Direction);
            double   b1 = -diff.Dot(segment.Direction);
            double   c = diff.LengthSquared;
            double   det = Math.Abs(1 - a01 * a01);
            double   s0, s1, sqrDist, extDet;

            if (det >= MathUtil.ZeroTolerance)
            {
                // The Ray and Segment are not parallel.
                s0     = a01 * b1 - b0;
                s1     = a01 * b0 - b1;
                extDet = segment.Extent * det;

                if (s0 >= 0)
                {
                    if (s1 >= -extDet)
                    {
                        if (s1 <= extDet)  // region 0
                        {
                            // Minimum at interior points of Ray and Segment.
                            double invDet = (1) / det;
                            s0     *= invDet;
                            s1     *= invDet;
                            sqrDist = s0 * (s0 + a01 * s1 + (2) * b0) +
                                      s1 * (a01 * s0 + s1 + (2) * b1) + c;
                        }
                        else    // region 1
                        {
                            s1 = segment.Extent;
                            s0 = -(a01 * s1 + b0);
                            if (s0 > 0)
                            {
                                sqrDist = -s0 * s0 + s1 * (s1 + (2) * b1) + c;
                            }
                            else
                            {
                                s0      = 0;
                                sqrDist = s1 * (s1 + (2) * b1) + c;
                            }
                        }
                    }
                    else    // region 5
                    {
                        s1 = -segment.Extent;
                        s0 = -(a01 * s1 + b0);
                        if (s0 > 0)
                        {
                            sqrDist = -s0 * s0 + s1 * (s1 + (2) * b1) + c;
                        }
                        else
                        {
                            s0      = 0;
                            sqrDist = s1 * (s1 + (2) * b1) + c;
                        }
                    }
                }
                else
                {
                    if (s1 <= -extDet)  // region 4
                    {
                        s0 = -(-a01 * segment.Extent + b0);
                        if (s0 > 0)
                        {
                            s1      = -segment.Extent;
                            sqrDist = -s0 * s0 + s1 * (s1 + (2) * b1) + c;
                        }
                        else
                        {
                            s0 = 0;
                            s1 = -b1;
                            if (s1 < -segment.Extent)
                            {
                                s1 = -segment.Extent;
                            }
                            else if (s1 > segment.Extent)
                            {
                                s1 = segment.Extent;
                            }
                            sqrDist = s1 * (s1 + (2) * b1) + c;
                        }
                    }
                    else if (s1 <= extDet)    // region 3
                    {
                        s0 = 0;
                        s1 = -b1;
                        if (s1 < -segment.Extent)
                        {
                            s1 = -segment.Extent;
                        }
                        else if (s1 > segment.Extent)
                        {
                            s1 = segment.Extent;
                        }
                        sqrDist = s1 * (s1 + (2) * b1) + c;
                    }
                    else    // region 2
                    {
                        s0 = -(a01 * segment.Extent + b0);
                        if (s0 > 0)
                        {
                            s1      = segment.Extent;
                            sqrDist = -s0 * s0 + s1 * (s1 + (2) * b1) + c;
                        }
                        else
                        {
                            s0 = 0;
                            s1 = -b1;
                            if (s1 < -segment.Extent)
                            {
                                s1 = -segment.Extent;
                            }
                            else if (s1 > segment.Extent)
                            {
                                s1 = segment.Extent;
                            }
                            sqrDist = s1 * (s1 + (2) * b1) + c;
                        }
                    }
                }
            }
            else
            {
                // Ray and Segment are parallel.
                if (a01 > 0)
                {
                    // Opposite direction vectors.
                    s1 = -segment.Extent;
                }
                else
                {
                    // Same direction vectors.
                    s1 = segment.Extent;
                }

                s0 = -(a01 * s1 + b0);
                if (s0 > 0)
                {
                    sqrDist = -s0 * s0 + s1 * (s1 + (2) * b1) + c;
                }
                else
                {
                    s0      = 0;
                    sqrDist = s1 * (s1 + (2) * b1) + c;
                }
            }

            rayT = s0;
            segT = s1;

            // Account for numerical round-off errors.
            if (sqrDist < 0)
            {
                sqrDist = 0;
            }
            return(sqrDist);
        }
 static public double MinDistance(Ray3d r, Segment3d s) {
     return new DistRay3Segment3(r, s).Get();
 }
Example #27
0
        // build tree of boxes as sequential array
        void build_sequential(DCurve3 curve)
        {
            int NV       = curve.VertexCount;
            int N        = (curve.Closed) ? NV : NV - 1;
            int boxCount = 0;

            layers       = 0;
            layer_counts = new List <int>();

            // count how many boxes in each layer, building up from initial segments
            int bi = 0;

            while (N > 1)
            {
                int layer_boxes = (N / 2) + (N % 2 == 0 ? 0 : 1);
                boxCount += layer_boxes;
                N         = layer_boxes;

                layer_counts.Add(layer_boxes);
                bi += layer_boxes;
                layers++;
            }
            // [RMS] this case happens if N = 1, previous loop is skipped and we have to
            // hardcode initialization to this redundant box
            if (layers == 0)
            {
                layers       = 1;
                boxCount     = 1;
                layer_counts = new List <int>()
                {
                    1
                };
            }

            boxes = new Box3d[boxCount];
            bi    = 0;

            // make first layer
            int NStop = (curve.Closed) ? NV : NV - 1;

            for (int si = 0; si < NStop; si += 2)
            {
                Vector3d v1   = curve[(si + 1) % NV];
                var      seg1 = new Segment3d(curve[si], v1);
                var      box  = new Box3d(seg1);
                if (si < NV - 1)
                {
                    var seg2 = new Segment3d(v1, curve[(si + 2) % NV]);
                    var box2 = new Box3d(seg2);
                    box = Box3d.Merge(ref box, ref box2);
                }
                boxes[bi++] = box;
            }

            // repeatedly build layers until we hit a single box
            N = bi;
            if (N == 1)
            {
                return;
            }

            int  prev_layer_start = 0;
            bool done             = false;

            while (done == false)
            {
                int layer_start = bi;

                for (int k = 0; k < N; k += 2)
                {
                    var mbox = Box3d.Merge(ref boxes[prev_layer_start + k], ref boxes[prev_layer_start + k + 1]);
                    boxes[bi++] = mbox;
                }

                N = (N / 2) + (N % 2 == 0 ? 0 : 1);
                prev_layer_start = layer_start;
                if (N == 1)
                {
                    done = true;
                }
            }
        }
 static public double MinDistanceSegmentParam(Ray3d r, Segment3d s) {
     return new DistRay3Segment3(r, s).Compute().SegmentParameter;
 }
Example #29
0
 public DistLine3Segment3(Line3d LineIn, Segment3d SegmentIn)
 {
     this.segment = SegmentIn; this.line = LineIn;
 }
Example #30
0
 static public double MinDistance(Line3d line, Segment3d segment)
 {
     return(new DistLine3Segment3(line, segment).Get());
 }