Beispiel #1
0
        private static List <Polygon> LinkToPolygon_Union()
        {
            //保存合并后的多边形数组
            var         rcNodes = new List <Vector2>();
            var         startV  = GetLeftBottomVertex();
            PolygonNode node    = null;

            if (GetNodeIndex(lnSubject, startV) != -1)
            {
                node = lnSubject[GetNodeIndex(lnSubject, startV)];
            }
            else if (GetNodeIndex(lnClip, startV) != -1)
            {
                node = lnClip[GetNodeIndex(lnClip, startV)];
            }

            while (node != null)
            {
                rcNodes.Add(node.vertex);
                if (node.isIntersectPoint)
                {
                    if (node.isOutPoint == false)                     //该交点为进点(跟踪主多边形边界)
                    {
                        if (node.isSubject == false)                  //当前点在副多边形中
                        {
                            node = node.other;                        //切换到主多边形中
                        }
                    }
                    else                       //该交点为出点(跟踪副多边形边界)
                    {
                        if (node.isSubject)    //当前点在主多边形中
                        {
                            node = node.other; //切换到副多边形中
                        }
                    }
                }

                if (node.next == null)                 //末尾点返回到开始点
                {
                    node = node.isSubject ? lnSubject[0] : lnClip[0];
                }
                else
                {
                    node = node.next;
                }

                //与首点相同,生成一个多边形
                if (node.vertex == rcNodes[0])
                {
                    break;
                }
            }

            var ret = new List <Polygon> {
                new Polygon(rcNodes.ToArray())
            };

            return(ret);
        }
Beispiel #2
0
        /// <summary>
        ///   创建polygon的nodes,最后一个node的next指向null
        /// </summary>
        /// <param name="polygon"></param>
        /// <param name="isIntersectPoint"></param>
        /// <param name="isSubject"></param>
        /// <returns></returns>
        public static List <PolygonNode> CreateNodes(Polygon polygon, bool isIntersectPoint, bool isSubject)
        {
            var         nodes = new List <PolygonNode>();
            PolygonNode node;

            for (var i = 0; i < polygon.vertexList.Count; i++)
            {
                node = new PolygonNode(polygon.vertexList[i], isIntersectPoint, isSubject);
                if (i > 0)
                {
                    nodes[i - 1].next = node;
                }
                nodes.Add(node);
            }

            return(nodes);
        }
