Exemple #1
0
        //------------------------------------------------------------------------------

        private void Triangulate(OutRec outrec)
        {
            OutPt op = outrec.Pts;

            if (op.Next == op.Prev)
            {
                return;
            }
            OutPt    end_op = op.Next;
            OutPtTri opt;

            for (;;)
            {
                OutPt op2   = op;
                Int64 cpval = 0;
                while (op.Prev != end_op)
                {
                    if (CrossProductVal(op.Pt, op.Prev.Pt, op.Prev.Prev.Pt, out cpval) >= 0)
                    {
                        break;
                    }
                    if (op2 != op)
                    {
                        //Due to rounding, the clipping algorithm can occasionally produce
                        //tiny self-intersections and these need removing ...
                        if (CrossProductVal(op2.Pt, op.Pt, op.Prev.Prev.Pt, out cpval) > 0)
                        {
                            opt = (OutPtTri)op;
                            if (opt.outrec != null)
                            {
                                UpdateHelper(opt.outrec, op2);
                            }
                            DisposeOutPt(op);
                            op = op2;
                            continue;
                        }
                    }
                    op = op.Prev;
                }

                if (op.Prev == end_op)
                {
                    break;
                }
                if (cpval != 0)
                {
                    AddPolygon(op.Pt, op.Prev.Pt, op.Prev.Prev.Pt);
                }
                opt = (OutPtTri)op.Prev;
                if (opt.outrec != null)
                {
                    UpdateHelper(opt.outrec, op);
                }
                DisposeOutPt(op.Prev);
                if (op != outrec.Pts)
                {
                    op = op.Next;
                }
            }
        }
        /// <summary>
        /// Reset all fields to default values in preparation for object recycling
        /// </summary>
        public void PrepareForRecycle()
        {
            Idx    = 0;
            IsHole = IsOpen = false;

            FirstLeft = null;
            Pts       = BottomPt = null;
            PolyNode  = null;
        }
Exemple #3
0
        //------------------------------------------------------------------------------

        private OutPtTri InsertPt(Point pt, OutPt afterOutPt)
        {
            OutPtTri result = (OutPtTri)CreateOutPt();

            result.Pt            = pt;
            result.Prev          = afterOutPt;
            result.Next          = afterOutPt.Next;
            result.outrec        = (afterOutPt as OutPtTri).outrec;
            result.rightOutrec   = null;
            afterOutPt.Next.Prev = result;
            afterOutPt.Next      = result;
            return(result);
        }
Exemple #4
0
        //------------------------------------------------------------------------------

        internal bool PointIsVertex(IntPoint pt, OutPt pp)
        {
            OutPt pp2 = pp;

            do
            {
                if (pp2.Pt == pt)
                {
                    return(true);
                }
                pp2 = pp2.Next;
            }while (pp2 != pp);
            return(false);
        }
        internal bool PointIsVertex(IntPoint pt, OutPt pp)
        {
            OutPt outPt = pp;

            do
            {
                if (outPt.Pt == pt)
                {
                    return(true);
                }
                outPt = outPt.Next;
            }while (outPt != pp);
            return(false);
        }
        internal bool PointOnPolygon(IntPoint pt, OutPt pp, bool UseFullRange)
        {
            OutPt outPt = pp;

            do
            {
                if (PointOnLineSegment(pt, outPt.Pt, outPt.Next.Pt, UseFullRange))
                {
                    return(true);
                }
                outPt = outPt.Next;
            }while (outPt != pp);
            return(false);
        }
Exemple #7
0
        //------------------------------------------------------------------------------

        void Update(OutPt op, OutRec outrec)
        {
            OutPt op2 = op;

            do
            {
                OutPtTri opt = (OutPtTri)op2;
                if (opt.rightOutrec != null)
                {
                    UpdateHelper(opt.rightOutrec, null);
                }
                opt.outrec = outrec;
                op2        = op2.Next;
            } while (op2 != op);
        }
Exemple #8
0
        //------------------------------------------------------------------------------

        private int PointCount(OutPt op)
        {
            if (op == null)
            {
                return(0);
            }
            OutPt p   = op;
            int   cnt = 0;

            do
            {
                cnt++;
                p = p.Next;
            } while (p != op);
            return(cnt);
        }
Exemple #9
0
        //------------------------------------------------------------------------------

        private void DisposeOutPt(OutPt op)
        {
            if (op.Prev != null)
            {
                op.Prev.Next = op.Next;
            }
            if (op.Next != null)
            {
                op.Next.Prev = op.Prev;
            }
            OutPtTri opt = (OutPtTri)op;

            if (opt.rightOutrec != null)
            {
                opt.rightOutrec.leftOutpt = null;
            }
        }
Exemple #10
0
        //------------------------------------------------------------------------------

        internal bool PointOnPolygon(IntPoint pt, OutPt pp, bool UseFullRange)
        {
            OutPt pp2 = pp;

            while (true)
            {
                if (PointOnLineSegment(pt, pp2.Pt, pp2.Next.Pt, UseFullRange))
                {
                    return(true);
                }
                pp2 = pp2.Next;
                if (pp2 == pp)
                {
                    break;
                }
            }
            return(false);
        }
Exemple #11
0
        //------------------------------------------------------------------------------

        private void UpdateHelper(OutRec rightOutrec, OutPt leftOutpt)
        {
            OutPtTri  leftOpt  = (OutPtTri)leftOutpt;
            OutRecTri rightOrt = (OutRecTri)rightOutrec;

            if (leftOpt != null && leftOpt.rightOutrec != null)
            {
                leftOpt.rightOutrec.leftOutpt = null;
            }
            if (rightOrt.leftOutpt != null)
            {
                rightOrt.leftOutpt.rightOutrec = null;
            }
            rightOrt.leftOutpt = leftOpt;
            if (leftOpt != null)
            {
                leftOpt.rightOutrec = rightOrt;
            }
        }
