Example #1
0
        public static bool Contains(ref IntVector2 p1, ref IntVector2 p2, ref IntVector2 q)
        {
            var p1p2 = p1.To(p2);
            var p1q  = p1.To(q);

            // not on line between p1 p2
            if (GeometryOperations.Clockness(p1p2, p1q) != Clockness.Neither)
            {
                return(false);
            }

            var a = p1p2.Dot(p1q);
            var b = p1p2.SquaredNorm2();

            // outside segment p1-p2 on the side of p1
            if (a < 0)
            {
                return(false);
            }

            // outside segment p1-p2 on the side of p2
            if (a > b)
            {
                return(false);
            }

            return(true);
        }
Example #2
0
        public static bool Contains(cInt p1x, cInt p1y, cInt p2x, cInt p2y, cInt qx, cInt qy)
        {
            var p1p2x = p2x - p1x;
            var p1p2y = p2y - p1y;
            var p1qx  = qx - p1x;
            var p1qy  = qy - p1y;

            // not on line between p1 p2
            if (GeometryOperations.Clockness(p1p2x, p1p2y, p1qx, p1qy) != Clockness.Neither)
            {
                return(false);
            }

            var a = (long)p1p2x * p1qx + (long)p1p2y * p1qy;   //p1p2.Dot(p1q);
            var b = (long)p1p2x * p1p2x + (long)p1p2y * p1p2y; //p1p2.SquaredNorm2();

            // outside segment p1-p2 on the side of p1
            if (a < 0)
            {
                return(false);
            }

            // outside segment p1-p2 on the side of p2
            if (a > b)
            {
                return(false);
            }

            return(true);
        }
Example #3
0
        public static bool Intersects(cInt ax, cInt ay, cInt bx, cInt by, cInt cx, cInt cy, cInt dx, cInt dy)
        {
            // https://www.cdn.geeksforgeeks.org/check-if-two-given-line-segments-intersect/
            // Note, didn't do SO variant because not robust to collinear segments
            // http://stackoverflow.com/questions/3838329/how-can-i-check-if-two-segments-intersect
            var o1 = GeometryOperations.Clockness(ax, ay, bx, by, cx, cy);
            var o2 = GeometryOperations.Clockness(ax, ay, bx, by, dx, dy);
            var o3 = GeometryOperations.Clockness(cx, cy, dx, dy, ax, ay);
            var o4 = GeometryOperations.Clockness(cx, cy, dx, dy, bx, by);

            if (o1 != o2 && o3 != o4)
            {
                return(true);
            }

            // handle endpoint containment.
            if (o1 == 0 && Contains(ax, ay, bx, by, cx, cy))
            {
                return(true);
            }
            if (o2 == 0 && Contains(ax, ay, bx, by, dx, dy))
            {
                return(true);
            }
            if (o3 == 0 && Contains(cx, cy, dx, dy, ax, ay))
            {
                return(true);
            }
            if (o4 == 0 && Contains(cx, cy, dx, dy, bx, by))
            {
                return(true);
            }

            return(false);
        }
Example #4
0
        public static int Compare(IntVector2 p, IntLineSegment2 a, IntLineSegment2 b)
        {
#if DEBUG
            if (GeometryOperations.Clockness(p.X, p.Y, a.X1, a.Y1, a.X2, a.Y2) != Clockness.Clockwise)
            {
                throw new InvalidStateException();
            }
            if (GeometryOperations.Clockness(p.X, p.Y, b.X1, b.Y1, b.X2, b.Y2) != Clockness.Clockwise)
            {
                throw new InvalidStateException();
            }
#endif
            var clk = GeometryOperations.Clockness(p.X, p.Y, a.X1, a.Y1, b.X1, b.Y1);
            if (clk != Clockness.Clockwise)
            {
                // b before a; b \' a *origin
                var res = (int)GeometryOperations.Clockness(b.First, b.Second, a.First);
                if (res != 0)
                {
                    return(res);
                }

                // just need something to resolve ambiguity. b1 b2 a1 is collinear.
                // a1 must be within the angle b1 p b2 (see visibility polygon building algorithm)
                // so a1 is BETWEEN b1 b2. a2 cannot be collinear with b1 b2 (disallow segments intersecting
                // other than at endpoint), but still, a2 is either 'in front of' or 'behind' b.
                res = (int)GeometryOperations.Clockness(b.First, b.Second, a.Second);
#if DEBUG
                if (res == 0 && a != b)
                {
                    throw new BadInputException();
                }
#endif
                return(res);
            }
            else
            {
                // a before b; a \' b *origin
                var res = -(int)GeometryOperations.Clockness(a.First, a.Second, b.First);
                if (res != 0)
                {
                    return(res);
                }

                // just need something to resolve ambiguity. a1 a2 b1 is collinear.
                res = -(int)GeometryOperations.Clockness(a.First, a.Second, b.Second);
#if DEBUG
                if (res == 0 && a != b)
                {
                    throw new BadInputException();
                }
#endif
                return(res);
            }
        }
        /// <summary>
        /// https://en.wikipedia.org/wiki/Sutherland%E2%80%93Hodgman_algorithm#Pseudo_code
        /// Fails if result would be empty
        /// </summary>
        public static bool TryConvexClip(Polygon2 subject, Polygon2 clip, out Polygon2 result)
        {
            bool Inside(IntVector2 p, IntLineSegment2 edge) => GeometryOperations.Clockness(edge.First, edge.Second, p) != Clockness.CounterClockwise;

            List <IntVector2> outputList = subject.Points;

            for (var i = 0; i < clip.Points.Count - 1; i++)
            {
                var clipEdge = new IntLineSegment2(clip.Points[i], clip.Points[i + 1]);
                List <IntVector2> inputList = outputList;
                outputList = new List <IntVector2>();

                var S = inputList[inputList.Count - 2];
                for (var j = 0; j < inputList.Count - 1; j++)
                {
                    var E = inputList[j];
                    if (Inside(E, clipEdge))
                    {
                        if (!Inside(S, clipEdge))
                        {
                            var SE = new IntLineSegment2(S, E);
                            if (!GeometryOperations.TryFindLineLineIntersection(SE, clipEdge, out var intersection))
                            {
                                throw new NotImplementedException();
                            }
                            outputList.Add(intersection.LossyToIntVector2());
                        }
                        outputList.Add(E);
                    }
                    else if (Inside(S, clipEdge))
                    {
                        var SE = new IntLineSegment2(S, E);
                        if (!GeometryOperations.TryFindLineLineIntersection(SE, clipEdge, out var intersection))
                        {
                            throw new NotImplementedException();
                        }
                        outputList.Add(intersection.LossyToIntVector2());
                    }
                    S = E;
                }

                if (outputList.Count == 0)
                {
                    result = null;
                    return(false);
                }

                outputList.Add(outputList[0]);
            }

            result = new Polygon2(outputList);
            return(true);
        }