示例#1
0
 //------------------------------------------------------------------------------
 private void AddIntersectNode(TEdge4 e1, TEdge4 e2, IntPoint pt)
 {
     IntersectNode newNode = new IntersectNode();
       newNode.edge1 = e1;
       newNode.edge2 = e2;
       newNode.pt = pt;
       newNode.next = null;
       if (m_IntersectNodes == null) m_IntersectNodes = newNode;
       else if( Process1Before2(newNode, m_IntersectNodes) )
       {
     newNode.next = m_IntersectNodes;
     m_IntersectNodes = newNode;
       }
       else
       {
     IntersectNode iNode = m_IntersectNodes;
     while( iNode.next != null  && Process1Before2(iNode.next, newNode) )
         iNode = iNode.next;
     newNode.next = iNode.next;
     iNode.next = newNode;
       }
 }
示例#2
0
 //------------------------------------------------------------------------------
 private void AddLocalMaxPoly(TEdge4 e1, TEdge4 e2, IntPoint pt)
 {
     AddPolyPt(e1, pt);
     if (e1.outIdx == e2.outIdx)
     {
         e1.outIdx = -1;
         e2.outIdx = -1;
     }
     else AppendPolygon(e1, e2);
 }
示例#3
0
        //------------------------------------------------------------------------------
        private void IntersectEdges(TEdge4 e1, TEdge4 e2, IntPoint pt, Protects protects)
        {
            //e1 will be to the left of e2 BELOW the intersection. Therefore e1 is before
            //e2 in AEL except when e1 is being inserted at the intersection point ...

            bool e1stops = (Protects.ipLeft & protects) == 0 && e1.nextInLML == null &&
              e1.xtop == pt.X && e1.ytop == pt.Y;
            bool e2stops = (Protects.ipRight & protects) == 0 && e2.nextInLML == null &&
              e2.xtop == pt.X && e2.ytop == pt.Y;
            bool e1Contributing = (e1.outIdx >= 0);
            bool e2contributing = (e2.outIdx >= 0);

            //update winding counts...
            //assumes that e1 will be to the right of e2 ABOVE the intersection
            if (e1.polyType == e2.polyType)
            {
                if (IsNonZeroFillType(e1))
                {
                    if (e1.windCnt + e2.windDelta == 0) e1.windCnt = -e1.windCnt;
                    else e1.windCnt += e2.windDelta;
                    if (e2.windCnt - e1.windDelta == 0) e2.windCnt = -e2.windCnt;
                    else e2.windCnt -= e1.windDelta;
                }
                else
                {
                    int oldE1WindCnt = e1.windCnt;
                    e1.windCnt = e2.windCnt;
                    e2.windCnt = oldE1WindCnt;
                }
            }
            else
            {
                if (IsNonZeroFillType(e2)) e1.windCnt2 += e2.windDelta;
                else e1.windCnt2 = (e1.windCnt2 == 0) ? 1 : 0;
                if (IsNonZeroFillType(e1)) e2.windCnt2 -= e1.windDelta;
                else e2.windCnt2 = (e2.windCnt2 == 0) ? 1 : 0;
            }

            if (e1Contributing && e2contributing)
            {
                if (e1stops || e2stops || Math.Abs(e1.windCnt) > 1 ||
                  Math.Abs(e2.windCnt) > 1 ||
                  (e1.polyType != e2.polyType && m_ClipType != ClipType.ctXor))
                    AddLocalMaxPoly(e1, e2, pt);
                else
                    DoBothEdges(e1, e2, pt);
            }
            else if (e1Contributing)
            {
                if (m_ClipType == ClipType.ctIntersection)
                {
                    if ((e2.polyType == PolyType.ptSubject || e2.windCnt2 != 0) &&
                        Math.Abs(e2.windCnt) < 2)
                        DoEdge1(e1, e2, pt);
                }
                else
                {
                    if (Math.Abs(e2.windCnt) < 2)
                        DoEdge1(e1, e2, pt);
                }
            }
            else if (e2contributing)
            {
                if (m_ClipType == ClipType.ctIntersection)
                {
                    if ((e1.polyType == PolyType.ptSubject || e1.windCnt2 != 0) &&
                  Math.Abs(e1.windCnt) < 2) DoEdge2(e1, e2, pt);
                }
                else
                {
                    if (Math.Abs(e1.windCnt) < 2)
                        DoEdge2(e1, e2, pt);
                }
            }
            else if (Math.Abs(e1.windCnt) < 2 && Math.Abs(e2.windCnt) < 2)
            {
                //neither edge is currently contributing ...
                if (e1.polyType != e2.polyType && !e1stops && !e2stops &&
                  Math.Abs(e1.windCnt) < 2 && Math.Abs(e2.windCnt) < 2)
                    AddLocalMinPoly(e1, e2, pt);
                else if (Math.Abs(e1.windCnt) == 1 && Math.Abs(e2.windCnt) == 1)
                    switch (m_ClipType)
                    {
                        case ClipType.ctIntersection:
                            {
                                if (Math.Abs(e1.windCnt2) > 0 && Math.Abs(e2.windCnt2) > 0)
                                    AddLocalMinPoly(e1, e2, pt);
                                break;
                            }
                        case ClipType.ctUnion:
                            {
                                if (e1.windCnt2 == 0 && e2.windCnt2 == 0)
                                    AddLocalMinPoly(e1, e2, pt);
                                break;
                            }
                        case ClipType.ctDifference:
                            {
                                if ((e1.polyType == PolyType.ptClip && e2.polyType == PolyType.ptClip &&
                              e1.windCnt2 != 0 && e2.windCnt2 != 0) ||
                              (e1.polyType == PolyType.ptSubject && e2.polyType == PolyType.ptSubject &&
                              e1.windCnt2 == 0 && e2.windCnt2 == 0))
                                    AddLocalMinPoly(e1, e2, pt);
                                break;
                            }
                        case ClipType.ctXor:
                            {
                                AddLocalMinPoly(e1, e2, pt);
                                break;
                            }
                    }
                else if (Math.Abs(e1.windCnt) < 2 && Math.Abs(e2.windCnt) < 2)
                    SwapSides(e1, e2);
            }

            if ((e1stops != e2stops) &&
              ((e1stops && (e1.outIdx >= 0)) || (e2stops && (e2.outIdx >= 0))))
            {
                SwapSides(e1, e2);
                SwapPolyIndexes(e1, e2);
            }

            //finally, delete any non-contributing maxima edges  ...
            if (e1stops) DeleteFromAEL(e1);
            if (e2stops) DeleteFromAEL(e2);
        }