Exemple #12
0
        //------------------------------------------------------------------------------

        protected override OutPt AddOutPt(Active e, Point pt)
        {
            OutPt    result = base.AddOutPt(e, pt);
            OutPtTri opt    = (OutPtTri)result;

            opt.outrec = e.OutRec;
            LastOp     = result;
            Triangulate(e.OutRec);
            //Triangulate() above may assign Result.OutRecRt so ...
            if (IsStartSide(e) && opt.rightOutrec == null)
            {
                Active e2 = GetRightAdjacentHotEdge(e);
                if (e2 != null)
                {
                    UpdateHelper(e2.OutRec, result);
                }
            }
            return(result);
        }
Exemple #13
0
        //------------------------------------------------------------------------------

        internal bool PointInPolygon(IntPoint pt, OutPt pp, bool UseFulllongRange)
        {
            OutPt pp2    = pp;
            bool  result = false;

            if (UseFulllongRange)
            {
                do
                {
                    if ((((pp2.Pt.Y <= pt.Y) && (pt.Y < pp2.Prev.Pt.Y)) ||
                         ((pp2.Prev.Pt.Y <= pt.Y) && (pt.Y < pp2.Pt.Y))) &&
                        new Int128(pt.X - pp2.Pt.X) <
                        Int128.Int128Mul(pp2.Prev.Pt.X - pp2.Pt.X, pt.Y - pp2.Pt.Y) /
                        new Int128(pp2.Prev.Pt.Y - pp2.Pt.Y))
                    {
                        result = !result;
                    }
                    pp2 = pp2.Next;
                } while (pp2 != pp);
            }
            else
            {
                do
                {
                    if ((((pp2.Pt.Y <= pt.Y) && (pt.Y < pp2.Prev.Pt.Y)) ||
                         ((pp2.Prev.Pt.Y <= pt.Y) && (pt.Y < pp2.Pt.Y))) &&
                        (pt.X - pp2.Pt.X < (pp2.Prev.Pt.X - pp2.Pt.X) * (pt.Y - pp2.Pt.Y) /
                         (pp2.Prev.Pt.Y - pp2.Pt.Y)))
                    {
                        result = !result;
                    }
                    pp2 = pp2.Next;
                } while (pp2 != pp);
            }

            return(result);
        }
Exemple #14
0
      //------------------------------------------------------------------------------

      internal bool PointInPolygon(IntPoint pt, OutPt pp, bool UseFullRange)
      {
        OutPt pp2 = pp;
        bool result = false;
        if (UseFullRange)
        {
            do
            {
              if (((pp2.Pt.Y > pt.Y) != (pp2.Prev.Pt.Y > pt.Y)) && 
                (new Int128(pt.X - pp2.Pt.X) < 
                Int128.Int128Mul(pp2.Prev.Pt.X - pp2.Pt.X, pt.Y - pp2.Pt.Y) /
                new Int128(pp2.Prev.Pt.Y - pp2.Pt.Y))) result = !result;
              pp2 = pp2.Next;
            }
            while (pp2 != pp);
        }
        else
        {
          do
          {
            //http://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html
            if (((pp2.Pt.Y > pt.Y) != (pp2.Prev.Pt.Y > pt.Y)) &&                     
              ((pt.X - pp2.Pt.X) < (pp2.Prev.Pt.X - pp2.Pt.X) * (pt.Y - pp2.Pt.Y) / 
              (pp2.Prev.Pt.Y - pp2.Pt.Y))) result = !result;
            pp2 = pp2.Next;
          }
          while (pp2 != pp);
        }
        return result;
      }
Exemple #15
0
 //----------------------------------------------------------------------
 private bool Poly2ContainsPoly1(OutPt outPt1, OutPt outPt2, bool UseFullInt64Range)
 {
     OutPt pt = outPt1;
     //Because the polygons may be touching, we need to find a vertex that
     //isn't touching the other polygon ...
     if (PointOnPolygon(pt.pt, outPt2, UseFullInt64Range))
     {
         pt = pt.next;
         while (pt != outPt1 && PointOnPolygon(pt.pt, outPt2, UseFullInt64Range))
             pt = pt.next;
         if (pt == outPt1) return true;
     }
     return PointInPolygon(pt.pt, outPt2, UseFullInt64Range);
 }
