private static Tuple<CrossInOut, int, bool> CutByLineVerticalForCrossDi(VertexBase v1, VertexBase v2, List<VertexBase> list, bool withIdx, int line2Idx = 0)
        {
            bool hasIntersection = false;
            bool smallToBig = true;

            var crossXsmaller = new List<IntersWithIndex>();
            var crossXbigger = new List<IntersWithIndex>();

            var minY = v1.Y;
            var maxY = v2.Y;
            if (v1.Y > v2.Y)
            {
                minY = v2.Y;
                maxY = v1.Y;
                smallToBig = false;
            }
            var x = v1.X;

            for (var toCutLineStart = 0; toCutLineStart < list.Count; toCutLineStart++)
            {
                var c1 = list[toCutLineStart % list.Count];
                var c2 = list[(toCutLineStart + 1) % list.Count];

                // 重合
                if (c1.X == c2.X && c1.X == x) continue;
                //不相交
                if (c1.X > x && c2.X > x) continue;
                if (c1.X < x && c2.X < x) continue;

                var y = LineCrossV(x, c1, c2);

                if (!hasIntersection)
                    if ((y > minY && y < maxY) ||
                        (c2.X == x && y == v2.Y) ||
                        (y == minY && c1.X != x && c2.X != x) ||
                        (y == maxY && c1.X != x && c2.X != x)
                    )
                        hasIntersection = true;

                var inters = new IntersWithIndex(x, y, toCutLineStart);
                if (smallToBig)
                {
                    if (y < minY) crossXsmaller.Add(inters);
                    if ((y > minY && y < maxY) ||
                        (y == minY && c2.X == x) ||
                        (y == minY && c1.X != x && c2.X != x) ||
                        (y == maxY && c2.X == x) ||
                        (y == maxY && c1.X != x && c2.X != x) ||
                        (y > maxY)
                        )
                        crossXbigger.Add(inters);
                }
                else
                {
                    if (y > maxY) crossXsmaller.Add(inters);
                    if ((y > minY && y < maxY) ||
                        (y == maxY && c2.X == x) ||
                        (y == maxY && c1.X != x && c2.X != x) ||
                        (y == minY && c2.X == x) ||
                        (y == minY && c1.X != x && c2.X != x) ||
                        (y < minY)
                        )
                        crossXbigger.Add(inters);
                }
            }

            if (!hasIntersection) return Tuple.Create(CrossInOut.In, 0, false);

            if (smallToBig)
                crossXbigger.Sort((p1, p2) => p1.X.CompareTo(p2.X));
            else
                crossXbigger.Sort((p1, p2) => -(p1.X.CompareTo(p2.X)));

            var count = crossXbigger.Count;
            CrossInOut crossRet;
            int cuttedLineIdx;

            if (withIdx)//切割多边形的一条边去切实体多边形的一条边
            {
                int countSkip = 0;
                for (; ; countSkip++)
                {
                    if (crossXbigger[countSkip].Idx == line2Idx)//line2Idx确定了实体多边形的这条边
                        break;
                }
                count += countSkip;
                crossRet = count % 2 == 0 ? CrossInOut.In : CrossInOut.Out;
                cuttedLineIdx = crossXbigger[countSkip].Idx;
            }
            else//实体多边形的一条边去切切割多边形
            {
                crossRet = count % 2 == 0 ? CrossInOut.In : CrossInOut.Out;
                cuttedLineIdx = crossXbigger[0].Idx;
            }

            return Tuple.Create(crossRet, cuttedLineIdx, true);
        }