示例#4
0
 //------------------------------------------------------------------------------
 internal void SwapPoints(ref IntPoint pt1, ref IntPoint pt2)
 {
     IntPoint tmp = pt1;
     pt1 = pt2;
     pt2 = tmp;
 }
示例#5
0
 //------------------------------------------------------------------------------
 private bool FindSegment(ref PolyPt pp, IntPoint pt1, IntPoint pt2)
 {
     if (pp == null) return false;
     PolyPt pp2 = pp;
     do
     {
     if (PointsEqual(pp.pt, pt1) &&
         (PointsEqual(pp.next.pt, pt2) || PointsEqual(pp.prev.pt, pt2)))
         return true;
     pp = pp.next;
     }
     while (pp != pp2);
     return false;
 }
示例#6
0
        //------------------------------------------------------------------------------
        private void InsertLocalMinimaIntoAEL(int botY)
        {
            while(  m_CurrentLM != null  && ( m_CurrentLM.Y == botY ) )
              {
            TEdge4 lb = m_CurrentLM.leftBound;
            TEdge4 rb = m_CurrentLM.rightBound;

            InsertEdgeIntoAEL( lb );
            InsertScanbeam( lb.ytop );
            InsertEdgeIntoAEL( rb );

            if ( IsNonZeroFillType( lb) )
              rb.windDelta = -lb.windDelta;
            else
            {
              lb.windDelta = 1;
              rb.windDelta = 1;
            }
            SetWindingCount( lb );
            rb.windCnt = lb.windCnt;
            rb.windCnt2 = lb.windCnt2;

            if(  rb.dx == horizontal )
            {
              //nb: only rightbounds can have a horizontal bottom edge
              AddEdgeToSEL( rb );
              InsertScanbeam( rb.nextInLML.ytop );
            }
            else
              InsertScanbeam( rb.ytop );

            if( IsContributing(lb) )
                AddLocalMinPoly(lb, rb, new IntPoint(lb.xcurr, m_CurrentLM.Y));

            //if output polygons share an edge, they'll need joining later ...
            if (lb.outIdx >= 0 && lb.prevInAEL != null &&
              lb.prevInAEL.outIdx >= 0 && lb.prevInAEL.xcurr == lb.xbot &&
               SlopesEqual(lb, lb.prevInAEL))
                AddJoin(lb, lb.prevInAEL);

            //if any output polygons share an edge, they'll need joining later ...
            if (rb.outIdx >= 0)
            {
                if (rb.dx == horizontal)
                {
                    for (int i = 0; i < m_HorizJoins.Count; i++)
                    {
                        IntPoint pt = new IntPoint(), pt2 = new IntPoint(); //used as dummy params.
                        HorzJoinRec hj = m_HorizJoins[i];
                        //if horizontals rb and hj.edge overlap, flag for joining later ...
                        if (GetOverlapSegment(new IntPoint(hj.edge.xbot, hj.edge.ybot),
                            new IntPoint(hj.edge.xtop, hj.edge.ytop),
                            new IntPoint(rb.xbot, rb.ybot),
                            new IntPoint(rb.xtop, rb.ytop),
                            ref pt, ref pt2))
                                AddJoin(hj.edge, rb, hj.savedIdx);
                    }
                }
            }

            if( lb.nextInAEL != rb )
            {
              TEdge4 e = lb.nextInAEL;
              IntPoint pt = new IntPoint(lb.xcurr, lb.ycurr);
              while( e != rb )
              {
                if(e == null)
                    throw new ClipperException("InsertLocalMinimaIntoAEL: missing rightbound!");
                //nb: For calculating winding counts etc, IntersectEdges() assumes
                //that param1 will be to the right of param2 ABOVE the intersection ...
                IntersectEdges( rb , e , pt , Protects.ipNone); //order important here
                e = e.nextInAEL;
              }
            }
            PopLocalMinima();
              }
        }