Exemple #16
0
      //------------------------------------------------------------------------------

      private bool JoinPoints(Join j, out OutPt p1, out OutPt p2)
      {
        OutRec outRec1 = GetOutRec(j.OutPt1.Idx);
        OutRec outRec2 = GetOutRec(j.OutPt2.Idx);
        OutPt op1 = j.OutPt1, op1b;
        OutPt op2 = j.OutPt2, op2b;
        p1 = null; p2 = null;

        //There are 3 kinds of joins for output polygons ...
        //1. Horizontal joins where Join.OutPt1 & Join.OutPt2 are a vertices anywhere
        //along (horizontal) collinear edges (& Join.OffPt is on the same horizontal).
        //2. Non-horizontal joins where Join.OutPt1 & Join.OutPt2 are at the same
        //location at the Bottom of the overlapping segment (& Join.OffPt is above).
        //3. StrictlySimple joins where edges touch but are not collinear and where
        //Join.OutPt1, Join.OutPt2 & Join.OffPt all share the same point.
        bool isHorizontal = (j.OutPt1.Pt.Y == j.OffPt.Y);

        if (isHorizontal && (j.OffPt == j.OutPt1.Pt) && (j.OffPt == j.OutPt2.Pt))
        {          
          //Strictly Simple join ...
          op1b = j.OutPt1.Next;
          while (op1b != op1 && (op1b.Pt == j.OffPt)) 
            op1b = op1b.Next;
          bool reverse1 = (op1b.Pt.Y > j.OffPt.Y);
          op2b = j.OutPt2.Next;
          while (op2b != op2 && (op2b.Pt == j.OffPt)) 
            op2b = op2b.Next;
          bool reverse2 = (op2b.Pt.Y > j.OffPt.Y);
          if (reverse1 == reverse2) return false;
          if (reverse1)
          {
            op1b = DupOutPt(op1, false);
            op2b = DupOutPt(op2, true);
            op1.Prev = op2;
            op2.Next = op1;
            op1b.Next = op2b;
            op2b.Prev = op1b;
            p1 = op1;
            p2 = op1b;
            return true;
          } else
          {
            op1b = DupOutPt(op1, true);
            op2b = DupOutPt(op2, false);
            op1.Next = op2;
            op2.Prev = op1;
            op1b.Prev = op2b;
            op2b.Next = op1b;
            p1 = op1;
            p2 = op1b;
            return true;
          }
        } 
        else if (isHorizontal)
        {
          //treat horizontal joins differently to non-horizontal joins since with
          //them we're not yet sure where the overlapping is. OutPt1.Pt & OutPt2.Pt
          //may be anywhere along the horizontal edge.
          op1b = op1;
          while (op1.Prev.Pt.Y == op1.Pt.Y && op1.Prev != op1b && op1.Prev != op2)
            op1 = op1.Prev;
          while (op1b.Next.Pt.Y == op1b.Pt.Y && op1b.Next != op1 && op1b.Next != op2)
            op1b = op1b.Next;
          if (op1b.Next == op1 || op1b.Next == op2) return false; //a flat 'polygon'

          op2b = op2;
          while (op2.Prev.Pt.Y == op2.Pt.Y && op2.Prev != op2b && op2.Prev != op1b)
            op2 = op2.Prev;
          while (op2b.Next.Pt.Y == op2b.Pt.Y && op2b.Next != op2 && op2b.Next != op1)
            op2b = op2b.Next;
          if (op2b.Next == op2 || op2b.Next == op1) return false; //a flat 'polygon'

          cInt Left, Right;
          //Op1 -. Op1b & Op2 -. Op2b are the extremites of the horizontal edges
          if (!GetOverlap(op1.Pt.X, op1b.Pt.X, op2.Pt.X, op2b.Pt.X, out Left, out Right))
            return false;

          //DiscardLeftSide: when overlapping edges are joined, a spike will created
          //which needs to be cleaned up. However, we don't want Op1 or Op2 caught up
          //on the discard Side as either may still be needed for other joins ...
          IntPoint Pt;
          bool DiscardLeftSide;
          if (op1.Pt.X >= Left && op1.Pt.X <= Right) 
          {
            Pt = op1.Pt; DiscardLeftSide = (op1.Pt.X > op1b.Pt.X);
          } 
          else if (op2.Pt.X >= Left&& op2.Pt.X <= Right) 
          {
            Pt = op2.Pt; DiscardLeftSide = (op2.Pt.X > op2b.Pt.X);
          } 
          else if (op1b.Pt.X >= Left && op1b.Pt.X <= Right)
          {
            Pt = op1b.Pt; DiscardLeftSide = op1b.Pt.X > op1.Pt.X;
          } 
          else
          {
            Pt = op2b.Pt; DiscardLeftSide = (op2b.Pt.X > op2.Pt.X);
          }
          p1 = op1; p2 = op2;
          return JoinHorz(op1, op1b, op2, op2b, Pt, DiscardLeftSide);
        } else
        {
          //nb: For non-horizontal joins ...
          //    1. Jr.OutPt1.Pt.Y == Jr.OutPt2.Pt.Y
          //    2. Jr.OutPt1.Pt > Jr.OffPt.Y

          //make sure the polygons are correctly oriented ...
          op1b = op1.Next;
          while ((op1b.Pt == op1.Pt) && (op1b != op1)) op1b = op1b.Next;
          bool Reverse1 = ((op1b.Pt.Y > op1.Pt.Y) ||
            !SlopesEqual(op1.Pt, op1b.Pt, j.OffPt, m_UseFullRange));
          if (Reverse1)
          {
            op1b = op1.Prev;
            while ((op1b.Pt == op1.Pt) && (op1b != op1)) op1b = op1b.Prev;
            if ((op1b.Pt.Y > op1.Pt.Y) ||
              !SlopesEqual(op1.Pt, op1b.Pt, j.OffPt, m_UseFullRange)) return false;
          };
          op2b = op2.Next;
          while ((op2b.Pt == op2.Pt) && (op2b != op2)) op2b = op2b.Next;
          bool Reverse2 = ((op2b.Pt.Y > op2.Pt.Y) ||
            !SlopesEqual(op2.Pt, op2b.Pt, j.OffPt, m_UseFullRange));
          if (Reverse2)
          {
            op2b = op2.Prev;
            while ((op2b.Pt == op2.Pt) && (op2b != op2)) op2b = op2b.Prev;
            if ((op2b.Pt.Y > op2.Pt.Y) ||
              !SlopesEqual(op2.Pt, op2b.Pt, j.OffPt, m_UseFullRange)) return false;
          }

          if ((op1b == op1) || (op2b == op2) || (op1b == op2b) ||
            ((outRec1 == outRec2) && (Reverse1 == Reverse2))) return false;

          if (Reverse1)
          {
            op1b = DupOutPt(op1, false);
            op2b = DupOutPt(op2, true);
            op1.Prev = op2;
            op2.Next = op1;
            op1b.Next = op2b;
            op2b.Prev = op1b;
            p1 = op1;
            p2 = op1b;
            return true;
          } else
          {
            op1b = DupOutPt(op1, true);
            op2b = DupOutPt(op2, false);
            op1.Next = op2;
            op2.Prev = op1;
            op1b.Prev = op2b;
            op2b.Next = op1b;
            p1 = op1;
            p2 = op1b;
            return true;
          }
        }
      }