Example #2
0
        private static Tuple <CrossInOut, int, bool> CutByLineVerticalForCrossDi(VertexBase v1, VertexBase v2, List <VertexBase> list, bool withIdx, int line2Idx = 0)
        {
            bool hasIntersection = false;
            bool smallToBig      = true;

            var crossXsmaller = new List <IntersWithIndex>();
            var crossXbigger  = new List <IntersWithIndex>();

            var minY = v1.Y;
            var maxY = v2.Y;

            if (v1.Y > v2.Y)
            {
                minY       = v2.Y;
                maxY       = v1.Y;
                smallToBig = false;
            }
            var x = v1.X;

            for (var toCutLineStart = 0; toCutLineStart < list.Count; toCutLineStart++)
            {
                var c1 = list[toCutLineStart % list.Count];
                var c2 = list[(toCutLineStart + 1) % list.Count];

                // 重合
                if (c1.X == c2.X && c1.X == x)
                {
                    continue;
                }
                //不相交
                if (c1.X > x && c2.X > x)
                {
                    continue;
                }
                if (c1.X < x && c2.X < x)
                {
                    continue;
                }

                var y = LineCrossV(x, c1, c2);

                if (!hasIntersection)
                {
                    if ((y > minY && y < maxY) ||
                        (c2.X == x && y == v2.Y) ||
                        (y == minY && c1.X != x && c2.X != x) ||
                        (y == maxY && c1.X != x && c2.X != x)
                        )
                    {
                        hasIntersection = true;
                    }
                }

                var inters = new IntersWithIndex(x, y, toCutLineStart);
                if (smallToBig)
                {
                    if (y < minY)
                    {
                        crossXsmaller.Add(inters);
                    }
                    if ((y > minY && y < maxY) ||
                        (y == minY && c2.X == x) ||
                        (y == minY && c1.X != x && c2.X != x) ||
                        (y == maxY && c2.X == x) ||
                        (y == maxY && c1.X != x && c2.X != x) ||
                        (y > maxY)
                        )
                    {
                        crossXbigger.Add(inters);
                    }
                }
                else
                {
                    if (y > maxY)
                    {
                        crossXsmaller.Add(inters);
                    }
                    if ((y > minY && y < maxY) ||
                        (y == maxY && c2.X == x) ||
                        (y == maxY && c1.X != x && c2.X != x) ||
                        (y == minY && c2.X == x) ||
                        (y == minY && c1.X != x && c2.X != x) ||
                        (y < minY)
                        )
                    {
                        crossXbigger.Add(inters);
                    }
                }
            }

            if (!hasIntersection)
            {
                return(Tuple.Create(CrossInOut.In, 0, false));
            }

            if (smallToBig)
            {
                crossXbigger.Sort((p1, p2) => p1.X.CompareTo(p2.X));
            }
            else
            {
                crossXbigger.Sort((p1, p2) => - (p1.X.CompareTo(p2.X)));
            }

            var        count = crossXbigger.Count;
            CrossInOut crossRet;
            int        cuttedLineIdx;

            if (withIdx)//切割多边形的一条边去切实体多边形的一条边
            {
                int countSkip = 0;
                for (; ; countSkip++)
                {
                    if (crossXbigger[countSkip].Idx == line2Idx)//line2Idx确定了实体多边形的这条边
                    {
                        break;
                    }
                }
                count        += countSkip;
                crossRet      = count % 2 == 0 ? CrossInOut.In : CrossInOut.Out;
                cuttedLineIdx = crossXbigger[countSkip].Idx;
            }
            else//实体多边形的一条边去切切割多边形
            {
                crossRet      = count % 2 == 0 ? CrossInOut.In : CrossInOut.Out;
                cuttedLineIdx = crossXbigger[0].Idx;
            }

            return(Tuple.Create(crossRet, cuttedLineIdx, true));
        }
        /// <summary>
        /// 用于获得交点进出性的切割函数
        /// </summary>
        /// <param name="v1"></param>
        /// <param name="v2"></param>
        /// <param name="list"></param>
        /// <param name="line2Idx"> </param>
        /// <returns></returns>
        private static Tuple<CrossInOut, int, bool> CutByLineForCrossDi(VertexBase v1, VertexBase v2, List<VertexBase> list, bool withIdx, int line2Idx = 0)
        {
            bool hasIntersection = false;
            bool smallToBig = true;

            var crossXsmaller = new List<IntersWithIndex>();
            var crossXbigger = new List<IntersWithIndex>();

            var slope = (v2.Y - v1.Y) / (v1.X - v2.X);
            var minX = v1.X;
            var maxX = v2.X;
            if (v1.X > v2.X)
            {
                minX = v2.X;
                maxX = v1.X;
                smallToBig = false;
            }

            //错切后的切割多边形
            var shearedPolyC = list.Select(r => new Vertex(r.X, r.X * slope + r.Y) { Name = r.Name }).ToList();
            //把实体多边形的第一条边(即切线)错切后得到一条水平直线
            var y = v1.X * slope + v1.Y;

            for (var toCutLineStart = 0; toCutLineStart < list.Count; toCutLineStart++)
            {
                var c1 = shearedPolyC[toCutLineStart % list.Count];//注意,不要漏了文档中C4->C1这种结尾的线段
                var c2 = shearedPolyC[(toCutLineStart + 1) % list.Count];

                // 重合
                if (c1.Y == c2.Y && c1.Y == y) continue;
                //不相交
                if (c1.Y > y && c2.Y > y) continue;
                if (c1.Y < y && c2.Y < y) continue;

                var x = LineCrossH(y, c1, c2);
                var npy = y - x * slope;

                if (!hasIntersection)
                    if ((x > minX && x < maxX) ||
                        (c2.Y == y && x == v2.X) ||
                        (x == minX && c1.Y != y && c2.Y != y) ||
                        (x == maxX && c1.Y != y && c2.Y != y)
                    )
                        hasIntersection = true;

                var inters = new IntersWithIndex(x, npy, toCutLineStart);
                if (smallToBig)
                {
                    if (x < minX) crossXsmaller.Add(inters);
                    if ((x > minX && x < maxX) ||
                        (x == minX && c2.Y == y) ||
                        (x == minX && c1.Y != y && c2.Y != y) ||
                        (x == maxX && c2.Y == y) ||
                        (x == maxX && c1.Y != y && c2.Y != y) ||
                        (x > maxX) //这个必不可少,不然影响进出性判断
                        )
                        crossXbigger.Add(inters);
                }
                else
                {
                    if (x > maxX) crossXsmaller.Add(inters);
                    if ((x > minX && x < maxX) ||
                        (x == maxX && c2.Y == y) ||
                        (x == maxX && c1.Y != y && c2.Y != y) ||
                        (c2.Y == y && x == minX) ||
                        (x == minX && c1.Y != y && c2.Y != y) ||
                        (x < minX) //这个必不可少,不然影响进出性判断
                        )
                        crossXbigger.Add(inters);
                }
            }

            if (!hasIntersection) return Tuple.Create(CrossInOut.In, 0, false);

            if (smallToBig)
                crossXbigger.Sort((p1, p2) => p1.X.CompareTo(p2.X));
            else
                crossXbigger.Sort((p1, p2) => -(p1.X.CompareTo(p2.X)));

            var count = crossXbigger.Count;
            CrossInOut crossRet;
            int cuttedLineIdx;

            if (withIdx)//切割多边形的一条边去切实体多边形的一条边
            {
                int countSkip = 0;
                for (; ; countSkip++)
                {
                    if (crossXbigger[countSkip].Idx == line2Idx)//line2Idx确定了实体多边形的这条边
                        break;
                }
                count += countSkip;
                crossRet = count % 2 == 0 ? CrossInOut.In : CrossInOut.Out;
                cuttedLineIdx = crossXbigger[countSkip].Idx;
            }
            else//实体多边形的一条边去切切割多边形
            {
                crossRet = count % 2 == 0 ? CrossInOut.In : CrossInOut.Out;
                cuttedLineIdx = crossXbigger[0].Idx;
            }

            return Tuple.Create(crossRet, cuttedLineIdx, true);
        }