示例#7
0
 //------------------------------------------------------------------------------
 private void InitEdge(TEdge4 e, TEdge4 eNext,
     TEdge4 ePrev, IntPoint pt, PolyType polyType)
 {
     e.next = eNext;
       e.prev = ePrev;
       e.xcurr = pt.X;
       e.ycurr = pt.Y;
       if (e.ycurr >= e.next.ycurr)
       {
     e.xbot = e.xcurr;
     e.ybot = e.ycurr;
     e.xtop = e.next.xcurr;
     e.ytop = e.next.ycurr;
     e.windDelta = 1;
       } else
       {
     e.xtop = e.xcurr;
     e.ytop = e.ycurr;
     e.xbot = e.next.xcurr;
     e.ybot = e.next.ycurr;
     e.windDelta = -1;
       }
       SetDx(e);
       e.polyType = polyType;
       e.outIdx = -1;
 }
示例#8
0
        //------------------------------------------------------------------------------
        private void BuildIntersectList(int topY)
        {
            if ( m_ActiveEdges == null ) return;

              //prepare for sorting ...
              TEdge4 e = m_ActiveEdges;
              e.tmpX = TopX( e, topY );
              m_SortedEdges = e;
              m_SortedEdges.prevInSEL = null;
              e = e.nextInAEL;
              while( e != null )
              {
            e.prevInSEL = e.prevInAEL;
            e.prevInSEL.nextInSEL = e;
            e.nextInSEL = null;
            e.tmpX = TopX( e, topY );
            e = e.nextInAEL;
              }

              //bubblesort ...
              bool isModified = true;
              while( isModified && m_SortedEdges != null )
              {
            isModified = false;
            e = m_SortedEdges;
            while( e.nextInSEL != null )
            {
              TEdge4 eNext = e.nextInSEL;
              IntPoint pt = new IntPoint();
              if(e.tmpX > eNext.tmpX && IntersectPoint(e, eNext, ref pt))
              {
                AddIntersectNode( e, eNext, pt );
                SwapPositionsInSEL(e, eNext);
                isModified = true;
              }
              else
                e = eNext;
            }
            if( e.prevInSEL != null ) e.prevInSEL.nextInSEL = null;
            else break;
              }
              m_SortedEdges = null;
        }
示例#9
0
 //------------------------------------------------------------------------------
 protected bool PointsEqual(IntPoint pt1, IntPoint pt2)
 {
     return ( pt1.X == pt2.X && pt1.Y == pt2.Y );
 }