Exemple #17
0
      //------------------------------------------------------------------------------

      internal bool PointIsVertex(IntPoint pt, OutPt pp)
      {
        OutPt pp2 = pp;
        do
        {
          if (pp2.Pt == pt) return true;
          pp2 = pp2.Next;
        }
        while (pp2 != pp);
        return false;
      }
        //------------------------------------------------------------------------------
        private void AddOutPt(TEdge e, IntPoint pt)
        {
            bool ToFront = (e.side == EdgeSide.esLeft);
              if(  e.outIdx < 0 )
              {
              OutRec outRec = CreateOutRec();
              m_PolyOuts.Add(outRec);
              outRec.idx = m_PolyOuts.Count -1;
              e.outIdx = outRec.idx;
              OutPt op = new OutPt();
              outRec.pts = op;
              outRec.bottomPt = op;
              op.pt = pt;
              op.idx = outRec.idx;
              op.next = op;
              op.prev = op;
              SetHoleState(e, outRec);
              } else
              {
              OutRec outRec = m_PolyOuts[e.outIdx];
              OutPt op = outRec.pts, op2, opBot;
              if (ToFront && PointsEqual(pt, op.pt) ||
                  (!ToFront && PointsEqual(pt, op.prev.pt))) return;

              if ((e.side | outRec.sides) != outRec.sides)
              {
                  //check for 'rounding' artefacts ...
                  if (outRec.sides == EdgeSide.esNeither && pt.Y == op.pt.Y)
                      if (ToFront)
                      {
                          if (pt.X == op.pt.X + 1) return;    //ie wrong side of bottomPt
                      }
                      else if (pt.X == op.pt.X - 1) return; //ie wrong side of bottomPt

                  outRec.sides = (EdgeSide)(outRec.sides | e.side);
                  if (outRec.sides == EdgeSide.esBoth)
                  {
                    //A vertex from each side has now been added.
                    //Vertices of one side of an output polygon are quite commonly close to
                    //or even 'touching' edges of the other side of the output polygon.
                    //Very occasionally vertices from one side can 'cross' an edge on the
                    //the other side. The distance 'crossed' is always less that a unit
                    //and is purely an artefact of coordinate rounding. Nevertheless, this
                    //results in very tiny self-intersections. Because of the way
                    //orientation is calculated, even tiny self-intersections can cause
                    //the Orientation function to return the wrong result. Therefore, it's
                    //important to ensure that any self-intersections close to BottomPt are
                    //detected and removed before orientation is assigned.

                    if (ToFront)
                    {
                      opBot = outRec.pts;
                      op2 = opBot.next; //op2 == right side
                      if (opBot.pt.Y != op2.pt.Y && opBot.pt.Y != pt.Y &&
                        ((opBot.pt.X - pt.X) / (opBot.pt.Y - pt.Y) <
                        (opBot.pt.X - op2.pt.X) / (opBot.pt.Y - op2.pt.Y)))
                          outRec.bottomFlag = opBot;
                    }
                    else
                    {
                      opBot = outRec.pts.prev;
                      op2 = opBot.next; //op2 == left side
                      if (opBot.pt.Y != op2.pt.Y && opBot.pt.Y != pt.Y &&
                        ((opBot.pt.X - pt.X) / (opBot.pt.Y - pt.Y) >
                        (opBot.pt.X - op2.pt.X) / (opBot.pt.Y - op2.pt.Y)))
                          outRec.bottomFlag = opBot;
                    }
                  }
              }

              op2 = new OutPt();
              op2.pt = pt;
              op2.idx = outRec.idx;
              if (op2.pt.Y == outRec.bottomPt.pt.Y &&
                op2.pt.X < outRec.bottomPt.pt.X)
                  outRec.bottomPt = op2;
              op2.next = op;
              op2.prev = op.prev;
              op2.prev.next = op2;
              op.prev = op2;
              if (ToFront) outRec.pts = op2;
              }
        }
 /// <summary>
 /// Reset all fields to default values in preparation for object recycling
 /// </summary>
 public void PrepareForRecycle()
 {
     OutPt1 = null;
     OutPt2 = null;
     OffPt  = new IntPoint();
 }
 //------------------------------------------------------------------------------
 private OutPt PolygonBottom(OutPt pp)
 {
     OutPt p = pp.next;
     OutPt result = pp;
     while (p != pp)
     {
     if (p.pt.Y > result.pt.Y) result = p;
     else if (p.pt.Y == result.pt.Y && p.pt.X < result.pt.X) result = p;
     p = p.next;
     }
     return result;
 }
 /// <summary>
 /// Reset all fields to default values in preparation for object recycling
 /// </summary>
 public void PrepareForRecycle()
 {
     Idx  = 0;
     Pt   = new IntPoint();
     Next = Prev = null;
 }
Exemple #22
0
        //----------------------------------------------------------------------

        private bool Poly2ContainsPoly1(OutPt outPt1, OutPt outPt2, bool UseFullInt64Range)
        {
            //find the first pt in outPt1 that isn't also a vertex of outPt2 ...
            OutPt outPt = outPt1;
            do
            {
                if (!PointIsVertex(outPt.pt, outPt2)) break;
                outPt = outPt.next;
            }
            while (outPt != outPt1);
            bool result;
            //sometimes a point on one polygon can be touching the other polygon 
            //so to be totally confident outPt1 is inside outPt2 repeat ...
            do
            {
                result = PointInPolygon(outPt.pt, outPt2, UseFullInt64Range);
                outPt = outPt.next;
            }
            while (result && outPt != outPt1);
            return result;
        }
 //------------------------------------------------------------------------------
 private OutPt InsertPolyPtBetween(OutPt p1, OutPt p2, IntPoint pt)
 {
     OutPt result = new OutPt();
     result.pt = pt;
     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;
 }