Beispiel #3
0
        private static int IntersectPoint_Union()
        {
            var         insCnt      = 0; //交点数
            var         nSubjectCur = lnSubject[0];
            PolygonNode nClipCur;
            Line        lSubject;
            Line        lClip;
            bool        hasIntersectPoint;      //是否有交点

            while (nSubjectCur != null)         //主多边形
            {
                lSubject = nSubjectCur.next == null
                                        ? new Line(nSubjectCur.vertex, lnSubject[0].vertex)
                                        : new Line(nSubjectCur.vertex, nSubjectCur.next.vertex);

                //奇异情况:与裁剪多边形重合的主多边形的边不参与求交点 http://course.baidu.com/view/58a00497daef5ef7ba0d3c52.html
                if (IsOverLap_Union(lSubject, pClip))
                {
                    nSubjectCur = nSubjectCur.next;
                    continue;
                }

                nClipCur          = lnClip[0];
                hasIntersectPoint = false;

                while (nClipCur != null)
                {
                    lClip = nClipCur.next == null
                                                ? new Line(nClipCur.vertex, lnClip[0].vertex)
                                                : new Line(nClipCur.vertex, nClipCur.next.vertex);

                    var lineRelation = lSubject.Intersection(lClip, out var intersectPoint);
                    if (lineRelation == Line.LineClassification.SegmentsIntersect)                     //相交
                    {
                        var a_on_lClip        = lClip.ClassifyPoint(lSubject.pointA) == PointClassification.OnSegment;
                        var a_index_of_lnClip = GetNodeIndex(lnClip, lSubject.pointA);
                        var b_on_lClip        = lClip.ClassifyPoint(lSubject.pointB) == PointClassification.OnSegment;
                        var b_index_of_lnClip = GetNodeIndex(lnClip, lSubject.pointB);

                        //主多边形边上的顶点A是在副多边形上
                        if (a_on_lClip && (a_index_of_lnClip == -1 ||
                                           a_index_of_lnClip != -1 && lnClip[a_index_of_lnClip].isChecked == false))
                        {
                            insCnt++;
                            PolygonNode nSubjectInter = null;
                            PolygonNode nClipInter    = null;

                            if (GetNodeIndex(lnSubject, lSubject.pointA) == -1)
                            {
                                nSubjectInter           = new PolygonNode(lSubject.pointA, true, true);
                                nSubjectInter.isChecked = true;
                                lnSubject.Add(nSubjectInter);
                                nSubjectInter.next = nSubjectCur.next;
                                nSubjectCur.next   = nSubjectInter;
                                hasIntersectPoint  = true;
                            }
                            else
                            {
                                nSubjectInter = lnSubject[GetNodeIndex(lnSubject, lSubject.pointA)];
                                nSubjectInter.isIntersectPoint = true;
                                nSubjectInter.isChecked        = true;
                            }

                            if (GetNodeIndex(lnClip, lSubject.pointA) == -1)
                            {
                                nClipInter           = new PolygonNode(lSubject.pointA, true, false);
                                nClipInter.isChecked = true;
                                lnClip.Add(nClipInter);
                                nClipInter.next = nClipCur.next;
                                nClipCur.next   = nClipInter;
                            }
                            else
                            {
                                nClipInter                  = lnClip[GetNodeIndex(lnClip, lSubject.pointA)];
                                nClipInter.isChecked        = true;
                                nClipInter.isIntersectPoint = true;
                            }


                            //双向引用
                            nSubjectInter.other = nClipInter;
                            nClipInter.other    = nSubjectInter;

                            if (!IsOutter(lSubject, pClip))
                            {
                                nSubjectInter.isOutPoint = true;
                                nClipInter.isOutPoint    = true;
                            }
                            else
                            {
                                nSubjectInter.isOutPoint = false;
                                nClipInter.isOutPoint    = false;
                            }
                        }

                        //主多边形边上的顶点B是在副多边形上
                        if (b_on_lClip && (b_index_of_lnClip == -1 ||
                                           b_index_of_lnClip != -1 && lnClip[b_index_of_lnClip].isChecked == false))
                        {
                            insCnt++;
                            PolygonNode nSubjectInter = null;
                            PolygonNode nClipInter    = null;

                            if (GetNodeIndex(lnSubject, lSubject.pointB) == -1)
                            {
                                nSubjectInter           = new PolygonNode(lSubject.pointB, true, true);
                                nSubjectInter.isChecked = true;
                                lnSubject.Add(nSubjectInter);
                                nSubjectInter.next = nSubjectCur.next;
                                nSubjectCur.next   = nSubjectInter;
                                hasIntersectPoint  = true;
                            }
                            else
                            {
                                nSubjectInter = lnSubject[GetNodeIndex(lnSubject, lSubject.pointB)];
                                nSubjectInter.isIntersectPoint = true;
                                nSubjectInter.isChecked        = true;
                            }

                            if (GetNodeIndex(lnClip, lSubject.pointB) == -1)
                            {
                                nClipInter           = new PolygonNode(lSubject.pointB, true, false);
                                nClipInter.isChecked = true;
                                lnClip.Add(nClipInter);
                                nClipInter.next = nClipCur.next;
                                nClipCur.next   = nClipInter;
                            }
                            else
                            {
                                nClipInter                  = lnClip[GetNodeIndex(lnClip, lSubject.pointB)];
                                nClipInter.isChecked        = true;
                                nClipInter.isIntersectPoint = true;
                            }

                            nSubjectInter.other = nClipInter;
                            nClipInter.other    = nSubjectInter;

                            if (!IsOutter(lSubject, pClip))
                            {
                                nSubjectInter.isOutPoint = false;
                                nClipInter.isOutPoint    = false;
                            }
                            else
                            {
                                nSubjectInter.isOutPoint = true;
                                nClipInter.isOutPoint    = true;
                            }
                        }

                        //交点不在顶点上的情况(主多边形的一条线段肯能跟副多边形的多条边相交)
                        //忽略交点已在顶点列表中的
                        if (GetNodeIndex(lnSubject, intersectPoint.Value) == -1)
                        {
                            insCnt++;
                            ///////// 插入交点
                            var nSubjectInter = new PolygonNode(intersectPoint.Value, true, true);
                            nSubjectInter.isChecked = true;
                            var nClipInter = new PolygonNode(intersectPoint.Value, true, false);
                            nClipInter.isChecked = true;

                            lnSubject.Add(nSubjectInter);
                            lnClip.Add(nClipInter);
                            //双向引用
                            nSubjectInter.other = nClipInter;
                            nClipInter.other    = nSubjectInter;
                            //插入
                            nSubjectInter.next = nSubjectCur.next;
                            nSubjectCur.next   = nSubjectInter;
                            nClipInter.next    = nClipCur.next;
                            nClipCur.next      = nClipInter;


                            //出点
                            if (lSubject.ClassifyPoint(lClip.pointB) == PointClassification.LeftSide)
                            {
                                nSubjectInter.isOutPoint = true;
                                nClipInter.isOutPoint    = true;
                            }
                            else
                            {
                                nSubjectInter.isOutPoint = false;
                                nClipInter.isOutPoint    = false;
                            }

                            hasIntersectPoint = true;                             //有交点
                            //有交点,返回重新处理
                            break;
                        }
                    }

                    nClipCur = nClipCur.next;
                }

                //如果没有交点继续处理下一个边,否则重新处理该点与插入的交点所形成的线段
                //原因:这条线段上还可能有其他的交点,注意hasIntersectPoint是只检测一次true就break,而且无法确定同一条边的交点先后顺序,所以如果有交点的时候要重新处理该点与插入的交点所形成的线段
                if (hasIntersectPoint == false)
                {
                    nSubjectCur = nSubjectCur.next;
                }
            }

            return(insCnt);
        }
