Exemplo n.º 1
0
        public static void ClosestPointOnPolygon(RenderVertex3D[] rgv, Vertex2D pvin, bool fClosed, out Vertex2D pvOut, out int piSeg)
        {
            var count   = rgv.Length;
            var minDist = Constants.FloatMax;

            piSeg = -1;             // in case we are not next to the line
            pvOut = new Vertex2D();
            var loopCount = count;

            if (!fClosed)
            {
                --loopCount;                 // Don"t check segment running from the end point to the beginning point
            }

            // Go through line segment, calculate distance from point to the line
            // then pick the shortest distance
            for (var i = 0; i < loopCount; ++i)
            {
                var p2 = i < count - 1 ? i + 1 : 0;

                var rgvi = new RenderVertex3D();
                rgvi.Set(rgv[i].X, rgv[i].Y, rgv[i].Z);
                var rgvp2 = new RenderVertex3D();
                rgvp2.Set(rgv[p2].X, rgv[p2].Y, rgv[p2].Z);
                var a = rgvi.Y - rgvp2.Y;
                var b = rgvp2.X - rgvi.X;
                var c = -(a * rgvi.X + b * rgvi.Y);

                var dist = MathF.Abs(a * pvin.X + b * pvin.Y + c) / MathF.Sqrt(a * a + b * b);

                if (dist < minDist)
                {
                    // Assuming we got a segment that we are closet to, calculate the intersection
                    // of the line with the perpendicular line projected from the point,
                    // to find the closest point on the line
                    var d = -b;
                    var f = -(d * pvin.X + a * pvin.Y);

                    var det        = a * a - b * d;
                    var invDet     = det != 0.0f ? 1.0f / det : 0.0f;
                    var intersectX = (b * f - a * c) * invDet;
                    var intersectY = (c * d - a * f) * invDet;

                    // If the intersect point lies on the polygon segment
                    // (not out in space), then make this the closest known point
                    if (intersectX >= MathF.Min(rgvi.X, rgvp2.X) - 0.1 &&
                        intersectX <= MathF.Max(rgvi.X, rgvp2.X) + 0.1 &&
                        intersectY >= MathF.Min(rgvi.Y, rgvp2.Y) - 0.1 &&
                        intersectY <= MathF.Max(rgvi.Y, rgvp2.Y) + 0.1)
                    {
                        minDist = dist;
                        var seg = i;

                        pvOut.X = intersectX;
                        pvOut.Y = intersectY;
                        piSeg   = seg;
                    }
                }
            }
        }
Exemplo n.º 2
0
        private static bool AdvancePoint(IReadOnlyList <IRenderVertex> rgv, IReadOnlyList <int> poly, int a, int b, int c, int pre, int post)
        {
            var pv1 = rgv[a];
            var pv2 = rgv[b];
            var pv3 = rgv[c];

            var pvPre  = rgv[pre];
            var pvPost = rgv[post];

            if (GetDot(pv1, pv2, pv3) < 0 ||
                // Make sure angle created by new triangle line falls inside existing angles
                // If the existing angle is a concave angle, then new angle must be smaller,
                // because our triangle can"t have angles greater than 180
                GetDot(pvPre, pv1, pv2) > 0 &&
                GetDot(pvPre, pv1, pv3) < 0 ||             // convex angle, make sure new angle is smaller than it
                GetDot(pv2, pv3, pvPost) > 0 && GetDot(pv1, pv3, pvPost) < 0)
            {
                return(false);
            }

            // Now make sure the interior segment of this triangle (line ac) does not
            // intersect the polygon anywhere

            // sort our static line segment
            var minX = MathF.Min(pv1.GetX(), pv3.GetX());
            var maxX = MathF.Max(pv1.GetX(), pv3.GetX());
            var minY = MathF.Min(pv1.GetY(), pv3.GetY());
            var maxY = MathF.Max(pv1.GetY(), pv3.GetY());

            for (var i = 0; i < poly.Count; ++i)
            {
                var pvCross1 = rgv[poly[i]];
                var pvCross2 = rgv[poly[i < poly.Count - 1 ? i + 1 : 0]];

                if (pvCross1 != pv1 && pvCross2 != pv1 && pvCross1 != pv3 && pvCross2 != pv3 &&
                    (pvCross1.GetY() >= minY || pvCross2.GetY() >= minY) &&
                    (pvCross1.GetY() <= maxY || pvCross2.GetY() <= maxY) &&
                    (pvCross1.GetX() >= minX || pvCross2.GetX() >= minX) &&
                    (pvCross1.GetX() <= maxX || pvCross2.GetX() <= maxX) &&
                    LinesIntersect(pv1, pv3, pvCross1, pvCross2))
                {
                    return(false);
                }
            }

            return(true);
        }
Exemplo n.º 3
0
        private static bool LinesIntersect(IRenderVertex start1, IRenderVertex start2, IRenderVertex end1, IRenderVertex end2)
        {
            var x1 = start1.GetX();
            var y1 = start1.GetY();
            var x2 = start2.GetX();
            var y2 = start2.GetY();
            var x3 = end1.GetX();
            var y3 = end1.GetY();
            var x4 = end2.GetX();
            var y4 = end2.GetY();

            var d123 = (x2 - x1) * (y3 - y1) - (x3 - x1) * (y2 - y1);

            if (d123 == 0.0)               // p3 lies on the same line as p1 and p2
            {
                return(x3 >= MathF.Min(x1, x2) && x3 <= MathF.Max(x2, x1));
            }

            var d124 = (x2 - x1) * (y4 - y1) - (x4 - x1) * (y2 - y1);

            if (d124 == 0.0)               // p4 lies on the same line as p1 and p2
            {
                return(x4 >= MathF.Min(x1, x2) && x4 <= MathF.Max(x2, x1));
            }

            if (d123 * d124 >= 0.0)
            {
                return(false);
            }

            var d341 = (x3 - x1) * (y4 - y1) - (x4 - x1) * (y3 - y1);

            if (d341 == 0.0)               // p1 lies on the same line as p3 and p4
            {
                return(x1 >= MathF.Min(x3, x4) && x1 <= MathF.Max(x3, x4));
            }

            var d342 = d123 - d124 + d341;

            if (d342 == 0.0)               // p1 lies on the same line as p3 and p4
            {
                return(x2 >= MathF.Min(x3, x4) && x2 <= MathF.Max(x3, x4));
            }

            return(d341 * d342 < 0.0);
        }