Exemple #24
0
        //------------------------------------------------------------------------------

        private bool JoinPoints(JoinRec j, out OutPt p1, out OutPt p2)
        {
            p1 = null; p2 = null;
            OutRec outRec1 = m_PolyOuts[j.poly1Idx];
            OutRec outRec2 = m_PolyOuts[j.poly2Idx];
            if (outRec1  == null || outRec2 == null)  return false;  
            OutPt pp1a = outRec1.pts;
            OutPt pp2a = outRec2.pts;
            IntPoint pt1 = j.pt2a, pt2 = j.pt2b;
            IntPoint pt3 = j.pt1a, pt4 = j.pt1b;
            if (!FindSegment(ref pp1a, ref pt1, ref pt2)) return false;
            if (outRec1 == outRec2)
            {
              //we're searching the same polygon for overlapping segments so
              //segment 2 mustn't be the same as segment 1 ...
              pp2a = pp1a.next;
              if (!FindSegment(ref pp2a, ref pt3, ref pt4) || (pp2a == pp1a)) return false;
            }
            else if (!FindSegment(ref pp2a, ref pt3, ref pt4)) return false;

            if (!GetOverlapSegment(pt1, pt2, pt3, pt4, ref pt1, ref pt2)) return false;

            OutPt p3, p4, prev = pp1a.prev;
            //get p1 & p2 polypts - the overlap start & endpoints on poly1
            if (PointsEqual(pp1a.pt, pt1)) p1 = pp1a;
            else if (PointsEqual(prev.pt, pt1)) p1 = prev;
            else p1 = InsertPolyPtBetween(pp1a, prev, pt1);

            if (PointsEqual(pp1a.pt, pt2)) p2 = pp1a;
            else if (PointsEqual(prev.pt, pt2)) p2 = prev;
            else if ((p1 == pp1a) || (p1 == prev))
              p2 = InsertPolyPtBetween(pp1a, prev, pt2);
            else if (Pt3IsBetweenPt1AndPt2(pp1a.pt, p1.pt, pt2))
              p2 = InsertPolyPtBetween(pp1a, p1, pt2); else
              p2 = InsertPolyPtBetween(p1, prev, pt2);

            //get p3 & p4 polypts - the overlap start & endpoints on poly2
            prev = pp2a.prev;
            if (PointsEqual(pp2a.pt, pt1)) p3 = pp2a;
            else if (PointsEqual(prev.pt, pt1)) p3 = prev;
            else p3 = InsertPolyPtBetween(pp2a, prev, pt1);

            if (PointsEqual(pp2a.pt, pt2)) p4 = pp2a;
            else if (PointsEqual(prev.pt, pt2)) p4 = prev;
            else if ((p3 == pp2a) || (p3 == prev))
              p4 = InsertPolyPtBetween(pp2a, prev, pt2);
            else if (Pt3IsBetweenPt1AndPt2(pp2a.pt, p3.pt, pt2))
              p4 = InsertPolyPtBetween(pp2a, p3, pt2); else
              p4 = InsertPolyPtBetween(p3, prev, pt2);

            //p1.pt == p3.pt and p2.pt == p4.pt so join p1 to p3 and p2 to p4 ...
            if (p1.next == p2 && p3.prev == p4)
            {
              p1.next = p3;
              p3.prev = p1;
              p2.prev = p4;
              p4.next = p2;
              return true;
            }
            else if (p1.prev == p2 && p3.next == p4)
            {
              p1.prev = p3;
              p3.next = p1;
              p2.next = p4;
              p4.prev = p2;
              return true;
            }
            else
              return false; //an orientation is probably wrong
        }
Exemple #25
0
        //---------------------------------------------------------------------------

        private bool FirstIsBottomPt(OutPt btmPt1, OutPt btmPt2)
        {
          OutPt p = btmPt1.prev;
          while (PointsEqual(p.pt, btmPt1.pt) && (p != btmPt1)) p = p.prev;
          double dx1p = Math.Abs(GetDx(btmPt1.pt, p.pt));
          p = btmPt1.next;
          while (PointsEqual(p.pt, btmPt1.pt) && (p != btmPt1)) p = p.next;
          double dx1n = Math.Abs(GetDx(btmPt1.pt, p.pt));

          p = btmPt2.prev;
          while (PointsEqual(p.pt, btmPt2.pt) && (p != btmPt2)) p = p.prev;
          double dx2p = Math.Abs(GetDx(btmPt2.pt, p.pt));
          p = btmPt2.next;
          while (PointsEqual(p.pt, btmPt2.pt) && (p != btmPt2)) p = p.next;
          double dx2n = Math.Abs(GetDx(btmPt2.pt, p.pt));
          return (dx1p >= dx2p && dx1p >= dx2n) || (dx1n >= dx2p && dx1n >= dx2n);
        }
Exemple #26
0
        //------------------------------------------------------------------------------
        //See "The Point in Polygon Problem for Arbitrary Polygons" by Hormann & Agathos
        //http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.88.5498&rep=rep1&type=pdf
        private static int PointInPolygon(IntPoint pt, OutPt op)
        {
            //returns 0 if false, +1 if true, -1 if pt ON polygon boundary
            int result = 0;
            OutPt startOp = op;
            int ptx = pt.X, pty = pt.Y;
            int poly0x = op.Pt.X, poly0y = op.Pt.Y;
            do
            {
                op = op.Next;
                int poly1x = op.Pt.X, poly1y = op.Pt.Y;

                if (poly1y == pty)
                {
                    if ((poly1x == ptx) || (poly0y == pty &&
                      ((poly1x > ptx) == (poly0x < ptx)))) return -1;
                }
                if ((poly0y < pty) != (poly1y < pty))
                {
                    if (poly0x >= ptx)
                    {
                        if (poly1x > ptx) result = 1 - result;
                        else
                        {
                            double d = (double)(poly0x - ptx) * (poly1y - pty) -
                              (double)(poly1x - ptx) * (poly0y - pty);
                            if (d == 0) return -1;
                            if ((d > 0) == (poly1y > poly0y)) result = 1 - result;
                        }
                    }
                    else
                    {
                        if (poly1x > ptx)
                        {
                            double d = (double)(poly0x - ptx) * (poly1y - pty) -
                              (double)(poly1x - ptx) * (poly0y - pty);
                            if (d == 0) return -1;
                            if ((d > 0) == (poly1y > poly0y)) result = 1 - result;
                        }
                    }
                }
                poly0x = poly1x; poly0y = poly1y;
            } while (startOp != op);
            return result;
        }
Exemple #27
0
 //------------------------------------------------------------------------------
 internal bool PointOnPolygon(IntPoint pt, OutPt pp, bool UseFullInt64Range)
 {
     OutPt pp2 = pp;
     while (true)
     {
         if (PointOnLineSegment(pt, pp2.pt, pp2.next.pt, UseFullInt64Range))
             return true;
         pp2 = pp2.next;
         if (pp2 == pp) break;
     }
     return false;
 }
