Ejemplo n.º 1
0
        internal bool PointInPolygon(IntPoint pt, OutPt pp, bool UseFullRange)
        {
            OutPt next = pp;
            bool  flag = false;

            if (UseFullRange)
            {
                do
                {
                    if ((next.Pt.Y > pt.Y) != (next.Prev.Pt.Y > pt.Y))
                    {
                        Int128 introduced2 = Int128.Int128Mul(next.Prev.Pt.X - next.Pt.X, pt.Y - next.Pt.Y);
                        if (new Int128(pt.X - next.Pt.X) < (introduced2 / new Int128(next.Prev.Pt.Y - next.Pt.Y)))
                        {
                            flag = !flag;
                        }
                    }
                    next = next.Next;
                }while (next != pp);
                return(flag);
            }
            do
            {
                if (((next.Pt.Y > pt.Y) != (next.Prev.Pt.Y > pt.Y)) && ((pt.X - next.Pt.X) < (((next.Prev.Pt.X - next.Pt.X) * (pt.Y - next.Pt.Y)) / (next.Prev.Pt.Y - next.Pt.Y))))
                {
                    flag = !flag;
                }
                next = next.Next;
            }while (next != pp);
            return(flag);
        }
Ejemplo n.º 2
0
        internal bool PointInPolygon(IntPoint pt, OutPt pp, bool UseFullRange)
        {
            OutPt outPt = pp;
            bool  flag  = false;

            if (UseFullRange)
            {
                do
                {
                    if (outPt.Pt.Y > pt.Y != outPt.Prev.Pt.Y > pt.Y && new Int128(pt.X - outPt.Pt.X) < Int128.Int128Mul(outPt.Prev.Pt.X - outPt.Pt.X, pt.Y - outPt.Pt.Y) / new Int128(outPt.Prev.Pt.Y - outPt.Pt.Y))
                    {
                        flag = !flag;
                    }
                    outPt = outPt.Next;
                }while (outPt != pp);
            }
            else
            {
                do
                {
                    if (outPt.Pt.Y > pt.Y != outPt.Prev.Pt.Y > pt.Y && pt.X - outPt.Pt.X < (outPt.Prev.Pt.X - outPt.Pt.X) * (pt.Y - outPt.Pt.Y) / (outPt.Prev.Pt.Y - outPt.Pt.Y))
                    {
                        flag = !flag;
                    }
                    outPt = outPt.Next;
                }while (outPt != pp);
            }
            return(flag);
        }
Ejemplo n.º 3
0
        internal bool PointOnPolygon(IntPoint pt, OutPt pp, bool UseFullRange)
        {
            OutPt next = pp;

            do
            {
                if (this.PointOnLineSegment(pt, next.Pt, next.Next.Pt, UseFullRange))
                {
                    return(true);
                }
                next = next.Next;
            }while (next != pp);
            return(false);
        }
Ejemplo n.º 4
0
        internal bool PointIsVertex(IntPoint pt, OutPt pp)
        {
            OutPt outPt = pp;

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

            while (!this.PointOnLineSegment(pt, outPt.Pt, outPt.Next.Pt, UseFullRange))
            {
                outPt = outPt.Next;
                if (outPt == pp)
                {
                    return(false);
                }
            }
            return(true);
        }
Ejemplo n.º 6
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;
		}
Ejemplo n.º 7
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;
		}
Ejemplo n.º 8
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;
		}
Ejemplo n.º 9
0
		//----------------------------------------------------------------------
		
		
		private bool Poly2ContainsPoly1(OutPt outPt1, OutPt outPt2, bool UseFullRange)
		{
			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, UseFullRange))
			{
				pt = pt.Next;
				while (pt != outPt1 && PointOnPolygon(pt.Pt, outPt2, UseFullRange))
					pt = pt.Next;
				if (pt == outPt1) return true;
			}
			return PointInPolygon(pt.Pt, outPt2, UseFullRange);
		}
Ejemplo n.º 10
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;
		}
Ejemplo n.º 11
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);
		}
Ejemplo n.º 12
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;
				}
			}
		}
Ejemplo n.º 13
0
		//------------------------------------------------------------------------------
		
		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;
		}
Ejemplo n.º 14
0
		//------------------------------------------------------------------------------
		
		private void AddGhostJoin(OutPt Op, IntPoint OffPt)
		{
			Join j = new Join();
			j.OutPt1 = Op;
			j.OffPt = OffPt;
			m_GhostJoins.Add(j);
		}
Ejemplo n.º 15
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);
		}
Ejemplo n.º 16
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 (dups.Pt != pp.Pt) dups = dups.Next;
				}
			}
			return pp;
		}
Ejemplo n.º 17
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);
		}
Ejemplo n.º 18
0
		//------------------------------------------------------------------------------
		
		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;
		}
Ejemplo n.º 19
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;
			}
		}
Ejemplo n.º 20
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;
		}
Ejemplo n.º 21
0
		//------------------------------------------------------------------------------
		
		private void DisposeOutPts(OutPt pp)
		{
			if (pp == null) return;
			pp.Prev.Next = null;
			while (pp != null)
			{
				pp = pp.Next;
			}
		}