示例#10
0
 //------------------------------------------------------------------------------
 protected bool SlopesEqual(IntPoint pt1, IntPoint pt2, IntPoint pt3)
 {
     if (pt1.Y == pt2.Y) return (pt2.Y == pt3.Y);
       else if (pt2.Y == pt3.Y) return false;
       else return
     (Int64)(pt1.Y-pt2.Y)*(pt2.X-pt3.X) - (Int64)(pt1.X-pt2.X)*(pt2.Y-pt3.Y) == 0;
 }
示例#11
0
 //------------------------------------------------------------------------------
 private int TopX(IntPoint pt1, IntPoint pt2, int currentY)
 {
     //preconditions: pt1.Y <> pt2.Y and pt1.Y > pt2.Y
       if (currentY >= pt1.Y) return pt1.X;
       else if (currentY == pt2.Y) return pt2.X;
       else if (pt1.X == pt2.X) return pt1.X;
       else
       {
     double q = (pt1.X-pt2.X)/(pt1.Y-pt2.Y);
     return (int)(pt1.X + (currentY - pt1.Y) *q);
       }
 }
示例#12
0
        //----------------------------------------------------------------------
        private void JoinCommonEdges()
        {
            for (int i = 0; i < m_Joins.Count; i++)
              {
            PolyPt pp1a, pp1b, pp2a, pp2b;
            IntPoint pt1 = new IntPoint(), pt2 = new IntPoint();

            JoinRec j = m_Joins[i];
            if (j.poly1Idx < 0 || j.poly2Idx < 0)
                throw new ClipperException("JoinCommonEdges error");

            pp1a = m_PolyPts[j.poly1Idx];
            pp2a = m_PolyPts[j.poly2Idx];
            if (FindSegment(ref pp1a, j.pt1a, j.pt1b) &&
              FindSegment(ref pp2a, j.pt2a, j.pt2b))
            {
              if (PointsEqual(pp1a.next.pt, j.pt1b))
                pp1b = pp1a.next; else pp1b = pp1a.prev;
              if (PointsEqual(pp2a.next.pt, j.pt2b))
                pp2b = pp2a.next; else pp2b = pp2a.prev;
              if (j.poly1Idx != j.poly2Idx &&
                GetOverlapSegment(pp1a.pt, pp1b.pt, pp2a.pt, pp2b.pt, ref pt1, ref pt2))
              {
                PolyPt p1, p2, p3, p4;
                //get p1 & p2 polypts - the overlap start & endpoints on poly1
                Position pos1 = GetPosition(pp1a.pt, pp1b.pt, pt1);
                if (pos1 == Position.pFirst) p1 = pp1a;
                else if (pos1 == Position.pSecond) p1 = pp1b;
                else p1 = InsertPolyPtBetween(pp1a, pp1b, pt1);
                Position pos2 = GetPosition(pp1a.pt, pp1b.pt, pt2);
                if (pos2 == Position.pMiddle)
                {
                    if (pos1 == Position.pMiddle)
                  {
                    if (Pt3IsBetweenPt1AndPt2(pp1a.pt, p1.pt, pt2))
                      p2 = InsertPolyPtBetween(pp1a, p1, pt2); else
                      p2 = InsertPolyPtBetween(p1, pp1b, pt2);
                  }
                    else if (pos2 == Position.pFirst) p2 = pp1a;
                  else p2 = pp1b;
                }
                else if (pos2 == Position.pFirst) p2 = pp1a;
                else p2 = pp1b;
                //get p3 & p4 polypts - the overlap start & endpoints on poly2
                pos1 = GetPosition(pp2a.pt, pp2b.pt, pt1);
                if (pos1 == Position.pFirst) p3 = pp2a;
                else if (pos1 == Position.pSecond) p3 = pp2b;
                else p3 = InsertPolyPtBetween(pp2a, pp2b, pt1);
                pos2 = GetPosition(pp2a.pt, pp2b.pt, pt2);
                if (pos2 == Position.pMiddle)
                {
                    if (pos1 == Position.pMiddle)
                  {
                    if (Pt3IsBetweenPt1AndPt2(pp2a.pt, p3.pt, pt2))
                      p4 = InsertPolyPtBetween(pp2a, p3, pt2); else
                      p4 = InsertPolyPtBetween(p3, pp2b, pt2);
                  }
                    else if (pos2 == Position.pFirst) p4 = pp2a;
                  else p4 = pp2b;
                }
                else if (pos2 == Position.pFirst) p4 = pp2a;
                else p4 = pp2b;

                if (p1.next == p2) p1.next = p3; else p1.prev = p3;
                if (p3.next == p4) p3.next = p1; else p3.prev = p1;

                if (p2.next == p1) p2.next = p4; else p2.prev = p4;
                if (p4.next == p3) p4.next = p2; else p4.prev = p2;

                m_PolyPts[j.poly2Idx] = null;
              }
            }
              }
        }