Exemple #28
0
        //------------------------------------------------------------------------------

        protected override void AddLocalMinPoly(Active e1, Active e2, Point pt)
        {
            base.AddLocalMinPoly(e1, e2, pt);

            OutRec locMinOr = e1.OutRec;

            (locMinOr.Pts as OutPtTri).outrec = locMinOr;
            UpdateHelper(locMinOr, locMinOr.Pts);
            if (locMinOr.Flag == OutrecFlag.Outer)
            {
                return;
            }

            //do 'keyholing' ...
            Active e = GetRightAdjacentHotEdge(e1);

            if (e == e2)
            {
                e = GetRightAdjacentHotEdge(e2);
            }
            if (e == null)
            {
                e = GetLeftAdjacentHotEdge(e1);
            }
            OutPt botLft = (e.OutRec as OutRecTri).leftOutpt;
            OutPt botRt  = GetOutPt(e);

            if (botLft == null || botRt.Pt.Y < botLft.Pt.Y)
            {
                botLft = botRt;
            }

            botRt = InsertPt(botLft.Pt, botLft.Prev);
            OutRec botOr = (botLft as OutPtTri).outrec;

            if (botOr.Pts == null)
            {
                botOr = botOr.Owner;
            }

            OutPt startOp = botOr.Pts;
            OutPt endOp   = startOp.Next;

            locMinOr.Flag  = OutrecFlag.Outer;
            locMinOr.Owner = null;
            OutPt locMinLft = locMinOr.Pts;
            OutPt locMinRt  = InsertPt(locMinLft.Pt, locMinLft);

            //locMinOr will contain the polygon to the right of the join (ascending),
            //and botOr will contain the polygon to the left of the join (descending).

            //tail . botRt . locMinRt : locMinRt is joined by botRt tail
            locMinRt.Next = endOp;
            endOp.Prev    = locMinRt;
            botRt.Next    = locMinRt;
            locMinRt.Prev = botRt;
            locMinOr.Pts  = locMinRt;

            //locMinLft . botLft . head : locMinLft joins behind botLft (left)
            startOp.Next   = locMinLft;
            locMinLft.Prev = startOp;
            botLft.Prev    = locMinLft;
            locMinLft.Next = botLft;
            (locMinLft as OutPtTri).outrec = botOr; //ie abreviated update()

            Update(locMinRt, locMinOr);             //updates the outrec for each op

            //exchange endE's ...
            e                    = botOr.EndE;
            botOr.EndE           = locMinOr.EndE;
            locMinOr.EndE        = e;
            botOr.EndE.OutRec    = botOr;
            locMinOr.EndE.OutRec = locMinOr;

            //update helper info  ...
            UpdateHelper(locMinOr, locMinRt);
            UpdateHelper(botOr, botOr.Pts);
            Triangulate(locMinOr);
            Triangulate(botOr);
        }
Exemple #29
0
        //------------------------------------------------------------------------------
        private void AddOutPt(TEdge e, IntPoint pt)
        {
            bool ToFront = (e.side == EdgeSide.esLeft);
            if (e.outIdx < 0)
            {
                OutRec outRec = CreateOutRec();
                e.outIdx = outRec.idx;
                OutPt op = new OutPt();
                outRec.pts = op;
                op.pt = pt;
                op.idx = outRec.idx;
                op.next = op;
                op.prev = op;
                SetHoleState(e, outRec);
            }
            else
            {
                OutRec outRec = m_PolyOuts[e.outIdx];
                OutPt op = outRec.pts, op2;
                if (ToFront && PointsEqual(pt, op.pt) ||
                    (!ToFront && PointsEqual(pt, op.prev.pt))) return;

                op2 = new OutPt();
                op2.pt = pt;
                op2.idx = outRec.idx;
                op2.next = op;
                op2.prev = op.prev;
                op2.prev.next = op2;
                op.prev = op2;
                if (ToFront) outRec.pts = op2;
            }
        }
 //------------------------------------------------------------------------------
 private void AddOutPt(TEdge e, TEdge altE, IntPoint pt)
 {
     bool ToFront = (e.side == EdgeSide.esLeft);
       if(  e.outIdx < 0 )
       {
       OutRec outRec = CreateOutRec();
       m_PolyOuts.Add(outRec);
       outRec.idx = m_PolyOuts.Count -1;
       e.outIdx = outRec.idx;
       OutPt op = new OutPt();
       outRec.pts = op;
       outRec.bottomPt = op;
       outRec.bottomE1 = e;
       outRec.bottomE2 = altE;
       op.pt = pt;
       op.idx = outRec.idx;
       op.next = op;
       op.prev = op;
       SetHoleState(e, outRec);
       } else
       {
       OutRec outRec = m_PolyOuts[e.outIdx];
       OutPt op = outRec.pts;
       if (ToFront && PointsEqual(pt, op.pt) ||
           (!ToFront && PointsEqual(pt, op.prev.pt))) return;
       OutPt op2 = new OutPt();
       op2.pt = pt;
       op2.idx = outRec.idx;
       if (op2.pt.Y == outRec.bottomPt.pt.Y &&
         op2.pt.X < outRec.bottomPt.pt.X)
       {
           outRec.bottomPt = op2;
           outRec.bottomE1 = e;
           outRec.bottomE2 = altE;
       }
       op2.next = op;
       op2.prev = op.prev;
       op2.prev.next = op2;
       op.prev = op2;
       if (ToFront) outRec.pts = op2;
       }
 }
 //------------------------------------------------------------------------------
 internal bool PointInPolygon(IntPoint pt, OutPt pp, bool UseFulllongRange)
 {
     OutPt pp2 = pp;
       bool result = false;
       if (UseFulllongRange)
       {
       do
       {
           if ((((pp2.pt.Y <= pt.Y) && (pt.Y < pp2.prev.pt.Y)) ||
               ((pp2.prev.pt.Y <= pt.Y) && (pt.Y < pp2.pt.Y))) &&
               new Int128(pt.X - pp2.pt.X) <
               Int128.Int128Mul(pp2.prev.pt.X - pp2.pt.X,  pt.Y - pp2.pt.Y) /
               new Int128(pp2.prev.pt.Y - pp2.pt.Y))
                 result = !result;
           pp2 = pp2.next;
       }
       while (pp2 != pp);
       }
       else
       {
       do
       {
           if ((((pp2.pt.Y <= pt.Y) && (pt.Y < pp2.prev.pt.Y)) ||
             ((pp2.prev.pt.Y <= pt.Y) && (pt.Y < pp2.pt.Y))) &&
             (pt.X - pp2.pt.X < (pp2.prev.pt.X - pp2.pt.X) * (pt.Y - pp2.pt.Y) /
             (pp2.prev.pt.Y - pp2.pt.Y))) result = !result;
           pp2 = pp2.next;
       }
       while (pp2 != pp);
       }
       return result;
 }