Example #4
0
        /// <summary>
        /// 用于获得交点进出性的切割函数
        /// </summary>
        /// <param name="v1"></param>
        /// <param name="v2"></param>
        /// <param name="list"></param>
        /// <param name="line2Idx"> </param>
        /// <returns></returns>
        private static Tuple <CrossInOut, int, bool> CutByLineForCrossDi(VertexBase v1, VertexBase v2, List <VertexBase> list, bool withIdx, int line2Idx = 0)
        {
            bool hasIntersection = false;
            bool smallToBig      = true;

            var crossXsmaller = new List <IntersWithIndex>();
            var crossXbigger  = new List <IntersWithIndex>();

            var slope = (v2.Y - v1.Y) / (v1.X - v2.X);
            var minX  = v1.X;
            var maxX  = v2.X;

            if (v1.X > v2.X)
            {
                minX       = v2.X;
                maxX       = v1.X;
                smallToBig = false;
            }

            //错切后的切割多边形
            var shearedPolyC = list.Select(r => new Vertex(r.X, r.X * slope + r.Y)
            {
                Name = r.Name
            }).ToList();
            //把实体多边形的第一条边(即切线)错切后得到一条水平直线
            var y = v1.X * slope + v1.Y;

            for (var toCutLineStart = 0; toCutLineStart < list.Count; toCutLineStart++)
            {
                var c1 = shearedPolyC[toCutLineStart % list.Count];//注意,不要漏了文档中C4->C1这种结尾的线段
                var c2 = shearedPolyC[(toCutLineStart + 1) % list.Count];

                // 重合
                if (c1.Y == c2.Y && c1.Y == y)
                {
                    continue;
                }
                //不相交
                if (c1.Y > y && c2.Y > y)
                {
                    continue;
                }
                if (c1.Y < y && c2.Y < y)
                {
                    continue;
                }

                var x   = LineCrossH(y, c1, c2);
                var npy = y - x * slope;

                if (!hasIntersection)
                {
                    if ((x > minX && x < maxX) ||
                        (c2.Y == y && x == v2.X) ||
                        (x == minX && c1.Y != y && c2.Y != y) ||
                        (x == maxX && c1.Y != y && c2.Y != y)
                        )
                    {
                        hasIntersection = true;
                    }
                }

                var inters = new IntersWithIndex(x, npy, toCutLineStart);
                if (smallToBig)
                {
                    if (x < minX)
                    {
                        crossXsmaller.Add(inters);
                    }
                    if ((x > minX && x < maxX) ||
                        (x == minX && c2.Y == y) ||
                        (x == minX && c1.Y != y && c2.Y != y) ||
                        (x == maxX && c2.Y == y) ||
                        (x == maxX && c1.Y != y && c2.Y != y) ||
                        (x > maxX) //这个必不可少,不然影响进出性判断
                        )
                    {
                        crossXbigger.Add(inters);
                    }
                }
                else
                {
                    if (x > maxX)
                    {
                        crossXsmaller.Add(inters);
                    }
                    if ((x > minX && x < maxX) ||
                        (x == maxX && c2.Y == y) ||
                        (x == maxX && c1.Y != y && c2.Y != y) ||
                        (c2.Y == y && x == minX) ||
                        (x == minX && c1.Y != y && c2.Y != y) ||
                        (x < minX) //这个必不可少,不然影响进出性判断
                        )
                    {
                        crossXbigger.Add(inters);
                    }
                }
            }

            if (!hasIntersection)
            {
                return(Tuple.Create(CrossInOut.In, 0, false));
            }

            if (smallToBig)
            {
                crossXbigger.Sort((p1, p2) => p1.X.CompareTo(p2.X));
            }
            else
            {
                crossXbigger.Sort((p1, p2) => - (p1.X.CompareTo(p2.X)));
            }

            var        count = crossXbigger.Count;
            CrossInOut crossRet;
            int        cuttedLineIdx;

            if (withIdx)//切割多边形的一条边去切实体多边形的一条边
            {
                int countSkip = 0;
                for (; ; countSkip++)
                {
                    if (crossXbigger[countSkip].Idx == line2Idx)//line2Idx确定了实体多边形的这条边
                    {
                        break;
                    }
                }
                count        += countSkip;
                crossRet      = count % 2 == 0 ? CrossInOut.In : CrossInOut.Out;
                cuttedLineIdx = crossXbigger[countSkip].Idx;
            }
            else//实体多边形的一条边去切切割多边形
            {
                crossRet      = count % 2 == 0 ? CrossInOut.In : CrossInOut.Out;
                cuttedLineIdx = crossXbigger[0].Idx;
            }

            return(Tuple.Create(crossRet, cuttedLineIdx, true));
        }