示例#13
0
        //------------------------------------------------------------------------------
        private bool IntersectPoint(TEdge4 edge1, TEdge4 edge2, ref IntPoint ip)
        {
            double b1, b2;
              if (SlopesEqual(edge1, edge2)) return false;
              else if (edge1.dx == 0)
              {
            ip.X = edge1.xbot;
            if (edge2.dx == horizontal)
            {
              ip.Y = edge2.ybot;
            } else
            {
              b2 = edge2.ybot - (edge2.xbot/edge2.dx);
              ip.Y = Round(ip.X/edge2.dx + b2);
            }
              }
              else if (edge2.dx == 0)
              {
            ip.X = edge2.xbot;
            if (edge1.dx == horizontal)
            {
              ip.Y = edge1.ybot;
            } else
            {
              b1 = edge1.ybot - (edge1.xbot/edge1.dx);
              ip.Y = Round(ip.X/edge1.dx + b1);
            }
              } else
              {
            b1 = edge1.xbot - edge1.ybot * edge1.dx;
            b2 = edge2.xbot - edge2.ybot * edge2.dx;
            b2 = (b2-b1)/(edge1.dx - edge2.dx);
            ip.Y = Round(b2);
            ip.X = Round(edge1.dx * b2 + b1);
              }

              return
            //can be *so close* to the top of one edge that the rounded Y equals one ytop ...
            (ip.Y == edge1.ytop && ip.Y >= edge2.ytop && edge1.tmpX > edge2.tmpX) ||
            (ip.Y == edge2.ytop && ip.Y >= edge1.ytop && edge1.tmpX > edge2.tmpX) ||
            (ip.Y > edge1.ytop && ip.Y > edge2.ytop);
        }
示例#14
0
 //------------------------------------------------------------------------------
 private void AddLocalMinPoly(TEdge4 e1, TEdge4 e2, IntPoint pt)
 {
     if (e2.dx == horizontal || (e1.dx > e2.dx))
     {
         AddPolyPt(e1, pt);
         e2.outIdx = e1.outIdx;
         e1.side = EdgeSide.esLeft;
         e2.side = EdgeSide.esRight;
     }
     else
     {
         AddPolyPt(e2, pt);
         e1.outIdx = e2.outIdx;
         e1.side = EdgeSide.esRight;
         e2.side = EdgeSide.esLeft;
     }
 }
示例#15
0
 //------------------------------------------------------------------------------
 internal static Polygon BuildArc(IntPoint pt, double a1, double a2, double r)
 {
     int steps = Math.Max(6, (int)(Math.Sqrt(Math.Abs(r)) * Math.Abs(a2 - a1)));
       Polygon result = new Polygon(steps);
       int n = steps - 1;
       double da = (a2 - a1) / n;
       double a = a1;
       for (int i = 0; i < steps; ++i)
       {
     result.Add(new IntPoint(pt.X + (int)(Math.Cos(a)*r), pt.Y + (int)(Math.Sin(a)*r)));
     a += da;
       }
       return result;
 }
示例#16
0
        //------------------------------------------------------------------------------
        private PolyPt AddPolyPt(TEdge4 e, IntPoint pt)
        {
            bool ToFront = (e.side == EdgeSide.esLeft);
              if(  e.outIdx < 0 )
              {
            PolyPt newPolyPt = new PolyPt();
            newPolyPt.pt = pt;
            newPolyPt.isHole = IsHole(e);
            m_PolyPts.Add(newPolyPt);
            newPolyPt.next = newPolyPt;
            newPolyPt.prev = newPolyPt;
            e.outIdx = m_PolyPts.Count-1;
            return newPolyPt;
              } else
              {
            PolyPt pp = m_PolyPts[e.outIdx];
            if (ToFront && PointsEqual(pt, pp.pt)) return pp;
            if (!ToFront && PointsEqual(pt, pp.prev.pt)) return pp.prev;

            PolyPt newPolyPt = new PolyPt();
            newPolyPt.pt = pt;
            newPolyPt.isHole = pp.isHole;
            newPolyPt.next = pp;
            newPolyPt.prev = pp.prev;
            newPolyPt.prev.next = newPolyPt;
            pp.prev = newPolyPt;
            if (ToFront) m_PolyPts[e.outIdx] = newPolyPt;
            return newPolyPt;
              }
        }