Exemple #32
0
 //------------------------------------------------------------------------------
 private static bool Poly2ContainsPoly1(OutPt outPt1, OutPt outPt2)
 {
     OutPt op = outPt1;
     do
     {
         //nb: PointInPolygon returns 0 if false, +1 if true, -1 if pt on polygon
         int res = PointInPolygon(op.Pt, outPt2);
         if (res >= 0) return res > 0;
         op = op.Next;
     }
     while (op != outPt1);
     return true;
 }
Exemple #33
0
        //------------------------------------------------------------------------------

        private OutPt GetBottomPt(OutPt pp)
        {
          OutPt dups = null;
          OutPt p = pp.next;
          while (p != pp)
          {
            if (p.pt.Y > pp.pt.Y)
            {
              pp = p;
              dups = null;
            }
            else if (p.pt.Y == pp.pt.Y && p.pt.X <= pp.pt.X)
            {
              if (p.pt.X < pp.pt.X)
              {
                  dups = null;
                  pp = p;
              } else
              {
                if (p.next != pp && p.prev != pp) dups = p;
              }
            }
            p = p.next;
          }
          if (dups != null)
          {
            //there appears to be at least 2 vertices at bottomPt so ...
            while (dups != p)
            {
              if (!FirstIsBottomPt(p, dups)) pp = dups;
              dups = dups.next;
              while (!PointsEqual(dups.pt, pp.pt)) dups = dups.next;
            }
          }
          return pp;
        }
Exemple #34
0
      //------------------------------------------------------------------------------

      private void AddJoin(OutPt Op1, OutPt Op2, IntPoint OffPt)
      {
        Join j = new Join();
        j.OutPt1 = Op1;
        j.OutPt2 = Op2;
        j.OffPt = OffPt;
        m_Joins.Add(j);
      }
Exemple #35
0
        //----------------------------------------------------------------------

        private void FixupJoinRecs(JoinRec j, OutPt pt, int startIdx)
        {
          for (int k = startIdx; k < m_Joins.Count; k++)
            {
              JoinRec j2 = m_Joins[k];
              if (j2.poly1Idx == j.poly1Idx && PointIsVertex(j2.pt1a, pt))
                j2.poly1Idx = j.poly2Idx;
              if (j2.poly2Idx == j.poly1Idx && PointIsVertex(j2.pt2a, pt))
                j2.poly2Idx = j.poly2Idx;
            }
        }
Exemple #36
0
      //------------------------------------------------------------------------------

      private void AddGhostJoin(OutPt Op, IntPoint OffPt)
      {
        Join j = new Join();
        j.OutPt1 = Op;
        j.OffPt = OffPt;
        m_GhostJoins.Add(j);
      }
 //------------------------------------------------------------------------------
 private bool FindSegment(ref OutPt pp, ref IntPoint pt1, ref IntPoint pt2)
 {
     if (pp == null) return false;
     OutPt pp2 = pp;
     IntPoint pt1a = new IntPoint(pt1);
     IntPoint pt2a = new IntPoint(pt2);
     do
     {
         if (SlopesEqual(pt1a, pt2a, pp.pt, pp.prev.pt, true) &&
             SlopesEqual(pt1a, pt2a, pp.pt, true) &&
             GetOverlapSegment(pt1a, pt2a, pp.pt, pp.prev.pt, ref pt1, ref pt2))
                 return true;
     pp = pp.next;
     }
     while (pp != pp2);
     return false;
 }
Exemple #38
0
      //------------------------------------------------------------------------------

      private OutPt AddOutPt(TEdge e, IntPoint pt)
      {
        bool ToFront = (e.Side == EdgeSide.esLeft);
        if(  e.OutIdx < 0 )
        {
          OutRec outRec = CreateOutRec();
          outRec.IsOpen = (e.WindDelta == 0);
          OutPt newOp = new OutPt();
          outRec.Pts = newOp;
          newOp.Idx = outRec.Idx;
          newOp.Pt = pt;
          newOp.Next = newOp;
          newOp.Prev = newOp;
          if (!outRec.IsOpen)
            SetHoleState(e, outRec);
#if use_xyz
          if (pt == e.Bot)
            newOp.Pt = e.Bot;
          else if (pt == e.Top)
            newOp.Pt = e.Top;
          else
            SetZ(ref newOp.Pt, e);
#endif
          e.OutIdx = outRec.Idx; //nb: do this after SetZ !
          return newOp;
        } else
        {
          OutRec outRec = m_PolyOuts[e.OutIdx];
          //OutRec.Pts is the 'Left-most' point & OutRec.Pts.Prev is the 'Right-most'
          OutPt op = outRec.Pts;
          if (ToFront && pt == op.Pt) return op;
          else if (!ToFront && pt == op.Prev.Pt) return op.Prev;

          OutPt newOp = new OutPt();
          newOp.Idx = outRec.Idx;
          newOp.Pt = pt;
          newOp.Next = op;
          newOp.Prev = op.Prev;
          newOp.Prev.Next = newOp;
          op.Prev = newOp;
          if (ToFront) outRec.Pts = newOp;
#if use_xyz
          if (pt == e.Bot)
            newOp.Pt = e.Bot;
          else if (pt == e.Top)
            newOp.Pt = e.Top;
          else
            SetZ(ref newOp.Pt, e);
#endif
          return newOp;
        }
      }
 //------------------------------------------------------------------------------
 private int PointCount(OutPt pts)
 {
     if (pts == null) return 0;
     int result = 0;
     OutPt p = pts;
     do
     {
         result++;
         p = p.next;
     }
     while (p != pts);
     return result;
 }