Beispiel #4
0
        private static int IntersectPoint_Cut()
        {
            var         insCnt      = 0; //交点数
            var         nSubjectCur = lnSubject[0];
            PolygonNode nClipCur;
            Line        lSubject;
            Line        lClip;
            bool        isHasIntersectPoint;      //是否有交点

            while (nSubjectCur != null)           //主多边形
            {
                lSubject = nSubjectCur.next == null
                                        ? new Line(nSubjectCur.vertex, lnSubject[0].vertex)
                                        : new Line(nSubjectCur.vertex, nSubjectCur.next.vertex);

                //奇异情况:与裁剪多边形重合的主多边形的边不参与求交点 http://course.baidu.com/view/58a00497daef5ef7ba0d3c52.html
                if (IsOverLap_Cut(lSubject, pClip))
                {
                    nSubjectCur = nSubjectCur.next;
                    continue;
                }


                nClipCur            = lnClip[0];
                isHasIntersectPoint = false;

                while (nClipCur != null)
                {
                    lClip = nClipCur.next == null
                                                ? new Line(nClipCur.vertex, lnClip[0].vertex)
                                                : new Line(nClipCur.vertex, nClipCur.next.vertex);

                    var lineRelation = lSubject.Intersection(lClip, out var intersectPoint);
                    if (lineRelation == Line.LineClassification.SegmentsIntersect)                     //相交
                    {
                        if (lClip.ClassifyPoint(lSubject.pointA) == PointClassification.OnSegment &&
                            GetNodeIndex(lnClip, lSubject.pointA) == -1)
                        {
                            if (!IsOutter(lSubject, pClip))
                            {
                                insCnt++;
                                var nSubjectInter = nSubjectCur;
                                nSubjectInter.isIntersectPoint = true;


                                var nClipInter = new PolygonNode(lSubject.pointA, true, false);
                                lnClip.Add(nClipInter);

                                nClipInter.other    = nSubjectInter;
                                nSubjectInter.other = nClipInter;

                                nClipCur        = lnClip[GetNodeIndex(lnClip, lClip.pointA)];
                                nClipInter.next = nClipCur.next;
                                nClipCur.next   = nClipInter;


                                nSubjectInter.isOutPoint = false;
                                nClipInter.isOutPoint    = false;
                            }
                        }

                        if (lClip.ClassifyPoint(lSubject.pointB) == PointClassification.OnSegment &&
                            GetNodeIndex(lnClip, lSubject.pointB) == -1)
                        {
                            if (!IsOutter(lSubject, pClip))
                            {
                                insCnt++;
                                var nSubjectInter = lnSubject[GetNodeIndex(lnSubject, lSubject.pointB)];
                                nSubjectInter.isIntersectPoint = true;

                                var nClipInter = new PolygonNode(lSubject.pointB, true, false);
                                lnClip.Add(nClipInter);

                                nSubjectInter.other = nClipInter;
                                nClipInter.other    = nSubjectInter;

                                nClipInter.next = nClipCur.next;
                                nClipCur.next   = nClipInter;


                                nSubjectInter.isOutPoint = true;
                                nClipInter.isOutPoint    = true;
                            }
                        }

                        //忽略交点已在顶点列表中的
                        if (GetNodeIndex(lnSubject, intersectPoint.Value) == -1)
                        {
                            insCnt++;
                            ///////// 插入交点
                            var nSubjectInter = new PolygonNode(intersectPoint.Value, true, true);
                            var nClipInter    = new PolygonNode(intersectPoint.Value, true, false);

                            lnSubject.Add(nSubjectInter);
                            lnClip.Add(nClipInter);
                            //双向引用
                            nSubjectInter.other = nClipInter;
                            nClipInter.other    = nSubjectInter;

                            //插入
                            nSubjectInter.next = nSubjectCur.next;
                            nSubjectCur.next   = nSubjectInter;
                            nClipInter.next    = nClipCur.next;
                            nClipCur.next      = nClipInter;


                            //出点
                            if (lSubject.ClassifyPoint(lClip.pointB) == PointClassification.RightSide)
                            {
                                nSubjectInter.isOutPoint = true;
                                nClipInter.isOutPoint    = true;
                            }
                            else
                            {
                                nSubjectInter.isOutPoint = false;
                                nClipInter.isOutPoint    = false;
                            }

                            isHasIntersectPoint = true;                             //有交点
                            //有交点,返回重新处理
                            break;
                        }
                    }

                    nClipCur = nClipCur.next;
                }

                //如果没有交点继续处理下一个边,否则重新处理该点与插入的交点所形成的线段
                //原因:这条线段上还可能有其他的交点,注意hasIntersectPoint是只检测一次true就break,而且无法确定同一条边的交点先后顺序,所以如果有交点的时候要重新处理该点与插入的交点所形成的线段
                if (isHasIntersectPoint == false)
                {
                    nSubjectCur = nSubjectCur.next;
                }
            }

            return(insCnt);
        }