示例#17
0
        //------------------------------------------------------------------------------
        internal static DoublePoint GetUnitNormal(IntPoint pt1, IntPoint pt2)
        {
            double dx = ( pt2.X - pt1.X );
              double dy = ( pt2.Y - pt1.Y );
              if(  ( dx == 0 ) && ( dy == 0 ) ) return new DoublePoint();

              double f = 1 *1.0/ Math.Sqrt( dx*dx + dy*dy );
              dx *= f;
              dy *= f;
              return new DoublePoint(dy, -dx);
        }
示例#18
0
 //------------------------------------------------------------------------------
 private void DoEdge2(TEdge4 edge1, TEdge4 edge2, IntPoint pt)
 {
     AddPolyPt(edge2, pt);
     SwapSides(edge1, edge2);
     SwapPolyIndexes(edge1, edge2);
 }
示例#19
0
 //------------------------------------------------------------------------------
 internal Position GetPosition(IntPoint pt1, IntPoint pt2, IntPoint pt)
 {
     if (PointsEqual(pt1, pt)) return Position.pFirst;
     else if (PointsEqual(pt2, pt)) return Position.pSecond;
     else return Position.pMiddle;
 }
示例#20
0
 //------------------------------------------------------------------------------
 private bool GetOverlapSegment(IntPoint pt1a, IntPoint pt1b, IntPoint pt2a,
     IntPoint pt2b, ref IntPoint pt1, ref IntPoint pt2)
 {
     //precondition: segments are colinear.
     if ( pt1a.Y == pt1b.Y || Math.Abs((pt1a.X - pt1b.X)/(pt1a.Y - pt1b.Y)) > 1 )
     {
     if (pt1a.X > pt1b.X) SwapPoints(ref pt1a, ref pt1b);
     if (pt2a.X > pt2b.X) SwapPoints(ref pt2a, ref pt2b);
     if (pt1a.X > pt2a.X) pt1 = pt1a; else pt1 = pt2a;
     if (pt1b.X < pt2b.X) pt2 = pt1b; else pt2 = pt2b;
     return pt1.X < pt2.X;
     } else
     {
     if (pt1a.Y < pt1b.Y) SwapPoints(ref pt1a, ref pt1b);
     if (pt2a.Y < pt2b.Y) SwapPoints(ref pt2a, ref pt2b);
     if (pt1a.Y < pt2a.Y) pt1 = pt1a; else pt1 = pt2a;
     if (pt1b.Y > pt2b.Y) pt2 = pt1b; else pt2 = pt2b;
     return pt1.Y > pt2.Y;
     }
 }
示例#21
0
 //------------------------------------------------------------------------------
 internal bool Pt3IsBetweenPt1AndPt2(IntPoint pt1, IntPoint pt2, IntPoint pt3)
 {
     if (PointsEqual(pt1, pt3) || PointsEqual(pt2, pt3)) return true;
     else if (pt1.X != pt2.X) return (pt1.X < pt3.X) == (pt3.X < pt2.X);
     else return (pt1.Y < pt3.Y) == (pt3.Y < pt2.Y);
 }
示例#22
0
 //---------------------------------------------------------------------
 private IntPoint GenerateRandomPoint(int l, int t, int r, int b, Random rand)
 {
     IntPoint newPt = new IntPoint();
     newPt.X = (rand.Next(r / 10) * 10 + l + 10) * scale;
     newPt.Y = (rand.Next(b / 10) * 10 + t + 10) * scale;
     return newPt;
 }
示例#23
0
 //------------------------------------------------------------------------------
 private PolyPt InsertPolyPtBetween(PolyPt p1, PolyPt p2, IntPoint pt)
 {
     PolyPt result = new PolyPt();
     result.pt = pt;
     result.isHole = p1.isHole;
     if (p2 == p1.next)
     {
     p1.next = result;
     p2.prev = result;
     result.next = p2;
     result.prev = p1;
     } else
     {
     p2.next = result;
     p1.prev = result;
     result.next = p1;
     result.prev = p2;
     }
     return result;
 }