Exemple #40
0
      //---------------------------------------------------------------------------

      private bool FirstIsBottomPt(OutPt btmPt1, OutPt btmPt2)
      {
        OutPt p = btmPt1.Prev;
        while ((p.Pt == btmPt1.Pt) && (p != btmPt1)) p = p.Prev;
        double dx1p = Math.Abs(GetDx(btmPt1.Pt, p.Pt));
        p = btmPt1.Next;
        while ((p.Pt == btmPt1.Pt) && (p != btmPt1)) p = p.Next;
        double dx1n = Math.Abs(GetDx(btmPt1.Pt, p.Pt));

        p = btmPt2.Prev;
        while ((p.Pt == btmPt2.Pt) && (p != btmPt2)) p = p.Prev;
        double dx2p = Math.Abs(GetDx(btmPt2.Pt, p.Pt));
        p = btmPt2.Next;
        while ((p.Pt == btmPt2.Pt) && (p != btmPt2)) p = p.Next;
        double dx2n = Math.Abs(GetDx(btmPt2.Pt, p.Pt));
        return (dx1p >= dx2p && dx1p >= dx2n) || (dx1n >= dx2p && dx1n >= dx2n);
      }
 //------------------------------------------------------------------------------
 private void ReversePolyPtLinks(OutPt pp)
 {
     OutPt pp1;
     OutPt pp2;
     pp1 = pp;
     do
     {
         pp2 = pp1.next;
         pp1.next = pp1.prev;
         pp1.prev = pp2;
         pp1 = pp2;
     } while (pp1 != pp);
 }
Exemple #42
0
      //------------------------------------------------------------------------------

      private void ReversePolyPtLinks(OutPt pp)
      {
          if (pp == null) return;
          OutPt pp1;
          OutPt pp2;
          pp1 = pp;
          do
          {
              pp2 = pp1.Next;
              pp1.Next = pp1.Prev;
              pp1.Prev = pp2;
              pp1 = pp2;
          } while (pp1 != pp);
      }
 //------------------------------------------------------------------------------
 internal bool PointIsVertex(IntPoint pt, OutPt pp)
 {
     OutPt pp2 = pp;
       do
       {
     if (PointsEqual(pp2.pt, pt)) return true;
     pp2 = pp2.next;
       }
       while (pp2 != pp);
       return false;
 }
Exemple #44
0
      //------------------------------------------------------------------------------

      OutPt DupOutPt(OutPt outPt, bool InsertAfter)
      {
        OutPt result = new OutPt();
        result.Pt = outPt.Pt;
        result.Idx = outPt.Idx;
        if (InsertAfter)
        {
          result.Next = outPt.Next;
          result.Prev = outPt;
          outPt.Next.Prev = result;
          outPt.Next = result;
        } 
        else
        {
          result.Prev = outPt.Prev;
          result.Next = outPt;
          outPt.Prev.Next = result;
          outPt.Prev = result;
        }
        return result;
      }
 //------------------------------------------------------------------------------
 private void DisposeOutPts(OutPt pp)
 {
     if (pp == null) return;
     OutPt tmpPp = null;
     pp.prev.next = null;
     while (pp != null)
     {
         tmpPp = pp;
         pp = pp.next;
         tmpPp = null;
     }
 }
Exemple #46
0
      //------------------------------------------------------------------------------

      bool JoinHorz(OutPt op1, OutPt op1b, OutPt op2, OutPt op2b, 
        IntPoint Pt, bool DiscardLeft)
      {
        Direction Dir1 = (op1.Pt.X > op1b.Pt.X ? 
          Direction.dRightToLeft : Direction.dLeftToRight);
        Direction Dir2 = (op2.Pt.X > op2b.Pt.X ?
          Direction.dRightToLeft : Direction.dLeftToRight);
        if (Dir1 == Dir2) return false;

        //When DiscardLeft, we want Op1b to be on the Left of Op1, otherwise we
        //want Op1b to be on the Right. (And likewise with Op2 and Op2b.)
        //So, to facilitate this while inserting Op1b and Op2b ...
        //when DiscardLeft, make sure we're AT or RIGHT of Pt before adding Op1b,
        //otherwise make sure we're AT or LEFT of Pt. (Likewise with Op2b.)
        if (Dir1 == Direction.dLeftToRight) 
        {
          while (op1.Next.Pt.X <= Pt.X && 
            op1.Next.Pt.X >= op1.Pt.X && op1.Next.Pt.Y == Pt.Y)  
              op1 = op1.Next;
          if (DiscardLeft && (op1.Pt.X != Pt.X)) op1 = op1.Next;
          op1b = DupOutPt(op1, !DiscardLeft);
          if (op1b.Pt != Pt) 
          {
            op1 = op1b;
            op1.Pt = Pt;
            op1b = DupOutPt(op1, !DiscardLeft);
          }
        } 
        else
        {
          while (op1.Next.Pt.X >= Pt.X && 
            op1.Next.Pt.X <= op1.Pt.X && op1.Next.Pt.Y == Pt.Y) 
              op1 = op1.Next;
          if (!DiscardLeft && (op1.Pt.X != Pt.X)) op1 = op1.Next;
          op1b = DupOutPt(op1, DiscardLeft);
          if (op1b.Pt != Pt)
          {
            op1 = op1b;
            op1.Pt = Pt;
            op1b = DupOutPt(op1, DiscardLeft);
          }
        }

        if (Dir2 == Direction.dLeftToRight)
        {
          while (op2.Next.Pt.X <= Pt.X && 
            op2.Next.Pt.X >= op2.Pt.X && op2.Next.Pt.Y == Pt.Y)
              op2 = op2.Next;
          if (DiscardLeft && (op2.Pt.X != Pt.X)) op2 = op2.Next;
          op2b = DupOutPt(op2, !DiscardLeft);
          if (op2b.Pt != Pt)
          {
            op2 = op2b;
            op2.Pt = Pt;
            op2b = DupOutPt(op2, !DiscardLeft);
          };
        } else
        {
          while (op2.Next.Pt.X >= Pt.X && 
            op2.Next.Pt.X <= op2.Pt.X && op2.Next.Pt.Y == Pt.Y) 
              op2 = op2.Next;
          if (!DiscardLeft && (op2.Pt.X != Pt.X)) op2 = op2.Next;
          op2b = DupOutPt(op2, DiscardLeft);
          if (op2b.Pt != Pt)
          {
            op2 = op2b;
            op2.Pt = Pt;
            op2b = DupOutPt(op2, DiscardLeft);
          };
        };

        if ((Dir1 == Direction.dLeftToRight) == DiscardLeft)
        {
          op1.Prev = op2;
          op2.Next = op1;
          op1b.Next = op2b;
          op2b.Prev = op1b;
        }
        else
        {
          op1.Next = op2;
          op2.Prev = op1;
          op1b.Prev = op2b;
          op2b.Next = op1b;
        }
        return true;
      }