commit b14cfc92e4f30d7ebe9fbe35a01ca3fb23915381 Author: alex Date: Wed Aug 21 23:02:56 2024 +0700 init uwp commit diff --git a/PCUT/Clipper.Core/Clipper.Core.csproj b/PCUT/Clipper.Core/Clipper.Core.csproj new file mode 100644 index 0000000..9f5c4f4 --- /dev/null +++ b/PCUT/Clipper.Core/Clipper.Core.csproj @@ -0,0 +1,7 @@ + + + + netstandard2.0 + + + diff --git a/PCUT/Clipper.Core/clipper.cs b/PCUT/Clipper.Core/clipper.cs new file mode 100644 index 0000000..8c796e2 --- /dev/null +++ b/PCUT/Clipper.Core/clipper.cs @@ -0,0 +1,4913 @@ +/******************************************************************************* +* * +* Author : Angus Johnson * +* Version : 6.4.2 * +* Date : 27 February 2017 * +* Website : http://www.angusj.com * +* Copyright : Angus Johnson 2010-2017 * +* * +* License: * +* Use, modification & distribution is subject to Boost Software License Ver 1. * +* http://www.boost.org/LICENSE_1_0.txt * +* * +* Attributions: * +* The code in this library is an extension of Bala Vatti's clipping algorithm: * +* "A generic solution to polygon clipping" * +* Communications of the ACM, Vol 35, Issue 7 (July 1992) pp 56-63. * +* http://portal.acm.org/citation.cfm?id=129906 * +* * +* Computer graphics and geometric modeling: implementation and algorithms * +* By Max K. Agoston * +* Springer; 1 edition (January 4, 2005) * +* http://books.google.com/books?q=vatti+clipping+agoston * +* * +* See also: * +* "Polygon Offsetting by Computing Winding Numbers" * +* Paper no. DETC2005-85513 pp. 565-575 * +* ASME 2005 International Design Engineering Technical Conferences * +* and Computers and Information in Engineering Conference (IDETC/CIE2005) * +* September 24-28, 2005 , Long Beach, California, USA * +* http://www.me.berkeley.edu/~mcmains/pubs/DAC05OffsetPolygon.pdf * +* * +*******************************************************************************/ + +/******************************************************************************* +* * +* This is a translation of the Delphi Clipper library and the naming style * +* used has retained a Delphi flavour. * +* * +*******************************************************************************/ + +//use_int32: When enabled 32bit ints are used instead of 64bit ints. This +//improve performance but coordinate values are limited to the range +/- 46340 +//#define use_int32 + +//use_xyz: adds a Z member to IntPoint. Adds a minor cost to performance. +//#define use_xyz + +//use_lines: Enables open path clipping. Adds a very minor cost to performance. +#define use_lines + + +using System; +using System.Collections.Generic; +//using System.Text; //for Int128.AsString() & StringBuilder +//using System.IO; //debugging with streamReader & StreamWriter +//using System.Windows.Forms; //debugging to clipboard + +namespace ClipperLib +{ + +#if use_int32 + using cInt = Int32; +#else + using cInt = Int64; +#endif + + using Path = List; + using Paths = List>; + + public struct DoublePoint + { + public double X; + public double Y; + + public DoublePoint(double x = 0, double y = 0) + { + this.X = x; this.Y = y; + } + public DoublePoint(DoublePoint dp) + { + this.X = dp.X; this.Y = dp.Y; + } + public DoublePoint(IntPoint ip) + { + this.X = ip.X; this.Y = ip.Y; + } + }; + + + //------------------------------------------------------------------------------ + // PolyTree & PolyNode classes + //------------------------------------------------------------------------------ + + public class PolyTree : PolyNode + { + internal List m_AllPolys = new List(); + + //The GC probably handles this cleanup more efficiently ... + //~PolyTree(){Clear();} + + public void Clear() + { + for (int i = 0; i < m_AllPolys.Count; i++) + m_AllPolys[i] = null; + m_AllPolys.Clear(); + m_Childs.Clear(); + } + + public PolyNode GetFirst() + { + if (m_Childs.Count > 0) + return m_Childs[0]; + else + return null; + } + + public int Total + { + get + { + int result = m_AllPolys.Count; + //with negative offsets, ignore the hidden outer polygon ... + if (result > 0 && m_Childs[0] != m_AllPolys[0]) result--; + return result; + } + } + + } + + public class PolyNode + { + internal PolyNode m_Parent; + internal Path m_polygon = new Path(); + internal int m_Index; + internal JoinType m_jointype; + internal EndType m_endtype; + internal List m_Childs = new List(); + + private bool IsHoleNode() + { + bool result = true; + PolyNode node = m_Parent; + while (node != null) + { + result = !result; + node = node.m_Parent; + } + return result; + } + + public int ChildCount + { + get { return m_Childs.Count; } + } + + public Path Contour + { + get { return m_polygon; } + } + + internal void AddChild(PolyNode Child) + { + int cnt = m_Childs.Count; + m_Childs.Add(Child); + Child.m_Parent = this; + Child.m_Index = cnt; + } + + public PolyNode GetNext() + { + if (m_Childs.Count > 0) + return m_Childs[0]; + else + return GetNextSiblingUp(); + } + + internal PolyNode GetNextSiblingUp() + { + if (m_Parent == null) + return null; + else if (m_Index == m_Parent.m_Childs.Count - 1) + return m_Parent.GetNextSiblingUp(); + else + return m_Parent.m_Childs[m_Index + 1]; + } + + public List Childs + { + get { return m_Childs; } + } + + public PolyNode Parent + { + get { return m_Parent; } + } + + public bool IsHole + { + get { return IsHoleNode(); } + } + + public bool IsOpen { get; set; } + } + + + //------------------------------------------------------------------------------ + // Int128 struct (enables safe math on signed 64bit integers) + // eg Int128 val1((Int64)9223372036854775807); //ie 2^63 -1 + // Int128 val2((Int64)9223372036854775807); + // Int128 val3 = val1 * val2; + // val3.ToString => "85070591730234615847396907784232501249" (8.5e+37) + //------------------------------------------------------------------------------ + + internal struct Int128 + { + private Int64 hi; + private UInt64 lo; + + public Int128(Int64 _lo) + { + lo = (UInt64)_lo; + if (_lo < 0) hi = -1; + else hi = 0; + } + + public Int128(Int64 _hi, UInt64 _lo) + { + lo = _lo; + hi = _hi; + } + + public Int128(Int128 val) + { + hi = val.hi; + lo = val.lo; + } + + public bool IsNegative() + { + return hi < 0; + } + + public static bool operator ==(Int128 val1, Int128 val2) + { + if ((object)val1 == (object)val2) return true; + else if ((object)val1 == null || (object)val2 == null) return false; + return (val1.hi == val2.hi && val1.lo == val2.lo); + } + + public static bool operator !=(Int128 val1, Int128 val2) + { + return !(val1 == val2); + } + + public override bool Equals(System.Object obj) + { + if (obj == null || !(obj is Int128)) + return false; + Int128 i128 = (Int128)obj; + return (i128.hi == hi && i128.lo == lo); + } + + public override int GetHashCode() + { + return hi.GetHashCode() ^ lo.GetHashCode(); + } + + public static bool operator >(Int128 val1, Int128 val2) + { + if (val1.hi != val2.hi) + return val1.hi > val2.hi; + else + return val1.lo > val2.lo; + } + + public static bool operator <(Int128 val1, Int128 val2) + { + if (val1.hi != val2.hi) + return val1.hi < val2.hi; + else + return val1.lo < val2.lo; + } + + public static Int128 operator +(Int128 lhs, Int128 rhs) + { + lhs.hi += rhs.hi; + lhs.lo += rhs.lo; + if (lhs.lo < rhs.lo) lhs.hi++; + return lhs; + } + + public static Int128 operator -(Int128 lhs, Int128 rhs) + { + return lhs + -rhs; + } + + public static Int128 operator -(Int128 val) + { + if (val.lo == 0) + return new Int128(-val.hi, 0); + else + return new Int128(~val.hi, ~val.lo + 1); + } + + public static explicit operator double(Int128 val) + { + const double shift64 = 18446744073709551616.0; //2^64 + if (val.hi < 0) + { + if (val.lo == 0) + return (double)val.hi * shift64; + else + return -(double)(~val.lo + ~val.hi * shift64); + } + else + return (double)(val.lo + val.hi * shift64); + } + + //nb: Constructing two new Int128 objects every time we want to multiply longs + //is slow. So, although calling the Int128Mul method doesn't look as clean, the + //code runs significantly faster than if we'd used the * operator. + + public static Int128 Int128Mul(Int64 lhs, Int64 rhs) + { + bool negate = (lhs < 0) != (rhs < 0); + if (lhs < 0) lhs = -lhs; + if (rhs < 0) rhs = -rhs; + UInt64 int1Hi = (UInt64)lhs >> 32; + UInt64 int1Lo = (UInt64)lhs & 0xFFFFFFFF; + UInt64 int2Hi = (UInt64)rhs >> 32; + UInt64 int2Lo = (UInt64)rhs & 0xFFFFFFFF; + + //nb: see comments in clipper.pas + UInt64 a = int1Hi * int2Hi; + UInt64 b = int1Lo * int2Lo; + UInt64 c = int1Hi * int2Lo + int1Lo * int2Hi; + + UInt64 lo; + Int64 hi; + hi = (Int64)(a + (c >> 32)); + + unchecked { lo = (c << 32) + b; } + if (lo < b) hi++; + Int128 result = new Int128(hi, lo); + return negate ? -result : result; + } + + }; + + //------------------------------------------------------------------------------ + //------------------------------------------------------------------------------ + + public struct IntPoint + { + public cInt X; + public cInt Y; +#if use_xyz + public cInt Z; + + public IntPoint(cInt x, cInt y, cInt z = 0) + { + this.X = x; this.Y = y; this.Z = z; + } + + public IntPoint(double x, double y, double z = 0) + { + this.X = (cInt)x; this.Y = (cInt)y; this.Z = (cInt)z; + } + + public IntPoint(DoublePoint dp) + { + this.X = (cInt)dp.X; this.Y = (cInt)dp.Y; this.Z = 0; + } + + public IntPoint(IntPoint pt) + { + this.X = pt.X; this.Y = pt.Y; this.Z = pt.Z; + } +#else + public IntPoint(cInt X, cInt Y) + { + this.X = X; this.Y = Y; + } + public IntPoint(double x, double y) + { + this.X = (cInt)x; this.Y = (cInt)y; + } + + public IntPoint(IntPoint pt) + { + this.X = pt.X; this.Y = pt.Y; + } +#endif + + public static bool operator ==(IntPoint a, IntPoint b) + { + return a.X == b.X && a.Y == b.Y; + } + + public static bool operator !=(IntPoint a, IntPoint b) + { + return a.X != b.X || a.Y != b.Y; + } + + public override bool Equals(object obj) + { + if (obj == null) return false; + if (obj is IntPoint) + { + IntPoint a = (IntPoint)obj; + return (X == a.X) && (Y == a.Y); + } + else return false; + } + + public override int GetHashCode() + { + //simply prevents a compiler warning + return base.GetHashCode(); + } + + }// end struct IntPoint + + public struct IntRect + { + public cInt left; + public cInt top; + public cInt right; + public cInt bottom; + + public IntRect(cInt l, cInt t, cInt r, cInt b) + { + this.left = l; this.top = t; + this.right = r; this.bottom = b; + } + public IntRect(IntRect ir) + { + this.left = ir.left; this.top = ir.top; + this.right = ir.right; this.bottom = ir.bottom; + } + } + + public enum ClipType { ctIntersection, ctUnion, ctDifference, ctXor }; + public enum PolyType { ptSubject, ptClip }; + + //By far the most widely used winding rules for polygon filling are + //EvenOdd & NonZero (GDI, GDI+, XLib, OpenGL, Cairo, AGG, Quartz, SVG, Gr32) + //Others rules include Positive, Negative and ABS_GTR_EQ_TWO (only in OpenGL) + //see http://glprogramming.com/red/chapter11.html + public enum PolyFillType { pftEvenOdd, pftNonZero, pftPositive, pftNegative }; + + public enum JoinType { jtSquare, jtRound, jtMiter }; + public enum EndType { etClosedPolygon, etClosedLine, etOpenButt, etOpenSquare, etOpenRound }; + + internal enum EdgeSide {esLeft, esRight}; + internal enum Direction {dRightToLeft, dLeftToRight}; + + internal class TEdge { + internal IntPoint Bot; + internal IntPoint Curr; //current (updated for every new scanbeam) + internal IntPoint Top; + internal IntPoint Delta; + internal double Dx; + internal PolyType PolyTyp; + internal EdgeSide Side; //side only refers to current side of solution poly + internal int WindDelta; //1 or -1 depending on winding direction + internal int WindCnt; + internal int WindCnt2; //winding count of the opposite polytype + internal int OutIdx; + internal TEdge Next; + internal TEdge Prev; + internal TEdge NextInLML; + internal TEdge NextInAEL; + internal TEdge PrevInAEL; + internal TEdge NextInSEL; + internal TEdge PrevInSEL; + }; + + public class IntersectNode + { + internal TEdge Edge1; + internal TEdge Edge2; + internal IntPoint Pt; + }; + + public class MyIntersectNodeSort : IComparer + { + public int Compare(IntersectNode node1, IntersectNode node2) + { + cInt i = node2.Pt.Y - node1.Pt.Y; + if (i > 0) return 1; + else if (i < 0) return -1; + else return 0; + } + } + + internal class LocalMinima + { + internal cInt Y; + internal TEdge LeftBound; + internal TEdge RightBound; + internal LocalMinima Next; + }; + + internal class Scanbeam + { + internal cInt Y; + internal Scanbeam Next; + }; + + internal class Maxima + { + internal cInt X; + internal Maxima Next; + internal Maxima Prev; + }; + + //OutRec: contains a path in the clipping solution. Edges in the AEL will + //carry a pointer to an OutRec when they are part of the clipping solution. + internal class OutRec + { + internal int Idx; + internal bool IsHole; + internal bool IsOpen; + internal OutRec FirstLeft; //see comments in clipper.pas + internal OutPt Pts; + internal OutPt BottomPt; + internal PolyNode PolyNode; + }; + + internal class OutPt + { + internal int Idx; + internal IntPoint Pt; + internal OutPt Next; + internal OutPt Prev; + }; + + internal class Join + { + internal OutPt OutPt1; + internal OutPt OutPt2; + internal IntPoint OffPt; + }; + + public class ClipperBase + { + internal const double horizontal = -3.4E+38; + internal const int Skip = -2; + internal const int Unassigned = -1; + internal const double tolerance = 1.0E-20; + internal static bool near_zero(double val){return (val > -tolerance) && (val < tolerance);} + +#if use_int32 + public const cInt loRange = 0x7FFF; + public const cInt hiRange = 0x7FFF; +#else + public const cInt loRange = 0x3FFFFFFF; + public const cInt hiRange = 0x3FFFFFFFFFFFFFFFL; +#endif + + internal LocalMinima m_MinimaList; + internal LocalMinima m_CurrentLM; + internal List> m_edges = new List>(); + internal Scanbeam m_Scanbeam; + internal List m_PolyOuts; + internal TEdge m_ActiveEdges; + internal bool m_UseFullRange; + internal bool m_HasOpenPaths; + + //------------------------------------------------------------------------------ + + public bool PreserveCollinear + { + get; + set; + } + //------------------------------------------------------------------------------ + + public void Swap(ref cInt val1, ref cInt val2) + { + cInt tmp = val1; + val1 = val2; + val2 = tmp; + } + //------------------------------------------------------------------------------ + + internal static bool IsHorizontal(TEdge e) + { + return e.Delta.Y == 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 PointOnLineSegment(IntPoint pt, + IntPoint linePt1, IntPoint linePt2, bool UseFullRange) + { + if (UseFullRange) + return ((pt.X == linePt1.X) && (pt.Y == linePt1.Y)) || + ((pt.X == linePt2.X) && (pt.Y == linePt2.Y)) || + (((pt.X > linePt1.X) == (pt.X < linePt2.X)) && + ((pt.Y > linePt1.Y) == (pt.Y < linePt2.Y)) && + ((Int128.Int128Mul((pt.X - linePt1.X), (linePt2.Y - linePt1.Y)) == + Int128.Int128Mul((linePt2.X - linePt1.X), (pt.Y - linePt1.Y))))); + else + return ((pt.X == linePt1.X) && (pt.Y == linePt1.Y)) || + ((pt.X == linePt2.X) && (pt.Y == linePt2.Y)) || + (((pt.X > linePt1.X) == (pt.X < linePt2.X)) && + ((pt.Y > linePt1.Y) == (pt.Y < linePt2.Y)) && + ((pt.X - linePt1.X) * (linePt2.Y - linePt1.Y) == + (linePt2.X - linePt1.X) * (pt.Y - linePt1.Y))); + } + //------------------------------------------------------------------------------ + + 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; + } + //------------------------------------------------------------------------------ + + internal static bool SlopesEqual(TEdge e1, TEdge e2, bool UseFullRange) + { + if (UseFullRange) + return Int128.Int128Mul(e1.Delta.Y, e2.Delta.X) == + Int128.Int128Mul(e1.Delta.X, e2.Delta.Y); + else return (cInt)(e1.Delta.Y) * (e2.Delta.X) == + (cInt)(e1.Delta.X) * (e2.Delta.Y); + } + //------------------------------------------------------------------------------ + + internal static bool SlopesEqual(IntPoint pt1, IntPoint pt2, + IntPoint pt3, bool UseFullRange) + { + if (UseFullRange) + return Int128.Int128Mul(pt1.Y - pt2.Y, pt2.X - pt3.X) == + Int128.Int128Mul(pt1.X - pt2.X, pt2.Y - pt3.Y); + else return + (cInt)(pt1.Y - pt2.Y) * (pt2.X - pt3.X) - (cInt)(pt1.X - pt2.X) * (pt2.Y - pt3.Y) == 0; + } + //------------------------------------------------------------------------------ + + internal static bool SlopesEqual(IntPoint pt1, IntPoint pt2, + IntPoint pt3, IntPoint pt4, bool UseFullRange) + { + if (UseFullRange) + return Int128.Int128Mul(pt1.Y - pt2.Y, pt3.X - pt4.X) == + Int128.Int128Mul(pt1.X - pt2.X, pt3.Y - pt4.Y); + else return + (cInt)(pt1.Y - pt2.Y) * (pt3.X - pt4.X) - (cInt)(pt1.X - pt2.X) * (pt3.Y - pt4.Y) == 0; + } + //------------------------------------------------------------------------------ + + internal ClipperBase() //constructor (nb: no external instantiation) + { + m_MinimaList = null; + m_CurrentLM = null; + m_UseFullRange = false; + m_HasOpenPaths = false; + } + //------------------------------------------------------------------------------ + + public virtual void Clear() + { + DisposeLocalMinimaList(); + for (int i = 0; i < m_edges.Count; ++i) + { + for (int j = 0; j < m_edges[i].Count; ++j) m_edges[i][j] = null; + m_edges[i].Clear(); + } + m_edges.Clear(); + m_UseFullRange = false; + m_HasOpenPaths = false; + } + //------------------------------------------------------------------------------ + + private void DisposeLocalMinimaList() + { + while( m_MinimaList != null ) + { + LocalMinima tmpLm = m_MinimaList.Next; + m_MinimaList = null; + m_MinimaList = tmpLm; + } + m_CurrentLM = null; + } + //------------------------------------------------------------------------------ + + void RangeTest(IntPoint Pt, ref bool useFullRange) + { + if (useFullRange) + { + if (Pt.X > hiRange || Pt.Y > hiRange || -Pt.X > hiRange || -Pt.Y > hiRange) + throw new ClipperException("Coordinate outside allowed range"); + } + else if (Pt.X > loRange || Pt.Y > loRange || -Pt.X > loRange || -Pt.Y > loRange) + { + useFullRange = true; + RangeTest(Pt, ref useFullRange); + } + } + //------------------------------------------------------------------------------ + + private void InitEdge(TEdge e, TEdge eNext, + TEdge ePrev, IntPoint pt) + { + e.Next = eNext; + e.Prev = ePrev; + e.Curr = pt; + e.OutIdx = Unassigned; + } + //------------------------------------------------------------------------------ + + private void InitEdge2(TEdge e, PolyType polyType) + { + if (e.Curr.Y >= e.Next.Curr.Y) + { + e.Bot = e.Curr; + e.Top = e.Next.Curr; + } + else + { + e.Top = e.Curr; + e.Bot = e.Next.Curr; + } + SetDx(e); + e.PolyTyp = polyType; + } + //------------------------------------------------------------------------------ + + private TEdge FindNextLocMin(TEdge E) + { + TEdge E2; + for (;;) + { + while (E.Bot != E.Prev.Bot || E.Curr == E.Top) E = E.Next; + if (E.Dx != horizontal && E.Prev.Dx != horizontal) break; + while (E.Prev.Dx == horizontal) E = E.Prev; + E2 = E; + while (E.Dx == horizontal) E = E.Next; + if (E.Top.Y == E.Prev.Bot.Y) continue; //ie just an intermediate horz. + if (E2.Prev.Bot.X < E.Bot.X) E = E2; + break; + } + return E; + } + //------------------------------------------------------------------------------ + + private TEdge ProcessBound(TEdge E, bool LeftBoundIsForward) + { + TEdge EStart, Result = E; + TEdge Horz; + + if (Result.OutIdx == Skip) + { + //check if there are edges beyond the skip edge in the bound and if so + //create another LocMin and calling ProcessBound once more ... + E = Result; + if (LeftBoundIsForward) + { + while (E.Top.Y == E.Next.Bot.Y) E = E.Next; + while (E != Result && E.Dx == horizontal) E = E.Prev; + } + else + { + while (E.Top.Y == E.Prev.Bot.Y) E = E.Prev; + while (E != Result && E.Dx == horizontal) E = E.Next; + } + if (E == Result) + { + if (LeftBoundIsForward) Result = E.Next; + else Result = E.Prev; + } + else + { + //there are more edges in the bound beyond result starting with E + if (LeftBoundIsForward) + E = Result.Next; + else + E = Result.Prev; + LocalMinima locMin = new LocalMinima(); + locMin.Next = null; + locMin.Y = E.Bot.Y; + locMin.LeftBound = null; + locMin.RightBound = E; + E.WindDelta = 0; + Result = ProcessBound(E, LeftBoundIsForward); + InsertLocalMinima(locMin); + } + return Result; + } + + if (E.Dx == horizontal) + { + //We need to be careful with open paths because this may not be a + //true local minima (ie E may be following a skip edge). + //Also, consecutive horz. edges may start heading left before going right. + if (LeftBoundIsForward) EStart = E.Prev; + else EStart = E.Next; + if (EStart.Dx == horizontal) //ie an adjoining horizontal skip edge + { + if (EStart.Bot.X != E.Bot.X && EStart.Top.X != E.Bot.X) + ReverseHorizontal(E); + } + else if (EStart.Bot.X != E.Bot.X) + ReverseHorizontal(E); + } + + EStart = E; + if (LeftBoundIsForward) + { + while (Result.Top.Y == Result.Next.Bot.Y && Result.Next.OutIdx != Skip) + Result = Result.Next; + if (Result.Dx == horizontal && Result.Next.OutIdx != Skip) + { + //nb: at the top of a bound, horizontals are added to the bound + //only when the preceding edge attaches to the horizontal's left vertex + //unless a Skip edge is encountered when that becomes the top divide + Horz = Result; + while (Horz.Prev.Dx == horizontal) Horz = Horz.Prev; + if (Horz.Prev.Top.X > Result.Next.Top.X) Result = Horz.Prev; + } + while (E != Result) + { + E.NextInLML = E.Next; + if (E.Dx == horizontal && E != EStart && E.Bot.X != E.Prev.Top.X) + ReverseHorizontal(E); + E = E.Next; + } + if (E.Dx == horizontal && E != EStart && E.Bot.X != E.Prev.Top.X) + ReverseHorizontal(E); + Result = Result.Next; //move to the edge just beyond current bound + } + else + { + while (Result.Top.Y == Result.Prev.Bot.Y && Result.Prev.OutIdx != Skip) + Result = Result.Prev; + if (Result.Dx == horizontal && Result.Prev.OutIdx != Skip) + { + Horz = Result; + while (Horz.Next.Dx == horizontal) Horz = Horz.Next; + if (Horz.Next.Top.X == Result.Prev.Top.X || + Horz.Next.Top.X > Result.Prev.Top.X) Result = Horz.Next; + } + + while (E != Result) + { + E.NextInLML = E.Prev; + if (E.Dx == horizontal && E != EStart && E.Bot.X != E.Next.Top.X) + ReverseHorizontal(E); + E = E.Prev; + } + if (E.Dx == horizontal && E != EStart && E.Bot.X != E.Next.Top.X) + ReverseHorizontal(E); + Result = Result.Prev; //move to the edge just beyond current bound + } + return Result; + } + //------------------------------------------------------------------------------ + + + public bool AddPath(Path pg, PolyType polyType, bool Closed) + { +#if use_lines + if (!Closed && polyType == PolyType.ptClip) + throw new ClipperException("AddPath: Open paths must be subject."); +#else + if (!Closed) + throw new ClipperException("AddPath: Open paths have been disabled."); +#endif + + int highI = (int)pg.Count - 1; + if (Closed) while (highI > 0 && (pg[highI] == pg[0])) --highI; + while (highI > 0 && (pg[highI] == pg[highI - 1])) --highI; + if ((Closed && highI < 2) || (!Closed && highI < 1)) return false; + + //create a new edge array ... + List edges = new List(highI+1); + for (int i = 0; i <= highI; i++) edges.Add(new TEdge()); + + bool IsFlat = true; + + //1. Basic (first) edge initialization ... + edges[1].Curr = pg[1]; + RangeTest(pg[0], ref m_UseFullRange); + RangeTest(pg[highI], ref m_UseFullRange); + InitEdge(edges[0], edges[1], edges[highI], pg[0]); + InitEdge(edges[highI], edges[0], edges[highI - 1], pg[highI]); + for (int i = highI - 1; i >= 1; --i) + { + RangeTest(pg[i], ref m_UseFullRange); + InitEdge(edges[i], edges[i + 1], edges[i - 1], pg[i]); + } + TEdge eStart = edges[0]; + + //2. Remove duplicate vertices, and (when closed) collinear edges ... + TEdge E = eStart, eLoopStop = eStart; + for (;;) + { + //nb: allows matching start and end points when not Closed ... + if (E.Curr == E.Next.Curr && (Closed || E.Next != eStart)) + { + if (E == E.Next) break; + if (E == eStart) eStart = E.Next; + E = RemoveEdge(E); + eLoopStop = E; + continue; + } + if (E.Prev == E.Next) + break; //only two vertices + else if (Closed && + SlopesEqual(E.Prev.Curr, E.Curr, E.Next.Curr, m_UseFullRange) && + (!PreserveCollinear || + !Pt2IsBetweenPt1AndPt3(E.Prev.Curr, E.Curr, E.Next.Curr))) + { + //Collinear edges are allowed for open paths but in closed paths + //the default is to merge adjacent collinear edges into a single edge. + //However, if the PreserveCollinear property is enabled, only overlapping + //collinear edges (ie spikes) will be removed from closed paths. + if (E == eStart) eStart = E.Next; + E = RemoveEdge(E); + E = E.Prev; + eLoopStop = E; + continue; + } + E = E.Next; + if ((E == eLoopStop) || (!Closed && E.Next == eStart)) break; + } + + if ((!Closed && (E == E.Next)) || (Closed && (E.Prev == E.Next))) + return false; + + if (!Closed) + { + m_HasOpenPaths = true; + eStart.Prev.OutIdx = Skip; + } + + //3. Do second stage of edge initialization ... + E = eStart; + do + { + InitEdge2(E, polyType); + E = E.Next; + if (IsFlat && E.Curr.Y != eStart.Curr.Y) IsFlat = false; + } + while (E != eStart); + + //4. Finally, add edge bounds to LocalMinima list ... + + //Totally flat paths must be handled differently when adding them + //to LocalMinima list to avoid endless loops etc ... + if (IsFlat) + { + if (Closed) return false; + E.Prev.OutIdx = Skip; + LocalMinima locMin = new LocalMinima(); + locMin.Next = null; + locMin.Y = E.Bot.Y; + locMin.LeftBound = null; + locMin.RightBound = E; + locMin.RightBound.Side = EdgeSide.esRight; + locMin.RightBound.WindDelta = 0; + for ( ; ; ) + { + if (E.Bot.X != E.Prev.Top.X) ReverseHorizontal(E); + if (E.Next.OutIdx == Skip) break; + E.NextInLML = E.Next; + E = E.Next; + } + InsertLocalMinima(locMin); + m_edges.Add(edges); + return true; + } + + m_edges.Add(edges); + bool leftBoundIsForward; + TEdge EMin = null; + + //workaround to avoid an endless loop in the while loop below when + //open paths have matching start and end points ... + if (E.Prev.Bot == E.Prev.Top) E = E.Next; + + for (;;) + { + E = FindNextLocMin(E); + if (E == EMin) break; + else if (EMin == null) EMin = E; + + //E and E.Prev now share a local minima (left aligned if horizontal). + //Compare their slopes to find which starts which bound ... + LocalMinima locMin = new LocalMinima(); + locMin.Next = null; + locMin.Y = E.Bot.Y; + if (E.Dx < E.Prev.Dx) + { + locMin.LeftBound = E.Prev; + locMin.RightBound = E; + leftBoundIsForward = false; //Q.nextInLML = Q.prev + } else + { + locMin.LeftBound = E; + locMin.RightBound = E.Prev; + leftBoundIsForward = true; //Q.nextInLML = Q.next + } + locMin.LeftBound.Side = EdgeSide.esLeft; + locMin.RightBound.Side = EdgeSide.esRight; + + if (!Closed) locMin.LeftBound.WindDelta = 0; + else if (locMin.LeftBound.Next == locMin.RightBound) + locMin.LeftBound.WindDelta = -1; + else locMin.LeftBound.WindDelta = 1; + locMin.RightBound.WindDelta = -locMin.LeftBound.WindDelta; + + E = ProcessBound(locMin.LeftBound, leftBoundIsForward); + if (E.OutIdx == Skip) E = ProcessBound(E, leftBoundIsForward); + + TEdge E2 = ProcessBound(locMin.RightBound, !leftBoundIsForward); + if (E2.OutIdx == Skip) E2 = ProcessBound(E2, !leftBoundIsForward); + + if (locMin.LeftBound.OutIdx == Skip) + locMin.LeftBound = null; + else if (locMin.RightBound.OutIdx == Skip) + locMin.RightBound = null; + InsertLocalMinima(locMin); + if (!leftBoundIsForward) E = E2; + } + return true; + + } + //------------------------------------------------------------------------------ + + public bool AddPaths(Paths ppg, PolyType polyType, bool closed) + { + bool result = false; + for (int i = 0; i < ppg.Count; ++i) + if (AddPath(ppg[i], polyType, closed)) result = true; + return result; + } + //------------------------------------------------------------------------------ + + internal bool Pt2IsBetweenPt1AndPt3(IntPoint pt1, IntPoint pt2, IntPoint pt3) + { + if ((pt1 == pt3) || (pt1 == pt2) || (pt3 == pt2)) return false; + else if (pt1.X != pt3.X) return (pt2.X > pt1.X) == (pt2.X < pt3.X); + else return (pt2.Y > pt1.Y) == (pt2.Y < pt3.Y); + } + //------------------------------------------------------------------------------ + + TEdge RemoveEdge(TEdge e) + { + //removes e from double_linked_list (but without removing from memory) + e.Prev.Next = e.Next; + e.Next.Prev = e.Prev; + TEdge result = e.Next; + e.Prev = null; //flag as removed (see ClipperBase.Clear) + return result; + } + //------------------------------------------------------------------------------ + + private void SetDx(TEdge e) + { + e.Delta.X = (e.Top.X - e.Bot.X); + e.Delta.Y = (e.Top.Y - e.Bot.Y); + if (e.Delta.Y == 0) e.Dx = horizontal; + else e.Dx = (double)(e.Delta.X) / (e.Delta.Y); + } + //--------------------------------------------------------------------------- + + private void InsertLocalMinima(LocalMinima newLm) + { + if( m_MinimaList == null ) + { + m_MinimaList = newLm; + } + else if( newLm.Y >= m_MinimaList.Y ) + { + newLm.Next = m_MinimaList; + m_MinimaList = newLm; + } else + { + LocalMinima tmpLm = m_MinimaList; + while( tmpLm.Next != null && ( newLm.Y < tmpLm.Next.Y ) ) + tmpLm = tmpLm.Next; + newLm.Next = tmpLm.Next; + tmpLm.Next = newLm; + } + } + //------------------------------------------------------------------------------ + + internal Boolean PopLocalMinima(cInt Y, out LocalMinima current) + { + current = m_CurrentLM; + if (m_CurrentLM != null && m_CurrentLM.Y == Y) + { + m_CurrentLM = m_CurrentLM.Next; + return true; + } + return false; + } + //------------------------------------------------------------------------------ + + private void ReverseHorizontal(TEdge e) + { + //swap horizontal edges' top and bottom x's so they follow the natural + //progression of the bounds - ie so their xbots will align with the + //adjoining lower edge. [Helpful in the ProcessHorizontal() method.] + Swap(ref e.Top.X, ref e.Bot.X); +#if use_xyz + Swap(ref e.Top.Z, ref e.Bot.Z); +#endif + } + //------------------------------------------------------------------------------ + + internal virtual void Reset() + { + m_CurrentLM = m_MinimaList; + if (m_CurrentLM == null) return; //ie nothing to process + + //reset all edges ... + m_Scanbeam = null; + LocalMinima lm = m_MinimaList; + while (lm != null) + { + InsertScanbeam(lm.Y); + TEdge e = lm.LeftBound; + if (e != null) + { + e.Curr = e.Bot; + e.OutIdx = Unassigned; + } + e = lm.RightBound; + if (e != null) + { + e.Curr = e.Bot; + e.OutIdx = Unassigned; + } + lm = lm.Next; + } + m_ActiveEdges = null; + } + //------------------------------------------------------------------------------ + + public static IntRect GetBounds(Paths paths) + { + int i = 0, cnt = paths.Count; + while (i < cnt && paths[i].Count == 0) i++; + if (i == cnt) return new IntRect(0,0,0,0); + IntRect result = new IntRect(); + result.left = paths[i][0].X; + result.right = result.left; + result.top = paths[i][0].Y; + result.bottom = result.top; + for (; i < cnt; i++) + for (int j = 0; j < paths[i].Count; j++) + { + if (paths[i][j].X < result.left) result.left = paths[i][j].X; + else if (paths[i][j].X > result.right) result.right = paths[i][j].X; + if (paths[i][j].Y < result.top) result.top = paths[i][j].Y; + else if (paths[i][j].Y > result.bottom) result.bottom = paths[i][j].Y; + } + return result; + } + //------------------------------------------------------------------------------ + + internal void InsertScanbeam(cInt Y) + { + //single-linked list: sorted descending, ignoring dups. + if (m_Scanbeam == null) + { + m_Scanbeam = new Scanbeam(); + m_Scanbeam.Next = null; + m_Scanbeam.Y = Y; + } + else if (Y > m_Scanbeam.Y) + { + Scanbeam newSb = new Scanbeam(); + newSb.Y = Y; + newSb.Next = m_Scanbeam; + m_Scanbeam = newSb; + } + else + { + Scanbeam sb2 = m_Scanbeam; + while (sb2.Next != null && (Y <= sb2.Next.Y)) sb2 = sb2.Next; + if (Y == sb2.Y) return; //ie ignores duplicates + Scanbeam newSb = new Scanbeam(); + newSb.Y = Y; + newSb.Next = sb2.Next; + sb2.Next = newSb; + } + } + //------------------------------------------------------------------------------ + + internal Boolean PopScanbeam(out cInt Y) + { + if (m_Scanbeam == null) + { + Y = 0; + return false; + } + Y = m_Scanbeam.Y; + m_Scanbeam = m_Scanbeam.Next; + return true; + } + //------------------------------------------------------------------------------ + + internal Boolean LocalMinimaPending() + { + return (m_CurrentLM != null); + } + //------------------------------------------------------------------------------ + + internal OutRec CreateOutRec() + { + OutRec result = new OutRec(); + result.Idx = Unassigned; + result.IsHole = false; + result.IsOpen = false; + result.FirstLeft = null; + result.Pts = null; + result.BottomPt = null; + result.PolyNode = null; + m_PolyOuts.Add(result); + result.Idx = m_PolyOuts.Count - 1; + return result; + } + //------------------------------------------------------------------------------ + + internal void DisposeOutRec(int index) + { + OutRec outRec = m_PolyOuts[index]; + outRec.Pts = null; + outRec = null; + m_PolyOuts[index] = null; + } + //------------------------------------------------------------------------------ + + internal void UpdateEdgeIntoAEL(ref TEdge e) + { + if (e.NextInLML == null) + throw new ClipperException("UpdateEdgeIntoAEL: invalid call"); + TEdge AelPrev = e.PrevInAEL; + TEdge AelNext = e.NextInAEL; + e.NextInLML.OutIdx = e.OutIdx; + if (AelPrev != null) + AelPrev.NextInAEL = e.NextInLML; + else m_ActiveEdges = e.NextInLML; + if (AelNext != null) + AelNext.PrevInAEL = e.NextInLML; + e.NextInLML.Side = e.Side; + e.NextInLML.WindDelta = e.WindDelta; + e.NextInLML.WindCnt = e.WindCnt; + e.NextInLML.WindCnt2 = e.WindCnt2; + e = e.NextInLML; + e.Curr = e.Bot; + e.PrevInAEL = AelPrev; + e.NextInAEL = AelNext; + if (!IsHorizontal(e)) InsertScanbeam(e.Top.Y); + } + //------------------------------------------------------------------------------ + + internal void SwapPositionsInAEL(TEdge edge1, TEdge edge2) + { + //check that one or other edge hasn't already been removed from AEL ... + if (edge1.NextInAEL == edge1.PrevInAEL || + edge2.NextInAEL == edge2.PrevInAEL) return; + + if (edge1.NextInAEL == edge2) + { + TEdge next = edge2.NextInAEL; + if (next != null) + next.PrevInAEL = edge1; + TEdge prev = edge1.PrevInAEL; + if (prev != null) + prev.NextInAEL = edge2; + edge2.PrevInAEL = prev; + edge2.NextInAEL = edge1; + edge1.PrevInAEL = edge2; + edge1.NextInAEL = next; + } + else if (edge2.NextInAEL == edge1) + { + TEdge next = edge1.NextInAEL; + if (next != null) + next.PrevInAEL = edge2; + TEdge prev = edge2.PrevInAEL; + if (prev != null) + prev.NextInAEL = edge1; + edge1.PrevInAEL = prev; + edge1.NextInAEL = edge2; + edge2.PrevInAEL = edge1; + edge2.NextInAEL = next; + } + else + { + TEdge next = edge1.NextInAEL; + TEdge prev = edge1.PrevInAEL; + edge1.NextInAEL = edge2.NextInAEL; + if (edge1.NextInAEL != null) + edge1.NextInAEL.PrevInAEL = edge1; + edge1.PrevInAEL = edge2.PrevInAEL; + if (edge1.PrevInAEL != null) + edge1.PrevInAEL.NextInAEL = edge1; + edge2.NextInAEL = next; + if (edge2.NextInAEL != null) + edge2.NextInAEL.PrevInAEL = edge2; + edge2.PrevInAEL = prev; + if (edge2.PrevInAEL != null) + edge2.PrevInAEL.NextInAEL = edge2; + } + + if (edge1.PrevInAEL == null) + m_ActiveEdges = edge1; + else if (edge2.PrevInAEL == null) + m_ActiveEdges = edge2; + } + //------------------------------------------------------------------------------ + + internal void DeleteFromAEL(TEdge e) + { + TEdge AelPrev = e.PrevInAEL; + TEdge AelNext = e.NextInAEL; + if (AelPrev == null && AelNext == null && (e != m_ActiveEdges)) + return; //already deleted + if (AelPrev != null) + AelPrev.NextInAEL = AelNext; + else m_ActiveEdges = AelNext; + if (AelNext != null) + AelNext.PrevInAEL = AelPrev; + e.NextInAEL = null; + e.PrevInAEL = null; + } + //------------------------------------------------------------------------------ + + } //end ClipperBase + + public class Clipper : ClipperBase + { + //InitOptions that can be passed to the constructor ... + public const int ioReverseSolution = 1; + public const int ioStrictlySimple = 2; + public const int ioPreserveCollinear = 4; + + private ClipType m_ClipType; + private Maxima m_Maxima; + private TEdge m_SortedEdges; + private List m_IntersectList; + IComparer m_IntersectNodeComparer; + private bool m_ExecuteLocked; + private PolyFillType m_ClipFillType; + private PolyFillType m_SubjFillType; + private List m_Joins; + private List m_GhostJoins; + private bool m_UsingPolyTree; +#if use_xyz + public delegate void ZFillCallback(IntPoint bot1, IntPoint top1, + IntPoint bot2, IntPoint top2, ref IntPoint pt); + public ZFillCallback ZFillFunction { get; set; } +#endif + public Clipper(int InitOptions = 0): base() //constructor + { + m_Scanbeam = null; + m_Maxima = null; + m_ActiveEdges = null; + m_SortedEdges = null; + m_IntersectList = new List(); + m_IntersectNodeComparer = new MyIntersectNodeSort(); + m_ExecuteLocked = false; + m_UsingPolyTree = false; + m_PolyOuts = new List(); + m_Joins = new List(); + m_GhostJoins = new List(); + ReverseSolution = (ioReverseSolution & InitOptions) != 0; + StrictlySimple = (ioStrictlySimple & InitOptions) != 0; + PreserveCollinear = (ioPreserveCollinear & InitOptions) != 0; +#if use_xyz + ZFillFunction = null; +#endif + } + //------------------------------------------------------------------------------ + + private void InsertMaxima(cInt X) + { + //double-linked list: sorted ascending, ignoring dups. + Maxima newMax = new Maxima(); + newMax.X = X; + if (m_Maxima == null) + { + m_Maxima = newMax; + m_Maxima.Next = null; + m_Maxima.Prev = null; + } + else if (X < m_Maxima.X) + { + newMax.Next = m_Maxima; + newMax.Prev = null; + m_Maxima = newMax; + } + else + { + Maxima m = m_Maxima; + while (m.Next != null && (X >= m.Next.X)) m = m.Next; + if (X == m.X) return; //ie ignores duplicates (& CG to clean up newMax) + //insert newMax between m and m.Next ... + newMax.Next = m.Next; + newMax.Prev = m; + if (m.Next != null) m.Next.Prev = newMax; + m.Next = newMax; + } + } + //------------------------------------------------------------------------------ + + public bool ReverseSolution + { + get; + set; + } + //------------------------------------------------------------------------------ + + public bool StrictlySimple + { + get; + set; + } + //------------------------------------------------------------------------------ + + public bool Execute(ClipType clipType, Paths solution, + PolyFillType FillType = PolyFillType.pftEvenOdd) + { + return Execute(clipType, solution, FillType, FillType); + } + //------------------------------------------------------------------------------ + + public bool Execute(ClipType clipType, PolyTree polytree, + PolyFillType FillType = PolyFillType.pftEvenOdd) + { + return Execute(clipType, polytree, FillType, FillType); + } + //------------------------------------------------------------------------------ + + public bool Execute(ClipType clipType, Paths solution, + PolyFillType subjFillType, PolyFillType clipFillType) + { + if (m_ExecuteLocked) return false; + if (m_HasOpenPaths) throw + new ClipperException("Error: PolyTree struct is needed for open path clipping."); + + m_ExecuteLocked = true; + solution.Clear(); + m_SubjFillType = subjFillType; + m_ClipFillType = clipFillType; + m_ClipType = clipType; + m_UsingPolyTree = false; + bool succeeded; + try + { + succeeded = ExecuteInternal(); + //build the return polygons ... + if (succeeded) BuildResult(solution); + } + finally + { + DisposeAllPolyPts(); + m_ExecuteLocked = false; + } + return succeeded; + } + //------------------------------------------------------------------------------ + + public bool Execute(ClipType clipType, PolyTree polytree, + PolyFillType subjFillType, PolyFillType clipFillType) + { + if (m_ExecuteLocked) return false; + m_ExecuteLocked = true; + m_SubjFillType = subjFillType; + m_ClipFillType = clipFillType; + m_ClipType = clipType; + m_UsingPolyTree = true; + bool succeeded; + try + { + succeeded = ExecuteInternal(); + //build the return polygons ... + if (succeeded) BuildResult2(polytree); + } + finally + { + DisposeAllPolyPts(); + m_ExecuteLocked = false; + } + return succeeded; + } + //------------------------------------------------------------------------------ + + internal void FixHoleLinkage(OutRec outRec) + { + //skip if an outermost polygon or + //already already points to the correct FirstLeft ... + if (outRec.FirstLeft == null || + (outRec.IsHole != outRec.FirstLeft.IsHole && + outRec.FirstLeft.Pts != null)) return; + + OutRec orfl = outRec.FirstLeft; + while (orfl != null && ((orfl.IsHole == outRec.IsHole) || orfl.Pts == null)) + orfl = orfl.FirstLeft; + outRec.FirstLeft = orfl; + } + //------------------------------------------------------------------------------ + + private bool ExecuteInternal() + { + try + { + Reset(); + m_SortedEdges = null; + m_Maxima = null; + + cInt botY, topY; + if (!PopScanbeam(out botY)) return false; + InsertLocalMinimaIntoAEL(botY); + while (PopScanbeam(out topY) || LocalMinimaPending()) + { + ProcessHorizontals(); + m_GhostJoins.Clear(); + if (!ProcessIntersections(topY)) return false; + ProcessEdgesAtTopOfScanbeam(topY); + botY = topY; + InsertLocalMinimaIntoAEL(botY); + } + + //fix orientations ... + foreach (OutRec outRec in m_PolyOuts) + { + if (outRec.Pts == null || outRec.IsOpen) continue; + if ((outRec.IsHole ^ ReverseSolution) == (Area(outRec) > 0)) + ReversePolyPtLinks(outRec.Pts); + } + + JoinCommonEdges(); + + foreach (OutRec outRec in m_PolyOuts) + { + if (outRec.Pts == null) + continue; + else if (outRec.IsOpen) + FixupOutPolyline(outRec); + else + FixupOutPolygon(outRec); + } + + if (StrictlySimple) DoSimplePolygons(); + return true; + } + //catch { return false; } + finally + { + m_Joins.Clear(); + m_GhostJoins.Clear(); + } + } + //------------------------------------------------------------------------------ + + private void DisposeAllPolyPts(){ + for (int i = 0; i < m_PolyOuts.Count; ++i) DisposeOutRec(i); + m_PolyOuts.Clear(); + } + //------------------------------------------------------------------------------ + + 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); + } + //------------------------------------------------------------------------------ + + private void AddGhostJoin(OutPt Op, IntPoint OffPt) + { + Join j = new Join(); + j.OutPt1 = Op; + j.OffPt = OffPt; + m_GhostJoins.Add(j); + } + //------------------------------------------------------------------------------ + +#if use_xyz + internal void SetZ(ref IntPoint pt, TEdge e1, TEdge e2) + { + if (pt.Z != 0 || ZFillFunction == null) return; + else if (pt == e1.Bot) pt.Z = e1.Bot.Z; + else if (pt == e1.Top) pt.Z = e1.Top.Z; + else if (pt == e2.Bot) pt.Z = e2.Bot.Z; + else if (pt == e2.Top) pt.Z = e2.Top.Z; + else ZFillFunction(e1.Bot, e1.Top, e2.Bot, e2.Top, ref pt); + } + //------------------------------------------------------------------------------ +#endif + + private void InsertLocalMinimaIntoAEL(cInt botY) + { + LocalMinima lm; + while (PopLocalMinima(botY, out lm)) + { + TEdge lb = lm.LeftBound; + TEdge rb = lm.RightBound; + + OutPt Op1 = null; + if (lb == null) + { + InsertEdgeIntoAEL(rb, null); + SetWindingCount(rb); + if (IsContributing(rb)) + Op1 = AddOutPt(rb, rb.Bot); + } + else if (rb == null) + { + InsertEdgeIntoAEL(lb, null); + SetWindingCount(lb); + if (IsContributing(lb)) + Op1 = AddOutPt(lb, lb.Bot); + InsertScanbeam(lb.Top.Y); + } + else + { + InsertEdgeIntoAEL(lb, null); + InsertEdgeIntoAEL(rb, lb); + SetWindingCount(lb); + rb.WindCnt = lb.WindCnt; + rb.WindCnt2 = lb.WindCnt2; + if (IsContributing(lb)) + Op1 = AddLocalMinPoly(lb, rb, lb.Bot); + InsertScanbeam(lb.Top.Y); + } + + if (rb != null) + { + if (IsHorizontal(rb)) + { + if (rb.NextInLML != null) + InsertScanbeam(rb.NextInLML.Top.Y); + AddEdgeToSEL(rb); + } + else + InsertScanbeam(rb.Top.Y); + } + + if (lb == null || rb == null) continue; + + //if output polygons share an Edge with a horizontal rb, they'll need joining later ... + if (Op1 != null && IsHorizontal(rb) && + m_GhostJoins.Count > 0 && rb.WindDelta != 0) + { + for (int i = 0; i < m_GhostJoins.Count; i++) + { + //if the horizontal Rb and a 'ghost' horizontal overlap, then convert + //the 'ghost' join to a real join ready for later ... + Join j = m_GhostJoins[i]; + if (HorzSegmentsOverlap(j.OutPt1.Pt.X, j.OffPt.X, rb.Bot.X, rb.Top.X)) + AddJoin(j.OutPt1, Op1, j.OffPt); + } + } + + if (lb.OutIdx >= 0 && lb.PrevInAEL != null && + lb.PrevInAEL.Curr.X == lb.Bot.X && + lb.PrevInAEL.OutIdx >= 0 && + SlopesEqual(lb.PrevInAEL.Curr, lb.PrevInAEL.Top, lb.Curr, lb.Top, m_UseFullRange) && + lb.WindDelta != 0 && lb.PrevInAEL.WindDelta != 0) + { + OutPt Op2 = AddOutPt(lb.PrevInAEL, lb.Bot); + AddJoin(Op1, Op2, lb.Top); + } + + if( lb.NextInAEL != rb ) + { + + if (rb.OutIdx >= 0 && rb.PrevInAEL.OutIdx >= 0 && + SlopesEqual(rb.PrevInAEL.Curr, rb.PrevInAEL.Top, rb.Curr, rb.Top, m_UseFullRange) && + rb.WindDelta != 0 && rb.PrevInAEL.WindDelta != 0) + { + OutPt Op2 = AddOutPt(rb.PrevInAEL, rb.Bot); + AddJoin(Op1, Op2, rb.Top); + } + + TEdge e = lb.NextInAEL; + if (e != null) + while (e != rb) + { + //nb: For calculating winding counts etc, IntersectEdges() assumes + //that param1 will be to the right of param2 ABOVE the intersection ... + IntersectEdges(rb, e, lb.Curr); //order important here + e = e.NextInAEL; + } + } + } + } + //------------------------------------------------------------------------------ + + private void InsertEdgeIntoAEL(TEdge edge, TEdge startEdge) + { + if (m_ActiveEdges == null) + { + edge.PrevInAEL = null; + edge.NextInAEL = null; + m_ActiveEdges = edge; + } + else if (startEdge == null && E2InsertsBeforeE1(m_ActiveEdges, edge)) + { + edge.PrevInAEL = null; + edge.NextInAEL = m_ActiveEdges; + m_ActiveEdges.PrevInAEL = edge; + m_ActiveEdges = edge; + } + else + { + if (startEdge == null) startEdge = m_ActiveEdges; + while (startEdge.NextInAEL != null && + !E2InsertsBeforeE1(startEdge.NextInAEL, edge)) + startEdge = startEdge.NextInAEL; + edge.NextInAEL = startEdge.NextInAEL; + if (startEdge.NextInAEL != null) startEdge.NextInAEL.PrevInAEL = edge; + edge.PrevInAEL = startEdge; + startEdge.NextInAEL = edge; + } + } + //---------------------------------------------------------------------- + + private bool E2InsertsBeforeE1(TEdge e1, TEdge e2) + { + if (e2.Curr.X == e1.Curr.X) + { + if (e2.Top.Y > e1.Top.Y) + return e2.Top.X < TopX(e1, e2.Top.Y); + else return e1.Top.X > TopX(e2, e1.Top.Y); + } + else return e2.Curr.X < e1.Curr.X; + } + //------------------------------------------------------------------------------ + + private bool IsEvenOddFillType(TEdge edge) + { + if (edge.PolyTyp == PolyType.ptSubject) + return m_SubjFillType == PolyFillType.pftEvenOdd; + else + return m_ClipFillType == PolyFillType.pftEvenOdd; + } + //------------------------------------------------------------------------------ + + private bool IsEvenOddAltFillType(TEdge edge) + { + if (edge.PolyTyp == PolyType.ptSubject) + return m_ClipFillType == PolyFillType.pftEvenOdd; + else + return m_SubjFillType == PolyFillType.pftEvenOdd; + } + //------------------------------------------------------------------------------ + + private bool IsContributing(TEdge edge) + { + PolyFillType pft, pft2; + if (edge.PolyTyp == PolyType.ptSubject) + { + pft = m_SubjFillType; + pft2 = m_ClipFillType; + } + else + { + pft = m_ClipFillType; + pft2 = m_SubjFillType; + } + + switch (pft) + { + case PolyFillType.pftEvenOdd: + //return false if a subj line has been flagged as inside a subj polygon + if (edge.WindDelta == 0 && edge.WindCnt != 1) return false; + break; + case PolyFillType.pftNonZero: + if (Math.Abs(edge.WindCnt) != 1) return false; + break; + case PolyFillType.pftPositive: + if (edge.WindCnt != 1) return false; + break; + default: //PolyFillType.pftNegative + if (edge.WindCnt != -1) return false; + break; + } + + switch (m_ClipType) + { + case ClipType.ctIntersection: + switch (pft2) + { + case PolyFillType.pftEvenOdd: + case PolyFillType.pftNonZero: + return (edge.WindCnt2 != 0); + case PolyFillType.pftPositive: + return (edge.WindCnt2 > 0); + default: + return (edge.WindCnt2 < 0); + } + case ClipType.ctUnion: + switch (pft2) + { + case PolyFillType.pftEvenOdd: + case PolyFillType.pftNonZero: + return (edge.WindCnt2 == 0); + case PolyFillType.pftPositive: + return (edge.WindCnt2 <= 0); + default: + return (edge.WindCnt2 >= 0); + } + case ClipType.ctDifference: + if (edge.PolyTyp == PolyType.ptSubject) + switch (pft2) + { + case PolyFillType.pftEvenOdd: + case PolyFillType.pftNonZero: + return (edge.WindCnt2 == 0); + case PolyFillType.pftPositive: + return (edge.WindCnt2 <= 0); + default: + return (edge.WindCnt2 >= 0); + } + else + switch (pft2) + { + case PolyFillType.pftEvenOdd: + case PolyFillType.pftNonZero: + return (edge.WindCnt2 != 0); + case PolyFillType.pftPositive: + return (edge.WindCnt2 > 0); + default: + return (edge.WindCnt2 < 0); + } + case ClipType.ctXor: + if (edge.WindDelta == 0) //XOr always contributing unless open + switch (pft2) + { + case PolyFillType.pftEvenOdd: + case PolyFillType.pftNonZero: + return (edge.WindCnt2 == 0); + case PolyFillType.pftPositive: + return (edge.WindCnt2 <= 0); + default: + return (edge.WindCnt2 >= 0); + } + else + return true; + } + return true; + } + //------------------------------------------------------------------------------ + + private void SetWindingCount(TEdge edge) + { + TEdge e = edge.PrevInAEL; + //find the edge of the same polytype that immediately preceeds 'edge' in AEL + while (e != null && ((e.PolyTyp != edge.PolyTyp) || (e.WindDelta == 0))) e = e.PrevInAEL; + if (e == null) + { + PolyFillType pft; + pft = (edge.PolyTyp == PolyType.ptSubject ? m_SubjFillType : m_ClipFillType); + if (edge.WindDelta == 0) edge.WindCnt = (pft == PolyFillType.pftNegative ? -1 : 1); + else edge.WindCnt = edge.WindDelta; + edge.WindCnt2 = 0; + e = m_ActiveEdges; //ie get ready to calc WindCnt2 + } + else if (edge.WindDelta == 0 && m_ClipType != ClipType.ctUnion) + { + edge.WindCnt = 1; + edge.WindCnt2 = e.WindCnt2; + e = e.NextInAEL; //ie get ready to calc WindCnt2 + } + else if (IsEvenOddFillType(edge)) + { + //EvenOdd filling ... + if (edge.WindDelta == 0) + { + //are we inside a subj polygon ... + bool Inside = true; + TEdge e2 = e.PrevInAEL; + while (e2 != null) + { + if (e2.PolyTyp == e.PolyTyp && e2.WindDelta != 0) + Inside = !Inside; + e2 = e2.PrevInAEL; + } + edge.WindCnt = (Inside ? 0 : 1); + } + else + { + edge.WindCnt = edge.WindDelta; + } + edge.WindCnt2 = e.WindCnt2; + e = e.NextInAEL; //ie get ready to calc WindCnt2 + } + else + { + //nonZero, Positive or Negative filling ... + if (e.WindCnt * e.WindDelta < 0) + { + //prev edge is 'decreasing' WindCount (WC) toward zero + //so we're outside the previous polygon ... + if (Math.Abs(e.WindCnt) > 1) + { + //outside prev poly but still inside another. + //when reversing direction of prev poly use the same WC + if (e.WindDelta * edge.WindDelta < 0) edge.WindCnt = e.WindCnt; + //otherwise continue to 'decrease' WC ... + else edge.WindCnt = e.WindCnt + edge.WindDelta; + } + else + //now outside all polys of same polytype so set own WC ... + edge.WindCnt = (edge.WindDelta == 0 ? 1 : edge.WindDelta); + } + else + { + //prev edge is 'increasing' WindCount (WC) away from zero + //so we're inside the previous polygon ... + if (edge.WindDelta == 0) + edge.WindCnt = (e.WindCnt < 0 ? e.WindCnt - 1 : e.WindCnt + 1); + //if wind direction is reversing prev then use same WC + else if (e.WindDelta * edge.WindDelta < 0) + edge.WindCnt = e.WindCnt; + //otherwise add to WC ... + else edge.WindCnt = e.WindCnt + edge.WindDelta; + } + edge.WindCnt2 = e.WindCnt2; + e = e.NextInAEL; //ie get ready to calc WindCnt2 + } + + //update WindCnt2 ... + if (IsEvenOddAltFillType(edge)) + { + //EvenOdd filling ... + while (e != edge) + { + if (e.WindDelta != 0) + edge.WindCnt2 = (edge.WindCnt2 == 0 ? 1 : 0); + e = e.NextInAEL; + } + } + else + { + //nonZero, Positive or Negative filling ... + while (e != edge) + { + edge.WindCnt2 += e.WindDelta; + e = e.NextInAEL; + } + } + } + //------------------------------------------------------------------------------ + + private void AddEdgeToSEL(TEdge edge) + { + //SEL pointers in PEdge are use to build transient lists of horizontal edges. + //However, since we don't need to worry about processing order, all additions + //are made to the front of the list ... + if (m_SortedEdges == null) + { + m_SortedEdges = edge; + edge.PrevInSEL = null; + edge.NextInSEL = null; + } + else + { + edge.NextInSEL = m_SortedEdges; + edge.PrevInSEL = null; + m_SortedEdges.PrevInSEL = edge; + m_SortedEdges = edge; + } + } + //------------------------------------------------------------------------------ + + internal Boolean PopEdgeFromSEL(out TEdge e) + { + //Pop edge from front of SEL (ie SEL is a FILO list) + e = m_SortedEdges; + if (e == null) return false; + TEdge oldE = e; + m_SortedEdges = e.NextInSEL; + if (m_SortedEdges != null) m_SortedEdges.PrevInSEL = null; + oldE.NextInSEL = null; + oldE.PrevInSEL = null; + return true; + } + //------------------------------------------------------------------------------ + + private void CopyAELToSEL() + { + TEdge e = m_ActiveEdges; + m_SortedEdges = e; + while (e != null) + { + e.PrevInSEL = e.PrevInAEL; + e.NextInSEL = e.NextInAEL; + e = e.NextInAEL; + } + } + //------------------------------------------------------------------------------ + + private void SwapPositionsInSEL(TEdge edge1, TEdge edge2) + { + if (edge1.NextInSEL == null && edge1.PrevInSEL == null) + return; + if (edge2.NextInSEL == null && edge2.PrevInSEL == null) + return; + + if (edge1.NextInSEL == edge2) + { + TEdge next = edge2.NextInSEL; + if (next != null) + next.PrevInSEL = edge1; + TEdge prev = edge1.PrevInSEL; + if (prev != null) + prev.NextInSEL = edge2; + edge2.PrevInSEL = prev; + edge2.NextInSEL = edge1; + edge1.PrevInSEL = edge2; + edge1.NextInSEL = next; + } + else if (edge2.NextInSEL == edge1) + { + TEdge next = edge1.NextInSEL; + if (next != null) + next.PrevInSEL = edge2; + TEdge prev = edge2.PrevInSEL; + if (prev != null) + prev.NextInSEL = edge1; + edge1.PrevInSEL = prev; + edge1.NextInSEL = edge2; + edge2.PrevInSEL = edge1; + edge2.NextInSEL = next; + } + else + { + TEdge next = edge1.NextInSEL; + TEdge prev = edge1.PrevInSEL; + edge1.NextInSEL = edge2.NextInSEL; + if (edge1.NextInSEL != null) + edge1.NextInSEL.PrevInSEL = edge1; + edge1.PrevInSEL = edge2.PrevInSEL; + if (edge1.PrevInSEL != null) + edge1.PrevInSEL.NextInSEL = edge1; + edge2.NextInSEL = next; + if (edge2.NextInSEL != null) + edge2.NextInSEL.PrevInSEL = edge2; + edge2.PrevInSEL = prev; + if (edge2.PrevInSEL != null) + edge2.PrevInSEL.NextInSEL = edge2; + } + + if (edge1.PrevInSEL == null) + m_SortedEdges = edge1; + else if (edge2.PrevInSEL == null) + m_SortedEdges = edge2; + } + //------------------------------------------------------------------------------ + + + private void AddLocalMaxPoly(TEdge e1, TEdge e2, IntPoint pt) + { + AddOutPt(e1, pt); + if (e2.WindDelta == 0) AddOutPt(e2, pt); + if (e1.OutIdx == e2.OutIdx) + { + e1.OutIdx = Unassigned; + e2.OutIdx = Unassigned; + } + else if (e1.OutIdx < e2.OutIdx) + AppendPolygon(e1, e2); + else + AppendPolygon(e2, e1); + } + //------------------------------------------------------------------------------ + + private OutPt AddLocalMinPoly(TEdge e1, TEdge e2, IntPoint pt) + { + OutPt result; + TEdge e, prevE; + if (IsHorizontal(e2) || (e1.Dx > e2.Dx)) + { + result = AddOutPt(e1, pt); + e2.OutIdx = e1.OutIdx; + e1.Side = EdgeSide.esLeft; + e2.Side = EdgeSide.esRight; + e = e1; + if (e.PrevInAEL == e2) + prevE = e2.PrevInAEL; + else + prevE = e.PrevInAEL; + } + else + { + result = AddOutPt(e2, pt); + e1.OutIdx = e2.OutIdx; + e1.Side = EdgeSide.esRight; + e2.Side = EdgeSide.esLeft; + e = e2; + if (e.PrevInAEL == e1) + prevE = e1.PrevInAEL; + else + prevE = e.PrevInAEL; + } + + if (prevE != null && prevE.OutIdx >= 0 && prevE.Top.Y < pt.Y && e.Top.Y < pt.Y) + { + cInt xPrev = TopX(prevE, pt.Y); + cInt xE = TopX(e, pt.Y); + if ((xPrev == xE) && (e.WindDelta != 0) && (prevE.WindDelta != 0) && + SlopesEqual(new IntPoint(xPrev, pt.Y), prevE.Top, new IntPoint(xE, pt.Y), e.Top, m_UseFullRange)) + { + OutPt outPt = AddOutPt(prevE, pt); + AddJoin(result, outPt, e.Top); + } + } + return result; + } + //------------------------------------------------------------------------------ + + private OutPt AddOutPt(TEdge e, IntPoint pt) + { + 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); + 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; + bool ToFront = (e.Side == EdgeSide.esLeft); + 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; + return newOp; + } + } + //------------------------------------------------------------------------------ + + private OutPt GetLastOutPt(TEdge e) + { + OutRec outRec = m_PolyOuts[e.OutIdx]; + if (e.Side == EdgeSide.esLeft) + return outRec.Pts; + else + return outRec.Pts.Prev; + } + //------------------------------------------------------------------------------ + + internal void SwapPoints(ref IntPoint pt1, ref IntPoint pt2) + { + IntPoint tmp = new IntPoint(pt1); + pt1 = pt2; + pt2 = tmp; + } + //------------------------------------------------------------------------------ + + private bool HorzSegmentsOverlap(cInt seg1a, cInt seg1b, cInt seg2a, cInt seg2b) + { + if (seg1a > seg1b) Swap(ref seg1a, ref seg1b); + if (seg2a > seg2b) Swap(ref seg2a, ref seg2b); + return (seg1a < seg2b) && (seg2a < seg1b); + } + //------------------------------------------------------------------------------ + + private void SetHoleState(TEdge e, OutRec outRec) + { + TEdge e2 = e.PrevInAEL; + TEdge eTmp = null; + while (e2 != null) + { + if (e2.OutIdx >= 0 && e2.WindDelta != 0) + { + if (eTmp == null) + eTmp = e2; + else if (eTmp.OutIdx == e2.OutIdx) + eTmp = null; //paired + } + e2 = e2.PrevInAEL; + } + + if (eTmp == null) + { + outRec.FirstLeft = null; + outRec.IsHole = false; + } + else + { + outRec.FirstLeft = m_PolyOuts[eTmp.OutIdx]; + outRec.IsHole = !outRec.FirstLeft.IsHole; + } + } + //------------------------------------------------------------------------------ + + private double GetDx(IntPoint pt1, IntPoint pt2) + { + if (pt1.Y == pt2.Y) return horizontal; + else return (double)(pt2.X - pt1.X) / (pt2.Y - pt1.Y); + } + //--------------------------------------------------------------------------- + + 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)); + + if (Math.Max(dx1p, dx1n) == Math.Max(dx2p, dx2n) && + Math.Min(dx1p, dx1n) == Math.Min(dx2p, dx2n)) + return Area(btmPt1) > 0; //if otherwise identical use orientation + else + return (dx1p >= dx2p && dx1p >= dx2n) || (dx1n >= dx2p && dx1n >= dx2n); + } + //------------------------------------------------------------------------------ + + 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; + } + //------------------------------------------------------------------------------ + + private OutRec GetLowermostRec(OutRec outRec1, OutRec outRec2) + { + //work out which polygon fragment has the correct hole state ... + if (outRec1.BottomPt == null) + outRec1.BottomPt = GetBottomPt(outRec1.Pts); + if (outRec2.BottomPt == null) + outRec2.BottomPt = GetBottomPt(outRec2.Pts); + OutPt bPt1 = outRec1.BottomPt; + OutPt bPt2 = outRec2.BottomPt; + if (bPt1.Pt.Y > bPt2.Pt.Y) return outRec1; + else if (bPt1.Pt.Y < bPt2.Pt.Y) return outRec2; + else if (bPt1.Pt.X < bPt2.Pt.X) return outRec1; + else if (bPt1.Pt.X > bPt2.Pt.X) return outRec2; + else if (bPt1.Next == bPt1) return outRec2; + else if (bPt2.Next == bPt2) return outRec1; + else if (FirstIsBottomPt(bPt1, bPt2)) return outRec1; + else return outRec2; + } + //------------------------------------------------------------------------------ + + bool OutRec1RightOfOutRec2(OutRec outRec1, OutRec outRec2) + { + do + { + outRec1 = outRec1.FirstLeft; + if (outRec1 == outRec2) return true; + } while (outRec1 != null); + return false; + } + //------------------------------------------------------------------------------ + + private OutRec GetOutRec(int idx) + { + OutRec outrec = m_PolyOuts[idx]; + while (outrec != m_PolyOuts[outrec.Idx]) + outrec = m_PolyOuts[outrec.Idx]; + return outrec; + } + //------------------------------------------------------------------------------ + + private void AppendPolygon(TEdge e1, TEdge e2) + { + OutRec outRec1 = m_PolyOuts[e1.OutIdx]; + OutRec outRec2 = m_PolyOuts[e2.OutIdx]; + + OutRec holeStateRec; + if (OutRec1RightOfOutRec2(outRec1, outRec2)) + holeStateRec = outRec2; + else if (OutRec1RightOfOutRec2(outRec2, outRec1)) + holeStateRec = outRec1; + else + holeStateRec = GetLowermostRec(outRec1, outRec2); + + //get the start and ends of both output polygons and + //join E2 poly onto E1 poly and delete pointers to E2 ... + OutPt p1_lft = outRec1.Pts; + OutPt p1_rt = p1_lft.Prev; + OutPt p2_lft = outRec2.Pts; + OutPt p2_rt = p2_lft.Prev; + + //join e2 poly onto e1 poly and delete pointers to e2 ... + if( e1.Side == EdgeSide.esLeft ) + { + if (e2.Side == EdgeSide.esLeft) + { + //z y x a b c + ReversePolyPtLinks(p2_lft); + p2_lft.Next = p1_lft; + p1_lft.Prev = p2_lft; + p1_rt.Next = p2_rt; + p2_rt.Prev = p1_rt; + outRec1.Pts = p2_rt; + } else + { + //x y z a b c + p2_rt.Next = p1_lft; + p1_lft.Prev = p2_rt; + p2_lft.Prev = p1_rt; + p1_rt.Next = p2_lft; + outRec1.Pts = p2_lft; + } + } else + { + if (e2.Side == EdgeSide.esRight) + { + //a b c z y x + ReversePolyPtLinks( p2_lft ); + p1_rt.Next = p2_rt; + p2_rt.Prev = p1_rt; + p2_lft.Next = p1_lft; + p1_lft.Prev = p2_lft; + } else + { + //a b c x y z + p1_rt.Next = p2_lft; + p2_lft.Prev = p1_rt; + p1_lft.Prev = p2_rt; + p2_rt.Next = p1_lft; + } + } + + outRec1.BottomPt = null; + if (holeStateRec == outRec2) + { + if (outRec2.FirstLeft != outRec1) + outRec1.FirstLeft = outRec2.FirstLeft; + outRec1.IsHole = outRec2.IsHole; + } + outRec2.Pts = null; + outRec2.BottomPt = null; + + outRec2.FirstLeft = outRec1; + + int OKIdx = e1.OutIdx; + int ObsoleteIdx = e2.OutIdx; + + e1.OutIdx = Unassigned; //nb: safe because we only get here via AddLocalMaxPoly + e2.OutIdx = Unassigned; + + TEdge e = m_ActiveEdges; + while( e != null ) + { + if( e.OutIdx == ObsoleteIdx ) + { + e.OutIdx = OKIdx; + e.Side = e1.Side; + break; + } + e = e.NextInAEL; + } + outRec2.Idx = outRec1.Idx; + } + //------------------------------------------------------------------------------ + + 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); + } + //------------------------------------------------------------------------------ + + private static void SwapSides(TEdge edge1, TEdge edge2) + { + EdgeSide side = edge1.Side; + edge1.Side = edge2.Side; + edge2.Side = side; + } + //------------------------------------------------------------------------------ + + private static void SwapPolyIndexes(TEdge edge1, TEdge edge2) + { + int outIdx = edge1.OutIdx; + edge1.OutIdx = edge2.OutIdx; + edge2.OutIdx = outIdx; + } + //------------------------------------------------------------------------------ + + private void IntersectEdges(TEdge e1, TEdge e2, IntPoint pt) + { + //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 e1Contributing = (e1.OutIdx >= 0); + bool e2Contributing = (e2.OutIdx >= 0); + +#if use_xyz + SetZ(ref pt, e1, e2); +#endif + +#if use_lines + //if either edge is on an OPEN path ... + if (e1.WindDelta == 0 || e2.WindDelta == 0) + { + //ignore subject-subject open path intersections UNLESS they + //are both open paths, AND they are both 'contributing maximas' ... + if (e1.WindDelta == 0 && e2.WindDelta == 0) return; + //if intersecting a subj line with a subj poly ... + else if (e1.PolyTyp == e2.PolyTyp && + e1.WindDelta != e2.WindDelta && m_ClipType == ClipType.ctUnion) + { + if (e1.WindDelta == 0) + { + if (e2Contributing) + { + AddOutPt(e1, pt); + if (e1Contributing) e1.OutIdx = Unassigned; + } + } + else + { + if (e1Contributing) + { + AddOutPt(e2, pt); + if (e2Contributing) e2.OutIdx = Unassigned; + } + } + } + else if (e1.PolyTyp != e2.PolyTyp) + { + if ((e1.WindDelta == 0) && Math.Abs(e2.WindCnt) == 1 && + (m_ClipType != ClipType.ctUnion || e2.WindCnt2 == 0)) + { + AddOutPt(e1, pt); + if (e1Contributing) e1.OutIdx = Unassigned; + } + else if ((e2.WindDelta == 0) && (Math.Abs(e1.WindCnt) == 1) && + (m_ClipType != ClipType.ctUnion || e1.WindCnt2 == 0)) + { + AddOutPt(e2, pt); + if (e2Contributing) e2.OutIdx = Unassigned; + } + } + return; + } +#endif + + //update winding counts... + //assumes that e1 will be to the Right of e2 ABOVE the intersection + if (e1.PolyTyp == e2.PolyTyp) + { + if (IsEvenOddFillType(e1)) + { + int oldE1WindCnt = e1.WindCnt; + e1.WindCnt = e2.WindCnt; + e2.WindCnt = oldE1WindCnt; + } + else + { + 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 + { + if (!IsEvenOddFillType(e2)) e1.WindCnt2 += e2.WindDelta; + else e1.WindCnt2 = (e1.WindCnt2 == 0) ? 1 : 0; + if (!IsEvenOddFillType(e1)) e2.WindCnt2 -= e1.WindDelta; + else e2.WindCnt2 = (e2.WindCnt2 == 0) ? 1 : 0; + } + + PolyFillType e1FillType, e2FillType, e1FillType2, e2FillType2; + if (e1.PolyTyp == PolyType.ptSubject) + { + e1FillType = m_SubjFillType; + e1FillType2 = m_ClipFillType; + } + else + { + e1FillType = m_ClipFillType; + e1FillType2 = m_SubjFillType; + } + if (e2.PolyTyp == PolyType.ptSubject) + { + e2FillType = m_SubjFillType; + e2FillType2 = m_ClipFillType; + } + else + { + e2FillType = m_ClipFillType; + e2FillType2 = m_SubjFillType; + } + + int e1Wc, e2Wc; + switch (e1FillType) + { + case PolyFillType.pftPositive: e1Wc = e1.WindCnt; break; + case PolyFillType.pftNegative: e1Wc = -e1.WindCnt; break; + default: e1Wc = Math.Abs(e1.WindCnt); break; + } + switch (e2FillType) + { + case PolyFillType.pftPositive: e2Wc = e2.WindCnt; break; + case PolyFillType.pftNegative: e2Wc = -e2.WindCnt; break; + default: e2Wc = Math.Abs(e2.WindCnt); break; + } + + if (e1Contributing && e2Contributing) + { + if ((e1Wc != 0 && e1Wc != 1) || (e2Wc != 0 && e2Wc != 1) || + (e1.PolyTyp != e2.PolyTyp && m_ClipType != ClipType.ctXor)) + { + AddLocalMaxPoly(e1, e2, pt); + } + else + { + AddOutPt(e1, pt); + AddOutPt(e2, pt); + SwapSides(e1, e2); + SwapPolyIndexes(e1, e2); + } + } + else if (e1Contributing) + { + if (e2Wc == 0 || e2Wc == 1) + { + AddOutPt(e1, pt); + SwapSides(e1, e2); + SwapPolyIndexes(e1, e2); + } + + } + else if (e2Contributing) + { + if (e1Wc == 0 || e1Wc == 1) + { + AddOutPt(e2, pt); + SwapSides(e1, e2); + SwapPolyIndexes(e1, e2); + } + } + else if ( (e1Wc == 0 || e1Wc == 1) && (e2Wc == 0 || e2Wc == 1)) + { + //neither edge is currently contributing ... + cInt e1Wc2, e2Wc2; + switch (e1FillType2) + { + case PolyFillType.pftPositive: e1Wc2 = e1.WindCnt2; break; + case PolyFillType.pftNegative: e1Wc2 = -e1.WindCnt2; break; + default: e1Wc2 = Math.Abs(e1.WindCnt2); break; + } + switch (e2FillType2) + { + case PolyFillType.pftPositive: e2Wc2 = e2.WindCnt2; break; + case PolyFillType.pftNegative: e2Wc2 = -e2.WindCnt2; break; + default: e2Wc2 = Math.Abs(e2.WindCnt2); break; + } + + if (e1.PolyTyp != e2.PolyTyp) + { + AddLocalMinPoly(e1, e2, pt); + } + else if (e1Wc == 1 && e2Wc == 1) + switch (m_ClipType) + { + case ClipType.ctIntersection: + if (e1Wc2 > 0 && e2Wc2 > 0) + AddLocalMinPoly(e1, e2, pt); + break; + case ClipType.ctUnion: + if (e1Wc2 <= 0 && e2Wc2 <= 0) + AddLocalMinPoly(e1, e2, pt); + break; + case ClipType.ctDifference: + if (((e1.PolyTyp == PolyType.ptClip) && (e1Wc2 > 0) && (e2Wc2 > 0)) || + ((e1.PolyTyp == PolyType.ptSubject) && (e1Wc2 <= 0) && (e2Wc2 <= 0))) + AddLocalMinPoly(e1, e2, pt); + break; + case ClipType.ctXor: + AddLocalMinPoly(e1, e2, pt); + break; + } + else + SwapSides(e1, e2); + } + } + //------------------------------------------------------------------------------ + + private void DeleteFromSEL(TEdge e) + { + TEdge SelPrev = e.PrevInSEL; + TEdge SelNext = e.NextInSEL; + if (SelPrev == null && SelNext == null && (e != m_SortedEdges)) + return; //already deleted + if (SelPrev != null) + SelPrev.NextInSEL = SelNext; + else m_SortedEdges = SelNext; + if (SelNext != null) + SelNext.PrevInSEL = SelPrev; + e.NextInSEL = null; + e.PrevInSEL = null; + } + //------------------------------------------------------------------------------ + + private void ProcessHorizontals() + { + TEdge horzEdge; //m_SortedEdges; + while (PopEdgeFromSEL(out horzEdge)) + ProcessHorizontal(horzEdge); + } + //------------------------------------------------------------------------------ + + void GetHorzDirection(TEdge HorzEdge, out Direction Dir, out cInt Left, out cInt Right) + { + if (HorzEdge.Bot.X < HorzEdge.Top.X) + { + Left = HorzEdge.Bot.X; + Right = HorzEdge.Top.X; + Dir = Direction.dLeftToRight; + } else + { + Left = HorzEdge.Top.X; + Right = HorzEdge.Bot.X; + Dir = Direction.dRightToLeft; + } + } + //------------------------------------------------------------------------ + + private void ProcessHorizontal(TEdge horzEdge) + { + Direction dir; + cInt horzLeft, horzRight; + bool IsOpen = horzEdge.WindDelta == 0; + + GetHorzDirection(horzEdge, out dir, out horzLeft, out horzRight); + + TEdge eLastHorz = horzEdge, eMaxPair = null; + while (eLastHorz.NextInLML != null && IsHorizontal(eLastHorz.NextInLML)) + eLastHorz = eLastHorz.NextInLML; + if (eLastHorz.NextInLML == null) + eMaxPair = GetMaximaPair(eLastHorz); + + Maxima currMax = m_Maxima; + if (currMax != null) + { + //get the first maxima in range (X) ... + if (dir == Direction.dLeftToRight) + { + while (currMax != null && currMax.X <= horzEdge.Bot.X) + currMax = currMax.Next; + if (currMax != null && currMax.X >= eLastHorz.Top.X) + currMax = null; + } + else + { + while (currMax.Next != null && currMax.Next.X < horzEdge.Bot.X) + currMax = currMax.Next; + if (currMax.X <= eLastHorz.Top.X) currMax = null; + } + } + + OutPt op1 = null; + for (;;) //loop through consec. horizontal edges + { + bool IsLastHorz = (horzEdge == eLastHorz); + TEdge e = GetNextInAEL(horzEdge, dir); + while(e != null) + { + + //this code block inserts extra coords into horizontal edges (in output + //polygons) whereever maxima touch these horizontal edges. This helps + //'simplifying' polygons (ie if the Simplify property is set). + if (currMax != null) + { + if (dir == Direction.dLeftToRight) + { + while (currMax != null && currMax.X < e.Curr.X) + { + if (horzEdge.OutIdx >= 0 && !IsOpen) + AddOutPt(horzEdge, new IntPoint(currMax.X, horzEdge.Bot.Y)); + currMax = currMax.Next; + } + } + else + { + while (currMax != null && currMax.X > e.Curr.X) + { + if (horzEdge.OutIdx >= 0 && !IsOpen) + AddOutPt(horzEdge, new IntPoint(currMax.X, horzEdge.Bot.Y)); + currMax = currMax.Prev; + } + } + }; + + if ((dir == Direction.dLeftToRight && e.Curr.X > horzRight) || + (dir == Direction.dRightToLeft && e.Curr.X < horzLeft)) break; + + //Also break if we've got to the end of an intermediate horizontal edge ... + //nb: Smaller Dx's are to the right of larger Dx's ABOVE the horizontal. + if (e.Curr.X == horzEdge.Top.X && horzEdge.NextInLML != null && + e.Dx < horzEdge.NextInLML.Dx) break; + + if (horzEdge.OutIdx >= 0 && !IsOpen) //note: may be done multiple times + { +#if use_xyz + if (dir == Direction.dLeftToRight) SetZ(ref e.Curr, horzEdge, e); + else SetZ(ref e.Curr, e, horzEdge); +#endif + + op1 = AddOutPt(horzEdge, e.Curr); + TEdge eNextHorz = m_SortedEdges; + while (eNextHorz != null) + { + if (eNextHorz.OutIdx >= 0 && + HorzSegmentsOverlap(horzEdge.Bot.X, + horzEdge.Top.X, eNextHorz.Bot.X, eNextHorz.Top.X)) + { + OutPt op2 = GetLastOutPt(eNextHorz); + AddJoin(op2, op1, eNextHorz.Top); + } + eNextHorz = eNextHorz.NextInSEL; + } + AddGhostJoin(op1, horzEdge.Bot); + } + + //OK, so far we're still in range of the horizontal Edge but make sure + //we're at the last of consec. horizontals when matching with eMaxPair + if(e == eMaxPair && IsLastHorz) + { + if (horzEdge.OutIdx >= 0) + AddLocalMaxPoly(horzEdge, eMaxPair, horzEdge.Top); + DeleteFromAEL(horzEdge); + DeleteFromAEL(eMaxPair); + return; + } + + if(dir == Direction.dLeftToRight) + { + IntPoint Pt = new IntPoint(e.Curr.X, horzEdge.Curr.Y); + IntersectEdges(horzEdge, e, Pt); + } + else + { + IntPoint Pt = new IntPoint(e.Curr.X, horzEdge.Curr.Y); + IntersectEdges(e, horzEdge, Pt); + } + TEdge eNext = GetNextInAEL(e, dir); + SwapPositionsInAEL(horzEdge, e); + e = eNext; + } //end while(e != null) + + //Break out of loop if HorzEdge.NextInLML is not also horizontal ... + if (horzEdge.NextInLML == null || !IsHorizontal(horzEdge.NextInLML)) break; + + UpdateEdgeIntoAEL(ref horzEdge); + if (horzEdge.OutIdx >= 0) AddOutPt(horzEdge, horzEdge.Bot); + GetHorzDirection(horzEdge, out dir, out horzLeft, out horzRight); + + } //end for (;;) + + if (horzEdge.OutIdx >= 0 && op1 == null) + { + op1 = GetLastOutPt(horzEdge); + TEdge eNextHorz = m_SortedEdges; + while (eNextHorz != null) + { + if (eNextHorz.OutIdx >= 0 && + HorzSegmentsOverlap(horzEdge.Bot.X, + horzEdge.Top.X, eNextHorz.Bot.X, eNextHorz.Top.X)) + { + OutPt op2 = GetLastOutPt(eNextHorz); + AddJoin(op2, op1, eNextHorz.Top); + } + eNextHorz = eNextHorz.NextInSEL; + } + AddGhostJoin(op1, horzEdge.Top); + } + + if (horzEdge.NextInLML != null) + { + if(horzEdge.OutIdx >= 0) + { + op1 = AddOutPt( horzEdge, horzEdge.Top); + + UpdateEdgeIntoAEL(ref horzEdge); + if (horzEdge.WindDelta == 0) return; + //nb: HorzEdge is no longer horizontal here + TEdge ePrev = horzEdge.PrevInAEL; + TEdge eNext = horzEdge.NextInAEL; + if (ePrev != null && ePrev.Curr.X == horzEdge.Bot.X && + ePrev.Curr.Y == horzEdge.Bot.Y && ePrev.WindDelta != 0 && + (ePrev.OutIdx >= 0 && ePrev.Curr.Y > ePrev.Top.Y && + SlopesEqual(horzEdge, ePrev, m_UseFullRange))) + { + OutPt op2 = AddOutPt(ePrev, horzEdge.Bot); + AddJoin(op1, op2, horzEdge.Top); + } + else if (eNext != null && eNext.Curr.X == horzEdge.Bot.X && + eNext.Curr.Y == horzEdge.Bot.Y && eNext.WindDelta != 0 && + eNext.OutIdx >= 0 && eNext.Curr.Y > eNext.Top.Y && + SlopesEqual(horzEdge, eNext, m_UseFullRange)) + { + OutPt op2 = AddOutPt(eNext, horzEdge.Bot); + AddJoin(op1, op2, horzEdge.Top); + } + } + else + UpdateEdgeIntoAEL(ref horzEdge); + } + else + { + if (horzEdge.OutIdx >= 0) AddOutPt(horzEdge, horzEdge.Top); + DeleteFromAEL(horzEdge); + } + } + //------------------------------------------------------------------------------ + + private TEdge GetNextInAEL(TEdge e, Direction Direction) + { + return Direction == Direction.dLeftToRight ? e.NextInAEL: e.PrevInAEL; + } + //------------------------------------------------------------------------------ + + private bool IsMinima(TEdge e) + { + return e != null && (e.Prev.NextInLML != e) && (e.Next.NextInLML != e); + } + //------------------------------------------------------------------------------ + + private bool IsMaxima(TEdge e, double Y) + { + return (e != null && e.Top.Y == Y && e.NextInLML == null); + } + //------------------------------------------------------------------------------ + + private bool IsIntermediate(TEdge e, double Y) + { + return (e.Top.Y == Y && e.NextInLML != null); + } + //------------------------------------------------------------------------------ + + internal TEdge GetMaximaPair(TEdge e) + { + if ((e.Next.Top == e.Top) && e.Next.NextInLML == null) + return e.Next; + else if ((e.Prev.Top == e.Top) && e.Prev.NextInLML == null) + return e.Prev; + else + return null; + } + //------------------------------------------------------------------------------ + + internal TEdge GetMaximaPairEx(TEdge e) + { + //as above but returns null if MaxPair isn't in AEL (unless it's horizontal) + TEdge result = GetMaximaPair(e); + if (result == null || result.OutIdx == Skip || + ((result.NextInAEL == result.PrevInAEL) && !IsHorizontal(result))) return null; + return result; + } + //------------------------------------------------------------------------------ + + private bool ProcessIntersections(cInt topY) + { + if( m_ActiveEdges == null ) return true; + try { + BuildIntersectList(topY); + if ( m_IntersectList.Count == 0) return true; + if (m_IntersectList.Count == 1 || FixupIntersectionOrder()) + ProcessIntersectList(); + else + return false; + } + catch { + m_SortedEdges = null; + m_IntersectList.Clear(); + throw new ClipperException("ProcessIntersections error"); + } + m_SortedEdges = null; + return true; + } + //------------------------------------------------------------------------------ + + private void BuildIntersectList(cInt topY) + { + if ( m_ActiveEdges == null ) return; + + //prepare for sorting ... + TEdge e = m_ActiveEdges; + m_SortedEdges = e; + while( e != null ) + { + e.PrevInSEL = e.PrevInAEL; + e.NextInSEL = e.NextInAEL; + e.Curr.X = TopX( e, topY ); + e = e.NextInAEL; + } + + //bubblesort ... + bool isModified = true; + while( isModified && m_SortedEdges != null ) + { + isModified = false; + e = m_SortedEdges; + while( e.NextInSEL != null ) + { + TEdge eNext = e.NextInSEL; + IntPoint pt; + if (e.Curr.X > eNext.Curr.X) + { + IntersectPoint(e, eNext, out pt); + if (pt.Y < topY) + pt = new IntPoint(TopX(e, topY), topY); + IntersectNode newNode = new IntersectNode(); + newNode.Edge1 = e; + newNode.Edge2 = eNext; + newNode.Pt = pt; + m_IntersectList.Add(newNode); + + SwapPositionsInSEL(e, eNext); + isModified = true; + } + else + e = eNext; + } + if( e.PrevInSEL != null ) e.PrevInSEL.NextInSEL = null; + else break; + } + m_SortedEdges = null; + } + //------------------------------------------------------------------------------ + + private bool EdgesAdjacent(IntersectNode inode) + { + return (inode.Edge1.NextInSEL == inode.Edge2) || + (inode.Edge1.PrevInSEL == inode.Edge2); + } + //------------------------------------------------------------------------------ + + private static int IntersectNodeSort(IntersectNode node1, IntersectNode node2) + { + //the following typecast is safe because the differences in Pt.Y will + //be limited to the height of the scanbeam. + return (int)(node2.Pt.Y - node1.Pt.Y); + } + //------------------------------------------------------------------------------ + + private bool FixupIntersectionOrder() + { + //pre-condition: intersections are sorted bottom-most first. + //Now it's crucial that intersections are made only between adjacent edges, + //so to ensure this the order of intersections may need adjusting ... + m_IntersectList.Sort(m_IntersectNodeComparer); + + CopyAELToSEL(); + int cnt = m_IntersectList.Count; + for (int i = 0; i < cnt; i++) + { + if (!EdgesAdjacent(m_IntersectList[i])) + { + int j = i + 1; + while (j < cnt && !EdgesAdjacent(m_IntersectList[j])) j++; + if (j == cnt) return false; + + IntersectNode tmp = m_IntersectList[i]; + m_IntersectList[i] = m_IntersectList[j]; + m_IntersectList[j] = tmp; + + } + SwapPositionsInSEL(m_IntersectList[i].Edge1, m_IntersectList[i].Edge2); + } + return true; + } + //------------------------------------------------------------------------------ + + private void ProcessIntersectList() + { + for (int i = 0; i < m_IntersectList.Count; i++) + { + IntersectNode iNode = m_IntersectList[i]; + { + IntersectEdges(iNode.Edge1, iNode.Edge2, iNode.Pt); + SwapPositionsInAEL(iNode.Edge1, iNode.Edge2); + } + } + m_IntersectList.Clear(); + } + //------------------------------------------------------------------------------ + + internal static cInt Round(double value) + { + return value < 0 ? (cInt)(value - 0.5) : (cInt)(value + 0.5); + } + //------------------------------------------------------------------------------ + + private static cInt TopX(TEdge edge, cInt currentY) + { + if (currentY == edge.Top.Y) + return edge.Top.X; + return edge.Bot.X + Round(edge.Dx *(currentY - edge.Bot.Y)); + } + //------------------------------------------------------------------------------ + + private void IntersectPoint(TEdge edge1, TEdge edge2, out IntPoint ip) + { + ip = new IntPoint(); + double b1, b2; + //nb: with very large coordinate values, it's possible for SlopesEqual() to + //return false but for the edge.Dx value be equal due to double precision rounding. + if (edge1.Dx == edge2.Dx) + { + ip.Y = edge1.Curr.Y; + ip.X = TopX(edge1, ip.Y); + return; + } + + if (edge1.Delta.X == 0) + { + ip.X = edge1.Bot.X; + if (IsHorizontal(edge2)) + { + ip.Y = edge2.Bot.Y; + } + else + { + b2 = edge2.Bot.Y - (edge2.Bot.X / edge2.Dx); + ip.Y = Round(ip.X / edge2.Dx + b2); + } + } + else if (edge2.Delta.X == 0) + { + ip.X = edge2.Bot.X; + if (IsHorizontal(edge1)) + { + ip.Y = edge1.Bot.Y; + } + else + { + b1 = edge1.Bot.Y - (edge1.Bot.X / edge1.Dx); + ip.Y = Round(ip.X / edge1.Dx + b1); + } + } + else + { + b1 = edge1.Bot.X - edge1.Bot.Y * edge1.Dx; + b2 = edge2.Bot.X - edge2.Bot.Y * edge2.Dx; + double q = (b2 - b1) / (edge1.Dx - edge2.Dx); + ip.Y = Round(q); + if (Math.Abs(edge1.Dx) < Math.Abs(edge2.Dx)) + ip.X = Round(edge1.Dx * q + b1); + else + ip.X = Round(edge2.Dx * q + b2); + } + + if (ip.Y < edge1.Top.Y || ip.Y < edge2.Top.Y) + { + if (edge1.Top.Y > edge2.Top.Y) + ip.Y = edge1.Top.Y; + else + ip.Y = edge2.Top.Y; + if (Math.Abs(edge1.Dx) < Math.Abs(edge2.Dx)) + ip.X = TopX(edge1, ip.Y); + else + ip.X = TopX(edge2, ip.Y); + } + //finally, don't allow 'ip' to be BELOW curr.Y (ie bottom of scanbeam) ... + if (ip.Y > edge1.Curr.Y) + { + ip.Y = edge1.Curr.Y; + //better to use the more vertical edge to derive X ... + if (Math.Abs(edge1.Dx) > Math.Abs(edge2.Dx)) + ip.X = TopX(edge2, ip.Y); + else + ip.X = TopX(edge1, ip.Y); + } + } + //------------------------------------------------------------------------------ + + private void ProcessEdgesAtTopOfScanbeam(cInt topY) + { + TEdge e = m_ActiveEdges; + while(e != null) + { + //1. process maxima, treating them as if they're 'bent' horizontal edges, + // but exclude maxima with horizontal edges. nb: e can't be a horizontal. + bool IsMaximaEdge = IsMaxima(e, topY); + + if(IsMaximaEdge) + { + TEdge eMaxPair = GetMaximaPairEx(e); + IsMaximaEdge = (eMaxPair == null || !IsHorizontal(eMaxPair)); + } + + if(IsMaximaEdge) + { + if (StrictlySimple) InsertMaxima(e.Top.X); + TEdge ePrev = e.PrevInAEL; + DoMaxima(e); + if( ePrev == null) e = m_ActiveEdges; + else e = ePrev.NextInAEL; + } + else + { + //2. promote horizontal edges, otherwise update Curr.X and Curr.Y ... + if (IsIntermediate(e, topY) && IsHorizontal(e.NextInLML)) + { + UpdateEdgeIntoAEL(ref e); + if (e.OutIdx >= 0) + AddOutPt(e, e.Bot); + AddEdgeToSEL(e); + } + else + { + e.Curr.X = TopX( e, topY ); + e.Curr.Y = topY; +#if use_xyz + if (e.Top.Y == topY) e.Curr.Z = e.Top.Z; + else if (e.Bot.Y == topY) e.Curr.Z = e.Bot.Z; + else e.Curr.Z = 0; +#endif + } + //When StrictlySimple and 'e' is being touched by another edge, then + //make sure both edges have a vertex here ... + if (StrictlySimple) + { + TEdge ePrev = e.PrevInAEL; + if ((e.OutIdx >= 0) && (e.WindDelta != 0) && ePrev != null && + (ePrev.OutIdx >= 0) && (ePrev.Curr.X == e.Curr.X) && + (ePrev.WindDelta != 0)) + { + IntPoint ip = new IntPoint(e.Curr); +#if use_xyz + SetZ(ref ip, ePrev, e); +#endif + OutPt op = AddOutPt(ePrev, ip); + OutPt op2 = AddOutPt(e, ip); + AddJoin(op, op2, ip); //StrictlySimple (type-3) join + } + } + + e = e.NextInAEL; + } + } + + //3. Process horizontals at the Top of the scanbeam ... + ProcessHorizontals(); + m_Maxima = null; + + //4. Promote intermediate vertices ... + e = m_ActiveEdges; + while (e != null) + { + if(IsIntermediate(e, topY)) + { + OutPt op = null; + if( e.OutIdx >= 0 ) + op = AddOutPt(e, e.Top); + UpdateEdgeIntoAEL(ref e); + + //if output polygons share an edge, they'll need joining later ... + TEdge ePrev = e.PrevInAEL; + TEdge eNext = e.NextInAEL; + if (ePrev != null && ePrev.Curr.X == e.Bot.X && + ePrev.Curr.Y == e.Bot.Y && op != null && + ePrev.OutIdx >= 0 && ePrev.Curr.Y > ePrev.Top.Y && + SlopesEqual(e.Curr, e.Top, ePrev.Curr, ePrev.Top, m_UseFullRange) && + (e.WindDelta != 0) && (ePrev.WindDelta != 0)) + { + OutPt op2 = AddOutPt(ePrev, e.Bot); + AddJoin(op, op2, e.Top); + } + else if (eNext != null && eNext.Curr.X == e.Bot.X && + eNext.Curr.Y == e.Bot.Y && op != null && + eNext.OutIdx >= 0 && eNext.Curr.Y > eNext.Top.Y && + SlopesEqual(e.Curr, e.Top, eNext.Curr, eNext.Top, m_UseFullRange) && + (e.WindDelta != 0) && (eNext.WindDelta != 0)) + { + OutPt op2 = AddOutPt(eNext, e.Bot); + AddJoin(op, op2, e.Top); + } + } + e = e.NextInAEL; + } + } + //------------------------------------------------------------------------------ + + private void DoMaxima(TEdge e) + { + TEdge eMaxPair = GetMaximaPairEx(e); + if (eMaxPair == null) + { + if (e.OutIdx >= 0) + AddOutPt(e, e.Top); + DeleteFromAEL(e); + return; + } + + TEdge eNext = e.NextInAEL; + while(eNext != null && eNext != eMaxPair) + { + IntersectEdges(e, eNext, e.Top); + SwapPositionsInAEL(e, eNext); + eNext = e.NextInAEL; + } + + if(e.OutIdx == Unassigned && eMaxPair.OutIdx == Unassigned) + { + DeleteFromAEL(e); + DeleteFromAEL(eMaxPair); + } + else if( e.OutIdx >= 0 && eMaxPair.OutIdx >= 0 ) + { + if (e.OutIdx >= 0) AddLocalMaxPoly(e, eMaxPair, e.Top); + DeleteFromAEL(e); + DeleteFromAEL(eMaxPair); + } +#if use_lines + else if (e.WindDelta == 0) + { + if (e.OutIdx >= 0) + { + AddOutPt(e, e.Top); + e.OutIdx = Unassigned; + } + DeleteFromAEL(e); + + if (eMaxPair.OutIdx >= 0) + { + AddOutPt(eMaxPair, e.Top); + eMaxPair.OutIdx = Unassigned; + } + DeleteFromAEL(eMaxPair); + } +#endif + else throw new ClipperException("DoMaxima error"); + } + //------------------------------------------------------------------------------ + + public static void ReversePaths(Paths polys) + { + foreach (var poly in polys) { poly.Reverse(); } + } + //------------------------------------------------------------------------------ + + public static bool Orientation(Path poly) + { + return Area(poly) >= 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; + } + //------------------------------------------------------------------------------ + + private void BuildResult(Paths polyg) + { + polyg.Clear(); + polyg.Capacity = m_PolyOuts.Count; + for (int i = 0; i < m_PolyOuts.Count; i++) + { + OutRec outRec = m_PolyOuts[i]; + if (outRec.Pts == null) continue; + OutPt p = outRec.Pts.Prev; + int cnt = PointCount(p); + if (cnt < 2) continue; + Path pg = new Path(cnt); + for (int j = 0; j < cnt; j++) + { + pg.Add(p.Pt); + p = p.Prev; + } + polyg.Add(pg); + } + } + //------------------------------------------------------------------------------ + + private void BuildResult2(PolyTree polytree) + { + polytree.Clear(); + + //add each output polygon/contour to polytree ... + polytree.m_AllPolys.Capacity = m_PolyOuts.Count; + for (int i = 0; i < m_PolyOuts.Count; i++) + { + OutRec outRec = m_PolyOuts[i]; + int cnt = PointCount(outRec.Pts); + if ((outRec.IsOpen && cnt < 2) || + (!outRec.IsOpen && cnt < 3)) continue; + FixHoleLinkage(outRec); + PolyNode pn = new PolyNode(); + polytree.m_AllPolys.Add(pn); + outRec.PolyNode = pn; + pn.m_polygon.Capacity = cnt; + OutPt op = outRec.Pts.Prev; + for (int j = 0; j < cnt; j++) + { + pn.m_polygon.Add(op.Pt); + op = op.Prev; + } + } + + //fixup PolyNode links etc ... + polytree.m_Childs.Capacity = m_PolyOuts.Count; + for (int i = 0; i < m_PolyOuts.Count; i++) + { + OutRec outRec = m_PolyOuts[i]; + if (outRec.PolyNode == null) continue; + else if (outRec.IsOpen) + { + outRec.PolyNode.IsOpen = true; + polytree.AddChild(outRec.PolyNode); + } + else if (outRec.FirstLeft != null && + outRec.FirstLeft.PolyNode != null) + outRec.FirstLeft.PolyNode.AddChild(outRec.PolyNode); + else + polytree.AddChild(outRec.PolyNode); + } + } + //------------------------------------------------------------------------------ + + private void FixupOutPolyline(OutRec outrec) + { + OutPt pp = outrec.Pts; + OutPt lastPP = pp.Prev; + while (pp != lastPP) + { + pp = pp.Next; + if (pp.Pt == pp.Prev.Pt) + { + if (pp == lastPP) lastPP = pp.Prev; + OutPt tmpPP = pp.Prev; + tmpPP.Next = pp.Next; + pp.Next.Prev = tmpPP; + pp = tmpPP; + } + } + if (pp == pp.Prev) outrec.Pts = null; + } + //------------------------------------------------------------------------------ + + private void FixupOutPolygon(OutRec outRec) + { + //FixupOutPolygon() - removes duplicate points and simplifies consecutive + //parallel edges by removing the middle vertex. + OutPt lastOK = null; + outRec.BottomPt = null; + OutPt pp = outRec.Pts; + bool preserveCol = PreserveCollinear || StrictlySimple; + for (;;) + { + if (pp.Prev == pp || pp.Prev == pp.Next) + { + outRec.Pts = null; + return; + } + //test for duplicate points and collinear edges ... + if ((pp.Pt == pp.Next.Pt) || (pp.Pt == pp.Prev.Pt) || + (SlopesEqual(pp.Prev.Pt, pp.Pt, pp.Next.Pt, m_UseFullRange) && + (!preserveCol || !Pt2IsBetweenPt1AndPt3(pp.Prev.Pt, pp.Pt, pp.Next.Pt)))) + { + lastOK = null; + pp.Prev.Next = pp.Next; + pp.Next.Prev = pp.Prev; + pp = pp.Prev; + } + else if (pp == lastOK) break; + else + { + if (lastOK == null) lastOK = pp; + pp = pp.Next; + } + } + outRec.Pts = pp; + } + //------------------------------------------------------------------------------ + + 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; + } + //------------------------------------------------------------------------------ + + bool GetOverlap(cInt a1, cInt a2, cInt b1, cInt b2, out cInt Left, out cInt Right) + { + if (a1 < a2) + { + if (b1 < b2) {Left = Math.Max(a1,b1); Right = Math.Min(a2,b2);} + else {Left = Math.Max(a1,b2); Right = Math.Min(a2,b1);} + } + else + { + if (b1 < b2) {Left = Math.Max(a2,b1); Right = Math.Min(a1,b2);} + else { Left = Math.Max(a2, b2); Right = Math.Min(a1, b1); } + } + return Left < Right; + } + //------------------------------------------------------------------------------ + + 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; + } + //------------------------------------------------------------------------------ + + private bool JoinPoints(Join j, OutRec outRec1, OutRec outRec2) + { + OutPt op1 = j.OutPt1, op1b; + OutPt op2 = j.OutPt2, op2b; + + //There are 3 kinds of joins for output polygons ... + //1. Horizontal joins where Join.OutPt1 & Join.OutPt2 are 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 ... + if (outRec1 != outRec2) return false; + 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; + j.OutPt1 = op1; + j.OutPt2 = op1b; + return true; + } else + { + op1b = DupOutPt(op1, true); + op2b = DupOutPt(op2, false); + op1.Next = op2; + op2.Prev = op1; + op1b.Prev = op2b; + op2b.Next = op1b; + j.OutPt1 = op1; + j.OutPt2 = 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); + } + j.OutPt1 = op1; + j.OutPt2 = 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; + j.OutPt1 = op1; + j.OutPt2 = op1b; + return true; + } else + { + op1b = DupOutPt(op1, true); + op2b = DupOutPt(op2, false); + op1.Next = op2; + op2.Prev = op1; + op1b.Prev = op2b; + op2b.Next = op1b; + j.OutPt1 = op1; + j.OutPt2 = op1b; + return true; + } + } + } + //---------------------------------------------------------------------- + + public static int PointInPolygon(IntPoint pt, Path path) + { + //returns 0 if false, +1 if true, -1 if pt ON polygon boundary + //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 + int result = 0, cnt = path.Count; + if (cnt < 3) return 0; + IntPoint ip = path[0]; + for (int i = 1; i <= cnt; ++i) + { + IntPoint ipNext = (i == cnt ? path[0] : path[i]); + if (ipNext.Y == pt.Y) + { + if ((ipNext.X == pt.X) || (ip.Y == pt.Y && + ((ipNext.X > pt.X) == (ip.X < pt.X)))) return -1; + } + if ((ip.Y < pt.Y) != (ipNext.Y < pt.Y)) + { + if (ip.X >= pt.X) + { + if (ipNext.X > pt.X) result = 1 - result; + else + { + double d = (double)(ip.X - pt.X) * (ipNext.Y - pt.Y) - + (double)(ipNext.X - pt.X) * (ip.Y - pt.Y); + if (d == 0) return -1; + else if ((d > 0) == (ipNext.Y > ip.Y)) result = 1 - result; + } + } + else + { + if (ipNext.X > pt.X) + { + double d = (double)(ip.X - pt.X) * (ipNext.Y - pt.Y) - + (double)(ipNext.X - pt.X) * (ip.Y - pt.Y); + if (d == 0) return -1; + else if ((d > 0) == (ipNext.Y > ip.Y)) result = 1 - result; + } + } + } + ip = ipNext; + } + return result; + } + //------------------------------------------------------------------------------ + + //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; + cInt ptx = pt.X, pty = pt.Y; + cInt poly0x = op.Pt.X, poly0y = op.Pt.Y; + do + { + op = op.Next; + cInt 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; + } + //------------------------------------------------------------------------------ + + 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; + } + //---------------------------------------------------------------------- + + private void FixupFirstLefts1(OutRec OldOutRec, OutRec NewOutRec) + { + foreach (OutRec outRec in m_PolyOuts) + { + OutRec firstLeft = ParseFirstLeft(outRec.FirstLeft); + if (outRec.Pts != null && firstLeft == OldOutRec) + { + if (Poly2ContainsPoly1(outRec.Pts, NewOutRec.Pts)) + outRec.FirstLeft = NewOutRec; + } + } + } + //---------------------------------------------------------------------- + + private void FixupFirstLefts2(OutRec innerOutRec, OutRec outerOutRec) + { + //A polygon has split into two such that one is now the inner of the other. + //It's possible that these polygons now wrap around other polygons, so check + //every polygon that's also contained by OuterOutRec's FirstLeft container + //(including nil) to see if they've become inner to the new inner polygon ... + OutRec orfl = outerOutRec.FirstLeft; + foreach (OutRec outRec in m_PolyOuts) + { + if (outRec.Pts == null || outRec == outerOutRec || outRec == innerOutRec) + continue; + OutRec firstLeft = ParseFirstLeft(outRec.FirstLeft); + if (firstLeft != orfl && firstLeft != innerOutRec && firstLeft != outerOutRec) + continue; + if (Poly2ContainsPoly1(outRec.Pts, innerOutRec.Pts)) + outRec.FirstLeft = innerOutRec; + else if (Poly2ContainsPoly1(outRec.Pts, outerOutRec.Pts)) + outRec.FirstLeft = outerOutRec; + else if (outRec.FirstLeft == innerOutRec || outRec.FirstLeft == outerOutRec) + outRec.FirstLeft = orfl; + } + } + //---------------------------------------------------------------------- + + private void FixupFirstLefts3(OutRec OldOutRec, OutRec NewOutRec) + { + //same as FixupFirstLefts1 but doesn't call Poly2ContainsPoly1() + foreach (OutRec outRec in m_PolyOuts) + { + OutRec firstLeft = ParseFirstLeft(outRec.FirstLeft); + if (outRec.Pts != null && firstLeft == OldOutRec) + outRec.FirstLeft = NewOutRec; + } + } + //---------------------------------------------------------------------- + + private static OutRec ParseFirstLeft(OutRec FirstLeft) + { + while (FirstLeft != null && FirstLeft.Pts == null) + FirstLeft = FirstLeft.FirstLeft; + return FirstLeft; + } + //------------------------------------------------------------------------------ + + private void JoinCommonEdges() + { + for (int i = 0; i < m_Joins.Count; i++) + { + Join join = m_Joins[i]; + + OutRec outRec1 = GetOutRec(join.OutPt1.Idx); + OutRec outRec2 = GetOutRec(join.OutPt2.Idx); + + if (outRec1.Pts == null || outRec2.Pts == null) continue; + if (outRec1.IsOpen || outRec2.IsOpen) continue; + + //get the polygon fragment with the correct hole state (FirstLeft) + //before calling JoinPoints() ... + OutRec holeStateRec; + if (outRec1 == outRec2) holeStateRec = outRec1; + else if (OutRec1RightOfOutRec2(outRec1, outRec2)) holeStateRec = outRec2; + else if (OutRec1RightOfOutRec2(outRec2, outRec1)) holeStateRec = outRec1; + else holeStateRec = GetLowermostRec(outRec1, outRec2); + + if (!JoinPoints(join, outRec1, outRec2)) continue; + + if (outRec1 == outRec2) + { + //instead of joining two polygons, we've just created a new one by + //splitting one polygon into two. + outRec1.Pts = join.OutPt1; + outRec1.BottomPt = null; + outRec2 = CreateOutRec(); + outRec2.Pts = join.OutPt2; + + //update all OutRec2.Pts Idx's ... + UpdateOutPtIdxs(outRec2); + + if (Poly2ContainsPoly1(outRec2.Pts, outRec1.Pts)) + { + //outRec1 contains outRec2 ... + outRec2.IsHole = !outRec1.IsHole; + outRec2.FirstLeft = outRec1; + + if (m_UsingPolyTree) FixupFirstLefts2(outRec2, outRec1); + + if ((outRec2.IsHole ^ ReverseSolution) == (Area(outRec2) > 0)) + ReversePolyPtLinks(outRec2.Pts); + + } + else if (Poly2ContainsPoly1(outRec1.Pts, outRec2.Pts)) + { + //outRec2 contains outRec1 ... + outRec2.IsHole = outRec1.IsHole; + outRec1.IsHole = !outRec2.IsHole; + outRec2.FirstLeft = outRec1.FirstLeft; + outRec1.FirstLeft = outRec2; + + if (m_UsingPolyTree) FixupFirstLefts2(outRec1, outRec2); + + if ((outRec1.IsHole ^ ReverseSolution) == (Area(outRec1) > 0)) + ReversePolyPtLinks(outRec1.Pts); + } + else + { + //the 2 polygons are completely separate ... + outRec2.IsHole = outRec1.IsHole; + outRec2.FirstLeft = outRec1.FirstLeft; + + //fixup FirstLeft pointers that may need reassigning to OutRec2 + if (m_UsingPolyTree) FixupFirstLefts1(outRec1, outRec2); + } + + } else + { + //joined 2 polygons together ... + + outRec2.Pts = null; + outRec2.BottomPt = null; + outRec2.Idx = outRec1.Idx; + + outRec1.IsHole = holeStateRec.IsHole; + if (holeStateRec == outRec2) + outRec1.FirstLeft = outRec2.FirstLeft; + outRec2.FirstLeft = outRec1; + + //fixup FirstLeft pointers that may need reassigning to OutRec1 + if (m_UsingPolyTree) FixupFirstLefts3(outRec2, outRec1); + } + } + } + //------------------------------------------------------------------------------ + + private void UpdateOutPtIdxs(OutRec outrec) + { + OutPt op = outrec.Pts; + do + { + op.Idx = outrec.Idx; + op = op.Prev; + } + while(op != outrec.Pts); + } + //------------------------------------------------------------------------------ + + private void DoSimplePolygons() + { + int i = 0; + while (i < m_PolyOuts.Count) + { + OutRec outrec = m_PolyOuts[i++]; + OutPt op = outrec.Pts; + if (op == null || outrec.IsOpen) continue; + do //for each Pt in Polygon until duplicate found do ... + { + OutPt op2 = op.Next; + while (op2 != outrec.Pts) + { + if ((op.Pt == op2.Pt) && op2.Next != op && op2.Prev != op) + { + //split the polygon into two ... + OutPt op3 = op.Prev; + OutPt op4 = op2.Prev; + op.Prev = op4; + op4.Next = op; + op2.Prev = op3; + op3.Next = op2; + + outrec.Pts = op; + OutRec outrec2 = CreateOutRec(); + outrec2.Pts = op2; + UpdateOutPtIdxs(outrec2); + if (Poly2ContainsPoly1(outrec2.Pts, outrec.Pts)) + { + //OutRec2 is contained by OutRec1 ... + outrec2.IsHole = !outrec.IsHole; + outrec2.FirstLeft = outrec; + if (m_UsingPolyTree) FixupFirstLefts2(outrec2, outrec); + } + else + if (Poly2ContainsPoly1(outrec.Pts, outrec2.Pts)) + { + //OutRec1 is contained by OutRec2 ... + outrec2.IsHole = outrec.IsHole; + outrec.IsHole = !outrec2.IsHole; + outrec2.FirstLeft = outrec.FirstLeft; + outrec.FirstLeft = outrec2; + if (m_UsingPolyTree) FixupFirstLefts2(outrec, outrec2); + } + else + { + //the 2 polygons are separate ... + outrec2.IsHole = outrec.IsHole; + outrec2.FirstLeft = outrec.FirstLeft; + if (m_UsingPolyTree) FixupFirstLefts1(outrec, outrec2); + } + op2 = op; //ie get ready for the next iteration + } + op2 = op2.Next; + } + op = op.Next; + } + while (op != outrec.Pts); + } + } + //------------------------------------------------------------------------------ + + public static double Area(Path poly) + { + int cnt = (int)poly.Count; + if (cnt < 3) return 0; + double a = 0; + for (int i = 0, j = cnt - 1; i < cnt; ++i) + { + a += ((double)poly[j].X + poly[i].X) * ((double)poly[j].Y - poly[i].Y); + j = i; + } + return -a * 0.5; + } + //------------------------------------------------------------------------------ + + internal double Area(OutRec outRec) + { + return Area(outRec.Pts); + } + //------------------------------------------------------------------------------ + + internal double Area(OutPt op) + { + OutPt opFirst = op; + if (op == null) return 0; + double a = 0; + do { + a = a + (double)(op.Prev.Pt.X + op.Pt.X) * (double)(op.Prev.Pt.Y - op.Pt.Y); + op = op.Next; + } while (op != opFirst); + return a * 0.5; + } + + //------------------------------------------------------------------------------ + // SimplifyPolygon functions ... + // Convert self-intersecting polygons into simple polygons + //------------------------------------------------------------------------------ + + public static Paths SimplifyPolygon(Path poly, + PolyFillType fillType = PolyFillType.pftEvenOdd) + { + Paths result = new Paths(); + Clipper c = new Clipper(); + c.StrictlySimple = true; + c.AddPath(poly, PolyType.ptSubject, true); + c.Execute(ClipType.ctUnion, result, fillType, fillType); + return result; + } + //------------------------------------------------------------------------------ + + public static Paths SimplifyPolygons(Paths polys, + PolyFillType fillType = PolyFillType.pftEvenOdd) + { + Paths result = new Paths(); + Clipper c = new Clipper(); + c.StrictlySimple = true; + c.AddPaths(polys, PolyType.ptSubject, true); + c.Execute(ClipType.ctUnion, result, fillType, fillType); + return result; + } + //------------------------------------------------------------------------------ + + private static double DistanceSqrd(IntPoint pt1, IntPoint pt2) + { + double dx = ((double)pt1.X - pt2.X); + double dy = ((double)pt1.Y - pt2.Y); + return (dx*dx + dy*dy); + } + //------------------------------------------------------------------------------ + + private static double DistanceFromLineSqrd(IntPoint pt, IntPoint ln1, IntPoint ln2) + { + //The equation of a line in general form (Ax + By + C = 0) + //given 2 points (x¹,y¹) & (x²,y²) is ... + //(y¹ - y²)x + (x² - x¹)y + (y² - y¹)x¹ - (x² - x¹)y¹ = 0 + //A = (y¹ - y²); B = (x² - x¹); C = (y² - y¹)x¹ - (x² - x¹)y¹ + //perpendicular distance of point (x³,y³) = (Ax³ + By³ + C)/Sqrt(A² + B²) + //see http://en.wikipedia.org/wiki/Perpendicular_distance + double A = ln1.Y - ln2.Y; + double B = ln2.X - ln1.X; + double C = A * ln1.X + B * ln1.Y; + C = A * pt.X + B * pt.Y - C; + return (C * C) / (A * A + B * B); + } + //--------------------------------------------------------------------------- + + private static bool SlopesNearCollinear(IntPoint pt1, + IntPoint pt2, IntPoint pt3, double distSqrd) + { + //this function is more accurate when the point that's GEOMETRICALLY + //between the other 2 points is the one that's tested for distance. + //nb: with 'spikes', either pt1 or pt3 is geometrically between the other pts + if (Math.Abs(pt1.X - pt2.X) > Math.Abs(pt1.Y - pt2.Y)) + { + if ((pt1.X > pt2.X) == (pt1.X < pt3.X)) + return DistanceFromLineSqrd(pt1, pt2, pt3) < distSqrd; + else if ((pt2.X > pt1.X) == (pt2.X < pt3.X)) + return DistanceFromLineSqrd(pt2, pt1, pt3) < distSqrd; + else + return DistanceFromLineSqrd(pt3, pt1, pt2) < distSqrd; + } + else + { + if ((pt1.Y > pt2.Y) == (pt1.Y < pt3.Y)) + return DistanceFromLineSqrd(pt1, pt2, pt3) < distSqrd; + else if ((pt2.Y > pt1.Y) == (pt2.Y < pt3.Y)) + return DistanceFromLineSqrd(pt2, pt1, pt3) < distSqrd; + else + return DistanceFromLineSqrd(pt3, pt1, pt2) < distSqrd; + } + } + //------------------------------------------------------------------------------ + + private static bool PointsAreClose(IntPoint pt1, IntPoint pt2, double distSqrd) + { + double dx = (double)pt1.X - pt2.X; + double dy = (double)pt1.Y - pt2.Y; + return ((dx * dx) + (dy * dy) <= distSqrd); + } + //------------------------------------------------------------------------------ + + private static OutPt ExcludeOp(OutPt op) + { + OutPt result = op.Prev; + result.Next = op.Next; + op.Next.Prev = result; + result.Idx = 0; + return result; + } + //------------------------------------------------------------------------------ + + public static Path CleanPolygon(Path path, double distance = 1.415) + { + //distance = proximity in units/pixels below which vertices will be stripped. + //Default ~= sqrt(2) so when adjacent vertices or semi-adjacent vertices have + //both x & y coords within 1 unit, then the second vertex will be stripped. + + int cnt = path.Count; + + if (cnt == 0) return new Path(); + + OutPt [] outPts = new OutPt[cnt]; + for (int i = 0; i < cnt; ++i) outPts[i] = new OutPt(); + + for (int i = 0; i < cnt; ++i) + { + outPts[i].Pt = path[i]; + outPts[i].Next = outPts[(i + 1) % cnt]; + outPts[i].Next.Prev = outPts[i]; + outPts[i].Idx = 0; + } + + double distSqrd = distance * distance; + OutPt op = outPts[0]; + while (op.Idx == 0 && op.Next != op.Prev) + { + if (PointsAreClose(op.Pt, op.Prev.Pt, distSqrd)) + { + op = ExcludeOp(op); + cnt--; + } + else if (PointsAreClose(op.Prev.Pt, op.Next.Pt, distSqrd)) + { + ExcludeOp(op.Next); + op = ExcludeOp(op); + cnt -= 2; + } + else if (SlopesNearCollinear(op.Prev.Pt, op.Pt, op.Next.Pt, distSqrd)) + { + op = ExcludeOp(op); + cnt--; + } + else + { + op.Idx = 1; + op = op.Next; + } + } + + if (cnt < 3) cnt = 0; + Path result = new Path(cnt); + for (int i = 0; i < cnt; ++i) + { + result.Add(op.Pt); + op = op.Next; + } + outPts = null; + return result; + } + //------------------------------------------------------------------------------ + + public static Paths CleanPolygons(Paths polys, + double distance = 1.415) + { + Paths result = new Paths(polys.Count); + for (int i = 0; i < polys.Count; i++) + result.Add(CleanPolygon(polys[i], distance)); + return result; + } + //------------------------------------------------------------------------------ + + internal static Paths Minkowski(Path pattern, Path path, bool IsSum, bool IsClosed) + { + int delta = (IsClosed ? 1 : 0); + int polyCnt = pattern.Count; + int pathCnt = path.Count; + Paths result = new Paths(pathCnt); + if (IsSum) + for (int i = 0; i < pathCnt; i++) + { + Path p = new Path(polyCnt); + foreach (IntPoint ip in pattern) + p.Add(new IntPoint(path[i].X + ip.X, path[i].Y + ip.Y)); + result.Add(p); + } + else + for (int i = 0; i < pathCnt; i++) + { + Path p = new Path(polyCnt); + foreach (IntPoint ip in pattern) + p.Add(new IntPoint(path[i].X - ip.X, path[i].Y - ip.Y)); + result.Add(p); + } + + Paths quads = new Paths((pathCnt + delta) * (polyCnt + 1)); + for (int i = 0; i < pathCnt - 1 + delta; i++) + for (int j = 0; j < polyCnt; j++) + { + Path quad = new Path(4); + quad.Add(result[i % pathCnt][j % polyCnt]); + quad.Add(result[(i + 1) % pathCnt][j % polyCnt]); + quad.Add(result[(i + 1) % pathCnt][(j + 1) % polyCnt]); + quad.Add(result[i % pathCnt][(j + 1) % polyCnt]); + if (!Orientation(quad)) quad.Reverse(); + quads.Add(quad); + } + return quads; + } + //------------------------------------------------------------------------------ + + public static Paths MinkowskiSum(Path pattern, Path path, bool pathIsClosed) + { + Paths paths = Minkowski(pattern, path, true, pathIsClosed); + Clipper c = new Clipper(); + c.AddPaths(paths, PolyType.ptSubject, true); + c.Execute(ClipType.ctUnion, paths, PolyFillType.pftNonZero, PolyFillType.pftNonZero); + return paths; + } + //------------------------------------------------------------------------------ + + private static Path TranslatePath(Path path, IntPoint delta) + { + Path outPath = new Path(path.Count); + for (int i = 0; i < path.Count; i++) + outPath.Add(new IntPoint(path[i].X + delta.X, path[i].Y + delta.Y)); + return outPath; + } + //------------------------------------------------------------------------------ + + public static Paths MinkowskiSum(Path pattern, Paths paths, bool pathIsClosed) + { + Paths solution = new Paths(); + Clipper c = new Clipper(); + for (int i = 0; i < paths.Count; ++i) + { + Paths tmp = Minkowski(pattern, paths[i], true, pathIsClosed); + c.AddPaths(tmp, PolyType.ptSubject, true); + if (pathIsClosed) + { + Path path = TranslatePath(paths[i], pattern[0]); + c.AddPath(path, PolyType.ptClip, true); + } + } + c.Execute(ClipType.ctUnion, solution, + PolyFillType.pftNonZero, PolyFillType.pftNonZero); + return solution; + } + //------------------------------------------------------------------------------ + + public static Paths MinkowskiDiff(Path poly1, Path poly2) + { + Paths paths = Minkowski(poly1, poly2, false, true); + Clipper c = new Clipper(); + c.AddPaths(paths, PolyType.ptSubject, true); + c.Execute(ClipType.ctUnion, paths, PolyFillType.pftNonZero, PolyFillType.pftNonZero); + return paths; + } + //------------------------------------------------------------------------------ + + internal enum NodeType { ntAny, ntOpen, ntClosed }; + + public static Paths PolyTreeToPaths(PolyTree polytree) + { + + Paths result = new Paths(); + result.Capacity = polytree.Total; + AddPolyNodeToPaths(polytree, NodeType.ntAny, result); + return result; + } + //------------------------------------------------------------------------------ + + internal static void AddPolyNodeToPaths(PolyNode polynode, NodeType nt, Paths paths) + { + bool match = true; + switch (nt) + { + case NodeType.ntOpen: return; + case NodeType.ntClosed: match = !polynode.IsOpen; break; + default: break; + } + + if (polynode.m_polygon.Count > 0 && match) + paths.Add(polynode.m_polygon); + foreach (PolyNode pn in polynode.Childs) + AddPolyNodeToPaths(pn, nt, paths); + } + //------------------------------------------------------------------------------ + + public static Paths OpenPathsFromPolyTree(PolyTree polytree) + { + Paths result = new Paths(); + result.Capacity = polytree.ChildCount; + for (int i = 0; i < polytree.ChildCount; i++) + if (polytree.Childs[i].IsOpen) + result.Add(polytree.Childs[i].m_polygon); + return result; + } + //------------------------------------------------------------------------------ + + public static Paths ClosedPathsFromPolyTree(PolyTree polytree) + { + Paths result = new Paths(); + result.Capacity = polytree.Total; + AddPolyNodeToPaths(polytree, NodeType.ntClosed, result); + return result; + } + //------------------------------------------------------------------------------ + + } //end Clipper + + public class ClipperOffset + { + private Paths m_destPolys; + private Path m_srcPoly; + private Path m_destPoly; + private List m_normals = new List(); + private double m_delta, m_sinA, m_sin, m_cos; + private double m_miterLim, m_StepsPerRad; + + private IntPoint m_lowest; + private PolyNode m_polyNodes = new PolyNode(); + + public double ArcTolerance { get; set; } + public double MiterLimit { get; set; } + + private const double two_pi = Math.PI * 2; + private const double def_arc_tolerance = 0.25; + + public ClipperOffset( + double miterLimit = 2.0, double arcTolerance = def_arc_tolerance) + { + MiterLimit = miterLimit; + ArcTolerance = arcTolerance; + m_lowest.X = -1; + } + //------------------------------------------------------------------------------ + + public void Clear() + { + m_polyNodes.Childs.Clear(); + m_lowest.X = -1; + } + //------------------------------------------------------------------------------ + + internal static cInt Round(double value) + { + return value < 0 ? (cInt)(value - 0.5) : (cInt)(value + 0.5); + } + //------------------------------------------------------------------------------ + + public void AddPath(Path path, JoinType joinType, EndType endType) + { + int highI = path.Count - 1; + if (highI < 0) return; + PolyNode newNode = new PolyNode(); + newNode.m_jointype = joinType; + newNode.m_endtype = endType; + + //strip duplicate points from path and also get index to the lowest point ... + if (endType == EndType.etClosedLine || endType == EndType.etClosedPolygon) + while (highI > 0 && path[0] == path[highI]) highI--; + newNode.m_polygon.Capacity = highI + 1; + newNode.m_polygon.Add(path[0]); + int j = 0, k = 0; + for (int i = 1; i <= highI; i++) + if (newNode.m_polygon[j] != path[i]) + { + j++; + newNode.m_polygon.Add(path[i]); + if (path[i].Y > newNode.m_polygon[k].Y || + (path[i].Y == newNode.m_polygon[k].Y && + path[i].X < newNode.m_polygon[k].X)) k = j; + } + if (endType == EndType.etClosedPolygon && j < 2) return; + + m_polyNodes.AddChild(newNode); + + //if this path's lowest pt is lower than all the others then update m_lowest + if (endType != EndType.etClosedPolygon) return; + if (m_lowest.X < 0) + m_lowest = new IntPoint(m_polyNodes.ChildCount - 1, k); + else + { + IntPoint ip = m_polyNodes.Childs[(int)m_lowest.X].m_polygon[(int)m_lowest.Y]; + if (newNode.m_polygon[k].Y > ip.Y || + (newNode.m_polygon[k].Y == ip.Y && + newNode.m_polygon[k].X < ip.X)) + m_lowest = new IntPoint(m_polyNodes.ChildCount - 1, k); + } + } + //------------------------------------------------------------------------------ + + public void AddPaths(Paths paths, JoinType joinType, EndType endType) + { + foreach (Path p in paths) + AddPath(p, joinType, endType); + } + //------------------------------------------------------------------------------ + + private void FixOrientations() + { + //fixup orientations of all closed paths if the orientation of the + //closed path with the lowermost vertex is wrong ... + if (m_lowest.X >= 0 && + !Clipper.Orientation(m_polyNodes.Childs[(int)m_lowest.X].m_polygon)) + { + for (int i = 0; i < m_polyNodes.ChildCount; i++) + { + PolyNode node = m_polyNodes.Childs[i]; + if (node.m_endtype == EndType.etClosedPolygon || + (node.m_endtype == EndType.etClosedLine && + Clipper.Orientation(node.m_polygon))) + node.m_polygon.Reverse(); + } + } + else + { + for (int i = 0; i < m_polyNodes.ChildCount; i++) + { + PolyNode node = m_polyNodes.Childs[i]; + if (node.m_endtype == EndType.etClosedLine && + !Clipper.Orientation(node.m_polygon)) + node.m_polygon.Reverse(); + } + } + } + //------------------------------------------------------------------------------ + + 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); + } + //------------------------------------------------------------------------------ + + private void DoOffset(double delta) + { + m_destPolys = new Paths(); + m_delta = delta; + + //if Zero offset, just copy any CLOSED polygons to m_p and return ... + if (ClipperBase.near_zero(delta)) + { + m_destPolys.Capacity = m_polyNodes.ChildCount; + for (int i = 0; i < m_polyNodes.ChildCount; i++) + { + PolyNode node = m_polyNodes.Childs[i]; + if (node.m_endtype == EndType.etClosedPolygon) + m_destPolys.Add(node.m_polygon); + } + return; + } + + //see offset_triginometry3.svg in the documentation folder ... + if (MiterLimit > 2) m_miterLim = 2 / (MiterLimit * MiterLimit); + else m_miterLim = 0.5; + + double y; + if (ArcTolerance <= 0.0) + y = def_arc_tolerance; + else if (ArcTolerance > Math.Abs(delta) * def_arc_tolerance) + y = Math.Abs(delta) * def_arc_tolerance; + else + y = ArcTolerance; + //see offset_triginometry2.svg in the documentation folder ... + double steps = Math.PI / Math.Acos(1 - y / Math.Abs(delta)); + m_sin = Math.Sin(two_pi / steps); + m_cos = Math.Cos(two_pi / steps); + m_StepsPerRad = steps / two_pi; + if (delta < 0.0) m_sin = -m_sin; + + m_destPolys.Capacity = m_polyNodes.ChildCount * 2; + for (int i = 0; i < m_polyNodes.ChildCount; i++) + { + PolyNode node = m_polyNodes.Childs[i]; + m_srcPoly = node.m_polygon; + + int len = m_srcPoly.Count; + + if (len == 0 || (delta <= 0 && (len < 3 || + node.m_endtype != EndType.etClosedPolygon))) + continue; + + m_destPoly = new Path(); + + if (len == 1) + { + if (node.m_jointype == JoinType.jtRound) + { + double X = 1.0, Y = 0.0; + for (int j = 1; j <= steps; j++) + { + m_destPoly.Add(new IntPoint( + Round(m_srcPoly[0].X + X * delta), + Round(m_srcPoly[0].Y + Y * delta))); + double X2 = X; + X = X * m_cos - m_sin * Y; + Y = X2 * m_sin + Y * m_cos; + } + } + else + { + double X = -1.0, Y = -1.0; + for (int j = 0; j < 4; ++j) + { + m_destPoly.Add(new IntPoint( + Round(m_srcPoly[0].X + X * delta), + Round(m_srcPoly[0].Y + Y * delta))); + if (X < 0) X = 1; + else if (Y < 0) Y = 1; + else X = -1; + } + } + m_destPolys.Add(m_destPoly); + continue; + } + + //build m_normals ... + m_normals.Clear(); + m_normals.Capacity = len; + for (int j = 0; j < len - 1; j++) + m_normals.Add(GetUnitNormal(m_srcPoly[j], m_srcPoly[j + 1])); + if (node.m_endtype == EndType.etClosedLine || + node.m_endtype == EndType.etClosedPolygon) + m_normals.Add(GetUnitNormal(m_srcPoly[len - 1], m_srcPoly[0])); + else + m_normals.Add(new DoublePoint(m_normals[len - 2])); + + if (node.m_endtype == EndType.etClosedPolygon) + { + int k = len - 1; + for (int j = 0; j < len; j++) + OffsetPoint(j, ref k, node.m_jointype); + m_destPolys.Add(m_destPoly); + } + else if (node.m_endtype == EndType.etClosedLine) + { + int k = len - 1; + for (int j = 0; j < len; j++) + OffsetPoint(j, ref k, node.m_jointype); + m_destPolys.Add(m_destPoly); + m_destPoly = new Path(); + //re-build m_normals ... + DoublePoint n = m_normals[len - 1]; + for (int j = len - 1; j > 0; j--) + m_normals[j] = new DoublePoint(-m_normals[j - 1].X, -m_normals[j - 1].Y); + m_normals[0] = new DoublePoint(-n.X, -n.Y); + k = 0; + for (int j = len - 1; j >= 0; j--) + OffsetPoint(j, ref k, node.m_jointype); + m_destPolys.Add(m_destPoly); + } + else + { + int k = 0; + for (int j = 1; j < len - 1; ++j) + OffsetPoint(j, ref k, node.m_jointype); + + IntPoint pt1; + if (node.m_endtype == EndType.etOpenButt) + { + int j = len - 1; + pt1 = new IntPoint((cInt)Round(m_srcPoly[j].X + m_normals[j].X * + delta), (cInt)Round(m_srcPoly[j].Y + m_normals[j].Y * delta)); + m_destPoly.Add(pt1); + pt1 = new IntPoint((cInt)Round(m_srcPoly[j].X - m_normals[j].X * + delta), (cInt)Round(m_srcPoly[j].Y - m_normals[j].Y * delta)); + m_destPoly.Add(pt1); + } + else + { + int j = len - 1; + k = len - 2; + m_sinA = 0; + m_normals[j] = new DoublePoint(-m_normals[j].X, -m_normals[j].Y); + if (node.m_endtype == EndType.etOpenSquare) + DoSquare(j, k); + else + DoRound(j, k); + } + + //re-build m_normals ... + for (int j = len - 1; j > 0; j--) + m_normals[j] = new DoublePoint(-m_normals[j - 1].X, -m_normals[j - 1].Y); + + m_normals[0] = new DoublePoint(-m_normals[1].X, -m_normals[1].Y); + + k = len - 1; + for (int j = k - 1; j > 0; --j) + OffsetPoint(j, ref k, node.m_jointype); + + if (node.m_endtype == EndType.etOpenButt) + { + pt1 = new IntPoint((cInt)Round(m_srcPoly[0].X - m_normals[0].X * delta), + (cInt)Round(m_srcPoly[0].Y - m_normals[0].Y * delta)); + m_destPoly.Add(pt1); + pt1 = new IntPoint((cInt)Round(m_srcPoly[0].X + m_normals[0].X * delta), + (cInt)Round(m_srcPoly[0].Y + m_normals[0].Y * delta)); + m_destPoly.Add(pt1); + } + else + { + k = 1; + m_sinA = 0; + if (node.m_endtype == EndType.etOpenSquare) + DoSquare(0, 1); + else + DoRound(0, 1); + } + m_destPolys.Add(m_destPoly); + } + } + } + //------------------------------------------------------------------------------ + + public void Execute(ref Paths solution, double delta) + { + solution.Clear(); + FixOrientations(); + DoOffset(delta); + //now clean up 'corners' ... + Clipper clpr = new Clipper(); + clpr.AddPaths(m_destPolys, PolyType.ptSubject, true); + if (delta > 0) + { + clpr.Execute(ClipType.ctUnion, solution, + PolyFillType.pftPositive, PolyFillType.pftPositive); + } + else + { + IntRect r = Clipper.GetBounds(m_destPolys); + Path outer = new Path(4); + + outer.Add(new IntPoint(r.left - 10, r.bottom + 10)); + outer.Add(new IntPoint(r.right + 10, r.bottom + 10)); + outer.Add(new IntPoint(r.right + 10, r.top - 10)); + outer.Add(new IntPoint(r.left - 10, r.top - 10)); + + clpr.AddPath(outer, PolyType.ptSubject, true); + clpr.ReverseSolution = true; + clpr.Execute(ClipType.ctUnion, solution, PolyFillType.pftNegative, PolyFillType.pftNegative); + if (solution.Count > 0) solution.RemoveAt(0); + } + } + //------------------------------------------------------------------------------ + + public void Execute(ref PolyTree solution, double delta) + { + solution.Clear(); + FixOrientations(); + DoOffset(delta); + + //now clean up 'corners' ... + Clipper clpr = new Clipper(); + clpr.AddPaths(m_destPolys, PolyType.ptSubject, true); + if (delta > 0) + { + clpr.Execute(ClipType.ctUnion, solution, + PolyFillType.pftPositive, PolyFillType.pftPositive); + } + else + { + IntRect r = Clipper.GetBounds(m_destPolys); + Path outer = new Path(4); + + outer.Add(new IntPoint(r.left - 10, r.bottom + 10)); + outer.Add(new IntPoint(r.right + 10, r.bottom + 10)); + outer.Add(new IntPoint(r.right + 10, r.top - 10)); + outer.Add(new IntPoint(r.left - 10, r.top - 10)); + + clpr.AddPath(outer, PolyType.ptSubject, true); + clpr.ReverseSolution = true; + clpr.Execute(ClipType.ctUnion, solution, PolyFillType.pftNegative, PolyFillType.pftNegative); + //remove the outer PolyNode rectangle ... + if (solution.ChildCount == 1 && solution.Childs[0].ChildCount > 0) + { + PolyNode outerNode = solution.Childs[0]; + solution.Childs.Capacity = outerNode.ChildCount; + solution.Childs[0] = outerNode.Childs[0]; + solution.Childs[0].m_Parent = solution; + for (int i = 1; i < outerNode.ChildCount; i++) + solution.AddChild(outerNode.Childs[i]); + } + else + solution.Clear(); + } + } + //------------------------------------------------------------------------------ + + void OffsetPoint(int j, ref int k, JoinType jointype) + { + //cross product ... + m_sinA = (m_normals[k].X * m_normals[j].Y - m_normals[j].X * m_normals[k].Y); + + if (Math.Abs(m_sinA * m_delta) < 1.0) + { + //dot product ... + double cosA = (m_normals[k].X * m_normals[j].X + m_normals[j].Y * m_normals[k].Y); + if (cosA > 0) // angle ==> 0 degrees + { + m_destPoly.Add(new IntPoint(Round(m_srcPoly[j].X + m_normals[k].X * m_delta), + Round(m_srcPoly[j].Y + m_normals[k].Y * m_delta))); + return; + } + //else angle ==> 180 degrees + } + else if (m_sinA > 1.0) m_sinA = 1.0; + else if (m_sinA < -1.0) m_sinA = -1.0; + + if (m_sinA * m_delta < 0) + { + m_destPoly.Add(new IntPoint(Round(m_srcPoly[j].X + m_normals[k].X * m_delta), + Round(m_srcPoly[j].Y + m_normals[k].Y * m_delta))); + m_destPoly.Add(m_srcPoly[j]); + m_destPoly.Add(new IntPoint(Round(m_srcPoly[j].X + m_normals[j].X * m_delta), + Round(m_srcPoly[j].Y + m_normals[j].Y * m_delta))); + } + else + switch (jointype) + { + case JoinType.jtMiter: + { + double r = 1 + (m_normals[j].X * m_normals[k].X + + m_normals[j].Y * m_normals[k].Y); + if (r >= m_miterLim) DoMiter(j, k, r); else DoSquare(j, k); + break; + } + case JoinType.jtSquare: DoSquare(j, k); break; + case JoinType.jtRound: DoRound(j, k); break; + } + k = j; + } + //------------------------------------------------------------------------------ + + internal void DoSquare(int j, int k) + { + double dx = Math.Tan(Math.Atan2(m_sinA, + m_normals[k].X * m_normals[j].X + m_normals[k].Y * m_normals[j].Y) / 4); + m_destPoly.Add(new IntPoint( + Round(m_srcPoly[j].X + m_delta * (m_normals[k].X - m_normals[k].Y * dx)), + Round(m_srcPoly[j].Y + m_delta * (m_normals[k].Y + m_normals[k].X * dx)))); + m_destPoly.Add(new IntPoint( + Round(m_srcPoly[j].X + m_delta * (m_normals[j].X + m_normals[j].Y * dx)), + Round(m_srcPoly[j].Y + m_delta * (m_normals[j].Y - m_normals[j].X * dx)))); + } + //------------------------------------------------------------------------------ + + internal void DoMiter(int j, int k, double r) + { + double q = m_delta / r; + m_destPoly.Add(new IntPoint(Round(m_srcPoly[j].X + (m_normals[k].X + m_normals[j].X) * q), + Round(m_srcPoly[j].Y + (m_normals[k].Y + m_normals[j].Y) * q))); + } + //------------------------------------------------------------------------------ + + internal void DoRound(int j, int k) + { + double a = Math.Atan2(m_sinA, + m_normals[k].X * m_normals[j].X + m_normals[k].Y * m_normals[j].Y); + int steps = Math.Max((int)Round(m_StepsPerRad * Math.Abs(a)),1); + + double X = m_normals[k].X, Y = m_normals[k].Y, X2; + for (int i = 0; i < steps; ++i) + { + m_destPoly.Add(new IntPoint( + Round(m_srcPoly[j].X + X * m_delta), + Round(m_srcPoly[j].Y + Y * m_delta))); + X2 = X; + X = X * m_cos - m_sin * Y; + Y = X2 * m_sin + Y * m_cos; + } + m_destPoly.Add(new IntPoint( + Round(m_srcPoly[j].X + m_normals[j].X * m_delta), + Round(m_srcPoly[j].Y + m_normals[j].Y * m_delta))); + } + //------------------------------------------------------------------------------ + } + + class ClipperException : Exception + { + public ClipperException(string description) : base(description){} + } + //------------------------------------------------------------------------------ + +} //end ClipperLib namespace diff --git a/PCUT/DeepNestLib.Core/D3.cs b/PCUT/DeepNestLib.Core/D3.cs new file mode 100644 index 0000000..ea3dae9 --- /dev/null +++ b/PCUT/DeepNestLib.Core/D3.cs @@ -0,0 +1,93 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace DeepNestLib +{ + public class D3 + { + + // Returns the 2D cross product of AB and AC vectors, i.e., the z-component of + // the 3D cross product in a quadrant I Cartesian coordinate system (+x is + // right, +y is up). Returns a positive value if ABC is counter-clockwise, + // negative if clockwise, and zero if the points are collinear. + public static double cross(double[] a, double[] b, double[] c) + { + return (b[0] - a[0]) * (c[1] - a[1]) - (b[1] - a[1]) * (c[0] - a[0]); + } + // Computes the upper convex hull per the monotone chain algorithm. + // Assumes points.length >= 3, is sorted by x, unique in y. + // Returns an array of indices into points in left-to-right order. + public static int[] computeUpperHullIndexes(double[][] points) + { + Dictionary indexes = new Dictionary(); + indexes.Add(0, 0); + indexes.Add(1, 1); + var n = points.Count(); + var size = 2; + + for (var i = 2; i < n; ++i) + { + while (size > 1 && cross(points[indexes[size - 2]], points[indexes[size - 1]], points[i]) <= 0) --size; + + if (!indexes.ContainsKey(size)) + { + indexes.Add(size, -1); + } + indexes[size++] = i; + } + List ret = new List(); + for (int i = 0; i < size; i++) + { + ret.Add(indexes[i]); + } + return ret.ToArray(); + //return indexes.slice(0, size); // remove popped points + } + + public class HullInfoPoint + { + public double x; + public double y; + public int index; + } + public static double[][] polygonHull(double[][] points) + { + int n; + n = points.Count(); + if ((n) < 3) return null; + + + + HullInfoPoint[] sortedPoints = new HullInfoPoint[n]; + double[][] flippedPoints = new double[n][]; + + + + for (int i = 0; i < n; ++i) sortedPoints[i] = new HullInfoPoint { x = points[i][0], y = points[i][1], index = i }; + sortedPoints = sortedPoints.OrderBy(x => x.x).ThenBy(z => z.y).ToArray(); + + for (int i = 0; i < n; ++i) flippedPoints[i] = new double[] { sortedPoints[i].x, -sortedPoints[i].y }; + + var upperIndexes = computeUpperHullIndexes(sortedPoints.Select(z => new double[] { z.x, z.y, z.index }).ToArray()); + var lowerIndexes = computeUpperHullIndexes(flippedPoints); + + + // Construct the hull polygon, removing possible duplicate endpoints. + var skipLeft = lowerIndexes[0] == upperIndexes[0]; + var skipRight = lowerIndexes[lowerIndexes.Length - 1] == upperIndexes[upperIndexes.Length - 1]; + List hull = new List(); + + // Add upper hull in right-to-l order. + // Then add lower hull in left-to-right order. + for (int i = upperIndexes.Length - 1; i >= 0; --i) + hull.Add(points[sortedPoints[upperIndexes[i]].index]); + //for (int i = +skipLeft; i < lowerIndexes.Length - skipRight; ++i) hull.push(points[sortedPoints[lowerIndexes[i]][2]]); + for (int i = skipLeft ? 1 : 0; i < lowerIndexes.Length - (skipRight ? 1 : 0); ++i) hull.Add(points[sortedPoints[lowerIndexes[i]].index]); + + return hull.ToArray(); + } + + } +} diff --git a/PCUT/DeepNestLib.Core/DeepNestLib.Core.csproj b/PCUT/DeepNestLib.Core/DeepNestLib.Core.csproj new file mode 100644 index 0000000..ca16c9e --- /dev/null +++ b/PCUT/DeepNestLib.Core/DeepNestLib.Core.csproj @@ -0,0 +1,15 @@ + + + + netstandard2.0 + + + + + + + + + + + diff --git a/PCUT/DeepNestLib.Core/Extensions.cs b/PCUT/DeepNestLib.Core/Extensions.cs new file mode 100644 index 0000000..26b0085 --- /dev/null +++ b/PCUT/DeepNestLib.Core/Extensions.cs @@ -0,0 +1,42 @@ +using System; +using System.Collections.Generic; + +namespace DeepNestLib +{ + public static class Extensions + { + public static T[] splice(this T[] p, int a, int b) + { + List ret = new List(); + for (int i = 0; i < p.Length; i++) + { + if (i >= a && i < (a + b)) continue; + ret.Add(p[i]); + } + return ret.ToArray(); + } + + public static List> splice(this List> p, int a, int b) + { + List> ret = new List>(); + for (int i = a; i < (a + b); i++) + { + if (i >= a && i < (a + b)) continue; + ret.Add(p[i]); + } + return ret; + } + + public static NFP[] splice(this NFP[] p, int a, int b) + { + List ret = new List(); + for (int i = 0; i < p.Length; i++) + { + if (i >= a && i < (a + b)) continue; + ret.Add(p[i]); + } + + return ret.ToArray(); + } + } +} diff --git a/PCUT/DeepNestLib.Core/GeneticAlgorithm.cs b/PCUT/DeepNestLib.Core/GeneticAlgorithm.cs new file mode 100644 index 0000000..016fc1a --- /dev/null +++ b/PCUT/DeepNestLib.Core/GeneticAlgorithm.cs @@ -0,0 +1,202 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace DeepNestLib +{ + public class GeneticAlgorithm + { + SvgNestConfig Config; + public List population; + + public static bool StrictAngles = false; + float[] defaultAngles = new float[] { + 0, + 0, + 90, + 0, + 0, + 270, + 180, + 180, + 180, + 90 + }; + + public GeneticAlgorithm(NFP[] adam, SvgNestConfig config) + { + List ang2 = new List(); + for (int i = 0; i < adam.Length; i++) + { + ang2.Add((i * 90) % 360); + } + defaultAngles = ang2.ToArray(); + Config = config; + + + List angles = new List(); + for (int i = 0; i < adam.Length; i++) + { + if (StrictAngles) + { + angles.Add(defaultAngles[i]); + } + else + { + var angle = (float)Math.Floor(r.NextDouble() * Config.rotations) * (360f / Config.rotations); + angles.Add(angle); + } + + //angles.Add(randomAngle(adam[i])); + } + + + population = new List(); + population.Add(new PopulationItem() { placements = adam.ToList(), Rotation = angles.ToArray() }); + while (population.Count() < config.populationSize) + { + var mutant = this.mutate(population[0]); + population.Add(mutant); + } + } + + public PopulationItem mutate(PopulationItem p) + { + var clone = new PopulationItem(); + + clone.placements = p.placements.ToArray().ToList(); + clone.Rotation = p.Rotation.Clone() as float[]; + for (int i = 0; i < clone.placements.Count(); i++) + { + var rand = r.NextDouble(); + if (rand < 0.01 * Config.mutationRate) + { + var j = i + 1; + if (j < clone.placements.Count) + { + var temp = clone.placements[i]; + clone.placements[i] = clone.placements[j]; + clone.placements[j] = temp; + } + } + rand = r.NextDouble(); + if (rand < 0.01 * Config.mutationRate) + { + clone.Rotation[i] = (float)Math.Floor(r.NextDouble() * Config.rotations) * (360f / Config.rotations); + } + } + + + return clone; + } + Random r = new Random(); + public float[] shuffleArray(float[] array) + { + for (var i = array.Length - 1; i > 0; i--) + { + var j = (int)Math.Floor(r.NextDouble() * (i + 1)); + var temp = array[i]; + array[i] = array[j]; + array[j] = temp; + } + return array; + } + + + // returns a random individual from the population, weighted to the front of the list (lower fitness value is more likely to be selected) + public PopulationItem randomWeightedIndividual(PopulationItem exclude = null) + { + //var pop = this.population.slice(0); + var pop = this.population.ToArray(); + + if (exclude != null && Array.IndexOf(pop, exclude) >= 0) + { + pop.splice(Array.IndexOf(pop, exclude), 1); + } + + var rand = r.NextDouble(); + + float lower = 0; + var weight = 1 / (float)pop.Length; + float upper = weight; + + for (var i = 0; i < pop.Length; i++) + { + // if the random number falls between lower and upper bounds, select this individual + if (rand > lower && rand < upper) + { + return pop[i]; + } + lower = upper; + upper += 2 * weight * ((pop.Length - i) / (float)pop.Length); + } + + return pop[0]; + } + + // single point crossover + public PopulationItem[] mate(PopulationItem male, PopulationItem female) + { + var cutpoint = (int)Math.Round(Math.Min(Math.Max(r.NextDouble(), 0.1), 0.9) * (male.placements.Count - 1)); + + var gene1 = new List(male.placements.Take(cutpoint).ToArray()); + var rot1 = new List(male.Rotation.Take(cutpoint).ToArray()); + + var gene2 = new List(female.placements.Take(cutpoint).ToArray()); + var rot2 = new List(female.Rotation.Take(cutpoint).ToArray()); + + int i = 0; + + for (i = 0; i < female.placements.Count; i++) + { + if (!gene1.Any(z => z.id == female.placements[i].id)) + { + gene1.Add(female.placements[i]); + rot1.Add(female.Rotation[i]); + } + } + + for (i = 0; i < male.placements.Count; i++) + { + if (!gene2.Any(z => z.id == male.placements[i].id)) + { + gene2.Add(male.placements[i]); + rot2.Add(male.Rotation[i]); + } + } + + return new[] {new PopulationItem() { + placements= gene1, Rotation= rot1.ToArray()}, + new PopulationItem(){ placements= gene2, Rotation= rot2.ToArray()}}; + } + + public void generation() + { + // Individuals with higher fitness are more likely to be selected for mating + population = population.OrderBy(z => z.fitness).ToList(); + + // fittest individual is preserved in the new generation (elitism) + + List newpopulation = new List(); + newpopulation.Add(this.population[0]); + while (newpopulation.Count() < this.population.Count) + { + var male = randomWeightedIndividual(); + var female = randomWeightedIndividual(male); + + // each mating produces two children + var children = mate(male, female); + + // slightly mutate children + newpopulation.Add(this.mutate(children[0])); + + if (newpopulation.Count < this.population.Count) + { + newpopulation.Add(this.mutate(children[1])); + } + } + + this.population = newpopulation; + } + } +} \ No newline at end of file diff --git a/PCUT/DeepNestLib.Core/GeometryUtil.cs b/PCUT/DeepNestLib.Core/GeometryUtil.cs new file mode 100644 index 0000000..a03e7a8 --- /dev/null +++ b/PCUT/DeepNestLib.Core/GeometryUtil.cs @@ -0,0 +1,1447 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace DeepNestLib +{ + public class GeometryUtil + { + // returns true if points are within the given distance + public static bool _withinDistance(SvgPoint p1, SvgPoint p2, double distance) + { + var dx = p1.x - p2.x; + var dy = p1.y - p2.y; + return ((dx * dx + dy * dy) < distance * distance); + } + + // returns an interior NFP for the special case where A is a rectangle + public static NFP[] noFitPolygonRectangle(NFP A, NFP B) + { + var minAx = A[0].x; + var minAy = A[0].y; + var maxAx = A[0].x; + var maxAy = A[0].y; + + for (var i = 1; i < A.Length; i++) + { + if (A[i].x < minAx) + { + minAx = A[i].x; + } + if (A[i].y < minAy) + { + minAy = A[i].y; + } + if (A[i].x > maxAx) + { + maxAx = A[i].x; + } + if (A[i].y > maxAy) + { + maxAy = A[i].y; + } + } + + var minBx = B[0].x; + var minBy = B[0].y; + var maxBx = B[0].x; + var maxBy = B[0].y; + for (int i = 1; i < B.Length; i++) + { + if (B[i].x < minBx) + { + minBx = B[i].x; + } + if (B[i].y < minBy) + { + minBy = B[i].y; + } + if (B[i].x > maxBx) + { + maxBx = B[i].x; + } + if (B[i].y > maxBy) + { + maxBy = B[i].y; + } + } + + if (maxBx - minBx > maxAx - minAx) + { + return null; + } + if (maxBy - minBy > maxAy - minAy) + { + return null; + } + + + var pnts = new NFP[] { new NFP() { Points=new SvgPoint[]{ + + new SvgPoint(minAx - minBx + B[0].x, minAy - minBy + B[0].y), + new SvgPoint(maxAx - maxBx + B[0].x, minAy - minBy + B[0].y), + new SvgPoint( maxAx - maxBx + B[0].x, maxAy - maxBy + B[0].y), + new SvgPoint( minAx - minBx + B[0].x, maxAy - maxBy + B[0].y) + } } }; + return pnts; + } + + + // returns the rectangular bounding box of the given polygon + public static PolygonBounds getPolygonBounds(NFP _polygon) + { + return getPolygonBounds(_polygon.Points); + } + public static PolygonBounds getPolygonBounds(List polygon) + { + return getPolygonBounds(polygon.ToArray()); + } + public static PolygonBounds getPolygonBounds(SvgPoint[] polygon) + { + + if (polygon == null || polygon.Count() < 3) + { + throw new ArgumentException("null"); + } + + var xmin = polygon[0].x; + var xmax = polygon[0].x; + var ymin = polygon[0].y; + var ymax = polygon[0].y; + + for (var i = 1; i < polygon.Length; i++) + { + if (polygon[i].x > xmax) + { + xmax = polygon[i].x; + } + else if (polygon[i].x < xmin) + { + xmin = polygon[i].x; + } + + if (polygon[i].y > ymax) + { + ymax = polygon[i].y; + } + else if (polygon[i].y < ymin) + { + ymin = polygon[i].y; + } + } + + var w = xmax - xmin; + var h = ymax - ymin; + //return new rectanglef(xmin, ymin, xmax - xmin, ymax - ymin); + return new PolygonBounds(xmin, ymin, w, h); + + + } + + public static bool isRectangle(NFP poly, double? tolerance = null) + { + var bb = getPolygonBounds(poly); + if (tolerance == null) + { + tolerance = TOL; + } + + + for (var i = 0; i < poly.Points.Length; i++) + { + if (!_almostEqual(poly.Points[i].x, bb.x) && !_almostEqual(poly.Points[i].x, bb.x + bb.width)) + { + return false; + } + if (!_almostEqual(poly.Points[i].y, bb.y) && !_almostEqual(poly.Points[i].y, bb.y + bb.height)) + { + return false; + } + } + + return true; + } + + public static PolygonWithBounds rotatePolygon(NFP polygon, float angle) + { + + List rotated = new List(); + angle = (float)(angle * Math.PI / 180.0f); + for (var i = 0; i < polygon.Points.Length; i++) + { + var x = polygon.Points[i].x; + var y = polygon.Points[i].y; + var x1 = (float)(x * Math.Cos(angle) - y * Math.Sin(angle)); + var y1 = (float)(x * Math.Sin(angle) + y * Math.Cos(angle)); + + rotated.Add(new SvgPoint(x1, y1)); + } + // reset bounding box + //RectangleF rr = new RectangleF(); + + var ret = new PolygonWithBounds() + { + Points = rotated.ToArray() + }; + var bounds = GeometryUtil.getPolygonBounds(ret); + ret.x = bounds.x; + ret.y = bounds.y; + ret.width = bounds.width; + ret.height = bounds.height; + return ret; + + } + + public class PolygonWithBounds : NFP + { + public double x; + public double y; + public double width; + public double height; + } + public static bool _almostEqual(double a, double b, double? tolerance = null) + { + if (tolerance == null) + { + tolerance = TOL; + } + return Math.Abs(a - b) < tolerance; + } + public static bool _almostEqual(double? a, double? b, double? tolerance = null) + { + return _almostEqual(a.Value, b.Value, tolerance); + } + // returns true if point already exists in the given nfp + public static bool inNfp(SvgPoint p, NFP[] nfp) + { + if (nfp == null || nfp.Length == 0) + { + return false; + } + + for (var i = 0; i < nfp.Length; i++) + { + for (var j = 0; j < nfp[i].length; j++) + { + if (_almostEqual(p.x, nfp[i][j].x) && _almostEqual(p.y, nfp[i][j].y)) + { + return true; + } + } + } + + return false; + } + // normalize vector into a unit vector + public static SvgPoint _normalizeVector(SvgPoint v) + { + if (_almostEqual(v.x * v.x + v.y * v.y, 1)) + { + return v; // given vector was already a unit vector + } + var len = Math.Sqrt(v.x * v.x + v.y * v.y); + var inverse = (float)(1 / len); + + return new SvgPoint(v.x * inverse, v.y * inverse + ); + } + public static double? pointDistance(SvgPoint p, SvgPoint s1, SvgPoint s2, SvgPoint normal, bool infinite = false) + { + normal = _normalizeVector(normal); + + var dir = new SvgPoint(normal.y, -normal.x); + + var pdot = p.x * dir.x + p.y * dir.y; + var s1dot = s1.x * dir.x + s1.y * dir.y; + var s2dot = s2.x * dir.x + s2.y * dir.y; + + var pdotnorm = p.x * normal.x + p.y * normal.y; + var s1dotnorm = s1.x * normal.x + s1.y * normal.y; + var s2dotnorm = s2.x * normal.x + s2.y * normal.y; + + if (!infinite) + { + if (((pdot < s1dot || _almostEqual(pdot, s1dot)) && (pdot < s2dot || _almostEqual(pdot, s2dot))) || ((pdot > s1dot || _almostEqual(pdot, s1dot)) && (pdot > s2dot || _almostEqual(pdot, s2dot)))) + { + return null; // dot doesn't collide with segment, or lies directly on the vertex + } + if ((_almostEqual(pdot, s1dot) && _almostEqual(pdot, s2dot)) && (pdotnorm > s1dotnorm && pdotnorm > s2dotnorm)) + { + return Math.Min(pdotnorm - s1dotnorm, pdotnorm - s2dotnorm); + } + if ((_almostEqual(pdot, s1dot) && _almostEqual(pdot, s2dot)) && (pdotnorm < s1dotnorm && pdotnorm < s2dotnorm)) + { + return -Math.Min(s1dotnorm - pdotnorm, s2dotnorm - pdotnorm); + } + } + + return -(pdotnorm - s1dotnorm + (s1dotnorm - s2dotnorm) * (s1dot - pdot) / (s1dot - s2dot)); + } + static double TOL = (float)Math.Pow(10, -9); // Floating point error is likely to be above 1 epsilon + // returns true if p lies on the line segment defined by AB, but not at any endpoints + // may need work! + public static bool _onSegment(SvgPoint A, SvgPoint B, SvgPoint p) + { + + // vertical line + if (_almostEqual(A.x, B.x) && _almostEqual(p.x, A.x)) + { + if (!_almostEqual(p.y, B.y) && !_almostEqual(p.y, A.y) && p.y < Math.Max(B.y, A.y) && p.y > Math.Min(B.y, A.y)) + { + return true; + } + else + { + return false; + } + } + + // horizontal line + if (_almostEqual(A.y, B.y) && _almostEqual(p.y, A.y)) + { + if (!_almostEqual(p.x, B.x) && !_almostEqual(p.x, A.x) && p.x < Math.Max(B.x, A.x) && p.x > Math.Min(B.x, A.x)) + { + return true; + } + else + { + return false; + } + } + + //range check + if ((p.x < A.x && p.x < B.x) || (p.x > A.x && p.x > B.x) || (p.y < A.y && p.y < B.y) || (p.y > A.y && p.y > B.y)) + { + return false; + } + + + // exclude end points + if ((_almostEqual(p.x, A.x) && _almostEqual(p.y, A.y)) || (_almostEqual(p.x, B.x) && _almostEqual(p.y, B.y))) + { + return false; + } + + var cross = (p.y - A.y) * (B.x - A.x) - (p.x - A.x) * (B.y - A.y); + + if (Math.Abs(cross) > TOL) + { + return false; + } + + var dot = (p.x - A.x) * (B.x - A.x) + (p.y - A.y) * (B.y - A.y); + + + + if (dot < 0 || _almostEqual(dot, 0)) + { + return false; + } + + var len2 = (B.x - A.x) * (B.x - A.x) + (B.y - A.y) * (B.y - A.y); + + + + if (dot > len2 || _almostEqual(dot, len2)) + { + return false; + } + + return true; + } + + + // project each point of B onto A in the given direction, and return the + public static double? polygonProjectionDistance(NFP A, NFP B, SvgPoint direction) + { + var Boffsetx = B.offsetx ?? 0; + var Boffsety = B.offsety ?? 0; + + var Aoffsetx = A.offsetx ?? 0; + var Aoffsety = A.offsety ?? 0; + + A = A.slice(0); + B = B.slice(0); + + // close the loop for polygons + if (A[0] != A[A.length - 1]) + { + A.push(A[0]); + } + + if (B[0] != B[B.length - 1]) + { + B.push(B[0]); + } + + var edgeA = A; + var edgeB = B; + + double? distance = null; + SvgPoint p, s1, s2; + double? d; + + + for (var i = 0; i < edgeB.length; i++) + { + // the shortest/most negative projection of B onto A + double? minprojection = null; + SvgPoint minp = null; + for (var j = 0; j < edgeA.length - 1; j++) + { + p = new SvgPoint(edgeB[i].x + Boffsetx, edgeB[i].y + Boffsety); + s1 = new SvgPoint(edgeA[j].x + Aoffsetx, edgeA[j].y + Aoffsety); + s2 = new SvgPoint(edgeA[j + 1].x + Aoffsetx, edgeA[j + 1].y + Aoffsety); + + if (Math.Abs((s2.y - s1.y) * direction.x - (s2.x - s1.x) * direction.y) < TOL) + { + continue; + } + + // project point, ignore edge boundaries + d = pointDistance(p, s1, s2, direction); + + if (d != null && (minprojection == null || d < minprojection)) + { + minprojection = d; + minp = p; + } + } + if (minprojection != null && (distance == null || minprojection > distance)) + { + distance = minprojection; + } + } + + return distance; + } + + public static double polygonArea(NFP polygon) + { + double area = 0; + int i, j; + for (i = 0, j = polygon.Points.Length - 1; i < polygon.Points.Length; j = i++) + { + area += (polygon.Points[j].x + polygon.Points[i].x) * (polygon.Points[j].y + - polygon.Points[i].y); + } + return 0.5f * area; + } + + // return true if point is in the polygon, false if outside, and null if exactly on a point or edge + public static bool? pointInPolygon(SvgPoint point, NFP polygon) + { + if (polygon == null || polygon.Points.Length < 3) + { + throw new ArgumentException(); + } + + var inside = false; + //var offsetx = polygon.offsetx || 0; + //var offsety = polygon.offsety || 0; + double offsetx = polygon.offsetx == null ? 0 : polygon.offsetx.Value; + double offsety = polygon.offsety == null ? 0 : polygon.offsety.Value; + + int i, j; + for (i = 0, j = polygon.Points.Count() - 1; i < polygon.Points.Length; j = i++) + { + var xi = polygon.Points[i].x + offsetx; + var yi = polygon.Points[i].y + offsety; + var xj = polygon.Points[j].x + offsetx; + var yj = polygon.Points[j].y + offsety; + + if (_almostEqual(xi, point.x) && _almostEqual(yi, point.y)) + { + + return null; // no result + } + + if (_onSegment(new SvgPoint(xi, yi), new SvgPoint(xj, yj), point)) + { + return null; // exactly on the segment + } + + if (_almostEqual(xi, xj) && _almostEqual(yi, yj)) + { // ignore very small lines + continue; + } + + var intersect = ((yi > point.y) != (yj > point.y)) && (point.x < (xj - xi) * (point.y - yi) / (yj - yi) + xi); + if (intersect) inside = !inside; + } + + return inside; + } + // todo: swap this for a more efficient sweep-line implementation + // returnEdges: if set, return all edges on A that have intersections + + public static bool intersect(NFP A, NFP B) + { + var Aoffsetx = A.offsetx ?? 0; + var Aoffsety = A.offsety ?? 0; + + var Boffsetx = B.offsetx ?? 0; + var Boffsety = B.offsety ?? 0; + + A = A.slice(0); + B = B.slice(0); + + for (var i = 0; i < A.length - 1; i++) + { + for (var j = 0; j < B.length - 1; j++) + { + var a1 = new SvgPoint(A[i].x + Aoffsetx, A[i].y + Aoffsety); + var a2 = new SvgPoint(A[i + 1].x + Aoffsetx, A[i + 1].y + Aoffsety); + var b1 = new SvgPoint(B[j].x + Boffsetx, B[j].y + Boffsety); + var b2 = new SvgPoint(B[j + 1].x + Boffsetx, B[j + 1].y + Boffsety); + + var prevbindex = (j == 0) ? B.length - 1 : j - 1; + var prevaindex = (i == 0) ? A.length - 1 : i - 1; + var nextbindex = (j + 1 == B.length - 1) ? 0 : j + 2; + var nextaindex = (i + 1 == A.length - 1) ? 0 : i + 2; + + // go even further back if we happen to hit on a loop end point + if (B[prevbindex] == B[j] || (_almostEqual(B[prevbindex].x, B[j].x) && _almostEqual(B[prevbindex].y, B[j].y))) + { + prevbindex = (prevbindex == 0) ? B.length - 1 : prevbindex - 1; + } + + if (A[prevaindex] == A[i] || (_almostEqual(A[prevaindex].x, A[i].x) && _almostEqual(A[prevaindex].y, A[i].y))) + { + prevaindex = (prevaindex == 0) ? A.length - 1 : prevaindex - 1; + } + + // go even further forward if we happen to hit on a loop end point + if (B[nextbindex] == B[j + 1] || (_almostEqual(B[nextbindex].x, B[j + 1].x) && _almostEqual(B[nextbindex].y, B[j + 1].y))) + { + nextbindex = (nextbindex == B.length - 1) ? 0 : nextbindex + 1; + } + + if (A[nextaindex] == A[i + 1] || (_almostEqual(A[nextaindex].x, A[i + 1].x) && _almostEqual(A[nextaindex].y, A[i + 1].y))) + { + nextaindex = (nextaindex == A.length - 1) ? 0 : nextaindex + 1; + } + + var a0 = new SvgPoint(A[prevaindex].x + Aoffsetx, A[prevaindex].y + Aoffsety); + var b0 = new SvgPoint(B[prevbindex].x + Boffsetx, B[prevbindex].y + Boffsety); + + var a3 = new SvgPoint(A[nextaindex].x + Aoffsetx, A[nextaindex].y + Aoffsety); + var b3 = new SvgPoint(B[nextbindex].x + Boffsetx, B[nextbindex].y + Boffsety); + + if (_onSegment(a1, a2, b1) || (_almostEqual(a1.x, b1.x) && _almostEqual(a1.y, b1.y))) + { + // if a point is on a segment, it could intersect or it could not. Check via the neighboring points + var b0in = pointInPolygon(b0, A); + var b2in = pointInPolygon(b2, A); + if ((b0in == true && b2in == false) || (b0in == false && b2in == true)) + { + return true; + } + else + { + continue; + } + } + + if (_onSegment(a1, a2, b2) || (_almostEqual(a2.x, b2.x) && _almostEqual(a2.y, b2.y))) + { + // if a point is on a segment, it could intersect or it could not. Check via the neighboring points + var b1in = pointInPolygon(b1, A); + var b3in = pointInPolygon(b3, A); + + if ((b1in == true && b3in == false) || (b1in == false && b3in == true)) + { + return true; + } + else + { + continue; + } + } + + if (_onSegment(b1, b2, a1) || (_almostEqual(a1.x, b2.x) && _almostEqual(a1.y, b2.y))) + { + // if a point is on a segment, it could intersect or it could not. Check via the neighboring points + var a0in = pointInPolygon(a0, B); + var a2in = pointInPolygon(a2, B); + + if ((a0in == true && a2in == false) || (a0in == false && a2in == true)) + { + return true; + } + else + { + continue; + } + } + + if (_onSegment(b1, b2, a2) || (_almostEqual(a2.x, b1.x) && _almostEqual(a2.y, b1.y))) + { + // if a point is on a segment, it could intersect or it could not. Check via the neighboring points + var a1in = pointInPolygon(a1, B); + var a3in = pointInPolygon(a3, B); + + if ((a1in == true && a3in == false) || (a1in == false && a3in == true)) + { + return true; + } + else + { + continue; + } + } + + var p = _lineIntersect(b1, b2, a1, a2); + + if (p != null) + { + return true; + } + } + } + + return false; + } + + public static bool isFinite(object obj) + { + return true; + } + // returns the intersection of AB and EF + // or null if there are no intersections or other numerical error + // if the infinite flag is set, AE and EF describe infinite lines without endpoints, they are finite line segments otherwise + public static SvgPoint _lineIntersect(SvgPoint A, SvgPoint B, SvgPoint E, SvgPoint F, bool infinite = false) + { + double a1, a2, b1, b2, c1, c2, x, y; + + a1 = B.y - A.y; + b1 = A.x - B.x; + c1 = B.x * A.y - A.x * B.y; + a2 = F.y - E.y; + b2 = E.x - F.x; + c2 = F.x * E.y - E.x * F.y; + + var denom = a1 * b2 - a2 * b1; + + x = (b1 * c2 - b2 * c1) / denom; + y = (a2 * c1 - a1 * c2) / denom; + + + if (!isFinite(x) || !isFinite(y)) + { + return null; + } + + // lines are colinear + /*var crossABE = (E.y - A.y) * (B.x - A.x) - (E.x - A.x) * (B.y - A.y); + var crossABF = (F.y - A.y) * (B.x - A.x) - (F.x - A.x) * (B.y - A.y); + if(_almostEqual(crossABE,0) && _almostEqual(crossABF,0)){ + return null; + }*/ + + if (!infinite) + { + // coincident points do not count as intersecting + if (Math.Abs(A.x - B.x) > TOL && ((A.x < B.x) ? x < A.x || x > B.x : x > A.x || x < B.x)) return null; + if (Math.Abs(A.y - B.y) > TOL && ((A.y < B.y) ? y < A.y || y > B.y : y > A.y || y < B.y)) return null; + + if (Math.Abs(E.x - F.x) > TOL && ((E.x < F.x) ? x < E.x || x > F.x : x > E.x || x < F.x)) return null; + if (Math.Abs(E.y - F.y) > TOL && ((E.y < F.y) ? y < E.y || y > F.y : y > E.y || y < F.y)) return null; + } + + return new SvgPoint(x, y); + } + + // searches for an arrangement of A and B such that they do not overlap + // if an NFP is given, only search for startpoints that have not already been traversed in the given NFP + + public static SvgPoint searchStartPoint(NFP A, NFP B, bool inside, NFP[] NFP = null) + { + // clone arrays + A = A.slice(0); + B = B.slice(0); + + // close the loop for polygons + if (A[0] != A[A.length - 1]) + { + A.push(A[0]); + } + + if (B[0] != B[B.length - 1]) + { + B.push(B[0]); + } + + for (var i = 0; i < A.length - 1; i++) + { + if (!A[i].marked) + { + A[i].marked = true; + for (var j = 0; j < B.length; j++) + { + B.offsetx = A[i].x - B[j].x; + B.offsety = A[i].y - B[j].y; + + bool? Binside = null; + for (var k = 0; k < B.length; k++) + { + var inpoly = pointInPolygon(new SvgPoint(B[k].x + B.offsetx.Value, + B[k].y + B.offsety.Value), A); + if (inpoly != null) + { + Binside = inpoly; + break; + } + } + + if (Binside == null) + { // A and B are the same + return null; + } + + var startPoint = new SvgPoint(B.offsetx.Value, B.offsety.Value); + if (((Binside.Value && inside) || (!Binside.Value && !inside)) && + !intersect(A, B) && !inNfp(startPoint, NFP)) + { + return startPoint; + } + + // slide B along vector + var vx = A[i + 1].x - A[i].x; + var vy = A[i + 1].y - A[i].y; + + var d1 = polygonProjectionDistance(A, B, new SvgPoint(vx, vy)); + var d2 = polygonProjectionDistance(B, A, new SvgPoint(-vx, -vy)); + + double? d = null; + + // todo: clean this up + if (d1 == null && d2 == null) + { + // nothin + } + else if (d1 == null) + { + d = d2; + } + else if (d2 == null) + { + d = d1; + } + else + { + d = Math.Min(d1.Value, d2.Value); + } + + // only slide until no longer negative + // todo: clean this up + if (d != null && !_almostEqual(d, 0) && d > 0) + { + + } + else + { + continue; + } + + var vd2 = vx * vx + vy * vy; + + if (d * d < vd2 && !_almostEqual(d * d, vd2)) + { + var vd = (float)Math.Sqrt(vx * vx + vy * vy); + vx *= d.Value / vd; + vy *= d.Value / vd; + } + + B.offsetx += vx; + B.offsety += vy; + + for (var k = 0; k < B.length; k++) + { + var inpoly = pointInPolygon( + new SvgPoint( + B[k].x + B.offsetx.Value, B[k].y + B.offsety.Value), A); + if (inpoly != null) + { + Binside = inpoly; + break; + } + } + startPoint = + new SvgPoint(B.offsetx.Value, B.offsety.Value); + if (((Binside.Value && inside) || (!Binside.Value && !inside)) && + !intersect(A, B) && !inNfp(startPoint, NFP)) + { + return startPoint; + } + } + } + } + + + + return null; + } + + public class TouchingItem + { + public TouchingItem(int _type, int _a, int _b) + { + A = _a; + B = _b; + type = _type; + } + public int A; + public int B; + public int type; + + } + + public static double? segmentDistance(SvgPoint A, SvgPoint B, SvgPoint E, SvgPoint F, SvgPoint direction) + { + var normal = new SvgPoint( + direction.y, + -direction.x + + ); + + var reverse = new SvgPoint( + -direction.x, + -direction.y + ); + + var dotA = A.x * normal.x + A.y * normal.y; + var dotB = B.x * normal.x + B.y * normal.y; + var dotE = E.x * normal.x + E.y * normal.y; + var dotF = F.x * normal.x + F.y * normal.y; + + var crossA = A.x * direction.x + A.y * direction.y; + var crossB = B.x * direction.x + B.y * direction.y; + var crossE = E.x * direction.x + E.y * direction.y; + var crossF = F.x * direction.x + F.y * direction.y; + + var crossABmin = Math.Min(crossA, crossB); + var crossABmax = Math.Max(crossA, crossB); + + var crossEFmax = Math.Max(crossE, crossF); + var crossEFmin = Math.Min(crossE, crossF); + + var ABmin = Math.Min(dotA, dotB); + var ABmax = Math.Max(dotA, dotB); + + var EFmax = Math.Max(dotE, dotF); + var EFmin = Math.Min(dotE, dotF); + + // segments that will merely touch at one point + if (_almostEqual(ABmax, EFmin, TOL) || _almostEqual(ABmin, EFmax, TOL)) + { + return null; + } + // segments miss eachother completely + if (ABmax < EFmin || ABmin > EFmax) + { + return null; + } + + double overlap; + + if ((ABmax > EFmax && ABmin < EFmin) || (EFmax > ABmax && EFmin < ABmin)) + { + overlap = 1; + } + else + { + var minMax = Math.Min(ABmax, EFmax); + var maxMin = Math.Max(ABmin, EFmin); + + var maxMax = Math.Max(ABmax, EFmax); + var minMin = Math.Min(ABmin, EFmin); + + overlap = (minMax - maxMin) / (maxMax - minMin); + } + + var crossABE = (E.y - A.y) * (B.x - A.x) - (E.x - A.x) * (B.y - A.y); + var crossABF = (F.y - A.y) * (B.x - A.x) - (F.x - A.x) * (B.y - A.y); + + // lines are colinear + if (_almostEqual(crossABE, 0) && _almostEqual(crossABF, 0)) + { + + var ABnorm = new SvgPoint(B.y - A.y, A.x - B.x); + var EFnorm = new SvgPoint(F.y - E.y, E.x - F.x); + + var ABnormlength = (float)Math.Sqrt(ABnorm.x * ABnorm.x + ABnorm.y * ABnorm.y); + ABnorm.x /= ABnormlength; + ABnorm.y /= ABnormlength; + + var EFnormlength = (float)Math.Sqrt(EFnorm.x * EFnorm.x + EFnorm.y * EFnorm.y); + EFnorm.x /= EFnormlength; + EFnorm.y /= EFnormlength; + + // segment normals must point in opposite directions + if (Math.Abs(ABnorm.y * EFnorm.x - ABnorm.x * EFnorm.y) < TOL && ABnorm.y * EFnorm.y + ABnorm.x * EFnorm.x < 0) + { + // normal of AB segment must point in same direction as given direction vector + var normdot = ABnorm.y * direction.y + ABnorm.x * direction.x; + // the segments merely slide along eachother + if (_almostEqual(normdot, 0, TOL)) + { + return null; + } + if (normdot < 0) + { + return 0; + } + } + return null; + } + + var distances = new List(); + + // coincident points + if (_almostEqual(dotA, dotE)) + { + distances.Add(crossA - crossE); + } + else if (_almostEqual(dotA, dotF)) + { + distances.Add(crossA - crossF); + } + else if (dotA > EFmin && dotA < EFmax) + { + var d = pointDistance(A, E, F, reverse); + if (d != null && _almostEqual(d, 0)) + { // A currently touches EF, but AB is moving away from EF + var dB = pointDistance(B, E, F, reverse, true); + if (dB < 0 || _almostEqual(dB * overlap, 0)) + { + d = null; + } + } + if (d != null) + { + distances.Add(d.Value); + } + } + + if (_almostEqual(dotB, dotE)) + { + distances.Add(crossB - crossE); + } + else if (_almostEqual(dotB, dotF)) + { + distances.Add(crossB - crossF); + } + else if (dotB > EFmin && dotB < EFmax) + { + var d = pointDistance(B, E, F, reverse); + + if (d != null && _almostEqual(d, 0)) + { // crossA>crossB A currently touches EF, but AB is moving away from EF + var dA = pointDistance(A, E, F, reverse, true); + if (dA < 0 || _almostEqual(dA * overlap, 0)) + { + d = null; + } + } + if (d != null) + { + distances.Add(d.Value); + } + } + + if (dotE > ABmin && dotE < ABmax) + { + var d = pointDistance(E, A, B, direction); + if (d != null && _almostEqual(d, 0)) + { // crossF ABmin && dotF < ABmax) + { + var d = pointDistance(F, A, B, direction); + if (d != null && _almostEqual(d, 0)) + { // && crossE 0 || _almostEqual(d, 0)) + { + distance = d; + } + } + } + } + return distance; + } + public class nVector + { + public SvgPoint start; + public SvgPoint end; + public double x; + public double y; + + + public nVector(double v1, double v2, SvgPoint _start, SvgPoint _end) + { + this.x = v1; + this.y = v2; + this.start = _start; + this.end = _end; + } + } + + // given a static polygon A and a movable polygon B, compute a no fit polygon by orbiting B about A + // if the inside flag is set, B is orbited inside of A rather than outside + // if the searchEdges flag is set, all edges of A are explored for NFPs - multiple + public static NFP[] noFitPolygon(NFP A, NFP B, bool inside, bool searchEdges) + { + if (A == null || A.length < 3 || B == null || B.length < 3) + { + return null; + } + + A.offsetx = 0; + A.offsety = 0; + + int i = 0, j = 0; + + var minA = A[0].y; + var minAindex = 0; + + var maxB = B[0].y; + var maxBindex = 0; + + for (i = 1; i < A.length; i++) + { + A[i].marked = false; + if (A[i].y < minA) + { + minA = A[i].y; + minAindex = i; + } + } + + for (i = 1; i < B.length; i++) + { + B[i].marked = false; + if (B[i].y > maxB) + { + maxB = B[i].y; + maxBindex = i; + } + } + SvgPoint startpoint; + if (!inside) + { + // shift B such that the bottom-most point of B is at the top-most point of A. This guarantees an initial placement with no intersections + startpoint = new SvgPoint( + A[minAindex].x - B[maxBindex].x, + A[minAindex].y - B[maxBindex].y); + } + else + { + // no reliable heuristic for inside + + startpoint = searchStartPoint(A, B, true); + } + + List NFPlist = new List(); + + + + while (startpoint != null) + { + + B.offsetx = startpoint.x; + B.offsety = startpoint.y; + + // maintain a list of touching points/edges + List touching = null; + + nVector prevvector = null; // keep track of previous vector + NFP NFP = new NFP(); + /*var NFP = [{ + x: B[0].x + B.offsetx, + y: B[0].y + B.offsety + + + + + + }];*/ + NFP.push(new SvgPoint(B[0].x + B.offsetx.Value, B[0].y + B.offsety.Value)); + + double referencex = B[0].x + B.offsetx.Value; + double referencey = B[0].y + B.offsety.Value; + var startx = referencex; + var starty = referencey; + var counter = 0; + + while (counter < 10 * (A.length + B.length)) + { // sanity check, prevent infinite loop + touching = new List(); + // find touching vertices/edges + for (i = 0; i < A.length; i++) + { + var nexti = (i == A.length - 1) ? 0 : i + 1; + for (j = 0; j < B.length; j++) + { + var nextj = (j == B.length - 1) ? 0 : j + 1; + if (_almostEqual(A[i].x, B[j].x + B.offsetx) && _almostEqual(A[i].y, B[j].y + B.offsety)) + { + touching.Add(new TouchingItem(0, i, j)); + } + else if (_onSegment(A[i], A[nexti], + new SvgPoint(B[j].x + B.offsetx.Value, B[j].y + B.offsety.Value))) + { + touching.Add(new TouchingItem(1, nexti, j)); + } + else if (_onSegment( + new SvgPoint( + B[j].x + B.offsetx.Value, B[j].y + B.offsety.Value), + new SvgPoint( + B[nextj].x + B.offsetx.Value, B[nextj].y + B.offsety.Value), A[i])) + { + touching.Add(new TouchingItem(2, i, nextj)); + } + } + } + + // generate translation vectors from touching vertices/edges + var vectors = new List(); + for (i = 0; i < touching.Count; i++) + { + var vertexA = A[touching[i].A]; + vertexA.marked = true; + + // adjacent A vertices + var prevAindex = touching[i].A - 1; + var nextAindex = touching[i].A + 1; + + prevAindex = (prevAindex < 0) ? A.length - 1 : prevAindex; // loop + nextAindex = (nextAindex >= A.length) ? 0 : nextAindex; // loop + + var prevA = A[prevAindex]; + var nextA = A[nextAindex]; + + // adjacent B vertices + var vertexB = B[touching[i].B]; + + var prevBindex = touching[i].B - 1; + var nextBindex = touching[i].B + 1; + + prevBindex = (prevBindex < 0) ? B.length - 1 : prevBindex; // loop + nextBindex = (nextBindex >= B.length) ? 0 : nextBindex; // loop + + var prevB = B[prevBindex]; + var nextB = B[nextBindex]; + + if (touching[i].type == 0) + { + + var vA1 = new nVector( + prevA.x - vertexA.x, + prevA.y - vertexA.y, + vertexA, + prevA + ); + + var vA2 = new nVector( + nextA.x - vertexA.x, + nextA.y - vertexA.y, + vertexA, + nextA + ); + + // B vectors need to be inverted + var vB1 = new nVector( + vertexB.x - prevB.x, + vertexB.y - prevB.y, + prevB, + vertexB + ); + + var vB2 = new nVector( + vertexB.x - nextB.x, + vertexB.y - nextB.y, + nextB, + vertexB + ); + + vectors.Add(vA1); + vectors.Add(vA2); + vectors.Add(vB1); + vectors.Add(vB2); + } + else if (touching[i].type == 1) + { + vectors.Add(new nVector( + vertexA.x - (vertexB.x + B.offsetx.Value), + vertexA.y - (vertexB.y + B.offsety.Value), + prevA, + vertexA + )); + + vectors.Add(new nVector( + prevA.x - (vertexB.x + B.offsetx.Value), + prevA.y - (vertexB.y + B.offsety.Value), + vertexA, + prevA + )); + } + else if (touching[i].type == 2) + { + vectors.Add(new nVector( + vertexA.x - (vertexB.x + B.offsetx.Value), + vertexA.y - (vertexB.y + B.offsety.Value), + prevB, + vertexB + )); + + vectors.Add(new nVector( + vertexA.x - (prevB.x + B.offsetx.Value), + vertexA.y - (prevB.y + B.offsety.Value), + vertexB, + prevB + + )); + } + } + + // todo: there should be a faster way to reject vectors that will cause immediate intersection. For now just check them all + + nVector translate = null; + double maxd = 0; + + for (i = 0; i < vectors.Count; i++) + { + if (vectors[i].x == 0 && vectors[i].y == 0) + { + continue; + } + + // if this vector points us back to where we came from, ignore it. + // ie cross product = 0, dot product < 0 + if (prevvector != null && + vectors[i].y * prevvector.y + vectors[i].x * prevvector.x < 0) + { + + // compare magnitude with unit vectors + var vectorlength = (float)Math.Sqrt(vectors[i].x * vectors[i].x + vectors[i].y * vectors[i].y); + var unitv = new SvgPoint(vectors[i].x / vectorlength, vectors[i].y / vectorlength); + + var prevlength = (float)Math.Sqrt(prevvector.x * prevvector.x + prevvector.y * prevvector.y); + var prevunit = new SvgPoint(prevvector.x / prevlength, prevvector.y / prevlength); + + // we need to scale down to unit vectors to normalize vector length. Could also just do a tan here + if (Math.Abs(unitv.y * prevunit.x - unitv.x * prevunit.y) < 0.0001) + { + continue; + } + } + + var d = polygonSlideDistance(A, B, vectors[i], true); + var vecd2 = vectors[i].x * vectors[i].x + vectors[i].y * vectors[i].y; + + if (d == null || d * d > vecd2) + { + var vecd = (float)Math.Sqrt(vectors[i].x * vectors[i].x + vectors[i].y * vectors[i].y); + d = vecd; + } + + if (d != null && d > maxd) + { + maxd = d.Value; + translate = vectors[i]; + } + } + + + if (translate == null || _almostEqual(maxd, 0)) + { + // didn't close the loop, something went wrong here + NFP = null; + break; + } + + translate.start.marked = true; + translate.end.marked = true; + + prevvector = translate; + + // trim + var vlength2 = translate.x * translate.x + translate.y * translate.y; + if (maxd * maxd < vlength2 && !_almostEqual(maxd * maxd, vlength2)) + { + var scale = (float)Math.Sqrt((maxd * maxd) / vlength2); + translate.x *= scale; + translate.y *= scale; + } + + referencex += translate.x; + referencey += translate.y; + + if (_almostEqual(referencex, startx) && _almostEqual(referencey, starty)) + { + // we've made a full loop + break; + } + + // if A and B start on a touching horizontal line, the end point may not be the start point + var looped = false; + if (NFP.length > 0) + { + for (i = 0; i < NFP.length - 1; i++) + { + if (_almostEqual(referencex, NFP[i].x) && _almostEqual(referencey, NFP[i].y)) + { + looped = true; + } + } + } + + if (looped) + { + // we've made a full loop + break; + } + + NFP.push(new SvgPoint( + referencex, referencey + )); + + B.offsetx += translate.x; + B.offsety += translate.y; + + counter++; + } + + if (NFP != null && NFP.length > 0) + { + NFPlist.Add(NFP); + + } + + if (!searchEdges) + { + // only get outer NFP or first inner NFP + break; + } + startpoint = searchStartPoint(A, B, inside, NFPlist.ToArray()); + } + + return NFPlist.ToArray(); + } + public static bool pnpoly((double X, double Y)[] verts, double testx, double testy) + { + int nvert = verts.Length; + int i, j; + bool c = false; + for (i = 0, j = nvert - 1; i < nvert; j = i++) + { + if (((verts[i].Y > testy) != (verts[j].Y > testy)) && + (testx < (verts[j].X - verts[i].X) * (testy - verts[i].Y) / (verts[j].Y - verts[i].Y) + verts[i].X)) + c = !c; + } + return c; + } + + + + } +} diff --git a/PCUT/DeepNestLib.Core/IStringify.cs b/PCUT/DeepNestLib.Core/IStringify.cs new file mode 100644 index 0000000..ad7bd9b --- /dev/null +++ b/PCUT/DeepNestLib.Core/IStringify.cs @@ -0,0 +1,11 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace DeepNestLib +{ + public interface IStringify + { + string stringify(); + } +} diff --git a/PCUT/DeepNestLib.Core/NFP.cs b/PCUT/DeepNestLib.Core/NFP.cs new file mode 100644 index 0000000..98ae3fe --- /dev/null +++ b/PCUT/DeepNestLib.Core/NFP.cs @@ -0,0 +1,213 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace DeepNestLib +{ + public class NFP : IStringify + { + public int Z; + public bool fitted { get { return sheet != null; } } + public NFP sheet; + public object Tag; + public override string ToString() + { + var str1 = (Points != null) ? Points.Count() + "" : "null"; + return $"nfp: id: {id}; source: {source}; rotation: {rotation}; points: {str1}"; + } + public NFP() + { + Points = new SvgPoint[] { }; + } + + public string Name { get; set; } + public void AddPoint(SvgPoint point) + { + var list = Points.ToList(); + list.Add(point); + Points = list.ToArray(); + } + + #region gdi section + public bool isBin; + + #endregion + public void reverse() + { + Points = Points.Reverse().ToArray(); + } + + public StringBuilder GetXml() + { + StringBuilder sb = new StringBuilder(); + sb.AppendLine(""); + sb.AppendLine(""); + sb.AppendLine(""); + foreach (var item in Points) + { + sb.AppendLine($""); + } + sb.AppendLine(""); + if (children != null) + foreach (var item in children) + { + sb.AppendLine(""); + foreach (var citem in item.Points) + { + sb.AppendLine($""); + } + sb.AppendLine(""); + } + + sb.AppendLine(""); + + return sb; + } + public double x { get; set; } + public double y { get; set; } + + public double WidthCalculated + { + get + { + var maxx = Points.Max(z => z.x); + var minx = Points.Min(z => z.x); + + return maxx - minx; + } + } + + public double HeightCalculated + { + get + { + var maxy = Points.Max(z => z.y); + var miny = Points.Min(z => z.y); + return maxy - miny; + } + } + + public SvgPoint this[int ind] + { + get + { + return Points[ind]; + } + } + + public List children; + + + + + public int Length + { + get + { + return Points.Length; + } + } + + //public float? width; + //public float? height; + public int length + { + get + { + return Points.Length; + } + } + + public int Id; + public int id + { + get + { + return Id; + } + set + { + Id = value; + } + } + + public double? offsetx; + public double? offsety; + public int? source = null; + public float Rotation; + + public float rotation + { + get + { + return Rotation; + } + set + { + Rotation = value; + } + } + public SvgPoint[] Points; + public float Area + { + get + { + float ret = 0; + if (Points.Length < 3) return 0; + List pp = new List(); + pp.AddRange(Points); + pp.Add(Points[0]); + for (int i = 1; i < pp.Count; i++) + { + var s0 = pp[i - 1]; + var s1 = pp[i]; + ret += (float)(s0.x * s1.y - s0.y * s1.x); + } + return (float)Math.Abs(ret / 2); + } + } + + public void push(SvgPoint svgPoint) + { + List points = new List(); + if (Points == null) + { + Points = new SvgPoint[] { }; + } + points.AddRange(Points); + points.Add(svgPoint); + Points = points.ToArray(); + + } + + public NFP slice(int v) + { + var ret = new NFP(); + List pp = new List(); + for (int i = v; i < length; i++) + { + pp.Add(new SvgPoint(this[i].x, this[i].y)); + + } + ret.Points = pp.ToArray(); + return ret; + } + + public string stringify() + { + throw new NotImplementedException(); + } + + public static NFP Create(params SvgPoint[] points) + { + if (points == null || points.Length == 0) + return new NFP(); + else + return new NFP + { + Points = points + }; + } + } +} diff --git a/PCUT/DeepNestLib.Core/NfpKey.cs b/PCUT/DeepNestLib.Core/NfpKey.cs new file mode 100644 index 0000000..e6b0814 --- /dev/null +++ b/PCUT/DeepNestLib.Core/NfpKey.cs @@ -0,0 +1,24 @@ +namespace DeepNestLib +{ + public class NfpKey : IStringify + { + + public NFP A; + public NFP B; + public float ARotation { get; set; } + public float BRotation { get; set; } + public bool Inside { get; set; } + + public int AIndex { get; set; } + public int BIndex { get; set; } + public object Asource; + public object Bsource; + + + public string stringify() + { + return $"A:{AIndex} B:{BIndex} inside:{Inside} Arotation:{ARotation} Brotation:{BRotation}"; + } + } +} + diff --git a/PCUT/DeepNestLib.Core/PlacementItem.cs b/PCUT/DeepNestLib.Core/PlacementItem.cs new file mode 100644 index 0000000..2bf93f7 --- /dev/null +++ b/PCUT/DeepNestLib.Core/PlacementItem.cs @@ -0,0 +1,20 @@ +using System.Collections.Generic; + +namespace DeepNestLib +{ + public class PlacementItem + { + public double? mergedLength; + public object mergedSegments; + public List> nfp; + public int id; + public NFP hull; + public NFP hullsheet; + + public float rotation; + public double x; + public double y; + public int source; + } +} + diff --git a/PCUT/DeepNestLib.Core/PlacementTypeEnum.cs b/PCUT/DeepNestLib.Core/PlacementTypeEnum.cs new file mode 100644 index 0000000..b0ee253 --- /dev/null +++ b/PCUT/DeepNestLib.Core/PlacementTypeEnum.cs @@ -0,0 +1,11 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace DeepNestLib +{ + public enum PlacementTypeEnum + { + box, gravity, squeeze + } +} diff --git a/PCUT/DeepNestLib.Core/PolygonBounds.cs b/PCUT/DeepNestLib.Core/PolygonBounds.cs new file mode 100644 index 0000000..6d995d7 --- /dev/null +++ b/PCUT/DeepNestLib.Core/PolygonBounds.cs @@ -0,0 +1,17 @@ +namespace DeepNestLib +{ + public class PolygonBounds + { + public double x; + public double y; + public double width; + public double height; + public PolygonBounds(double _x, double _y, double _w, double _h) + { + x = _x; + y = _y; + width = _w; + height = _h; + } + } +} diff --git a/PCUT/DeepNestLib.Core/PopulationItem.cs b/PCUT/DeepNestLib.Core/PopulationItem.cs new file mode 100644 index 0000000..ea520e8 --- /dev/null +++ b/PCUT/DeepNestLib.Core/PopulationItem.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace DeepNestLib +{ + public class PopulationItem + { + public object processing = null; + + public double? fitness; + + public float[] Rotation; + public List placements; + + public NFP[] paths; + public double area; + } +} diff --git a/PCUT/DeepNestLib.Core/RectangleSheet.cs b/PCUT/DeepNestLib.Core/RectangleSheet.cs new file mode 100644 index 0000000..4e33f53 --- /dev/null +++ b/PCUT/DeepNestLib.Core/RectangleSheet.cs @@ -0,0 +1,15 @@ +namespace DeepNestLib +{ + public class RectangleSheet : Sheet + { + public void Rebuild() + { + Points = new SvgPoint[] { }; + AddPoint(new SvgPoint(x, y)); + AddPoint(new SvgPoint(x + Width, y)); + AddPoint(new SvgPoint(x + Width, y + Height)); + AddPoint(new SvgPoint(x, y + Height)); + } + } +} + diff --git a/PCUT/DeepNestLib.Core/Sheet.cs b/PCUT/DeepNestLib.Core/Sheet.cs new file mode 100644 index 0000000..2467f17 --- /dev/null +++ b/PCUT/DeepNestLib.Core/Sheet.cs @@ -0,0 +1,9 @@ +namespace DeepNestLib +{ + public class Sheet : NFP + { + public double Width; + public double Height; + } +} + diff --git a/PCUT/DeepNestLib.Core/SheetPlacement.cs b/PCUT/DeepNestLib.Core/SheetPlacement.cs new file mode 100644 index 0000000..683523d --- /dev/null +++ b/PCUT/DeepNestLib.Core/SheetPlacement.cs @@ -0,0 +1,18 @@ +using System.Collections.Generic; + +namespace DeepNestLib +{ + public class SheetPlacement + { + public double? fitness; + + public float[] Rotation; + public List[] placements; + + public NFP[] paths; + public double area; + public double mergedLength; + public int index; + } +} + diff --git a/PCUT/DeepNestLib.Core/SheetPlacementItem.cs b/PCUT/DeepNestLib.Core/SheetPlacementItem.cs new file mode 100644 index 0000000..398f27e --- /dev/null +++ b/PCUT/DeepNestLib.Core/SheetPlacementItem.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace DeepNestLib +{ + public class SheetPlacementItem + { + public int sheetId; + public int sheetSource; + + public List sheetplacements = new List(); + public List placements = new List(); + } +} diff --git a/PCUT/DeepNestLib.Core/Simplify.cs b/PCUT/DeepNestLib.Core/Simplify.cs new file mode 100644 index 0000000..a39fa96 --- /dev/null +++ b/PCUT/DeepNestLib.Core/Simplify.cs @@ -0,0 +1,143 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace DeepNestLib +{ + public class Simplify + { + + // to suit your point format, run search/replace for '.x' and '.y'; + // for 3D version, see 3d branch (configurability would draw significant performance overhead) + + // square distance between 2 points + public static double getSqDist(SvgPoint p1, SvgPoint p2) + { + + var dx = p1.x - p2.x; + var dy = p1.y - p2.y; + + return dx * dx + dy * dy; + } + + // square distance from a point to a segment + public static double getSqSegDist(SvgPoint p, SvgPoint p1, SvgPoint p2) + { + + var x = p1.x; + var y = p1.y; + var dx = p2.x - x; + var dy = p2.y - y; + + if (dx != 0 || dy != 0) + { + + var t = ((p.x - x) * dx + (p.y - y) * dy) / (dx * dx + dy * dy); + + if (t > 1) + { + x = p2.x; + y = p2.y; + + } + else if (t > 0) + { + x += dx * t; + y += dy * t; + } + } + + dx = p.x - x; + dy = p.y - y; + + return dx * dx + dy * dy; + } + // rest of the code doesn't care about point format + + // basic distance-based simplification + public static NFP simplifyRadialDist(NFP points, double? sqTolerance) + { + + var prevPoint = points[0]; + var newPoints = new NFP(); + newPoints.AddPoint(prevPoint); + + SvgPoint point = null; + int i = 1; + for (var len = points.length; i < len; i++) + { + point = points[i]; + + if (point.marked || getSqDist(point, prevPoint) > sqTolerance) + { + newPoints.AddPoint(point); + prevPoint = point; + } + } + + if (prevPoint != point) newPoints.AddPoint(point); + return newPoints; + } + + + public static void simplifyDPStep(NFP points, int first, int last, double? sqTolerance, NFP simplified) + { + var maxSqDist = sqTolerance; + var index = -1; + var marked = false; + for (var i = first + 1; i < last; i++) + { + var sqDist = getSqSegDist(points[i], points[first], points[last]); + + if (sqDist > maxSqDist) + { + index = i; + maxSqDist = sqDist; + } + /*if(points[i].marked && maxSqDist <= sqTolerance){ + index = i; + marked = true; + }*/ + } + + /*if(!points[index] && maxSqDist > sqTolerance){ + console.log('shit shit shit'); + }*/ + + if (maxSqDist > sqTolerance || marked) + { + if (index - first > 1) simplifyDPStep(points, first, index, sqTolerance, simplified); + simplified.push(points[index]); + if (last - index > 1) simplifyDPStep(points, index, last, sqTolerance, simplified); + } + } + + // simplification using Ramer-Douglas-Peucker algorithm + public static NFP simplifyDouglasPeucker(NFP points, double? sqTolerance) + { + var last = points.length - 1; + + var simplified = new NFP(); + simplified.AddPoint(points[0]); + simplifyDPStep(points, 0, last, sqTolerance, simplified); + simplified.push(points[last]); + + return simplified; + } + + // both algorithms combined for awesome performance + public static NFP simplify(NFP points, double? tolerance, bool highestQuality) + { + + if (points.length <= 2) return points; + + var sqTolerance = (tolerance != null) ? (tolerance * tolerance) : 1; + + points = highestQuality ? points : simplifyRadialDist(points, sqTolerance); + points = simplifyDouglasPeucker(points, sqTolerance); + + return points; + } + } +} diff --git a/PCUT/DeepNestLib.Core/SvgNestConfig.cs b/PCUT/DeepNestLib.Core/SvgNestConfig.cs new file mode 100644 index 0000000..54cdf4e --- /dev/null +++ b/PCUT/DeepNestLib.Core/SvgNestConfig.cs @@ -0,0 +1,25 @@ +namespace DeepNestLib +{ + public class SvgNestConfig + { + public PlacementTypeEnum placementType = PlacementTypeEnum.box; + public double curveTolerance = 0.72; + public double scale = 25; + public double clipperScale = 10000000; + public bool exploreConcave = false; + public int mutationRate = 10; + public int populationSize = 10; + public int rotations = 4; + public double spacing = 10; + public double sheetSpacing = 0; + public bool useHoles = false; + public double timeRatio = 0.5; + public bool mergeLines = false; + public bool simplify; + + #region port features (don't exist in the original DeepNest project) + public bool clipByHull = false; + public bool clipByRects = true; //clip by AABB + MinRect + #endregion + } +} diff --git a/PCUT/DeepNestLib.Core/SvgPoint.cs b/PCUT/DeepNestLib.Core/SvgPoint.cs new file mode 100644 index 0000000..ed7c1d0 --- /dev/null +++ b/PCUT/DeepNestLib.Core/SvgPoint.cs @@ -0,0 +1,33 @@ +namespace DeepNestLib +{ + public class SvgPoint + { + public bool exact = true; + public override string ToString() + { + return "x: " + x + "; y: " + y; + } + public int id; + public SvgPoint(double _x, double _y) + { + x = _x; + y = _y; + } + internal SvgPoint(SvgPoint point) + { + this.exact = point.exact; + this.id = point.id; + this.marked = point.marked; + this.x = point.x; + this.y = point.y; + } + public bool marked; + public double x; + public double y; + public SvgPoint Clone() + { + return new SvgPoint(this); + } + } +} + diff --git a/PCUT/DeepNestLib.Core/_Clipper.cs b/PCUT/DeepNestLib.Core/_Clipper.cs new file mode 100644 index 0000000..02d28a2 --- /dev/null +++ b/PCUT/DeepNestLib.Core/_Clipper.cs @@ -0,0 +1,60 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace DeepNestLib +{ + public class _Clipper + { + public static ClipperLib.IntPoint[] ScaleUpPaths(SvgPoint[] points, double scale = 1) + { + var result = new ClipperLib.IntPoint[points.Length]; + + Parallel.For(0, points.Length, i => result[i] = new ClipperLib.IntPoint((long)Math.Round((decimal)points[i].x * (decimal)scale), (long)Math.Round((decimal)points[i].y * (decimal)scale))); + + return result.ToArray(); + } // 2 secs + public static ClipperLib.IntPoint[] ScaleUpPaths(NFP p, double scale = 1) + { + List ret = new List(); + + for (int i = 0; i < p.Points.Count(); i++) + { + //p.Points[i] = new SvgNestPort.SvgPoint((float)Math.Round(p.Points[i].x * scale), (float)Math.Round(p.Points[i].y * scale)); + ret.Add(new ClipperLib.IntPoint( + (long)Math.Round((decimal)p.Points[i].x * (decimal)scale), + (long)Math.Round((decimal)p.Points[i].y * (decimal)scale) + )); + + } + return ret.ToArray(); + } + /*public static IntPoint[] ScaleUpPath(IntPoint[] p, double scale = 1) + { + for (int i = 0; i < p.Length; i++) + { + + //p[i] = new IntPoint(p[i].X * scale, p[i].Y * scale); + p[i] = new IntPoint( + (long)Math.Round((decimal)p[i].X * (decimal)scale), + (long)Math.Round((decimal)p[i].Y * (decimal)scale)); + } + return p.ToArray(); + } + public static void ScaleUpPaths(List> p, double scale = 1) + { + for (int i = 0; i < p.Count; i++) + { + for (int j = 0; j < p[i].Count; j++) + { + p[i][j] = new IntPoint(p[i][j].X * scale, p[i][j].Y * scale); + + } + } + + + }*/ + } +} + diff --git a/PCUT/Http.Core/Constants/HttpConstants.cs b/PCUT/Http.Core/Constants/HttpConstants.cs new file mode 100644 index 0000000..0871f69 --- /dev/null +++ b/PCUT/Http.Core/Constants/HttpConstants.cs @@ -0,0 +1,45 @@ +namespace Http.Core.Constants +{ + public static class HttpConstants + { + public static class ClientNames + { + public const string AuthClient = "LoginClient"; + public const string ApiClient = "ApiClient"; + } + + public static class Auth + { + public const string BaseUrl = "http://14.225.255.245:3003"; + + public const string Login = "api/auth/login"; + public const string Refresh = "api/auth/refresh"; + + } + + public static class Api + { + public const string BaseUrl = "http://14.225.255.245:3003"; + + public const string LogOut = "api/auth/logout"; + public const string Profile = "api/auth/profile"; + + public const string Users = "api/users"; + public const string UserById = "api/users/{0}"; + public const string UserUnlockDevice = "api/users/{0}/device/unlock"; + + public const string Categories = "api/categories"; + public const string CategoryById = "api/categories/{0}"; + + public const string Upload = "api/files/upload"; + public const string Download = "api/files/{0}"; + + public const string CdrFiles = "api/cdr-files"; + public const string CdrFileById = "api/cdr-files/{0}"; + + public const string Metadata = "api/metadata"; + public const string MetadataById = "api/metadata/{0}"; + + } + } +} diff --git a/PCUT/Http.Core/Contexts/UserContext.cs b/PCUT/Http.Core/Contexts/UserContext.cs new file mode 100644 index 0000000..781f52f --- /dev/null +++ b/PCUT/Http.Core/Contexts/UserContext.cs @@ -0,0 +1,75 @@ +using Microsoft.IdentityModel.JsonWebTokens; +using PCUT.Entities; +using System; + +namespace Http.Core.Contexts +{ + public class UserContext : IDisposable + { + private UserContext() { } + private static readonly object _instanceLock = new object(); + private static UserContext _instance; + public static UserContext Instance + { + get + { + if (_instance == null) + { + lock (_instanceLock) + { + if (_instance == null) + _instance = new UserContext(); + } + } + return _instance; + } + } + + public UserProfile Profile { get; private set; } + public string AccessToken { get; private set; } + public string RefreshToken { get; private set; } + public string DeviceId { get; private set; } + public DateTime? ExpiredTime { get; private set; } + + public bool IsPermittedEdit => Profile.Role == "admin" || (Profile.IsPermittedEdit ?? false); + + public void SetDeviceId(string deviceId) + { + if (DeviceId == null) + { + DeviceId = deviceId; + } + } + + private readonly object _updateLock = new object(); + internal void SetValue(string accessToken, string refreshToken, string userName = null) + { + lock(_updateLock) + { + AccessToken = accessToken; + RefreshToken = refreshToken; + try + { + var token = new JsonWebToken(AccessToken); + ExpiredTime = token.ValidTo != DateTime.MinValue ? token.ValidTo : (DateTime?)null; + } + catch { } + } + } + + internal void SetProfile(UserProfile profile) + { + Profile = profile; + } + + public void Dispose() + { + AccessToken = null; + RefreshToken = null; + DeviceId = null; + ExpiredTime = null; + Profile = null; + _instance = null; + } + } +} diff --git a/PCUT/Http.Core/Extensions/CategoryExtensions.cs b/PCUT/Http.Core/Extensions/CategoryExtensions.cs new file mode 100644 index 0000000..1d3a778 --- /dev/null +++ b/PCUT/Http.Core/Extensions/CategoryExtensions.cs @@ -0,0 +1,37 @@ +using Http.Core.Contexts; +using PCUT.Entities; +using PCUT.Entities.ApiResponse; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net.Http; +using System.Text; +using System.Threading.Tasks; +using static Http.Core.Constants.HttpConstants; + +namespace Http.Core.Extensions +{ + public static class CategoryExtensions + { + public static async Task> GetCategoriesAsync(this HttpClient client, bool filterByRole = false) + { + try + { + var response = await client.GetAsync(Api.Categories); + if (response.IsSuccessStatusCode) + { + var apiResponse = await response.DeserializeObjectAsync>>(); + var permittedCategories = apiResponse.Data; + if (filterByRole && UserContext.Instance?.Profile?.Role != "admin") + permittedCategories = permittedCategories.Where(x => UserContext.Instance.Profile.Permissions.Contains(x.Id)); + + return permittedCategories; + } + } + catch + { + } + return Enumerable.Empty(); + } + } +} diff --git a/PCUT/Http.Core/Extensions/HttpExtensions.cs b/PCUT/Http.Core/Extensions/HttpExtensions.cs new file mode 100644 index 0000000..a2a69c8 --- /dev/null +++ b/PCUT/Http.Core/Extensions/HttpExtensions.cs @@ -0,0 +1,179 @@ +using System.Net.Http; +using System.Text; +using System.Threading.Tasks; +using System.IO; +using Http.Core.Contexts; +using Http.Core.Models; +using static Http.Core.Constants.HttpConstants; +using Newtonsoft.Json; +using Newtonsoft.Json.Serialization; +using PCUT.Entities.ApiResponse; +using PCUT.Entities; + +namespace Http.Core.Extensions +{ + public static class HttpExtensions + { + public static readonly JsonSerializerSettings JsonSerializerSettings = new JsonSerializerSettings + { + ContractResolver = new CamelCasePropertyNamesContractResolver() + }; + + public static readonly JsonSerializerSettings IgnoreNullJsonSerializerSettings = new JsonSerializerSettings + { + ContractResolver = new CamelCasePropertyNamesContractResolver(), + NullValueHandling = NullValueHandling.Ignore + }; + + public static readonly JsonSerializer DefaultSerializer = JsonSerializer.Create(JsonSerializerSettings); + + public static string FormatRoute(this string path, params object[] routeParams) + { + if (string.IsNullOrEmpty(path)) + return null; + return string.Format(path, routeParams); + } + + public static Task PostAsJsonAsync(this HttpClient client, string requestUri, object content = null, bool ignoreNull = false) + { + var jsonContent = content != null ? JsonConvert.SerializeObject(content, ignoreNull ? IgnoreNullJsonSerializerSettings : JsonSerializerSettings) : null; + var httpContent = jsonContent != null ? new StringContent(jsonContent, Encoding.UTF8, "application/json") : null; + return client.PostAsync(requestUri, httpContent); + } + + public static Task PutAsJsonAsync(this HttpClient client, string requestUri, object content = null, bool ignoreNull = false) + { + var jsonContent = content != null ? JsonConvert.SerializeObject(content, ignoreNull ? IgnoreNullJsonSerializerSettings : JsonSerializerSettings) : null; + var httpContent = jsonContent != null ? new StringContent(jsonContent, Encoding.UTF8, "application/json") : null; + return client.PutAsync(requestUri, httpContent); + } + + public static Task UploadAsync(this HttpClient client, string requestUri, Stream stream, string name, string filename) + { + var streamContent = new StreamContent(stream); + var httpContent = new MultipartFormDataContent + { + { streamContent, name, filename } + }; + return client.PostAsync(requestUri, httpContent); + } + + public static async Task DownloadAsync(this HttpClient client, string requestUri, Stream outputStream) + { + HttpResponseMessage response = null; + var isSuccess = true; + try + { + response = await client.GetAsync(requestUri, HttpCompletionOption.ResponseHeadersRead); + response.EnsureSuccessStatusCode(); + await response.Content.CopyToAsync(outputStream); + } + catch + { + isSuccess = false; + } + finally + { + response?.Dispose(); + } + return isSuccess; + } + + public static async Task LoginAsync(this HttpClient client, LoginRequest loginRequest, string username) + { + var response = await client.PostAsJsonAsync(Auth.Login, loginRequest); + if (response.IsSuccessStatusCode) + { + var userCredential = await response.DeserializeObjectAsync(); + UserContext.Instance.SetValue(userCredential.AccessToken, userCredential.RefreshToken, username); + return new LoginResult { Success = true }; + } + else + { + var responseContent = await response.DeserializeObjectAsync(ensureSuccess: false); + return new LoginResult { Success = false, Message = responseContent.ErrorMessage }; + } + } + + public static async Task LogOutAsync(this HttpClient client) + { + var response = await client.PostAsync(Api.LogOut, null); + if (response.IsSuccessStatusCode) + { + return true; + } + return false; + } + + public static async Task RefreshTokenAsync(this HttpClient client) + { + var response = await client.PostAsJsonAsync(Auth.Refresh, new RefreshTokenRequest()); + if (response.IsSuccessStatusCode) + { + var userCredential = await response.DeserializeObjectAsync(); + UserContext.Instance.SetValue(userCredential.AccessToken, userCredential.RefreshToken, userCredential.Username); + return true; + } + return false; + } + + public static async Task LoadUserProfileAsync(this HttpClient client) + { + var response = await client.GetAsync(Api.Profile); + if (response.IsSuccessStatusCode) + { + var content = await response.DeserializeObjectAsync>(); + UserContext.Instance.SetProfile(content.Data); + } + } + + public static async Task DeserializeObjectAsync(this HttpResponseMessage response, bool ensureSuccess = true) + { + if (ensureSuccess) + response.EnsureSuccessStatusCode(); + + if (response.StatusCode == System.Net.HttpStatusCode.NoContent) + return default; + + var content = response.Content; + if (content.Headers.ContentLength <= 0 || !content.Headers.ContentType.MediaType.Contains("application/json")) + return default; + + var contentStream = await response.Content.ReadAsStreamAsync(); + using (var reader = new StreamReader(contentStream)) + using (var jsonReader = new JsonTextReader(reader)) + { + return DefaultSerializer.Deserialize(jsonReader); + } + } + + public static StringBuilder AppendFilter(this StringBuilder builder, string key, string op, string value) + { + if (builder.Length > 0) + builder.Append(','); + return builder.Append('\"') + .Append(key).Append(':') + .Append(op).Append(':') + .Append(value) + .Append('\"'); + } + + public static StringBuilder AppendFilter(this StringBuilder builder, string key, string value) + { + return builder.AppendFilter(key, "eq", value); + } + + public static StringBuilder BuildFilter(this StringBuilder builder) + { + return builder.Insert(0, '[').Append(']'); + } + + public class LoginResult + { + public bool Success { get; set; } + + [JsonProperty("message")] + public string Message { get; set; } = string.Empty; + } + } +} diff --git a/PCUT/Http.Core/Handlers/AuthenticationHandler.cs b/PCUT/Http.Core/Handlers/AuthenticationHandler.cs new file mode 100644 index 0000000..e065fad --- /dev/null +++ b/PCUT/Http.Core/Handlers/AuthenticationHandler.cs @@ -0,0 +1,68 @@ +using Http.Core.Constants; +using Http.Core.Contexts; +using Http.Core.Extensions; +using Http.Core.Models; +using System; +using System.Net.Http; +using System.Net.Http.Headers; +using System.Threading; +using System.Threading.Tasks; + +namespace Http.Core.Handlers +{ + public class AuthenticationHandler : DelegatingHandler + { + public static readonly TimeSpan _requiredRefreshTime = TimeSpan.FromMinutes(5); + + protected override async Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) + { + var shouldContinue = await AppendTokenAsync(request); + if (!shouldContinue) + return new HttpResponseMessage(System.Net.HttpStatusCode.Unauthorized); + return await base.SendAsync(request, cancellationToken); + } + + private static readonly SemaphoreSlim _refreshSemaphore = new SemaphoreSlim(1, 1); + private async Task AppendTokenAsync(HttpRequestMessage request) + { + if (request.Headers.Authorization == null) + { + if (UserContext.Instance.AccessToken == null) + return false; + + var expiredTime = UserContext.Instance.ExpiredTime; + if (expiredTime != null || expiredTime - DateTime.UtcNow < _requiredRefreshTime) + { + await _refreshSemaphore.WaitAsync(); + bool refreshSuccess; + { + expiredTime = UserContext.Instance.ExpiredTime; + if (expiredTime != null || expiredTime - DateTime.UtcNow < _requiredRefreshTime) + refreshSuccess = await RefreshTokenAsync(); + else + refreshSuccess = true; // Some other thread already refreshed token + } + _refreshSemaphore.Release(); + if (!refreshSuccess) + return false; + } + request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", UserContext.Instance.AccessToken); + return true; + } + return true; + } + + private async Task RefreshTokenAsync() + { + try + { + using (var client = HttpClientFactory.CreateClient(HttpConstants.ClientNames.AuthClient)) + { + return await client.RefreshTokenAsync(); + } + } + catch { } + return false; + } + } +} diff --git a/PCUT/Http.Core/Handlers/DeviceAuthHandler.cs b/PCUT/Http.Core/Handlers/DeviceAuthHandler.cs new file mode 100644 index 0000000..bee7eec --- /dev/null +++ b/PCUT/Http.Core/Handlers/DeviceAuthHandler.cs @@ -0,0 +1,19 @@ +using Http.Core.Contexts; +using System; +using System.Collections.Generic; +using System.Net.Http; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace Http.Core.Handlers +{ + public class DeviceAuthHandler : DelegatingHandler + { + protected override Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) + { + request.Headers.Add("x-device-id", $"{UserContext.Instance.DeviceId}"); + return base.SendAsync(request, cancellationToken); + } + } +} diff --git a/PCUT/Http.Core/Http.Core.csproj b/PCUT/Http.Core/Http.Core.csproj new file mode 100644 index 0000000..c5f0ed0 --- /dev/null +++ b/PCUT/Http.Core/Http.Core.csproj @@ -0,0 +1,16 @@ + + + + netstandard2.0 + + + + + + + + + + + + diff --git a/PCUT/Http.Core/HttpClientFactory.cs b/PCUT/Http.Core/HttpClientFactory.cs new file mode 100644 index 0000000..79fd01a --- /dev/null +++ b/PCUT/Http.Core/HttpClientFactory.cs @@ -0,0 +1,132 @@ +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Linq; +using System.Net.Http; + +namespace Http.Core +{ + public class HttpClientFactory : IDisposable + { + private HttpClientFactory() { } + private static readonly object _instanceLock = new object(); + private static HttpClientFactory _instance; + public static HttpClientFactory Instance + { + get + { + if (_instance == null) + { + lock (_instanceLock) + { + if (_instance == null) + _instance = new HttpClientFactory(); + } + } + return _instance; + } + } + + public void Dispose() + { + foreach (var config in _configs) + { + config.Value.Dispose(); + } + _configs.Clear(); + } + + private readonly ConcurrentDictionary _configs = new ConcurrentDictionary(); + + public delegate void ConfigureBuilder(HttpClientBuilder builder); + public static HttpClientBuilder AddHttpClient(string name) + { + var builder = new HttpClientBuilder(); + _ = Instance._configs.TryAdd(name, builder.Config); + return builder; + } + + public static HttpClient CreateClient(string name) + { + if (!Instance._configs.ContainsKey(name)) + _ = Instance._configs.TryAdd(name, new HttpClientConfig()); + var config = Instance._configs[name]; + + var client = new HttpClient(config.Handler, false); + config.ConfigureClient?.Invoke(client); + return client; + } + + public delegate void ConfigureClient(HttpClient client); + public delegate DelegatingHandler HandlerFactory(); + public class HttpClientBuilder + { + internal HttpClientConfig Config { get; } = new HttpClientConfig(); + + public HttpClientBuilder AddConfigureClient(ConfigureClient configureClient) + { + Config.ConfigureClient += configureClient; + return this; + } + + public HttpClientBuilder AddHttpMessageHandler(HandlerFactory configureHandler) + { + Config.HandlerFactories.Add(configureHandler); + return this; + } + } + + internal class HttpClientConfig : IDisposable + { + internal ConfigureClient ConfigureClient { get; set; } + internal ICollection HandlerFactories { get; private set; } + + internal HttpClientConfig() + { + HandlerFactories = new List(); + } + + private readonly object _handlerLock = new object(); + private HttpMessageHandler _handler; + internal HttpMessageHandler Handler + { + get + { + if (_handler == null) + { + lock (_handlerLock) + { + if (_handler == null) + _handler = BuildHandler(); + } + } + return _handler; + } + } + + private HttpMessageHandler BuildHandler() + { + if (HandlerFactories == null || !HandlerFactories.Any()) + return new HttpClientHandler(); + + DelegatingHandler handler, intermediate; + handler = intermediate = HandlerFactories.First().Invoke(); + foreach (var handlerFactory in HandlerFactories.Skip(1)) + { + intermediate.InnerHandler = handlerFactory(); + intermediate = intermediate.InnerHandler as DelegatingHandler; + } + intermediate.InnerHandler = new HttpClientHandler(); + return handler; + } + + public void Dispose() + { + ConfigureClient = null; + HandlerFactories?.Clear(); + HandlerFactories = null; + _handler?.Dispose(); + } + } + } +} diff --git a/PCUT/Http.Core/Models/LoginRequest.cs b/PCUT/Http.Core/Models/LoginRequest.cs new file mode 100644 index 0000000..8c77070 --- /dev/null +++ b/PCUT/Http.Core/Models/LoginRequest.cs @@ -0,0 +1,14 @@ +namespace Http.Core.Models +{ + public class LoginRequest + { + public string Username { get; set; } + public string Password { get; set; } + + public LoginRequest(string username, string password) + { + Username = username; + Password = password; + } + } +} diff --git a/PCUT/Http.Core/Models/RefreshTokenRequest.cs b/PCUT/Http.Core/Models/RefreshTokenRequest.cs new file mode 100644 index 0000000..ce3eb50 --- /dev/null +++ b/PCUT/Http.Core/Models/RefreshTokenRequest.cs @@ -0,0 +1,11 @@ +using Http.Core.Contexts; +using Newtonsoft.Json; + +namespace Http.Core.Models +{ + internal class RefreshTokenRequest + { + [JsonProperty("refresh_token")] + public string RefreshToken => UserContext.Instance.RefreshToken; + } +} diff --git a/PCUT/Http.Core/PathBuilder.cs b/PCUT/Http.Core/PathBuilder.cs new file mode 100644 index 0000000..502b04c --- /dev/null +++ b/PCUT/Http.Core/PathBuilder.cs @@ -0,0 +1,94 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Http.Core +{ + public class PathBuilder + { + private readonly string _uriTemplate; + private readonly List _routeParams; + + private PathBuilder(string uriTemplate) + { + _uriTemplate = uriTemplate; + _routeParams = new List(); + } + + public static PathBuilder FromRouteTemplate(string urlTemplate) + { + return new PathBuilder(urlTemplate); + } + + public PathBuilder AddRouteParams(params string[] routeParams) + { + _routeParams.AddRange(routeParams); + return this; + } + + public QueryBuilder ToQuery() + { + return new QueryBuilder(_uriTemplate, _routeParams); + } + + public QueryBuilder AddQuery(string key, string value) + { + return ToQuery().AddQuery(key, value); + } + + public string Build() + { + if (!_routeParams.Any()) + return _uriTemplate; + + return new StringBuilder() + .AppendFormat(_uriTemplate, _routeParams.ToArray()) + .ToString(); + } + + public class QueryBuilder + { + private readonly string _uriTemplate; + private readonly List _routeParams; + private readonly IDictionary _queryParams; + + internal QueryBuilder(string uriTemplate, List routeParams) + { + _uriTemplate = uriTemplate; + _routeParams = routeParams; + _queryParams = new Dictionary(); + } + + public QueryBuilder AddQuery(string key, string value) + { + _queryParams[key] = Uri.EscapeDataString(value); + return this; + } + + public string Build() + { + var builder = new StringBuilder(); + + if (_routeParams.Any()) + builder.AppendFormat(_uriTemplate, _routeParams.ToArray()); + else + builder.Append(_uriTemplate); + + if (_queryParams.Any()) + { + builder.Append("?"); + foreach (var keyValuePair in _queryParams) + { + builder.Append(keyValuePair.Key) + .Append('=') + .Append(keyValuePair.Value) + .Append('&'); + } + builder.Remove(builder.Length - 1, 1); // remove last & character + } + return builder.ToString(); + } + } + } +} diff --git a/PCUT/MinkowskiCpp/Minkowski.cpp b/PCUT/MinkowskiCpp/Minkowski.cpp new file mode 100644 index 0000000..1b7252c --- /dev/null +++ b/PCUT/MinkowskiCpp/Minkowski.cpp @@ -0,0 +1,337 @@ +#include "pch.h" +#include "Minkowski.h" +#include + +#undef min +#undef max + +typedef boost::polygon::point_data point; +typedef boost::polygon::polygon_set_data polygon_set; +typedef boost::polygon::polygon_with_holes_data polygon; +typedef std::pair edge; + +using namespace MinkowskiCpp; +using namespace Platform; +using namespace boost::polygon::operators; +using namespace std; + +Minkowski::Minkowski() +{ +} + +void convolve_two_segments(std::vector& figure, const edge& a, const edge& b) { + using namespace boost::polygon; + figure.clear(); + figure.push_back(point(a.first)); + figure.push_back(point(a.first)); + figure.push_back(point(a.second)); + figure.push_back(point(a.second)); + convolve(figure[0], b.second); + convolve(figure[1], b.first); + convolve(figure[2], b.first); + convolve(figure[3], b.second); +} + +template +void convolve_two_point_sequences(polygon_set& result, itrT1 ab, itrT1 ae, itrT2 bb, itrT2 be) { + using namespace boost::polygon; + if (ab == ae || bb == be) + return; + point first_a = *ab; + point prev_a = *ab; + std::vector vec; + polygon poly; + ++ab; + for (; ab != ae; ++ab) { + point first_b = *bb; + point prev_b = *bb; + itrT2 tmpb = bb; + ++tmpb; + for (; tmpb != be; ++tmpb) { + convolve_two_segments(vec, std::make_pair(prev_b, *tmpb), std::make_pair(prev_a, *ab)); + set_points(poly, vec.begin(), vec.end()); + result.insert(poly); + prev_b = *tmpb; + } + prev_a = *ab; + } +} + +template +void convolve_point_sequence_with_polygons(polygon_set& result, itrT b, itrT e, const std::vector& polygons) { + using namespace boost::polygon; + for (std::size_t i = 0; i < polygons.size(); ++i) { + convolve_two_point_sequences(result, b, e, begin_points(polygons[i]), end_points(polygons[i])); + for (polygon_with_holes_traits::iterator_holes_type itrh = begin_holes(polygons[i]); + itrh != end_holes(polygons[i]); ++itrh) { + convolve_two_point_sequences(result, b, e, begin_points(*itrh), end_points(*itrh)); + } + } +} + +void convolve_two_polygon_sets(polygon_set& result, const polygon_set& a, const polygon_set& b) { + using namespace boost::polygon; + result.clear(); + std::vector a_polygons; + std::vector b_polygons; + a.get(a_polygons); + b.get(b_polygons); + for (std::size_t ai = 0; ai < a_polygons.size(); ++ai) { + convolve_point_sequence_with_polygons(result, begin_points(a_polygons[ai]), + end_points(a_polygons[ai]), b_polygons); + for (polygon_with_holes_traits::iterator_holes_type itrh = begin_holes(a_polygons[ai]); + itrh != end_holes(a_polygons[ai]); ++itrh) { + convolve_point_sequence_with_polygons(result, begin_points(*itrh), + end_points(*itrh), b_polygons); + } + for (std::size_t bi = 0; bi < b_polygons.size(); ++bi) { + polygon tmp_poly = a_polygons[ai]; + result.insert(convolve(tmp_poly, *(begin_points(b_polygons[bi])))); + tmp_poly = b_polygons[bi]; + result.insert(convolve(tmp_poly, *(begin_points(a_polygons[ai])))); + } + } +} + +double inputscale; + +using namespace boost::polygon; + +vector Avec; +vector Bvec; +vector> chlds; +vector> retpnts; +vector> retholes; + + +void MinkowskiCpp::Minkowski::getResults(Platform::WriteOnlyArray^ data, Platform::WriteOnlyArray^ holesData) +{ + int index = 0; + for (int i = 0; i < retpnts.size(); i++) { + for (int j = 0; j < retpnts[i].size(); j++) { + data[index] = retpnts[i][j]; + index++; + } + } + + index = 0; + for (int i = 0; i < retholes.size(); i++) { + for (int j = 0; j < retholes[i].size(); j++) { + holesData[index] = retholes[i][j]; + index++; + } + } +} + +void MinkowskiCpp::Minkowski::getSizes1(Platform::WriteOnlyArray^ sizes) +{ + sizes[0] = retpnts.size(); + sizes[1] = retholes.size(); +} + +void MinkowskiCpp::Minkowski::getSizes2(Platform::WriteOnlyArray^ sizes1, Platform::WriteOnlyArray^ sizes2) +{ + for (int i = 0; i < retpnts.size(); i++) { + sizes1[i] = retpnts[i].size(); + } + for (int i = 0; i < retholes.size(); i++) { + sizes2[i] = retholes[i].size(); + } +} + +void MinkowskiCpp::Minkowski::setData(int cntA, + const Platform::Array^ pntsA, + int holesCnt, + const Platform::Array^ holesSizes, + const Platform::Array^ holesPoints, + int cntB, + const Platform::Array^ pntsB) +{ + Avec.clear(); + Bvec.clear(); + chlds.clear(); + + retpnts.clear(); + retholes.clear(); + + for (int i = 0; i < cntA; i++) { + Avec.push_back(pntsA[i]); + } + for (int i = 0; i < cntB; i++) { + Bvec.push_back(pntsB[i]); + } + + int index = 0; + for (int i = 0; i < holesCnt; i++) { + chlds.push_back(vector()); + for (int j = 0; j < holesSizes[i]; j++) { + chlds.back().push_back(holesPoints[index]); + index++; + } + } +} + + +void MinkowskiCpp::Minkowski::calculateNFP() +{ + + polygon_set a, b, c; + std::vector polys; + std::vector pts; + + + + // get maximum bounds for scaling factor + unsigned int len = Avec.size() / 2; + double Amaxx = 0; + double Aminx = 0; + double Amaxy = 0; + double Aminy = 0; + for (unsigned int i = 0; i < len; i++) { + double x1 = Avec[i * 2]; + double y1 = Avec[i * 2 + 1]; + Amaxx = (std::max)(Amaxx, (double)x1); + Aminx = (std::min)(Aminx, (double)x1); + Amaxy = (std::max)(Amaxy, (double)y1); + Aminy = (std::min)(Aminy, (double)y1); + } + + len = Bvec.size() / 2; + double Bmaxx = 0; + double Bminx = 0; + double Bmaxy = 0; + double Bminy = 0; + for (unsigned int i = 0; i < len * 2; i += 2) { + double x1 = Bvec[i]; + double y1 = Bvec[i + 1]; + Bmaxx = (std::max)(Bmaxx, (double)x1); + Bminx = (std::min)(Bminx, (double)x1); + Bmaxy = (std::max)(Bmaxy, (double)y1); + Bminy = (std::min)(Bminy, (double)y1); + } + + double Cmaxx = Amaxx + Bmaxx; + double Cminx = Aminx + Bminx; + double Cmaxy = Amaxy + Bmaxy; + double Cminy = Aminy + Bminy; + + double maxxAbs = (std::max)(Cmaxx, std::fabs(Cminx)); + double maxyAbs = (std::max)(Cmaxy, std::fabs(Cminy)); + + double maxda = (std::max)(maxxAbs, maxyAbs); + int maxi = std::numeric_limits::max(); + + if (maxda < 1) { + maxda = 1; + } + + // why 0.1? dunno. it doesn't screw up with 0.1 + inputscale = (0.1f * (double)(maxi)) / maxda; + + //double scale = 1000; + len = Avec.size() / 2; + + for (unsigned int i = 0; i < len; i++) { + double x1 = Avec[i * 2]; + double y1 = Avec[i * 2 + 1]; + int x = (int)(inputscale * (double)x1); + int y = (int)(inputscale * (double)y1); + + pts.push_back(point(x, y)); + } + + polygon poly; + boost::polygon::set_points(poly, pts.begin(), pts.end()); + a += poly; + + // subtract holes from a here... + + len = chlds.size(); + + for (unsigned int i = 0; i < len; i++) { + vector hole = chlds[i]; + pts.clear(); + unsigned int hlen = hole.size() / 2; + for (unsigned int j = 0; j < hlen; j++) { + double x1 = hole[j * 2]; + double y1 = hole[j * 2 + 1]; + int x = (int)(inputscale * (double)x1); + int y = (int)(inputscale * (double)y1); + pts.push_back(point(x, y)); + } + boost::polygon::set_points(poly, pts.begin(), pts.end()); + a -= poly; + } + + //and then load points B + pts.clear(); + len = Bvec.size() / 2; + + //javascript nfps are referenced with respect to the first point + double xshift = 0; + double yshift = 0; + + for (unsigned int i = 0; i < len; i++) { + double x1 = Bvec[i * 2]; + double y1 = Bvec[i * 2 + 1]; + + int x = -(int)(inputscale * (double)x1); + int y = -(int)(inputscale * (double)y1); + pts.push_back(point(x, y)); + + if (i == 0) { + xshift = (double)x1; + yshift = (double)y1; + } + } + + boost::polygon::set_points(poly, pts.begin(), pts.end()); + b += poly; + + polys.clear(); + + convolve_two_polygon_sets(c, a, b); + c.get(polys); + + for (unsigned int i = 0; i < polys.size(); ++i) { + + vector pointlist = vector(); + + int j = 0; + + for (polygon_traits::iterator_type itr = polys[i].begin(); itr != polys[i].end(); ++itr) { + + // std::cout << (double)(*itr).get(boost::polygon::HORIZONTAL) / inputscale << std::endl; + double x1 = ((double)(*itr).get(boost::polygon::HORIZONTAL)) / inputscale + xshift; + double y1 = ((double)(*itr).get(boost::polygon::VERTICAL)) / inputscale + yshift; + + pointlist.push_back(x1); + pointlist.push_back(y1); + + j++; + } + retpnts.push_back(pointlist); + // holes + + int k = 0; + for (polygon_with_holes_traits::iterator_holes_type itrh = begin_holes(polys[i]); itrh != end_holes(polys[i]); ++itrh) { + vector child = vector(); + + + int z = 0; + for (polygon_traits::iterator_type itr2 = (*itrh).begin(); itr2 != (*itrh).end(); ++itr2) { + + double x1 = ((double)(*itr2).get(boost::polygon::HORIZONTAL)) / inputscale + xshift; + double y1 = ((double)(*itr2).get(boost::polygon::VERTICAL)) / inputscale + yshift; + + child.push_back(x1); + child.push_back(y1); + + z++; + } + retholes.push_back(child); + + k++; + } + } +} \ No newline at end of file diff --git a/PCUT/MinkowskiCpp/Minkowski.h b/PCUT/MinkowskiCpp/Minkowski.h new file mode 100644 index 0000000..ce87054 --- /dev/null +++ b/PCUT/MinkowskiCpp/Minkowski.h @@ -0,0 +1,17 @@ +#pragma once + +namespace MinkowskiCpp +{ + public ref class Minkowski sealed + { + public: + static void setData(int cntA, const Platform::Array^ pntsA, int holesCnt, const Platform::Array^ holesSizes, const Platform::Array^ holesPoints, int cntB, const Platform::Array^ pntsB); + static void getSizes1(Platform::WriteOnlyArray^ sizes); + static void getSizes2(Platform::WriteOnlyArray^ sizes1, Platform::WriteOnlyArray^ sizes2); + static void getResults(Platform::WriteOnlyArray^ data, Platform::WriteOnlyArray^ holesData); + static void calculateNFP(); + private: + Minkowski(); + static Minkowski^ Instance; + }; +} diff --git a/PCUT/MinkowskiCpp/MinkowskiCpp.vcxproj b/PCUT/MinkowskiCpp/MinkowskiCpp.vcxproj new file mode 100644 index 0000000..ef27d78 --- /dev/null +++ b/PCUT/MinkowskiCpp/MinkowskiCpp.vcxproj @@ -0,0 +1,451 @@ + + + + + Debug + ARM + + + Debug + ARM64 + + + Debug + Win32 + + + Debug + x64 + + + Release + ARM + + + Release + ARM64 + + + Release + Win32 + + + Release + x64 + + + + {71998b3c-e08f-4324-a087-2edeff1e3256} + WindowsRuntimeComponent + MinkowskiCpp + en-US + 14.0 + true + Windows Store + 10.0.22621.0 + 10.0.17763.0 + 10.0 + + + + DynamicLibrary + true + v143 + + + DynamicLibrary + true + v143 + + + DynamicLibrary + true + v143 + + + DynamicLibrary + true + v143 + + + DynamicLibrary + false + true + v143 + + + DynamicLibrary + false + true + v143 + + + DynamicLibrary + false + true + v143 + + + DynamicLibrary + false + true + v143 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + false + + + false + + + false + + + false + + + false + + + false + + + false + + + false + + + + Use + _WINRT_DLL;%(PreprocessorDefinitions) + pch.h + $(IntDir)pch.pch + $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories) + /bigobj %(AdditionalOptions) + 28204 + $(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories);$(ProjectDir)\boost_1_84_0 + + + Console + false + + + + + Use + _WINRT_DLL;NDEBUG;%(PreprocessorDefinitions) + pch.h + $(IntDir)pch.pch + $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories) + /bigobj %(AdditionalOptions) + 28204 + $(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories);$(ProjectDir)\boost_1_84_0 + + + Console + false + + + + + Use + _WINRT_DLL;%(PreprocessorDefinitions) + pch.h + $(IntDir)pch.pch + $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories) + /bigobj %(AdditionalOptions) + 28204 + $(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories);$(ProjectDir)\boost_1_84_0 + + + Console + false + + + + + Use + _WINRT_DLL;NDEBUG;%(PreprocessorDefinitions) + pch.h + $(IntDir)pch.pch + $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories) + /bigobj %(AdditionalOptions) + 28204 + $(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories);$(ProjectDir)\boost_1_84_0 + + + Console + false + + + + + Use + _WINRT_DLL;%(PreprocessorDefinitions) + pch.h + $(IntDir)pch.pch + $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories) + /bigobj %(AdditionalOptions) + 28204 + $(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories);$(ProjectDir)\boost_1_84_0 + + + Console + false + + + + + Use + _WINRT_DLL;NDEBUG;%(PreprocessorDefinitions) + pch.h + $(IntDir)pch.pch + $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories) + /bigobj %(AdditionalOptions) + 28204 + $(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories);$(ProjectDir)\boost_1_84_0 + + + Console + false + + + + + Use + _WINRT_DLL;%(PreprocessorDefinitions) + pch.h + $(IntDir)pch.pch + $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories) + /bigobj %(AdditionalOptions) + 28204 + $(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories);$(ProjectDir)\boost_1_84_0 + + + Console + false + + + + + Use + _WINRT_DLL;NDEBUG;%(PreprocessorDefinitions) + pch.h + $(IntDir)pch.pch + $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories) + /bigobj %(AdditionalOptions) + 28204 + $(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories);$(ProjectDir)\boost_1_84_0 + + + Console + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Create + Create + Create + Create + Create + Create + Create + Create + + + + + + \ No newline at end of file diff --git a/PCUT/MinkowskiCpp/MinkowskiCpp.vcxproj.filters b/PCUT/MinkowskiCpp/MinkowskiCpp.vcxproj.filters new file mode 100644 index 0000000..d9ab6ce --- /dev/null +++ b/PCUT/MinkowskiCpp/MinkowskiCpp.vcxproj.filters @@ -0,0 +1,171 @@ + + + + + ab1c52c7-026a-42f8-9a9e-7fdceed91912 + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tga;tiff;tif;png;wav;mfcribbon-ms + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/config.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config.hpp new file mode 100644 index 0000000..f00a980 --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config.hpp @@ -0,0 +1,67 @@ +// Boost config.hpp configuration header file ------------------------------// + +// (C) Copyright John Maddock 2002. +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org/libs/config for most recent version. + +// Boost config.hpp policy and rationale documentation has been moved to +// http://www.boost.org/libs/config +// +// CAUTION: This file is intended to be completely stable - +// DO NOT MODIFY THIS FILE! +// + +#ifndef BOOST_CONFIG_HPP +#define BOOST_CONFIG_HPP + +// if we don't have a user config, then use the default location: +#if !defined(BOOST_USER_CONFIG) && !defined(BOOST_NO_USER_CONFIG) +# define BOOST_USER_CONFIG +#if 0 +// For dependency trackers: +# include +#endif +#endif +// include it first: +#ifdef BOOST_USER_CONFIG +# include BOOST_USER_CONFIG +#endif + +// if we don't have a compiler config set, try and find one: +#if !defined(BOOST_COMPILER_CONFIG) && !defined(BOOST_NO_COMPILER_CONFIG) && !defined(BOOST_NO_CONFIG) +# include +#endif +// if we have a compiler config, include it now: +#ifdef BOOST_COMPILER_CONFIG +# include BOOST_COMPILER_CONFIG +#endif + +// if we don't have a std library config set, try and find one: +#if !defined(BOOST_STDLIB_CONFIG) && !defined(BOOST_NO_STDLIB_CONFIG) && !defined(BOOST_NO_CONFIG) && defined(__cplusplus) +# include +#endif +// if we have a std library config, include it now: +#ifdef BOOST_STDLIB_CONFIG +# include BOOST_STDLIB_CONFIG +#endif + +// if we don't have a platform config set, try and find one: +#if !defined(BOOST_PLATFORM_CONFIG) && !defined(BOOST_NO_PLATFORM_CONFIG) && !defined(BOOST_NO_CONFIG) +# include +#endif +// if we have a platform config, include it now: +#ifdef BOOST_PLATFORM_CONFIG +# include BOOST_PLATFORM_CONFIG +#endif + +// get config suffix code: +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +#endif // BOOST_CONFIG_HPP diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/abi/borland_prefix.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/abi/borland_prefix.hpp new file mode 100644 index 0000000..3a0e5ae --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/abi/borland_prefix.hpp @@ -0,0 +1,27 @@ +// (C) Copyright John Maddock 2003. +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// for C++ Builder the following options effect the ABI: +// +// -b (on or off - effect emum sizes) +// -Vx (on or off - empty members) +// -Ve (on or off - empty base classes) +// -aX (alignment - 5 options). +// -pX (Calling convention - 4 options) +// -VmX (member pointer size and layout - 5 options) +// -VC (on or off, changes name mangling) +// -Vl (on or off, changes struct layout). + +// In addition the following warnings are sufficiently annoying (and +// unfixable) to have them turned off by default: +// +// 8027 - functions containing [for|while] loops are not expanded inline +// 8026 - functions taking class by value arguments are not expanded inline + +#pragma nopushoptwarn +# pragma option push -a8 -Vx- -Ve- -b- -pc -Vmv -VC- -Vl- -w-8027 -w-8026 + + + diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/abi/borland_suffix.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/abi/borland_suffix.hpp new file mode 100644 index 0000000..940535f --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/abi/borland_suffix.hpp @@ -0,0 +1,12 @@ +// (C) Copyright John Maddock 2003. +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +# pragma option pop +#pragma nopushoptwarn + + + + + diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/abi/msvc_prefix.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/abi/msvc_prefix.hpp new file mode 100644 index 0000000..97f06cd --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/abi/msvc_prefix.hpp @@ -0,0 +1,22 @@ +// (C) Copyright John Maddock 2003. +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// +// Boost binaries are built with the compiler's default ABI settings, +// if the user changes their default alignment in the VS IDE then their +// code will no longer be binary compatible with the bjam built binaries +// unless this header is included to force Boost code into a consistent ABI. +// +// Note that inclusion of this header is only necessary for libraries with +// separate source, header only libraries DO NOT need this as long as all +// translation units are built with the same options. +// +#if defined(_M_X64) +# pragma pack(push,16) +#else +# pragma pack(push,8) +#endif + + diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/abi/msvc_suffix.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/abi/msvc_suffix.hpp new file mode 100644 index 0000000..a64d783 --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/abi/msvc_suffix.hpp @@ -0,0 +1,8 @@ +// (C) Copyright John Maddock 2003. +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#pragma pack(pop) + + diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/abi_prefix.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/abi_prefix.hpp new file mode 100644 index 0000000..bcdc26d --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/abi_prefix.hpp @@ -0,0 +1,25 @@ +// abi_prefix header -------------------------------------------------------// + +// (c) Copyright John Maddock 2003 + +// Use, modification and distribution are subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt). + +#ifndef BOOST_CONFIG_ABI_PREFIX_HPP +# define BOOST_CONFIG_ABI_PREFIX_HPP +#else +# error double inclusion of header boost/config/abi_prefix.hpp is an error +#endif + +#include + +// this must occur after all other includes and before any code appears: +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_PREFIX +#endif + +#if defined( BOOST_BORLANDC ) +#pragma nopushoptwarn +#endif + diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/abi_suffix.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/abi_suffix.hpp new file mode 100644 index 0000000..a1eb78d --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/abi_suffix.hpp @@ -0,0 +1,25 @@ +// abi_sufffix header -------------------------------------------------------// + +// (c) Copyright John Maddock 2003 + +// Use, modification and distribution are subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt). + +// This header should be #included AFTER code that was preceded by a #include +// . + +#ifndef BOOST_CONFIG_ABI_PREFIX_HPP +# error Header boost/config/abi_suffix.hpp must only be used after boost/config/abi_prefix.hpp +#else +# undef BOOST_CONFIG_ABI_PREFIX_HPP +#endif + +// the suffix header occurs after all of our code: +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_SUFFIX +#endif + +#if defined( BOOST_BORLANDC ) +#pragma nopushoptwarn +#endif diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/assert_cxx03.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/assert_cxx03.hpp new file mode 100644 index 0000000..c914aa8 --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/assert_cxx03.hpp @@ -0,0 +1,211 @@ +// This file was automatically generated on Fri Oct 13 19:09:38 2023 +// by libs/config/tools/generate.cpp +// Copyright John Maddock 2002-21. +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org/libs/config for the most recent version.// +// Revision $Id$ +// + +#include + +#ifdef BOOST_NO_ADL_BARRIER +# error "Your compiler appears not to be fully C++03 compliant. Detected via defect macro BOOST_NO_ADL_BARRIER." +#endif +#ifdef BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP +# error "Your compiler appears not to be fully C++03 compliant. Detected via defect macro BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP." +#endif +#ifdef BOOST_NO_ARRAY_TYPE_SPECIALIZATIONS +# error "Your compiler appears not to be fully C++03 compliant. Detected via defect macro BOOST_NO_ARRAY_TYPE_SPECIALIZATIONS." +#endif +#ifdef BOOST_NO_COMPLETE_VALUE_INITIALIZATION +# error "Your compiler appears not to be fully C++03 compliant. Detected via defect macro BOOST_NO_COMPLETE_VALUE_INITIALIZATION." +#endif +#ifdef BOOST_NO_CTYPE_FUNCTIONS +# error "Your compiler appears not to be fully C++03 compliant. Detected via defect macro BOOST_NO_CTYPE_FUNCTIONS." +#endif +#ifdef BOOST_NO_CV_SPECIALIZATIONS +# error "Your compiler appears not to be fully C++03 compliant. Detected via defect macro BOOST_NO_CV_SPECIALIZATIONS." +#endif +#ifdef BOOST_NO_CV_VOID_SPECIALIZATIONS +# error "Your compiler appears not to be fully C++03 compliant. Detected via defect macro BOOST_NO_CV_VOID_SPECIALIZATIONS." +#endif +#ifdef BOOST_NO_CWCHAR +# error "Your compiler appears not to be fully C++03 compliant. Detected via defect macro BOOST_NO_CWCHAR." +#endif +#ifdef BOOST_NO_CWCTYPE +# error "Your compiler appears not to be fully C++03 compliant. Detected via defect macro BOOST_NO_CWCTYPE." +#endif +#ifdef BOOST_NO_DEPENDENT_NESTED_DERIVATIONS +# error "Your compiler appears not to be fully C++03 compliant. Detected via defect macro BOOST_NO_DEPENDENT_NESTED_DERIVATIONS." +#endif +#ifdef BOOST_NO_DEPENDENT_TYPES_IN_TEMPLATE_VALUE_PARAMETERS +# error "Your compiler appears not to be fully C++03 compliant. Detected via defect macro BOOST_NO_DEPENDENT_TYPES_IN_TEMPLATE_VALUE_PARAMETERS." +#endif +#ifdef BOOST_NO_EXCEPTIONS +# error "Your compiler appears not to be fully C++03 compliant. Detected via defect macro BOOST_NO_EXCEPTIONS." +#endif +#ifdef BOOST_NO_EXCEPTION_STD_NAMESPACE +# error "Your compiler appears not to be fully C++03 compliant. Detected via defect macro BOOST_NO_EXCEPTION_STD_NAMESPACE." +#endif +#ifdef BOOST_NO_EXPLICIT_FUNCTION_TEMPLATE_ARGUMENTS +# error "Your compiler appears not to be fully C++03 compliant. Detected via defect macro BOOST_NO_EXPLICIT_FUNCTION_TEMPLATE_ARGUMENTS." +#endif +#ifdef BOOST_NO_FENV_H +# error "Your compiler appears not to be fully C++03 compliant. Detected via defect macro BOOST_NO_FENV_H." +#endif +#ifdef BOOST_NO_FUNCTION_TEMPLATE_ORDERING +# error "Your compiler appears not to be fully C++03 compliant. Detected via defect macro BOOST_NO_FUNCTION_TEMPLATE_ORDERING." +#endif +#ifdef BOOST_NO_FUNCTION_TYPE_SPECIALIZATIONS +# error "Your compiler appears not to be fully C++03 compliant. Detected via defect macro BOOST_NO_FUNCTION_TYPE_SPECIALIZATIONS." +#endif +#ifdef BOOST_NO_INCLASS_MEMBER_INITIALIZATION +# error "Your compiler appears not to be fully C++03 compliant. Detected via defect macro BOOST_NO_INCLASS_MEMBER_INITIALIZATION." +#endif +#ifdef BOOST_NO_INTEGRAL_INT64_T +# error "Your compiler appears not to be fully C++03 compliant. Detected via defect macro BOOST_NO_INTEGRAL_INT64_T." +#endif +#ifdef BOOST_NO_INTRINSIC_WCHAR_T +# error "Your compiler appears not to be fully C++03 compliant. Detected via defect macro BOOST_NO_INTRINSIC_WCHAR_T." +#endif +#ifdef BOOST_NO_IOSFWD +# error "Your compiler appears not to be fully C++03 compliant. Detected via defect macro BOOST_NO_IOSFWD." +#endif +#ifdef BOOST_NO_IOSTREAM +# error "Your compiler appears not to be fully C++03 compliant. Detected via defect macro BOOST_NO_IOSTREAM." +#endif +#ifdef BOOST_NO_IS_ABSTRACT +# error "Your compiler appears not to be fully C++03 compliant. Detected via defect macro BOOST_NO_IS_ABSTRACT." +#endif +#ifdef BOOST_NO_LIMITS +# error "Your compiler appears not to be fully C++03 compliant. Detected via defect macro BOOST_NO_LIMITS." +#endif +#ifdef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS +# error "Your compiler appears not to be fully C++03 compliant. Detected via defect macro BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS." +#endif +#ifdef BOOST_NO_LONG_LONG +# error "Your compiler appears not to be fully C++03 compliant. Detected via defect macro BOOST_NO_LONG_LONG." +#endif +#ifdef BOOST_NO_LONG_LONG_NUMERIC_LIMITS +# error "Your compiler appears not to be fully C++03 compliant. Detected via defect macro BOOST_NO_LONG_LONG_NUMERIC_LIMITS." +#endif +#ifdef BOOST_NO_MEMBER_FUNCTION_SPECIALIZATIONS +# error "Your compiler appears not to be fully C++03 compliant. Detected via defect macro BOOST_NO_MEMBER_FUNCTION_SPECIALIZATIONS." +#endif +#ifdef BOOST_NO_MEMBER_TEMPLATES +# error "Your compiler appears not to be fully C++03 compliant. Detected via defect macro BOOST_NO_MEMBER_TEMPLATES." +#endif +#ifdef BOOST_NO_MEMBER_TEMPLATE_FRIENDS +# error "Your compiler appears not to be fully C++03 compliant. Detected via defect macro BOOST_NO_MEMBER_TEMPLATE_FRIENDS." +#endif +#ifdef BOOST_NO_MEMBER_TEMPLATE_KEYWORD +# error "Your compiler appears not to be fully C++03 compliant. Detected via defect macro BOOST_NO_MEMBER_TEMPLATE_KEYWORD." +#endif +#ifdef BOOST_NO_NESTED_FRIENDSHIP +# error "Your compiler appears not to be fully C++03 compliant. Detected via defect macro BOOST_NO_NESTED_FRIENDSHIP." +#endif +#ifdef BOOST_NO_OPERATORS_IN_NAMESPACE +# error "Your compiler appears not to be fully C++03 compliant. Detected via defect macro BOOST_NO_OPERATORS_IN_NAMESPACE." +#endif +#ifdef BOOST_NO_PARTIAL_SPECIALIZATION_IMPLICIT_DEFAULT_ARGS +# error "Your compiler appears not to be fully C++03 compliant. Detected via defect macro BOOST_NO_PARTIAL_SPECIALIZATION_IMPLICIT_DEFAULT_ARGS." +#endif +#ifdef BOOST_NO_POINTER_TO_MEMBER_CONST +# error "Your compiler appears not to be fully C++03 compliant. Detected via defect macro BOOST_NO_POINTER_TO_MEMBER_CONST." +#endif +#ifdef BOOST_NO_POINTER_TO_MEMBER_TEMPLATE_PARAMETERS +# error "Your compiler appears not to be fully C++03 compliant. Detected via defect macro BOOST_NO_POINTER_TO_MEMBER_TEMPLATE_PARAMETERS." +#endif +#ifdef BOOST_NO_PRIVATE_IN_AGGREGATE +# error "Your compiler appears not to be fully C++03 compliant. Detected via defect macro BOOST_NO_PRIVATE_IN_AGGREGATE." +#endif +#ifdef BOOST_NO_RESTRICT_REFERENCES +# error "Your compiler appears not to be fully C++03 compliant. Detected via defect macro BOOST_NO_RESTRICT_REFERENCES." +#endif +#ifdef BOOST_NO_RTTI +# error "Your compiler appears not to be fully C++03 compliant. Detected via defect macro BOOST_NO_RTTI." +#endif +#ifdef BOOST_NO_SFINAE +# error "Your compiler appears not to be fully C++03 compliant. Detected via defect macro BOOST_NO_SFINAE." +#endif +#ifdef BOOST_NO_SFINAE_EXPR +# error "Your compiler appears not to be fully C++03 compliant. Detected via defect macro BOOST_NO_SFINAE_EXPR." +#endif +#ifdef BOOST_NO_STDC_NAMESPACE +# error "Your compiler appears not to be fully C++03 compliant. Detected via defect macro BOOST_NO_STDC_NAMESPACE." +#endif +#ifdef BOOST_NO_STD_ALLOCATOR +# error "Your compiler appears not to be fully C++03 compliant. Detected via defect macro BOOST_NO_STD_ALLOCATOR." +#endif +#ifdef BOOST_NO_STD_DISTANCE +# error "Your compiler appears not to be fully C++03 compliant. Detected via defect macro BOOST_NO_STD_DISTANCE." +#endif +#ifdef BOOST_NO_STD_ITERATOR +# error "Your compiler appears not to be fully C++03 compliant. Detected via defect macro BOOST_NO_STD_ITERATOR." +#endif +#ifdef BOOST_NO_STD_ITERATOR_TRAITS +# error "Your compiler appears not to be fully C++03 compliant. Detected via defect macro BOOST_NO_STD_ITERATOR_TRAITS." +#endif +#ifdef BOOST_NO_STD_LOCALE +# error "Your compiler appears not to be fully C++03 compliant. Detected via defect macro BOOST_NO_STD_LOCALE." +#endif +#ifdef BOOST_NO_STD_MESSAGES +# error "Your compiler appears not to be fully C++03 compliant. Detected via defect macro BOOST_NO_STD_MESSAGES." +#endif +#ifdef BOOST_NO_STD_MIN_MAX +# error "Your compiler appears not to be fully C++03 compliant. Detected via defect macro BOOST_NO_STD_MIN_MAX." +#endif +#ifdef BOOST_NO_STD_OUTPUT_ITERATOR_ASSIGN +# error "Your compiler appears not to be fully C++03 compliant. Detected via defect macro BOOST_NO_STD_OUTPUT_ITERATOR_ASSIGN." +#endif +#ifdef BOOST_NO_STD_TYPEINFO +# error "Your compiler appears not to be fully C++03 compliant. Detected via defect macro BOOST_NO_STD_TYPEINFO." +#endif +#ifdef BOOST_NO_STD_USE_FACET +# error "Your compiler appears not to be fully C++03 compliant. Detected via defect macro BOOST_NO_STD_USE_FACET." +#endif +#ifdef BOOST_NO_STD_WSTREAMBUF +# error "Your compiler appears not to be fully C++03 compliant. Detected via defect macro BOOST_NO_STD_WSTREAMBUF." +#endif +#ifdef BOOST_NO_STD_WSTRING +# error "Your compiler appears not to be fully C++03 compliant. Detected via defect macro BOOST_NO_STD_WSTRING." +#endif +#ifdef BOOST_NO_STRINGSTREAM +# error "Your compiler appears not to be fully C++03 compliant. Detected via defect macro BOOST_NO_STRINGSTREAM." +#endif +#ifdef BOOST_NO_TEMPLATED_IOSTREAMS +# error "Your compiler appears not to be fully C++03 compliant. Detected via defect macro BOOST_NO_TEMPLATED_IOSTREAMS." +#endif +#ifdef BOOST_NO_TEMPLATED_ITERATOR_CONSTRUCTORS +# error "Your compiler appears not to be fully C++03 compliant. Detected via defect macro BOOST_NO_TEMPLATED_ITERATOR_CONSTRUCTORS." +#endif +#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +# error "Your compiler appears not to be fully C++03 compliant. Detected via defect macro BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION." +#endif +#ifdef BOOST_NO_TEMPLATE_TEMPLATES +# error "Your compiler appears not to be fully C++03 compliant. Detected via defect macro BOOST_NO_TEMPLATE_TEMPLATES." +#endif +#ifdef BOOST_NO_TWO_PHASE_NAME_LOOKUP +# error "Your compiler appears not to be fully C++03 compliant. Detected via defect macro BOOST_NO_TWO_PHASE_NAME_LOOKUP." +#endif +#ifdef BOOST_NO_TYPEID +# error "Your compiler appears not to be fully C++03 compliant. Detected via defect macro BOOST_NO_TYPEID." +#endif +#ifdef BOOST_NO_TYPENAME_WITH_CTOR +# error "Your compiler appears not to be fully C++03 compliant. Detected via defect macro BOOST_NO_TYPENAME_WITH_CTOR." +#endif +#ifdef BOOST_NO_UNREACHABLE_RETURN_DETECTION +# error "Your compiler appears not to be fully C++03 compliant. Detected via defect macro BOOST_NO_UNREACHABLE_RETURN_DETECTION." +#endif +#ifdef BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE +# error "Your compiler appears not to be fully C++03 compliant. Detected via defect macro BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE." +#endif +#ifdef BOOST_NO_USING_TEMPLATE +# error "Your compiler appears not to be fully C++03 compliant. Detected via defect macro BOOST_NO_USING_TEMPLATE." +#endif +#ifdef BOOST_NO_VOID_RETURNS +# error "Your compiler appears not to be fully C++03 compliant. Detected via defect macro BOOST_NO_VOID_RETURNS." +#endif diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/assert_cxx11.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/assert_cxx11.hpp new file mode 100644 index 0000000..addd06a --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/assert_cxx11.hpp @@ -0,0 +1,212 @@ +// This file was automatically generated on Fri Oct 13 19:09:38 2023 +// by libs/config/tools/generate.cpp +// Copyright John Maddock 2002-21. +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org/libs/config for the most recent version.// +// Revision $Id$ +// + +#include +#include + +#ifdef BOOST_NO_CXX11_ADDRESSOF +# error "Your compiler appears not to be fully C++11 compliant. Detected via defect macro BOOST_NO_CXX11_ADDRESSOF." +#endif +#ifdef BOOST_NO_CXX11_ALIGNAS +# error "Your compiler appears not to be fully C++11 compliant. Detected via defect macro BOOST_NO_CXX11_ALIGNAS." +#endif +#ifdef BOOST_NO_CXX11_ALIGNOF +# error "Your compiler appears not to be fully C++11 compliant. Detected via defect macro BOOST_NO_CXX11_ALIGNOF." +#endif +#ifdef BOOST_NO_CXX11_ALLOCATOR +# error "Your compiler appears not to be fully C++11 compliant. Detected via defect macro BOOST_NO_CXX11_ALLOCATOR." +#endif +#ifdef BOOST_NO_CXX11_AUTO_DECLARATIONS +# error "Your compiler appears not to be fully C++11 compliant. Detected via defect macro BOOST_NO_CXX11_AUTO_DECLARATIONS." +#endif +#ifdef BOOST_NO_CXX11_AUTO_MULTIDECLARATIONS +# error "Your compiler appears not to be fully C++11 compliant. Detected via defect macro BOOST_NO_CXX11_AUTO_MULTIDECLARATIONS." +#endif +#ifdef BOOST_NO_CXX11_CHAR16_T +# error "Your compiler appears not to be fully C++11 compliant. Detected via defect macro BOOST_NO_CXX11_CHAR16_T." +#endif +#ifdef BOOST_NO_CXX11_CHAR32_T +# error "Your compiler appears not to be fully C++11 compliant. Detected via defect macro BOOST_NO_CXX11_CHAR32_T." +#endif +#ifdef BOOST_NO_CXX11_CONSTEXPR +# error "Your compiler appears not to be fully C++11 compliant. Detected via defect macro BOOST_NO_CXX11_CONSTEXPR." +#endif +#ifdef BOOST_NO_CXX11_DECLTYPE +# error "Your compiler appears not to be fully C++11 compliant. Detected via defect macro BOOST_NO_CXX11_DECLTYPE." +#endif +#ifdef BOOST_NO_CXX11_DECLTYPE_N3276 +# error "Your compiler appears not to be fully C++11 compliant. Detected via defect macro BOOST_NO_CXX11_DECLTYPE_N3276." +#endif +#ifdef BOOST_NO_CXX11_DEFAULTED_FUNCTIONS +# error "Your compiler appears not to be fully C++11 compliant. Detected via defect macro BOOST_NO_CXX11_DEFAULTED_FUNCTIONS." +#endif +#ifdef BOOST_NO_CXX11_DEFAULTED_MOVES +# error "Your compiler appears not to be fully C++11 compliant. Detected via defect macro BOOST_NO_CXX11_DEFAULTED_MOVES." +#endif +#ifdef BOOST_NO_CXX11_DELETED_FUNCTIONS +# error "Your compiler appears not to be fully C++11 compliant. Detected via defect macro BOOST_NO_CXX11_DELETED_FUNCTIONS." +#endif +#ifdef BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS +# error "Your compiler appears not to be fully C++11 compliant. Detected via defect macro BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS." +#endif +#ifdef BOOST_NO_CXX11_EXTERN_TEMPLATE +# error "Your compiler appears not to be fully C++11 compliant. Detected via defect macro BOOST_NO_CXX11_EXTERN_TEMPLATE." +#endif +#ifdef BOOST_NO_CXX11_FINAL +# error "Your compiler appears not to be fully C++11 compliant. Detected via defect macro BOOST_NO_CXX11_FINAL." +#endif +#ifdef BOOST_NO_CXX11_FIXED_LENGTH_VARIADIC_TEMPLATE_EXPANSION_PACKS +# error "Your compiler appears not to be fully C++11 compliant. Detected via defect macro BOOST_NO_CXX11_FIXED_LENGTH_VARIADIC_TEMPLATE_EXPANSION_PACKS." +#endif +#ifdef BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS +# error "Your compiler appears not to be fully C++11 compliant. Detected via defect macro BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS." +#endif +#ifdef BOOST_NO_CXX11_HDR_ARRAY +# error "Your compiler appears not to be fully C++11 compliant. Detected via defect macro BOOST_NO_CXX11_HDR_ARRAY." +#endif +#ifdef BOOST_NO_CXX11_HDR_ATOMIC +# error "Your compiler appears not to be fully C++11 compliant. Detected via defect macro BOOST_NO_CXX11_HDR_ATOMIC." +#endif +#ifdef BOOST_NO_CXX11_HDR_CHRONO +# error "Your compiler appears not to be fully C++11 compliant. Detected via defect macro BOOST_NO_CXX11_HDR_CHRONO." +#endif +#ifdef BOOST_NO_CXX11_HDR_CONDITION_VARIABLE +# error "Your compiler appears not to be fully C++11 compliant. Detected via defect macro BOOST_NO_CXX11_HDR_CONDITION_VARIABLE." +#endif +#ifdef BOOST_NO_CXX11_HDR_EXCEPTION +# error "Your compiler appears not to be fully C++11 compliant. Detected via defect macro BOOST_NO_CXX11_HDR_EXCEPTION." +#endif +#ifdef BOOST_NO_CXX11_HDR_FORWARD_LIST +# error "Your compiler appears not to be fully C++11 compliant. Detected via defect macro BOOST_NO_CXX11_HDR_FORWARD_LIST." +#endif +#ifdef BOOST_NO_CXX11_HDR_FUNCTIONAL +# error "Your compiler appears not to be fully C++11 compliant. Detected via defect macro BOOST_NO_CXX11_HDR_FUNCTIONAL." +#endif +#ifdef BOOST_NO_CXX11_HDR_FUTURE +# error "Your compiler appears not to be fully C++11 compliant. Detected via defect macro BOOST_NO_CXX11_HDR_FUTURE." +#endif +#ifdef BOOST_NO_CXX11_HDR_INITIALIZER_LIST +# error "Your compiler appears not to be fully C++11 compliant. Detected via defect macro BOOST_NO_CXX11_HDR_INITIALIZER_LIST." +#endif +#ifdef BOOST_NO_CXX11_HDR_MUTEX +# error "Your compiler appears not to be fully C++11 compliant. Detected via defect macro BOOST_NO_CXX11_HDR_MUTEX." +#endif +#ifdef BOOST_NO_CXX11_HDR_RANDOM +# error "Your compiler appears not to be fully C++11 compliant. Detected via defect macro BOOST_NO_CXX11_HDR_RANDOM." +#endif +#ifdef BOOST_NO_CXX11_HDR_RATIO +# error "Your compiler appears not to be fully C++11 compliant. Detected via defect macro BOOST_NO_CXX11_HDR_RATIO." +#endif +#ifdef BOOST_NO_CXX11_HDR_REGEX +# error "Your compiler appears not to be fully C++11 compliant. Detected via defect macro BOOST_NO_CXX11_HDR_REGEX." +#endif +#ifdef BOOST_NO_CXX11_HDR_SYSTEM_ERROR +# error "Your compiler appears not to be fully C++11 compliant. Detected via defect macro BOOST_NO_CXX11_HDR_SYSTEM_ERROR." +#endif +#ifdef BOOST_NO_CXX11_HDR_THREAD +# error "Your compiler appears not to be fully C++11 compliant. Detected via defect macro BOOST_NO_CXX11_HDR_THREAD." +#endif +#ifdef BOOST_NO_CXX11_HDR_TUPLE +# error "Your compiler appears not to be fully C++11 compliant. Detected via defect macro BOOST_NO_CXX11_HDR_TUPLE." +#endif +#ifdef BOOST_NO_CXX11_HDR_TYPEINDEX +# error "Your compiler appears not to be fully C++11 compliant. Detected via defect macro BOOST_NO_CXX11_HDR_TYPEINDEX." +#endif +#ifdef BOOST_NO_CXX11_HDR_TYPE_TRAITS +# error "Your compiler appears not to be fully C++11 compliant. Detected via defect macro BOOST_NO_CXX11_HDR_TYPE_TRAITS." +#endif +#ifdef BOOST_NO_CXX11_HDR_UNORDERED_MAP +# error "Your compiler appears not to be fully C++11 compliant. Detected via defect macro BOOST_NO_CXX11_HDR_UNORDERED_MAP." +#endif +#ifdef BOOST_NO_CXX11_HDR_UNORDERED_SET +# error "Your compiler appears not to be fully C++11 compliant. Detected via defect macro BOOST_NO_CXX11_HDR_UNORDERED_SET." +#endif +#ifdef BOOST_NO_CXX11_INLINE_NAMESPACES +# error "Your compiler appears not to be fully C++11 compliant. Detected via defect macro BOOST_NO_CXX11_INLINE_NAMESPACES." +#endif +#ifdef BOOST_NO_CXX11_LAMBDAS +# error "Your compiler appears not to be fully C++11 compliant. Detected via defect macro BOOST_NO_CXX11_LAMBDAS." +#endif +#ifdef BOOST_NO_CXX11_LOCAL_CLASS_TEMPLATE_PARAMETERS +# error "Your compiler appears not to be fully C++11 compliant. Detected via defect macro BOOST_NO_CXX11_LOCAL_CLASS_TEMPLATE_PARAMETERS." +#endif +#ifdef BOOST_NO_CXX11_NOEXCEPT +# error "Your compiler appears not to be fully C++11 compliant. Detected via defect macro BOOST_NO_CXX11_NOEXCEPT." +#endif +#ifdef BOOST_NO_CXX11_NON_PUBLIC_DEFAULTED_FUNCTIONS +# error "Your compiler appears not to be fully C++11 compliant. Detected via defect macro BOOST_NO_CXX11_NON_PUBLIC_DEFAULTED_FUNCTIONS." +#endif +#ifdef BOOST_NO_CXX11_NULLPTR +# error "Your compiler appears not to be fully C++11 compliant. Detected via defect macro BOOST_NO_CXX11_NULLPTR." +#endif +#ifdef BOOST_NO_CXX11_NUMERIC_LIMITS +# error "Your compiler appears not to be fully C++11 compliant. Detected via defect macro BOOST_NO_CXX11_NUMERIC_LIMITS." +#endif +#ifdef BOOST_NO_CXX11_OVERRIDE +# error "Your compiler appears not to be fully C++11 compliant. Detected via defect macro BOOST_NO_CXX11_OVERRIDE." +#endif +#ifdef BOOST_NO_CXX11_POINTER_TRAITS +# error "Your compiler appears not to be fully C++11 compliant. Detected via defect macro BOOST_NO_CXX11_POINTER_TRAITS." +#endif +#ifdef BOOST_NO_CXX11_RANGE_BASED_FOR +# error "Your compiler appears not to be fully C++11 compliant. Detected via defect macro BOOST_NO_CXX11_RANGE_BASED_FOR." +#endif +#ifdef BOOST_NO_CXX11_RAW_LITERALS +# error "Your compiler appears not to be fully C++11 compliant. Detected via defect macro BOOST_NO_CXX11_RAW_LITERALS." +#endif +#ifdef BOOST_NO_CXX11_REF_QUALIFIERS +# error "Your compiler appears not to be fully C++11 compliant. Detected via defect macro BOOST_NO_CXX11_REF_QUALIFIERS." +#endif +#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES +# error "Your compiler appears not to be fully C++11 compliant. Detected via defect macro BOOST_NO_CXX11_RVALUE_REFERENCES." +#endif +#ifdef BOOST_NO_CXX11_SCOPED_ENUMS +# error "Your compiler appears not to be fully C++11 compliant. Detected via defect macro BOOST_NO_CXX11_SCOPED_ENUMS." +#endif +#ifdef BOOST_NO_CXX11_SFINAE_EXPR +# error "Your compiler appears not to be fully C++11 compliant. Detected via defect macro BOOST_NO_CXX11_SFINAE_EXPR." +#endif +#ifdef BOOST_NO_CXX11_SMART_PTR +# error "Your compiler appears not to be fully C++11 compliant. Detected via defect macro BOOST_NO_CXX11_SMART_PTR." +#endif +#ifdef BOOST_NO_CXX11_STATIC_ASSERT +# error "Your compiler appears not to be fully C++11 compliant. Detected via defect macro BOOST_NO_CXX11_STATIC_ASSERT." +#endif +#ifdef BOOST_NO_CXX11_STD_ALIGN +# error "Your compiler appears not to be fully C++11 compliant. Detected via defect macro BOOST_NO_CXX11_STD_ALIGN." +#endif +#ifdef BOOST_NO_CXX11_TEMPLATE_ALIASES +# error "Your compiler appears not to be fully C++11 compliant. Detected via defect macro BOOST_NO_CXX11_TEMPLATE_ALIASES." +#endif +#ifdef BOOST_NO_CXX11_THREAD_LOCAL +# error "Your compiler appears not to be fully C++11 compliant. Detected via defect macro BOOST_NO_CXX11_THREAD_LOCAL." +#endif +#ifdef BOOST_NO_CXX11_TRAILING_RESULT_TYPES +# error "Your compiler appears not to be fully C++11 compliant. Detected via defect macro BOOST_NO_CXX11_TRAILING_RESULT_TYPES." +#endif +#ifdef BOOST_NO_CXX11_UNICODE_LITERALS +# error "Your compiler appears not to be fully C++11 compliant. Detected via defect macro BOOST_NO_CXX11_UNICODE_LITERALS." +#endif +#ifdef BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX +# error "Your compiler appears not to be fully C++11 compliant. Detected via defect macro BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX." +#endif +#ifdef BOOST_NO_CXX11_UNRESTRICTED_UNION +# error "Your compiler appears not to be fully C++11 compliant. Detected via defect macro BOOST_NO_CXX11_UNRESTRICTED_UNION." +#endif +#ifdef BOOST_NO_CXX11_USER_DEFINED_LITERALS +# error "Your compiler appears not to be fully C++11 compliant. Detected via defect macro BOOST_NO_CXX11_USER_DEFINED_LITERALS." +#endif +#ifdef BOOST_NO_CXX11_VARIADIC_MACROS +# error "Your compiler appears not to be fully C++11 compliant. Detected via defect macro BOOST_NO_CXX11_VARIADIC_MACROS." +#endif +#ifdef BOOST_NO_CXX11_VARIADIC_TEMPLATES +# error "Your compiler appears not to be fully C++11 compliant. Detected via defect macro BOOST_NO_CXX11_VARIADIC_TEMPLATES." +#endif diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/assert_cxx14.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/assert_cxx14.hpp new file mode 100644 index 0000000..061aba3 --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/assert_cxx14.hpp @@ -0,0 +1,47 @@ +// This file was automatically generated on Fri Oct 13 19:09:38 2023 +// by libs/config/tools/generate.cpp +// Copyright John Maddock 2002-21. +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org/libs/config for the most recent version.// +// Revision $Id$ +// + +#include +#include + +#ifdef BOOST_NO_CXX14_AGGREGATE_NSDMI +# error "Your compiler appears not to be fully C++14 compliant. Detected via defect macro BOOST_NO_CXX14_AGGREGATE_NSDMI." +#endif +#ifdef BOOST_NO_CXX14_BINARY_LITERALS +# error "Your compiler appears not to be fully C++14 compliant. Detected via defect macro BOOST_NO_CXX14_BINARY_LITERALS." +#endif +#ifdef BOOST_NO_CXX14_CONSTEXPR +# error "Your compiler appears not to be fully C++14 compliant. Detected via defect macro BOOST_NO_CXX14_CONSTEXPR." +#endif +#ifdef BOOST_NO_CXX14_DECLTYPE_AUTO +# error "Your compiler appears not to be fully C++14 compliant. Detected via defect macro BOOST_NO_CXX14_DECLTYPE_AUTO." +#endif +#ifdef BOOST_NO_CXX14_DIGIT_SEPARATORS +# error "Your compiler appears not to be fully C++14 compliant. Detected via defect macro BOOST_NO_CXX14_DIGIT_SEPARATORS." +#endif +#ifdef BOOST_NO_CXX14_GENERIC_LAMBDAS +# error "Your compiler appears not to be fully C++14 compliant. Detected via defect macro BOOST_NO_CXX14_GENERIC_LAMBDAS." +#endif +#ifdef BOOST_NO_CXX14_HDR_SHARED_MUTEX +# error "Your compiler appears not to be fully C++14 compliant. Detected via defect macro BOOST_NO_CXX14_HDR_SHARED_MUTEX." +#endif +#ifdef BOOST_NO_CXX14_INITIALIZED_LAMBDA_CAPTURES +# error "Your compiler appears not to be fully C++14 compliant. Detected via defect macro BOOST_NO_CXX14_INITIALIZED_LAMBDA_CAPTURES." +#endif +#ifdef BOOST_NO_CXX14_RETURN_TYPE_DEDUCTION +# error "Your compiler appears not to be fully C++14 compliant. Detected via defect macro BOOST_NO_CXX14_RETURN_TYPE_DEDUCTION." +#endif +#ifdef BOOST_NO_CXX14_STD_EXCHANGE +# error "Your compiler appears not to be fully C++14 compliant. Detected via defect macro BOOST_NO_CXX14_STD_EXCHANGE." +#endif +#ifdef BOOST_NO_CXX14_VARIABLE_TEMPLATES +# error "Your compiler appears not to be fully C++14 compliant. Detected via defect macro BOOST_NO_CXX14_VARIABLE_TEMPLATES." +#endif diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/assert_cxx17.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/assert_cxx17.hpp new file mode 100644 index 0000000..ffa1ae9 --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/assert_cxx17.hpp @@ -0,0 +1,62 @@ +// This file was automatically generated on Fri Oct 13 19:09:38 2023 +// by libs/config/tools/generate.cpp +// Copyright John Maddock 2002-21. +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org/libs/config for the most recent version.// +// Revision $Id$ +// + +#include +#include + +#ifdef BOOST_NO_CXX17_DEDUCTION_GUIDES +# error "Your compiler appears not to be fully C++17 compliant. Detected via defect macro BOOST_NO_CXX17_DEDUCTION_GUIDES." +#endif +#ifdef BOOST_NO_CXX17_FOLD_EXPRESSIONS +# error "Your compiler appears not to be fully C++17 compliant. Detected via defect macro BOOST_NO_CXX17_FOLD_EXPRESSIONS." +#endif +#ifdef BOOST_NO_CXX17_HDR_ANY +# error "Your compiler appears not to be fully C++17 compliant. Detected via defect macro BOOST_NO_CXX17_HDR_ANY." +#endif +#ifdef BOOST_NO_CXX17_HDR_CHARCONV +# error "Your compiler appears not to be fully C++17 compliant. Detected via defect macro BOOST_NO_CXX17_HDR_CHARCONV." +#endif +#ifdef BOOST_NO_CXX17_HDR_EXECUTION +# error "Your compiler appears not to be fully C++17 compliant. Detected via defect macro BOOST_NO_CXX17_HDR_EXECUTION." +#endif +#ifdef BOOST_NO_CXX17_HDR_FILESYSTEM +# error "Your compiler appears not to be fully C++17 compliant. Detected via defect macro BOOST_NO_CXX17_HDR_FILESYSTEM." +#endif +#ifdef BOOST_NO_CXX17_HDR_MEMORY_RESOURCE +# error "Your compiler appears not to be fully C++17 compliant. Detected via defect macro BOOST_NO_CXX17_HDR_MEMORY_RESOURCE." +#endif +#ifdef BOOST_NO_CXX17_HDR_OPTIONAL +# error "Your compiler appears not to be fully C++17 compliant. Detected via defect macro BOOST_NO_CXX17_HDR_OPTIONAL." +#endif +#ifdef BOOST_NO_CXX17_HDR_STRING_VIEW +# error "Your compiler appears not to be fully C++17 compliant. Detected via defect macro BOOST_NO_CXX17_HDR_STRING_VIEW." +#endif +#ifdef BOOST_NO_CXX17_HDR_VARIANT +# error "Your compiler appears not to be fully C++17 compliant. Detected via defect macro BOOST_NO_CXX17_HDR_VARIANT." +#endif +#ifdef BOOST_NO_CXX17_IF_CONSTEXPR +# error "Your compiler appears not to be fully C++17 compliant. Detected via defect macro BOOST_NO_CXX17_IF_CONSTEXPR." +#endif +#ifdef BOOST_NO_CXX17_INLINE_VARIABLES +# error "Your compiler appears not to be fully C++17 compliant. Detected via defect macro BOOST_NO_CXX17_INLINE_VARIABLES." +#endif +#ifdef BOOST_NO_CXX17_ITERATOR_TRAITS +# error "Your compiler appears not to be fully C++17 compliant. Detected via defect macro BOOST_NO_CXX17_ITERATOR_TRAITS." +#endif +#ifdef BOOST_NO_CXX17_STD_APPLY +# error "Your compiler appears not to be fully C++17 compliant. Detected via defect macro BOOST_NO_CXX17_STD_APPLY." +#endif +#ifdef BOOST_NO_CXX17_STD_INVOKE +# error "Your compiler appears not to be fully C++17 compliant. Detected via defect macro BOOST_NO_CXX17_STD_INVOKE." +#endif +#ifdef BOOST_NO_CXX17_STRUCTURED_BINDINGS +# error "Your compiler appears not to be fully C++17 compliant. Detected via defect macro BOOST_NO_CXX17_STRUCTURED_BINDINGS." +#endif diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/assert_cxx20.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/assert_cxx20.hpp new file mode 100644 index 0000000..71a7415 --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/assert_cxx20.hpp @@ -0,0 +1,59 @@ +// This file was automatically generated on Fri Oct 13 19:09:38 2023 +// by libs/config/tools/generate.cpp +// Copyright John Maddock 2002-21. +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org/libs/config for the most recent version.// +// Revision $Id$ +// + +#include +#include + +#ifdef BOOST_NO_CXX20_HDR_BARRIER +# error "Your compiler appears not to be fully C++20 compliant. Detected via defect macro BOOST_NO_CXX20_HDR_BARRIER." +#endif +#ifdef BOOST_NO_CXX20_HDR_BIT +# error "Your compiler appears not to be fully C++20 compliant. Detected via defect macro BOOST_NO_CXX20_HDR_BIT." +#endif +#ifdef BOOST_NO_CXX20_HDR_COMPARE +# error "Your compiler appears not to be fully C++20 compliant. Detected via defect macro BOOST_NO_CXX20_HDR_COMPARE." +#endif +#ifdef BOOST_NO_CXX20_HDR_CONCEPTS +# error "Your compiler appears not to be fully C++20 compliant. Detected via defect macro BOOST_NO_CXX20_HDR_CONCEPTS." +#endif +#ifdef BOOST_NO_CXX20_HDR_COROUTINE +# error "Your compiler appears not to be fully C++20 compliant. Detected via defect macro BOOST_NO_CXX20_HDR_COROUTINE." +#endif +#ifdef BOOST_NO_CXX20_HDR_FORMAT +# error "Your compiler appears not to be fully C++20 compliant. Detected via defect macro BOOST_NO_CXX20_HDR_FORMAT." +#endif +#ifdef BOOST_NO_CXX20_HDR_LATCH +# error "Your compiler appears not to be fully C++20 compliant. Detected via defect macro BOOST_NO_CXX20_HDR_LATCH." +#endif +#ifdef BOOST_NO_CXX20_HDR_NUMBERS +# error "Your compiler appears not to be fully C++20 compliant. Detected via defect macro BOOST_NO_CXX20_HDR_NUMBERS." +#endif +#ifdef BOOST_NO_CXX20_HDR_RANGES +# error "Your compiler appears not to be fully C++20 compliant. Detected via defect macro BOOST_NO_CXX20_HDR_RANGES." +#endif +#ifdef BOOST_NO_CXX20_HDR_SEMAPHORE +# error "Your compiler appears not to be fully C++20 compliant. Detected via defect macro BOOST_NO_CXX20_HDR_SEMAPHORE." +#endif +#ifdef BOOST_NO_CXX20_HDR_SOURCE_LOCATION +# error "Your compiler appears not to be fully C++20 compliant. Detected via defect macro BOOST_NO_CXX20_HDR_SOURCE_LOCATION." +#endif +#ifdef BOOST_NO_CXX20_HDR_SPAN +# error "Your compiler appears not to be fully C++20 compliant. Detected via defect macro BOOST_NO_CXX20_HDR_SPAN." +#endif +#ifdef BOOST_NO_CXX20_HDR_STOP_TOKEN +# error "Your compiler appears not to be fully C++20 compliant. Detected via defect macro BOOST_NO_CXX20_HDR_STOP_TOKEN." +#endif +#ifdef BOOST_NO_CXX20_HDR_SYNCSTREAM +# error "Your compiler appears not to be fully C++20 compliant. Detected via defect macro BOOST_NO_CXX20_HDR_SYNCSTREAM." +#endif +#ifdef BOOST_NO_CXX20_HDR_VERSION +# error "Your compiler appears not to be fully C++20 compliant. Detected via defect macro BOOST_NO_CXX20_HDR_VERSION." +#endif diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/assert_cxx23.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/assert_cxx23.hpp new file mode 100644 index 0000000..feb4457 --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/assert_cxx23.hpp @@ -0,0 +1,41 @@ +// This file was automatically generated on Fri Oct 13 19:09:38 2023 +// by libs/config/tools/generate.cpp +// Copyright John Maddock 2002-21. +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org/libs/config for the most recent version.// +// Revision $Id$ +// + +#include +#include + +#ifdef BOOST_NO_CXX23_HDR_EXPECTED +# error "Your compiler appears not to be fully C++23 compliant. Detected via defect macro BOOST_NO_CXX23_HDR_EXPECTED." +#endif +#ifdef BOOST_NO_CXX23_HDR_FLAT_MAP +# error "Your compiler appears not to be fully C++23 compliant. Detected via defect macro BOOST_NO_CXX23_HDR_FLAT_MAP." +#endif +#ifdef BOOST_NO_CXX23_HDR_FLAT_SET +# error "Your compiler appears not to be fully C++23 compliant. Detected via defect macro BOOST_NO_CXX23_HDR_FLAT_SET." +#endif +#ifdef BOOST_NO_CXX23_HDR_GENERATOR +# error "Your compiler appears not to be fully C++23 compliant. Detected via defect macro BOOST_NO_CXX23_HDR_GENERATOR." +#endif +#ifdef BOOST_NO_CXX23_HDR_MDSPAN +# error "Your compiler appears not to be fully C++23 compliant. Detected via defect macro BOOST_NO_CXX23_HDR_MDSPAN." +#endif +#ifdef BOOST_NO_CXX23_HDR_PRINT +# error "Your compiler appears not to be fully C++23 compliant. Detected via defect macro BOOST_NO_CXX23_HDR_PRINT." +#endif +#ifdef BOOST_NO_CXX23_HDR_SPANSTREAM +# error "Your compiler appears not to be fully C++23 compliant. Detected via defect macro BOOST_NO_CXX23_HDR_SPANSTREAM." +#endif +#ifdef BOOST_NO_CXX23_HDR_STACKTRACE +# error "Your compiler appears not to be fully C++23 compliant. Detected via defect macro BOOST_NO_CXX23_HDR_STACKTRACE." +#endif +#ifdef BOOST_NO_CXX23_HDR_STDFLOAT +# error "Your compiler appears not to be fully C++23 compliant. Detected via defect macro BOOST_NO_CXX23_HDR_STDFLOAT." +#endif diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/assert_cxx98.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/assert_cxx98.hpp new file mode 100644 index 0000000..aa745d4 --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/assert_cxx98.hpp @@ -0,0 +1,23 @@ +// This file was automatically generated on Wed Mar 3 08:46:11 2021 +// by libs/config/tools/generate.cpp +// Copyright John Maddock 2002-4. +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org/libs/config for the most recent version.// +// Revision $Id$ +// + +#include +#include + +#ifdef BOOST_NO_CXX98_BINDERS +# error "Your compiler appears not to be fully C++98 compliant. Detected via defect macro BOOST_NO_CXX98_BINDERS." +#endif +#ifdef BOOST_NO_CXX98_FUNCTION_BASE +# error "Your compiler appears not to be fully C++98 compliant. Detected via defect macro BOOST_NO_CXX98_FUNCTION_BASE." +#endif +#ifdef BOOST_NO_CXX98_RANDOM_SHUFFLE +# error "Your compiler appears not to be fully C++98 compliant. Detected via defect macro BOOST_NO_CXX98_RANDOM_SHUFFLE." +#endif diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/auto_link.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/auto_link.hpp new file mode 100644 index 0000000..64dee1e --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/auto_link.hpp @@ -0,0 +1,525 @@ +// (C) Copyright John Maddock 2003. +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + + /* + * LOCATION: see http://www.boost.org for most recent version. + * FILE auto_link.hpp + * VERSION see + * DESCRIPTION: Automatic library inclusion for Borland/Microsoft compilers. + */ + +/************************************************************************* + +USAGE: +~~~~~~ + +Before including this header you must define one or more of define the following macros: + +BOOST_LIB_NAME: Required: A string containing the basename of the library, + for example boost_regex. +BOOST_LIB_TOOLSET: Optional: the base name of the toolset. +BOOST_DYN_LINK: Optional: when set link to dll rather than static library. +BOOST_LIB_DIAGNOSTIC: Optional: when set the header will print out the name + of the library selected (useful for debugging). +BOOST_AUTO_LINK_NOMANGLE: Specifies that we should link to BOOST_LIB_NAME.lib, + rather than a mangled-name version. +BOOST_AUTO_LINK_TAGGED: Specifies that we link to libraries built with the --layout=tagged option. + This is essentially the same as the default name-mangled version, but without + the compiler name and version, or the Boost version. Just the build options. +BOOST_AUTO_LINK_SYSTEM: Specifies that we link to libraries built with the --layout=system option. + This is essentially the same as the non-name-mangled version, but with + the prefix to differentiate static and dll builds + +These macros will be undef'ed at the end of the header, further this header +has no include guards - so be sure to include it only once from your library! + +Algorithm: +~~~~~~~~~~ + +Libraries for Borland and Microsoft compilers are automatically +selected here, the name of the lib is selected according to the following +formula: + +BOOST_LIB_PREFIX + + BOOST_LIB_NAME + + "_" + + BOOST_LIB_TOOLSET + + BOOST_LIB_THREAD_OPT + + BOOST_LIB_RT_OPT + + BOOST_LIB_ARCH_AND_MODEL_OPT + "-" + + BOOST_LIB_VERSION + + BOOST_LIB_SUFFIX + +These are defined as: + +BOOST_LIB_PREFIX: "lib" for static libraries otherwise "". + +BOOST_LIB_NAME: The base name of the lib ( for example boost_regex). + +BOOST_LIB_TOOLSET: The compiler toolset name (vc6, vc7, bcb5 etc). + +BOOST_LIB_THREAD_OPT: "-mt" for multithread builds, otherwise nothing. + +BOOST_LIB_RT_OPT: A suffix that indicates the runtime library used, + contains one or more of the following letters after + a hyphen: + + s static runtime (dynamic if not present). + g debug/diagnostic runtime (release if not present). + y Python debug/diagnostic runtime (release if not present). + d debug build (release if not present). + p STLport build. + n STLport build without its IOStreams. + +BOOST_LIB_ARCH_AND_MODEL_OPT: The architecture and address model + (-x32 or -x64 for x86/32 and x86/64 respectively) + +BOOST_LIB_VERSION: The Boost version, in the form x_y, for Boost version x.y. + +BOOST_LIB_SUFFIX: Static/import libraries extension (".lib", ".a") for the compiler. + +***************************************************************************/ + +#ifdef __cplusplus +# ifndef BOOST_CONFIG_HPP +# include +# endif +#elif defined(_MSC_VER) && !defined(__MWERKS__) && !defined(__EDG_VERSION__) +// +// C language compatability (no, honestly) +// +# define BOOST_MSVC _MSC_VER +# define BOOST_STRINGIZE(X) BOOST_DO_STRINGIZE(X) +# define BOOST_DO_STRINGIZE(X) #X +#endif +// +// Only include what follows for known and supported compilers: +// +#if defined(BOOST_MSVC) \ + || defined(BOOST_EMBTC_WINDOWS) \ + || defined(BOOST_BORLANDC) \ + || (defined(__MWERKS__) && defined(_WIN32) && (__MWERKS__ >= 0x3000)) \ + || (defined(__ICL) && defined(_MSC_EXTENSIONS) && (_MSC_VER >= 1200)) \ + || (defined(BOOST_CLANG) && defined(BOOST_WINDOWS) && defined(_MSC_VER) && (__clang_major__ >= 4)) + +#ifndef BOOST_VERSION_HPP +# include +#endif + +#ifndef BOOST_LIB_NAME +# error "Macro BOOST_LIB_NAME not set (internal error)" +#endif + +// +// error check: +// +#if defined(__MSVC_RUNTIME_CHECKS) && !defined(_DEBUG) +# pragma message("Using the /RTC option without specifying a debug runtime will lead to linker errors") +# pragma message("Hint: go to the code generation options and switch to one of the debugging runtimes") +# error "Incompatible build options" +#endif +// +// select toolset if not defined already: +// +#ifndef BOOST_LIB_TOOLSET +# if defined(BOOST_MSVC) && (BOOST_MSVC < 1200) + // Note: no compilers before 1200 are supported +# elif defined(BOOST_MSVC) && (BOOST_MSVC < 1300) + +# ifdef UNDER_CE + // eVC4: +# define BOOST_LIB_TOOLSET "evc4" +# else + // vc6: +# define BOOST_LIB_TOOLSET "vc6" +# endif + +# elif defined(BOOST_MSVC) && (BOOST_MSVC < 1310) + + // vc7: +# define BOOST_LIB_TOOLSET "vc7" + +# elif defined(BOOST_MSVC) && (BOOST_MSVC < 1400) + + // vc71: +# define BOOST_LIB_TOOLSET "vc71" + +# elif defined(BOOST_MSVC) && (BOOST_MSVC < 1500) + + // vc80: +# define BOOST_LIB_TOOLSET "vc80" + +# elif defined(BOOST_MSVC) && (BOOST_MSVC < 1600) + + // vc90: +# define BOOST_LIB_TOOLSET "vc90" + +# elif defined(BOOST_MSVC) && (BOOST_MSVC < 1700) + + // vc10: +# define BOOST_LIB_TOOLSET "vc100" + +# elif defined(BOOST_MSVC) && (BOOST_MSVC < 1800) + + // vc11: +# define BOOST_LIB_TOOLSET "vc110" + +# elif defined(BOOST_MSVC) && (BOOST_MSVC < 1900) + + // vc12: +# define BOOST_LIB_TOOLSET "vc120" + +# elif defined(BOOST_MSVC) && (BOOST_MSVC < 1910) + + // vc14: +# define BOOST_LIB_TOOLSET "vc140" + +# elif defined(BOOST_MSVC) && (BOOST_MSVC < 1920) + + // vc14.1: +# define BOOST_LIB_TOOLSET "vc141" + +# elif defined(BOOST_MSVC) && (BOOST_MSVC < 1930) + + // vc14.2: +# define BOOST_LIB_TOOLSET "vc142" + +# elif defined(BOOST_MSVC) + + // vc14.3: +# define BOOST_LIB_TOOLSET "vc143" + +# elif defined(BOOST_EMBTC_WINDOWS) + + // Embarcadero Clang based compilers: +# define BOOST_LIB_TOOLSET "embtc" + +# elif defined(BOOST_BORLANDC) + + // CBuilder 6: +# define BOOST_LIB_TOOLSET "bcb" + +# elif defined(__ICL) + + // Intel C++, no version number: +# define BOOST_LIB_TOOLSET "iw" + +# elif defined(__MWERKS__) && (__MWERKS__ <= 0x31FF ) + + // Metrowerks CodeWarrior 8.x +# define BOOST_LIB_TOOLSET "cw8" + +# elif defined(__MWERKS__) && (__MWERKS__ <= 0x32FF ) + + // Metrowerks CodeWarrior 9.x +# define BOOST_LIB_TOOLSET "cw9" + +# elif defined(BOOST_CLANG) && defined(BOOST_WINDOWS) && defined(_MSC_VER) && (__clang_major__ >= 4) + + // Clang on Windows +# define BOOST_LIB_TOOLSET "clangw" BOOST_STRINGIZE(__clang_major__) + +# endif +#endif // BOOST_LIB_TOOLSET + +// +// select thread opt: +// +#if defined(_MT) || defined(__MT__) +# define BOOST_LIB_THREAD_OPT "-mt" +#else +# define BOOST_LIB_THREAD_OPT +#endif + +#if defined(_MSC_VER) || defined(__MWERKS__) + +# ifdef _DLL + +# if (defined(__SGI_STL_PORT) || defined(_STLPORT_VERSION)) && (defined(_STLP_OWN_IOSTREAMS) || defined(__STL_OWN_IOSTREAMS)) + +# if defined(_DEBUG) && (defined(__STL_DEBUG) || defined(_STLP_DEBUG))\ + && defined(BOOST_DEBUG_PYTHON) && defined(BOOST_LINKING_PYTHON) +# define BOOST_LIB_RT_OPT "-gydp" +# elif defined(_DEBUG) && (defined(__STL_DEBUG) || defined(_STLP_DEBUG)) +# define BOOST_LIB_RT_OPT "-gdp" +# elif defined(_DEBUG)\ + && defined(BOOST_DEBUG_PYTHON) && defined(BOOST_LINKING_PYTHON) +# define BOOST_LIB_RT_OPT "-gydp" +# pragma message("warning: STLport debug versions are built with /D_STLP_DEBUG=1") +# error "Build options aren't compatible with pre-built libraries" +# elif defined(_DEBUG) +# define BOOST_LIB_RT_OPT "-gdp" +# pragma message("warning: STLport debug versions are built with /D_STLP_DEBUG=1") +# error "Build options aren't compatible with pre-built libraries" +# else +# define BOOST_LIB_RT_OPT "-p" +# endif + +# elif defined(__SGI_STL_PORT) || defined(_STLPORT_VERSION) + +# if defined(_DEBUG) && (defined(__STL_DEBUG) || defined(_STLP_DEBUG))\ + && defined(BOOST_DEBUG_PYTHON) && defined(BOOST_LINKING_PYTHON) +# define BOOST_LIB_RT_OPT "-gydpn" +# elif defined(_DEBUG) && (defined(__STL_DEBUG) || defined(_STLP_DEBUG)) +# define BOOST_LIB_RT_OPT "-gdpn" +# elif defined(_DEBUG)\ + && defined(BOOST_DEBUG_PYTHON) && defined(BOOST_LINKING_PYTHON) +# define BOOST_LIB_RT_OPT "-gydpn" +# pragma message("warning: STLport debug versions are built with /D_STLP_DEBUG=1") +# error "Build options aren't compatible with pre-built libraries" +# elif defined(_DEBUG) +# define BOOST_LIB_RT_OPT "-gdpn" +# pragma message("warning: STLport debug versions are built with /D_STLP_DEBUG=1") +# error "Build options aren't compatible with pre-built libraries" +# else +# define BOOST_LIB_RT_OPT "-pn" +# endif + +# else + +# if defined(_DEBUG) && defined(BOOST_DEBUG_PYTHON) && defined(BOOST_LINKING_PYTHON) +# define BOOST_LIB_RT_OPT "-gyd" +# elif defined(_DEBUG) +# define BOOST_LIB_RT_OPT "-gd" +# else +# define BOOST_LIB_RT_OPT +# endif + +# endif + +# else + +# if (defined(__SGI_STL_PORT) || defined(_STLPORT_VERSION)) && (defined(_STLP_OWN_IOSTREAMS) || defined(__STL_OWN_IOSTREAMS)) + +# if defined(_DEBUG) && (defined(__STL_DEBUG) || defined(_STLP_DEBUG))\ + && defined(BOOST_DEBUG_PYTHON) && defined(BOOST_LINKING_PYTHON) +# define BOOST_LIB_RT_OPT "-sgydp" +# elif defined(_DEBUG) && (defined(__STL_DEBUG) || defined(_STLP_DEBUG)) +# define BOOST_LIB_RT_OPT "-sgdp" +# elif defined(_DEBUG)\ + && defined(BOOST_DEBUG_PYTHON) && defined(BOOST_LINKING_PYTHON) +# define BOOST_LIB_RT_OPT "-sgydp" +# pragma message("warning: STLport debug versions are built with /D_STLP_DEBUG=1") +# error "Build options aren't compatible with pre-built libraries" +# elif defined(_DEBUG) +# define BOOST_LIB_RT_OPT "-sgdp" +# pragma message("warning: STLport debug versions are built with /D_STLP_DEBUG=1") +# error "Build options aren't compatible with pre-built libraries" +# else +# define BOOST_LIB_RT_OPT "-sp" +# endif + +# elif defined(__SGI_STL_PORT) || defined(_STLPORT_VERSION) + +# if defined(_DEBUG) && (defined(__STL_DEBUG) || defined(_STLP_DEBUG))\ + && defined(BOOST_DEBUG_PYTHON) && defined(BOOST_LINKING_PYTHON) +# define BOOST_LIB_RT_OPT "-sgydpn" +# elif defined(_DEBUG) && (defined(__STL_DEBUG) || defined(_STLP_DEBUG)) +# define BOOST_LIB_RT_OPT "-sgdpn" +# elif defined(_DEBUG)\ + && defined(BOOST_DEBUG_PYTHON) && defined(BOOST_LINKING_PYTHON) +# define BOOST_LIB_RT_OPT "-sgydpn" +# pragma message("warning: STLport debug versions are built with /D_STLP_DEBUG=1") +# error "Build options aren't compatible with pre-built libraries" +# elif defined(_DEBUG) +# define BOOST_LIB_RT_OPT "-sgdpn" +# pragma message("warning: STLport debug versions are built with /D_STLP_DEBUG=1") +# error "Build options aren't compatible with pre-built libraries" +# else +# define BOOST_LIB_RT_OPT "-spn" +# endif + +# else + +# if defined(_DEBUG)\ + && defined(BOOST_DEBUG_PYTHON) && defined(BOOST_LINKING_PYTHON) +# define BOOST_LIB_RT_OPT "-sgyd" +# elif defined(_DEBUG) +# define BOOST_LIB_RT_OPT "-sgd" +# else +# define BOOST_LIB_RT_OPT "-s" +# endif + +# endif + +# endif + +#elif defined(BOOST_EMBTC_WINDOWS) + +# ifdef _RTLDLL + +# if defined(_DEBUG) +# define BOOST_LIB_RT_OPT "-d" +# else +# define BOOST_LIB_RT_OPT +# endif + +# else + +# if defined(_DEBUG) +# define BOOST_LIB_RT_OPT "-sd" +# else +# define BOOST_LIB_RT_OPT "-s" +# endif + +# endif + +#elif defined(BOOST_BORLANDC) + +// +// figure out whether we want the debug builds or not: +// +#if BOOST_BORLANDC > 0x561 +#pragma defineonoption BOOST_BORLAND_DEBUG -v +#endif +// +// sanity check: +// +#if defined(__STL_DEBUG) || defined(_STLP_DEBUG) +#error "Pre-built versions of the Boost libraries are not provided in STLport-debug form" +#endif + +# ifdef _RTLDLL + +# if defined(BOOST_BORLAND_DEBUG)\ + && defined(BOOST_DEBUG_PYTHON) && defined(BOOST_LINKING_PYTHON) +# define BOOST_LIB_RT_OPT "-yd" +# elif defined(BOOST_BORLAND_DEBUG) +# define BOOST_LIB_RT_OPT "-d" +# elif defined(BOOST_DEBUG_PYTHON) && defined(BOOST_LINKING_PYTHON) +# define BOOST_LIB_RT_OPT "-y" +# else +# define BOOST_LIB_RT_OPT +# endif + +# else + +# if defined(BOOST_BORLAND_DEBUG)\ + && defined(BOOST_DEBUG_PYTHON) && defined(BOOST_LINKING_PYTHON) +# define BOOST_LIB_RT_OPT "-syd" +# elif defined(BOOST_BORLAND_DEBUG) +# define BOOST_LIB_RT_OPT "-sd" +# elif defined(BOOST_DEBUG_PYTHON) && defined(BOOST_LINKING_PYTHON) +# define BOOST_LIB_RT_OPT "-sy" +# else +# define BOOST_LIB_RT_OPT "-s" +# endif + +# endif + +#endif + +// +// BOOST_LIB_ARCH_AND_MODEL_OPT +// + +#if defined( _M_IX86 ) +# define BOOST_LIB_ARCH_AND_MODEL_OPT "-x32" +#elif defined( _M_X64 ) +# define BOOST_LIB_ARCH_AND_MODEL_OPT "-x64" +#elif defined( _M_ARM ) +# define BOOST_LIB_ARCH_AND_MODEL_OPT "-a32" +#elif defined( _M_ARM64 ) +# define BOOST_LIB_ARCH_AND_MODEL_OPT "-a64" +#endif + +// +// select linkage opt: +// +#if (defined(_DLL) || defined(_RTLDLL)) && defined(BOOST_DYN_LINK) +# define BOOST_LIB_PREFIX +#elif defined(BOOST_DYN_LINK) +# error "Mixing a dll boost library with a static runtime is a really bad idea..." +#else +# define BOOST_LIB_PREFIX "lib" +#endif + +// +// now include the lib: +// +#if defined(BOOST_LIB_NAME) \ + && defined(BOOST_LIB_PREFIX) \ + && defined(BOOST_LIB_TOOLSET) \ + && defined(BOOST_LIB_THREAD_OPT) \ + && defined(BOOST_LIB_RT_OPT) \ + && defined(BOOST_LIB_ARCH_AND_MODEL_OPT) \ + && defined(BOOST_LIB_VERSION) + +#if defined(BOOST_EMBTC_WIN64) +# define BOOST_LIB_SUFFIX ".a" +#else +# define BOOST_LIB_SUFFIX ".lib" +#endif + +#ifdef BOOST_AUTO_LINK_NOMANGLE +# pragma comment(lib, BOOST_STRINGIZE(BOOST_LIB_NAME) BOOST_LIB_SUFFIX) +# ifdef BOOST_LIB_DIAGNOSTIC +# pragma message ("Linking to lib file: " BOOST_STRINGIZE(BOOST_LIB_NAME) BOOST_LIB_SUFFIX) +# endif +#elif defined(BOOST_AUTO_LINK_TAGGED) +# pragma comment(lib, BOOST_LIB_PREFIX BOOST_STRINGIZE(BOOST_LIB_NAME) BOOST_LIB_THREAD_OPT BOOST_LIB_RT_OPT BOOST_LIB_ARCH_AND_MODEL_OPT BOOST_LIB_SUFFIX) +# ifdef BOOST_LIB_DIAGNOSTIC +# pragma message ("Linking to lib file: " BOOST_LIB_PREFIX BOOST_STRINGIZE(BOOST_LIB_NAME) BOOST_LIB_THREAD_OPT BOOST_LIB_RT_OPT BOOST_LIB_ARCH_AND_MODEL_OPT BOOST_LIB_SUFFIX) +# endif +#elif defined(BOOST_AUTO_LINK_SYSTEM) +# pragma comment(lib, BOOST_LIB_PREFIX BOOST_STRINGIZE(BOOST_LIB_NAME) BOOST_LIB_SUFFIX) +# ifdef BOOST_LIB_DIAGNOSTIC +# pragma message ("Linking to lib file: " BOOST_LIB_PREFIX BOOST_STRINGIZE(BOOST_LIB_NAME) BOOST_LIB_SUFFIX) +# endif +#elif defined(BOOST_LIB_BUILDID) +# pragma comment(lib, BOOST_LIB_PREFIX BOOST_STRINGIZE(BOOST_LIB_NAME) "-" BOOST_LIB_TOOLSET BOOST_LIB_THREAD_OPT BOOST_LIB_RT_OPT BOOST_LIB_ARCH_AND_MODEL_OPT "-" BOOST_LIB_VERSION "-" BOOST_STRINGIZE(BOOST_LIB_BUILDID) BOOST_LIB_SUFFIX) +# ifdef BOOST_LIB_DIAGNOSTIC +# pragma message ("Linking to lib file: " BOOST_LIB_PREFIX BOOST_STRINGIZE(BOOST_LIB_NAME) "-" BOOST_LIB_TOOLSET BOOST_LIB_THREAD_OPT BOOST_LIB_RT_OPT BOOST_LIB_ARCH_AND_MODEL_OPT "-" BOOST_LIB_VERSION "-" BOOST_STRINGIZE(BOOST_LIB_BUILDID) BOOST_LIB_SUFFIX) +# endif +#else +# pragma comment(lib, BOOST_LIB_PREFIX BOOST_STRINGIZE(BOOST_LIB_NAME) "-" BOOST_LIB_TOOLSET BOOST_LIB_THREAD_OPT BOOST_LIB_RT_OPT BOOST_LIB_ARCH_AND_MODEL_OPT "-" BOOST_LIB_VERSION BOOST_LIB_SUFFIX) +# ifdef BOOST_LIB_DIAGNOSTIC +# pragma message ("Linking to lib file: " BOOST_LIB_PREFIX BOOST_STRINGIZE(BOOST_LIB_NAME) "-" BOOST_LIB_TOOLSET BOOST_LIB_THREAD_OPT BOOST_LIB_RT_OPT BOOST_LIB_ARCH_AND_MODEL_OPT "-" BOOST_LIB_VERSION BOOST_LIB_SUFFIX) +# endif +#endif + +#else +# error "some required macros where not defined (internal logic error)." +#endif + + +#endif // _MSC_VER || __BORLANDC__ + +// +// finally undef any macros we may have set: +// +#ifdef BOOST_LIB_PREFIX +# undef BOOST_LIB_PREFIX +#endif +#if defined(BOOST_LIB_NAME) +# undef BOOST_LIB_NAME +#endif +// Don't undef this one: it can be set by the user and should be the +// same for all libraries: +//#if defined(BOOST_LIB_TOOLSET) +//# undef BOOST_LIB_TOOLSET +//#endif +#if defined(BOOST_LIB_THREAD_OPT) +# undef BOOST_LIB_THREAD_OPT +#endif +#if defined(BOOST_LIB_RT_OPT) +# undef BOOST_LIB_RT_OPT +#endif +#if defined(BOOST_LIB_ARCH_AND_MODEL_OPT) +# undef BOOST_LIB_ARCH_AND_MODEL_OPT +#endif +#if defined(BOOST_LIB_LINK_OPT) +# undef BOOST_LIB_LINK_OPT +#endif +#if defined(BOOST_LIB_DEBUG_OPT) +# undef BOOST_LIB_DEBUG_OPT +#endif +#if defined(BOOST_DYN_LINK) +# undef BOOST_DYN_LINK +#endif +#if defined(BOOST_LIB_SUFFIX) +# undef BOOST_LIB_SUFFIX +#endif diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/compiler/borland.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/compiler/borland.hpp new file mode 100644 index 0000000..567636c --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/compiler/borland.hpp @@ -0,0 +1,339 @@ +// (C) Copyright John Maddock 2001 - 2003. +// (C) Copyright David Abrahams 2002 - 2003. +// (C) Copyright Aleksey Gurtovoy 2002. +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for most recent version. + +// Borland C++ compiler setup: + +// +// versions check: +// we don't support Borland prior to version 5.4: +#if __BORLANDC__ < 0x540 +# error "Compiler not supported or configured - please reconfigure" +#endif + +// last known compiler version: +#if (__BORLANDC__ > 0x613) +//# if defined(BOOST_ASSERT_CONFIG) +# error "boost: Unknown compiler version - please run the configure tests and report the results" +//# else +//# pragma message( "boost: Unknown compiler version - please run the configure tests and report the results") +//# endif +#elif (__BORLANDC__ == 0x600) +# error "CBuilderX preview compiler is no longer supported" +#endif + +// +// Support macros to help with standard library detection +#if (__BORLANDC__ < 0x560) || defined(_USE_OLD_RW_STL) +# define BOOST_BCB_WITH_ROGUE_WAVE +#elif __BORLANDC__ < 0x570 +# define BOOST_BCB_WITH_STLPORT +#else +# define BOOST_BCB_WITH_DINKUMWARE +#endif + +// +// Version 5.0 and below: +# if __BORLANDC__ <= 0x0550 +// Borland C++Builder 4 and 5: +# define BOOST_NO_MEMBER_TEMPLATE_FRIENDS +# if __BORLANDC__ == 0x0550 +// Borland C++Builder 5, command-line compiler 5.5: +# define BOOST_NO_OPERATORS_IN_NAMESPACE +# endif +// Variadic macros do not exist for C++ Builder versions 5 and below +#define BOOST_NO_CXX11_VARIADIC_MACROS +# endif + +// Version 5.51 and below: +#if (__BORLANDC__ <= 0x551) +# define BOOST_NO_CV_SPECIALIZATIONS +# define BOOST_NO_CV_VOID_SPECIALIZATIONS +# define BOOST_NO_DEDUCED_TYPENAME +// workaround for missing WCHAR_MAX/WCHAR_MIN: +#ifdef __cplusplus +#include +#include +#else +#include +#include +#endif // __cplusplus +#ifndef WCHAR_MAX +# define WCHAR_MAX 0xffff +#endif +#ifndef WCHAR_MIN +# define WCHAR_MIN 0 +#endif +#endif + +// Borland C++ Builder 6 and below: +#if (__BORLANDC__ <= 0x564) + +# if defined(NDEBUG) && defined(__cplusplus) + // fix broken so that Boost.test works: +# include +# undef strcmp +# endif + // fix broken errno declaration: +# include +# ifndef errno +# define errno errno +# endif + +#endif + +// +// new bug in 5.61: +#if (__BORLANDC__ >= 0x561) && (__BORLANDC__ <= 0x580) + // this seems to be needed by the command line compiler, but not the IDE: +# define BOOST_NO_MEMBER_FUNCTION_SPECIALIZATIONS +#endif + +// Borland C++ Builder 2006 Update 2 and below: +#if (__BORLANDC__ <= 0x582) +# define BOOST_NO_SFINAE +# define BOOST_BCB_PARTIAL_SPECIALIZATION_BUG +# define BOOST_NO_TEMPLATE_TEMPLATES + +# define BOOST_NO_PRIVATE_IN_AGGREGATE + +# ifdef _WIN32 +# define BOOST_NO_SWPRINTF +# elif defined(linux) || defined(__linux__) || defined(__linux) + // we should really be able to do without this + // but the wcs* functions aren't imported into std:: +# define BOOST_NO_STDC_NAMESPACE + // _CPPUNWIND doesn't get automatically set for some reason: +# pragma defineonoption BOOST_CPPUNWIND -x +# endif +#endif + +#if (__BORLANDC__ <= 0x613) // Beman has asked Alisdair for more info + // we shouldn't really need this - but too many things choke + // without it, this needs more investigation: +# define BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS +# define BOOST_NO_IS_ABSTRACT +# define BOOST_NO_FUNCTION_TYPE_SPECIALIZATIONS +# define BOOST_NO_USING_TEMPLATE +# define BOOST_SP_NO_SP_CONVERTIBLE + +// Temporary workaround +#define BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS +#endif + +// Borland C++ Builder 2008 and below: +# define BOOST_NO_INTEGRAL_INT64_T +# define BOOST_FUNCTION_SCOPE_USING_DECLARATION_BREAKS_ADL +# define BOOST_NO_DEPENDENT_NESTED_DERIVATIONS +# define BOOST_NO_MEMBER_TEMPLATE_FRIENDS +# define BOOST_NO_TWO_PHASE_NAME_LOOKUP +# define BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE +# define BOOST_NO_NESTED_FRIENDSHIP +# define BOOST_NO_TYPENAME_WITH_CTOR +#if (__BORLANDC__ < 0x600) +# define BOOST_ILLEGAL_CV_REFERENCES +#endif + +// +// Positive Feature detection +// +// Borland C++ Builder 2008 and below: +#if (__BORLANDC__ >= 0x599) +# pragma defineonoption BOOST_CODEGEAR_0X_SUPPORT -Ax +#endif +// +// C++0x Macros: +// +#if !defined( BOOST_CODEGEAR_0X_SUPPORT ) || (__BORLANDC__ < 0x610) +# define BOOST_NO_CXX11_CHAR16_T +# define BOOST_NO_CXX11_CHAR32_T +# define BOOST_NO_CXX11_DECLTYPE +# define BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS +# define BOOST_NO_CXX11_EXTERN_TEMPLATE +# define BOOST_NO_CXX11_RVALUE_REFERENCES +# define BOOST_NO_CXX11_SCOPED_ENUMS +# define BOOST_NO_CXX11_STATIC_ASSERT +#else +# define BOOST_HAS_ALIGNOF +# define BOOST_HAS_CHAR16_T +# define BOOST_HAS_CHAR32_T +# define BOOST_HAS_DECLTYPE +# define BOOST_HAS_EXPLICIT_CONVERSION_OPS +# define BOOST_HAS_REF_QUALIFIER +# define BOOST_HAS_RVALUE_REFS +# define BOOST_HAS_STATIC_ASSERT +#endif + +#define BOOST_NO_CXX11_AUTO_DECLARATIONS +#define BOOST_NO_CXX11_AUTO_MULTIDECLARATIONS +#define BOOST_NO_CXX11_CONSTEXPR +#define BOOST_NO_CXX11_DECLTYPE_N3276 +#define BOOST_NO_CXX11_DEFAULTED_FUNCTIONS +#define BOOST_NO_CXX11_DEFAULTED_MOVES +#define BOOST_NO_CXX11_DELETED_FUNCTIONS +#define BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS +#define BOOST_NO_CXX11_HDR_INITIALIZER_LIST +#define BOOST_NO_CXX11_LAMBDAS +#define BOOST_NO_CXX11_LOCAL_CLASS_TEMPLATE_PARAMETERS +#define BOOST_NO_CXX11_NULLPTR +#define BOOST_NO_CXX11_RANGE_BASED_FOR +#define BOOST_NO_CXX11_RAW_LITERALS +#define BOOST_NO_CXX11_RVALUE_REFERENCES +#define BOOST_NO_CXX11_SCOPED_ENUMS +#define BOOST_NO_SFINAE_EXPR +#define BOOST_NO_CXX11_SFINAE_EXPR +#define BOOST_NO_CXX11_TEMPLATE_ALIASES +#define BOOST_NO_CXX11_UNICODE_LITERALS // UTF-8 still not supported +#define BOOST_NO_CXX11_VARIADIC_TEMPLATES +#define BOOST_NO_CXX11_NOEXCEPT +#define BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX +#define BOOST_NO_CXX11_USER_DEFINED_LITERALS +#define BOOST_NO_CXX11_ALIGNAS +#define BOOST_NO_CXX11_ALIGNOF +#define BOOST_NO_CXX11_TRAILING_RESULT_TYPES +#define BOOST_NO_CXX11_INLINE_NAMESPACES +#define BOOST_NO_CXX11_REF_QUALIFIERS +#define BOOST_NO_CXX11_FINAL +#define BOOST_NO_CXX11_OVERRIDE +#define BOOST_NO_CXX11_THREAD_LOCAL +#define BOOST_NO_CXX11_UNRESTRICTED_UNION + +// C++ 14: +#if !defined(__cpp_aggregate_nsdmi) || (__cpp_aggregate_nsdmi < 201304) +# define BOOST_NO_CXX14_AGGREGATE_NSDMI +#endif +#if !defined(__cpp_binary_literals) || (__cpp_binary_literals < 201304) +# define BOOST_NO_CXX14_BINARY_LITERALS +#endif +#if !defined(__cpp_constexpr) || (__cpp_constexpr < 201304) +# define BOOST_NO_CXX14_CONSTEXPR +#endif +#if !defined(__cpp_decltype_auto) || (__cpp_decltype_auto < 201304) +# define BOOST_NO_CXX14_DECLTYPE_AUTO +#endif +#if (__cplusplus < 201304) // There's no SD6 check for this.... +# define BOOST_NO_CXX14_DIGIT_SEPARATORS +#endif +#if !defined(__cpp_generic_lambdas) || (__cpp_generic_lambdas < 201304) +# define BOOST_NO_CXX14_GENERIC_LAMBDAS +#endif +#if !defined(__cpp_init_captures) || (__cpp_init_captures < 201304) +# define BOOST_NO_CXX14_INITIALIZED_LAMBDA_CAPTURES +#endif +#if !defined(__cpp_return_type_deduction) || (__cpp_return_type_deduction < 201304) +# define BOOST_NO_CXX14_RETURN_TYPE_DEDUCTION +#endif +#if !defined(__cpp_variable_templates) || (__cpp_variable_templates < 201304) +# define BOOST_NO_CXX14_VARIABLE_TEMPLATES +#endif + +// C++17 +#if !defined(__cpp_structured_bindings) || (__cpp_structured_bindings < 201606) +# define BOOST_NO_CXX17_STRUCTURED_BINDINGS +#endif +#if !defined(__cpp_inline_variables) || (__cpp_inline_variables < 201606) +# define BOOST_NO_CXX17_INLINE_VARIABLES +#endif +#if !defined(__cpp_fold_expressions) || (__cpp_fold_expressions < 201603) +# define BOOST_NO_CXX17_FOLD_EXPRESSIONS +#endif +#if !defined(__cpp_if_constexpr) || (__cpp_if_constexpr < 201606) +# define BOOST_NO_CXX17_IF_CONSTEXPR +#endif + +#if __BORLANDC__ >= 0x590 +# define BOOST_HAS_TR1_HASH + +# define BOOST_HAS_MACRO_USE_FACET +#endif + +// +// Post 0x561 we have long long and stdint.h: +#if __BORLANDC__ >= 0x561 +# ifndef __NO_LONG_LONG +# define BOOST_HAS_LONG_LONG +# else +# define BOOST_NO_LONG_LONG +# endif + // On non-Win32 platforms let the platform config figure this out: +# ifdef _WIN32 +# define BOOST_HAS_STDINT_H +# endif +#endif + +// Borland C++Builder 6 defaults to using STLPort. If _USE_OLD_RW_STL is +// defined, then we have 0x560 or greater with the Rogue Wave implementation +// which presumably has the std::DBL_MAX bug. +#if defined( BOOST_BCB_WITH_ROGUE_WAVE ) +// is partly broken, some macros define symbols that are really in +// namespace std, so you end up having to use illegal constructs like +// std::DBL_MAX, as a fix we'll just include float.h and have done with: +#include +#endif +// +// __int64: +// +#if (__BORLANDC__ >= 0x530) && !defined(__STRICT_ANSI__) +# define BOOST_HAS_MS_INT64 +#endif +// +// check for exception handling support: +// +#if !defined(_CPPUNWIND) && !defined(BOOST_CPPUNWIND) && !defined(__EXCEPTIONS) && !defined(BOOST_NO_EXCEPTIONS) +# define BOOST_NO_EXCEPTIONS +#endif +// +// all versions have a : +// +#ifndef __STRICT_ANSI__ +# define BOOST_HAS_DIRENT_H +#endif +// +// all versions support __declspec: +// +#if defined(__STRICT_ANSI__) +// config/platform/win32.hpp will define BOOST_SYMBOL_EXPORT, etc., unless already defined +# define BOOST_SYMBOL_EXPORT +#endif +// +// ABI fixing headers: +// +#if __BORLANDC__ != 0x600 // not implemented for version 6 compiler yet +#ifndef BOOST_ABI_PREFIX +# define BOOST_ABI_PREFIX "boost/config/abi/borland_prefix.hpp" +#endif +#ifndef BOOST_ABI_SUFFIX +# define BOOST_ABI_SUFFIX "boost/config/abi/borland_suffix.hpp" +#endif +#endif +// +// Disable Win32 support in ANSI mode: +// +#if __BORLANDC__ < 0x600 +# pragma defineonoption BOOST_DISABLE_WIN32 -A +#elif defined(__STRICT_ANSI__) +# define BOOST_DISABLE_WIN32 +#endif +// +// MSVC compatibility mode does some nasty things: +// TODO: look up if this doesn't apply to the whole 12xx range +// +#if defined(_MSC_VER) && (_MSC_VER <= 1200) +# define BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP +# define BOOST_NO_VOID_RETURNS +#endif + +// Borland did not implement value-initialization completely, as I reported +// in 2007, Borland Report 51854, "Value-initialization: POD struct should be +// zero-initialized", http://qc.embarcadero.com/wc/qcmain.aspx?d=51854 +// See also: http://www.boost.org/libs/utility/value_init.htm#compiler_issues +// (Niels Dekker, LKEB, April 2010) +#define BOOST_NO_COMPLETE_VALUE_INITIALIZATION + +#define BOOST_BORLANDC __BORLANDC__ +#define BOOST_COMPILER "Classic Borland C++ version " BOOST_STRINGIZE(__BORLANDC__) diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/compiler/clang.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/compiler/clang.hpp new file mode 100644 index 0000000..1eeed31 --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/compiler/clang.hpp @@ -0,0 +1,366 @@ +// (C) Copyright Douglas Gregor 2010 +// +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for most recent version. + +// Clang compiler setup. + +#define BOOST_HAS_PRAGMA_ONCE + +// Detecting `-fms-extension` compiler flag assuming that _MSC_VER defined when that flag is used. +#if defined (_MSC_VER) && (__clang_major__ > 3 || (__clang_major__ == 3 && __clang_minor__ >= 4)) +# define BOOST_HAS_PRAGMA_DETECT_MISMATCH +#endif + +// When compiling with clang before __has_extension was defined, +// even if one writes 'defined(__has_extension) && __has_extension(xxx)', +// clang reports a compiler error. So the only workaround found is: + +#ifndef __has_extension +#define __has_extension __has_feature +#endif + +#ifndef __has_attribute +#define __has_attribute(x) 0 +#endif + +#ifndef __has_cpp_attribute +#define __has_cpp_attribute(x) 0 +#endif + +#if !__has_feature(cxx_exceptions) && !defined(BOOST_NO_EXCEPTIONS) +# define BOOST_NO_EXCEPTIONS +#endif + +#if !__has_feature(cxx_rtti) && !defined(BOOST_NO_RTTI) +# define BOOST_NO_RTTI +#endif + +#if !__has_feature(cxx_rtti) && !defined(BOOST_NO_TYPEID) +# define BOOST_NO_TYPEID +#endif + +#if !__has_feature(cxx_thread_local) +# define BOOST_NO_CXX11_THREAD_LOCAL +#endif + +#ifdef __is_identifier +#if !__is_identifier(__int64) && !defined(__GNUC__) +# define BOOST_HAS_MS_INT64 +#endif +#endif + +#if __has_include() +# define BOOST_HAS_STDINT_H +#endif + +#if (defined(linux) || defined(__linux) || defined(__linux__) || defined(__GNU__) || defined(__GLIBC__)) && !defined(_CRAYC) +#if (__clang_major__ >= 4) && defined(__has_include) +#if __has_include() +# define BOOST_HAS_FLOAT128 +#endif +#endif +#endif + + +#define BOOST_HAS_NRVO + +// Branch prediction hints +#if !defined (__c2__) && defined(__has_builtin) +#if __has_builtin(__builtin_expect) +#define BOOST_LIKELY(x) __builtin_expect(x, 1) +#define BOOST_UNLIKELY(x) __builtin_expect(x, 0) +#endif +#endif + +// Clang supports "long long" in all compilation modes. +#define BOOST_HAS_LONG_LONG + +// +// We disable this if the compiler is really nvcc with C++03 as it +// doesn't actually support __int128 as of CUDA_VERSION=7500 +// even though it defines __SIZEOF_INT128__. +// See https://svn.boost.org/trac/boost/ticket/10418 +// https://svn.boost.org/trac/boost/ticket/11852 +// Only re-enable this for nvcc if you're absolutely sure +// of the circumstances under which it's supported. +// Similarly __SIZEOF_INT128__ is defined when targetting msvc +// compatibility even though the required support functions are absent. +// +#if defined(__CUDACC__) +# if defined(BOOST_GCC_CXX11) +# define BOOST_NVCC_CXX11 +# else +# define BOOST_NVCC_CXX03 +# endif +#endif + +#if defined(__SIZEOF_INT128__) && !defined(BOOST_NVCC_CXX03) && !defined(_MSC_VER) +# define BOOST_HAS_INT128 +#endif + + +// +// Dynamic shared object (DSO) and dynamic-link library (DLL) support +// +#if defined(_WIN32) || defined(__WIN32__) || defined(WIN32) || defined(__CYGWIN__) +# define BOOST_HAS_DECLSPEC +# define BOOST_SYMBOL_EXPORT __attribute__((__dllexport__)) +# define BOOST_SYMBOL_IMPORT __attribute__((__dllimport__)) +#else +# define BOOST_SYMBOL_EXPORT __attribute__((__visibility__("default"))) +# define BOOST_SYMBOL_VISIBLE __attribute__((__visibility__("default"))) +# define BOOST_SYMBOL_IMPORT +#endif + +// +// The BOOST_FALLTHROUGH macro can be used to annotate implicit fall-through +// between switch labels. +// +#if __cplusplus >= 201103L && defined(__has_warning) +# if __has_feature(cxx_attributes) && __has_warning("-Wimplicit-fallthrough") +# define BOOST_FALLTHROUGH [[clang::fallthrough]] +# endif +#endif + +#if !__has_feature(cxx_auto_type) +# define BOOST_NO_CXX11_AUTO_DECLARATIONS +# define BOOST_NO_CXX11_AUTO_MULTIDECLARATIONS +#endif + +// +// Currently clang on Windows using VC++ RTL does not support C++11's char16_t or char32_t +// +#if (defined(_MSC_VER) && (_MSC_VER < 1900)) || !(defined(__GXX_EXPERIMENTAL_CXX0X__) || __cplusplus >= 201103L) +# define BOOST_NO_CXX11_CHAR16_T +# define BOOST_NO_CXX11_CHAR32_T +#endif + +#if defined(_MSC_VER) && (_MSC_VER >= 1800) && !defined(__GNUC__) +#define BOOST_HAS_EXPM1 +#define BOOST_HAS_LOG1P +#endif + +#if !__has_feature(cxx_constexpr) +# define BOOST_NO_CXX11_CONSTEXPR +#endif + +#if !__has_feature(cxx_decltype) +# define BOOST_NO_CXX11_DECLTYPE +#endif + +#if !__has_feature(cxx_decltype_incomplete_return_types) +# define BOOST_NO_CXX11_DECLTYPE_N3276 +#endif + +#if !__has_feature(cxx_defaulted_functions) +# define BOOST_NO_CXX11_DEFAULTED_FUNCTIONS +#endif + +#if !__has_feature(cxx_deleted_functions) +# define BOOST_NO_CXX11_DELETED_FUNCTIONS +#endif + +#if !__has_feature(cxx_explicit_conversions) +# define BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS +#endif + +#if !__has_feature(cxx_default_function_template_args) +# define BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS +#endif + +#if !__has_feature(cxx_generalized_initializers) +# define BOOST_NO_CXX11_HDR_INITIALIZER_LIST +#endif + +#if !__has_feature(cxx_lambdas) +# define BOOST_NO_CXX11_LAMBDAS +#endif + +#if !__has_feature(cxx_local_type_template_args) +# define BOOST_NO_CXX11_LOCAL_CLASS_TEMPLATE_PARAMETERS +#endif + +#if !__has_feature(cxx_noexcept) +# define BOOST_NO_CXX11_NOEXCEPT +#endif + +#if !__has_feature(cxx_nullptr) +# define BOOST_NO_CXX11_NULLPTR +#endif + +#if !__has_feature(cxx_range_for) +# define BOOST_NO_CXX11_RANGE_BASED_FOR +#endif + +#if !__has_feature(cxx_raw_string_literals) +# define BOOST_NO_CXX11_RAW_LITERALS +#endif + +#if !__has_feature(cxx_reference_qualified_functions) +# define BOOST_NO_CXX11_REF_QUALIFIERS +#endif + +#if !__has_feature(cxx_generalized_initializers) +# define BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX +#endif + +#if !__has_feature(cxx_rvalue_references) +# define BOOST_NO_CXX11_RVALUE_REFERENCES +#endif + +#if !__has_feature(cxx_strong_enums) +# define BOOST_NO_CXX11_SCOPED_ENUMS +#endif + +#if !__has_feature(cxx_static_assert) +# define BOOST_NO_CXX11_STATIC_ASSERT +#endif + +#if !__has_feature(cxx_alias_templates) +# define BOOST_NO_CXX11_TEMPLATE_ALIASES +#endif + +#if !__has_feature(cxx_unicode_literals) +# define BOOST_NO_CXX11_UNICODE_LITERALS +#endif + +#if !__has_feature(cxx_variadic_templates) +# define BOOST_NO_CXX11_VARIADIC_TEMPLATES +#endif + +#if !__has_feature(cxx_user_literals) +# define BOOST_NO_CXX11_USER_DEFINED_LITERALS +#endif + +#if !__has_feature(cxx_alignas) +# define BOOST_NO_CXX11_ALIGNAS +#endif + +#if !__has_feature(cxx_alignof) +# define BOOST_NO_CXX11_ALIGNOF +#endif + +#if !__has_feature(cxx_trailing_return) +# define BOOST_NO_CXX11_TRAILING_RESULT_TYPES +#endif + +#if !__has_feature(cxx_inline_namespaces) +# define BOOST_NO_CXX11_INLINE_NAMESPACES +#endif + +#if !__has_feature(cxx_override_control) +# define BOOST_NO_CXX11_FINAL +# define BOOST_NO_CXX11_OVERRIDE +#endif + +#if !__has_feature(cxx_unrestricted_unions) +# define BOOST_NO_CXX11_UNRESTRICTED_UNION +#endif + +#if !(__has_feature(__cxx_binary_literals__) || __has_extension(__cxx_binary_literals__)) +# define BOOST_NO_CXX14_BINARY_LITERALS +#endif + +#if !__has_feature(__cxx_decltype_auto__) +# define BOOST_NO_CXX14_DECLTYPE_AUTO +#endif + +#if !__has_feature(__cxx_aggregate_nsdmi__) +# define BOOST_NO_CXX14_AGGREGATE_NSDMI +#endif + +#if !__has_feature(__cxx_init_captures__) +# define BOOST_NO_CXX14_INITIALIZED_LAMBDA_CAPTURES +#endif + +#if !__has_feature(__cxx_generic_lambdas__) +# define BOOST_NO_CXX14_GENERIC_LAMBDAS +#endif + +// clang < 3.5 has a defect with dependent type, like following. +// +// template +// constexpr typename enable_if >::type foo(T &) +// { } // error: no return statement in constexpr function +// +// This issue also affects C++11 mode, but C++11 constexpr requires return stmt. +// Therefore we don't care such case. +// +// Note that we can't check Clang version directly as the numbering system changes depending who's +// creating the Clang release (see https://github.com/boostorg/config/pull/39#issuecomment-59927873) +// so instead verify that we have a feature that was introduced at the same time as working C++14 +// constexpr (generic lambda's in this case): +// +#if !__has_feature(__cxx_generic_lambdas__) || !__has_feature(__cxx_relaxed_constexpr__) +# define BOOST_NO_CXX14_CONSTEXPR +#endif + +#if !__has_feature(__cxx_return_type_deduction__) +# define BOOST_NO_CXX14_RETURN_TYPE_DEDUCTION +#endif + +#if !__has_feature(__cxx_variable_templates__) +# define BOOST_NO_CXX14_VARIABLE_TEMPLATES +#endif + +#if !defined(__cpp_structured_bindings) || (__cpp_structured_bindings < 201606) +# define BOOST_NO_CXX17_STRUCTURED_BINDINGS +#endif + +#if !defined(__cpp_if_constexpr) || (__cpp_if_constexpr < 201606) +# define BOOST_NO_CXX17_IF_CONSTEXPR +#endif + +// Clang 3.9+ in c++1z +#if !__has_cpp_attribute(fallthrough) || __cplusplus < 201406L +# define BOOST_NO_CXX17_INLINE_VARIABLES +# define BOOST_NO_CXX17_FOLD_EXPRESSIONS +#endif + +#if __cplusplus < 201103L +#define BOOST_NO_CXX11_SFINAE_EXPR +#endif + +#if __cplusplus < 201400 +// All versions with __cplusplus above this value seem to support this: +# define BOOST_NO_CXX14_DIGIT_SEPARATORS +#endif + +// Unreachable code markup +#if defined(__has_builtin) +#if __has_builtin(__builtin_unreachable) +#define BOOST_UNREACHABLE_RETURN(x) __builtin_unreachable(); +#endif +#endif + +// Deprecated symbol markup +#if __has_attribute(deprecated) +#define BOOST_DEPRECATED(msg) __attribute__((deprecated(msg))) +#endif + +#if (__clang_major__ == 3) && (__clang_minor__ == 0) +// Apparently a clang bug: +# define BOOST_NO_CXX11_FIXED_LENGTH_VARIADIC_TEMPLATE_EXPANSION_PACKS +#endif + +// Clang has supported the 'unused' attribute since the first release. +#define BOOST_ATTRIBUTE_UNUSED __attribute__((__unused__)) + +// Type aliasing hint. +#if __has_attribute(__may_alias__) +# define BOOST_MAY_ALIAS __attribute__((__may_alias__)) +#endif + +#ifndef BOOST_COMPILER +# define BOOST_COMPILER "Clang version " __clang_version__ +#endif + +// Macro used to identify the Clang compiler. +#define BOOST_CLANG 1 + +// BOOST_CLANG_VERSION +#include diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/compiler/clang_version.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/compiler/clang_version.hpp new file mode 100644 index 0000000..a61de13 --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/compiler/clang_version.hpp @@ -0,0 +1,89 @@ +// Copyright 2021 Peter Dimov +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt) + +#if !defined(__apple_build_version__) + +# define BOOST_CLANG_VERSION (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__ % 100) + +#else +# define BOOST_CLANG_REPORTED_VERSION (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__ % 100) + +// https://en.wikipedia.org/wiki/Xcode#Toolchain_versions + +# if BOOST_CLANG_REPORTED_VERSION >= 150000 +# define BOOST_CLANG_VERSION 160000 + +# elif BOOST_CLANG_REPORTED_VERSION >= 140003 +# define BOOST_CLANG_VERSION 150000 + +# elif BOOST_CLANG_REPORTED_VERSION >= 140000 +# define BOOST_CLANG_VERSION 140000 + +# elif BOOST_CLANG_REPORTED_VERSION >= 130100 +# define BOOST_CLANG_VERSION 130000 + +# elif BOOST_CLANG_REPORTED_VERSION >= 130000 +# define BOOST_CLANG_VERSION 120000 + +# elif BOOST_CLANG_REPORTED_VERSION >= 120005 +# define BOOST_CLANG_VERSION 110100 + +# elif BOOST_CLANG_REPORTED_VERSION >= 120000 +# define BOOST_CLANG_VERSION 100000 + +# elif BOOST_CLANG_REPORTED_VERSION >= 110003 +# define BOOST_CLANG_VERSION 90000 + +# elif BOOST_CLANG_REPORTED_VERSION >= 110000 +# define BOOST_CLANG_VERSION 80000 + +# elif BOOST_CLANG_REPORTED_VERSION >= 100001 +# define BOOST_CLANG_VERSION 70000 + +# elif BOOST_CLANG_REPORTED_VERSION >= 100000 +# define BOOST_CLANG_VERSION 60001 + +# elif BOOST_CLANG_REPORTED_VERSION >= 90100 +# define BOOST_CLANG_VERSION 50002 + +# elif BOOST_CLANG_REPORTED_VERSION >= 90000 +# define BOOST_CLANG_VERSION 40000 + +# elif BOOST_CLANG_REPORTED_VERSION >= 80000 +# define BOOST_CLANG_VERSION 30900 + +# elif BOOST_CLANG_REPORTED_VERSION >= 70300 +# define BOOST_CLANG_VERSION 30800 + +# elif BOOST_CLANG_REPORTED_VERSION >= 70000 +# define BOOST_CLANG_VERSION 30700 + +# elif BOOST_CLANG_REPORTED_VERSION >= 60100 +# define BOOST_CLANG_VERSION 30600 + +# elif BOOST_CLANG_REPORTED_VERSION >= 60000 +# define BOOST_CLANG_VERSION 30500 + +# elif BOOST_CLANG_REPORTED_VERSION >= 50100 +# define BOOST_CLANG_VERSION 30400 + +# elif BOOST_CLANG_REPORTED_VERSION >= 50000 +# define BOOST_CLANG_VERSION 30300 + +# elif BOOST_CLANG_REPORTED_VERSION >= 40200 +# define BOOST_CLANG_VERSION 30200 + +# elif BOOST_CLANG_REPORTED_VERSION >= 30100 +# define BOOST_CLANG_VERSION 30100 + +# elif BOOST_CLANG_REPORTED_VERSION >= 20100 +# define BOOST_CLANG_VERSION 30000 + +# else +# define BOOST_CLANG_VERSION 20900 + +# endif + +# undef BOOST_CLANG_REPORTED_VERSION +#endif diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/compiler/codegear.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/compiler/codegear.hpp new file mode 100644 index 0000000..4d3f42a --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/compiler/codegear.hpp @@ -0,0 +1,385 @@ +// (C) Copyright John Maddock 2001 - 2003. +// (C) Copyright David Abrahams 2002 - 2003. +// (C) Copyright Aleksey Gurtovoy 2002. +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for most recent version. + +// CodeGear C++ compiler setup: + +// +// versions check: +// last known and checked version is 0x740 +#if (__CODEGEARC__ > 0x740) +# if defined(BOOST_ASSERT_CONFIG) +# error "boost: Unknown compiler version - please run the configure tests and report the results" +# else +# pragma message( "boost: Unknown compiler version - please run the configure tests and report the results") +# endif +#endif + +#ifdef __clang__ // Clang enhanced Windows compiler + +# include "clang.hpp" +# define BOOST_NO_CXX11_THREAD_LOCAL +# define BOOST_NO_CXX11_ATOMIC_SMART_PTR + +// This bug has been reported to Embarcadero + +#if defined(BOOST_HAS_INT128) +#undef BOOST_HAS_INT128 +#endif +#if defined(BOOST_HAS_FLOAT128) +#undef BOOST_HAS_FLOAT128 +#endif + +// The clang-based compilers can not do 128 atomic exchanges + +#define BOOST_ATOMIC_NO_CMPXCHG16B + +// 32 functions are missing from the current RTL in cwchar, so it really can not be used even if it exists + +# define BOOST_NO_CWCHAR + +# ifndef __MT__ /* If compiling in single-threaded mode, assume there is no CXX11_HDR_ATOMIC */ +# define BOOST_NO_CXX11_HDR_ATOMIC +# endif + +/* temporarily disable this until we can link against fegetround fesetround feholdexcept */ + +#define BOOST_NO_FENV_H + +/* Reported this bug to Embarcadero with the latest C++ Builder Rio release */ + +#define BOOST_NO_CXX11_HDR_EXCEPTION + +// +// check for exception handling support: +// +#if !defined(_CPPUNWIND) && !defined(__EXCEPTIONS) && !defined(BOOST_NO_EXCEPTIONS) +# define BOOST_NO_EXCEPTIONS +#endif + +/* + +// On non-Win32 platforms let the platform config figure this out: +#ifdef _WIN32 +# define BOOST_HAS_STDINT_H +#endif + +// +// __int64: +// +#if !defined(__STRICT_ANSI__) +# define BOOST_HAS_MS_INT64 +#endif +// +// all versions have a : +// +#if !defined(__STRICT_ANSI__) +# define BOOST_HAS_DIRENT_H +#endif +// +// Disable Win32 support in ANSI mode: +// +# pragma defineonoption BOOST_DISABLE_WIN32 -A +// +// MSVC compatibility mode does some nasty things: +// TODO: look up if this doesn't apply to the whole 12xx range +// +#if defined(_MSC_VER) && (_MSC_VER <= 1200) +# define BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP +# define BOOST_NO_VOID_RETURNS +#endif +// + +*/ + +// Specific settings for Embarcadero drivers +# define BOOST_EMBTC __CODEGEARC__ +# define BOOST_EMBTC_FULL_VER ((__clang_major__ << 16) | \ + (__clang_minor__ << 8) | \ + __clang_patchlevel__ ) + +// Detecting which Embarcadero driver is being used +#if defined(BOOST_EMBTC) +# if defined(_WIN64) +# define BOOST_EMBTC_WIN64 1 +# define BOOST_EMBTC_WINDOWS 1 +# ifndef BOOST_USE_WINDOWS_H +# define BOOST_USE_WINDOWS_H +# endif +# elif defined(_WIN32) +# define BOOST_EMBTC_WIN32C 1 +# define BOOST_EMBTC_WINDOWS 1 +# ifndef BOOST_USE_WINDOWS_H +# define BOOST_USE_WINDOWS_H +# endif +# elif defined(__APPLE__) && defined(__arm__) +# define BOOST_EMBTC_IOSARM 1 +# define BOOST_EMBTC_IOS 1 +# elif defined(__APPLE__) && defined(__aarch64__) +# define BOOST_EMBTC_IOSARM64 1 +# define BOOST_EMBTC_IOS 1 +# elif defined(__ANDROID__) && defined(__arm__) +# define BOOST_EMBTC_AARM 1 +# define BOOST_EMBTC_ANDROID 1 +# elif +# if defined(BOOST_ASSERT_CONFIG) +# error "Unknown Embarcadero driver" +# else +# warning "Unknown Embarcadero driver" +# endif /* defined(BOOST_ASSERT_CONFIG) */ +# endif +#endif /* defined(BOOST_EMBTC) */ + +#if defined(BOOST_EMBTC_WINDOWS) + +#if !defined(_chdir) +#define _chdir(x) chdir(x) +#endif + +#if !defined(_dup2) +#define _dup2(x,y) dup2(x,y) +#endif + +#endif + +# undef BOOST_COMPILER +# define BOOST_COMPILER "Embarcadero-Clang C++ version " BOOST_STRINGIZE(__CODEGEARC__) " clang: " __clang_version__ +// # define __CODEGEARC_CLANG__ __CODEGEARC__ +// # define __EMBARCADERO_CLANG__ __CODEGEARC__ +// # define __BORLANDC_CLANG__ __BORLANDC__ + +#else // #if !defined(__clang__) + +# define BOOST_CODEGEARC __CODEGEARC__ +# define BOOST_BORLANDC __BORLANDC__ + +#if !defined( BOOST_WITH_CODEGEAR_WARNINGS ) +// these warnings occur frequently in optimized template code +# pragma warn -8004 // var assigned value, but never used +# pragma warn -8008 // condition always true/false +# pragma warn -8066 // dead code can never execute +# pragma warn -8104 // static members with ctors not threadsafe +# pragma warn -8105 // reference member in class without ctors +#endif + +// CodeGear C++ Builder 2009 +#if (__CODEGEARC__ <= 0x613) +# define BOOST_NO_INTEGRAL_INT64_T +# define BOOST_NO_DEPENDENT_NESTED_DERIVATIONS +# define BOOST_NO_PRIVATE_IN_AGGREGATE +# define BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE + // we shouldn't really need this - but too many things choke + // without it, this needs more investigation: +# define BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS +# define BOOST_SP_NO_SP_CONVERTIBLE +#endif + +// CodeGear C++ Builder 2010 +#if (__CODEGEARC__ <= 0x621) +# define BOOST_NO_TYPENAME_WITH_CTOR // Cannot use typename keyword when making temporaries of a dependant type +# define BOOST_FUNCTION_SCOPE_USING_DECLARATION_BREAKS_ADL +# define BOOST_NO_MEMBER_TEMPLATE_FRIENDS +# define BOOST_NO_NESTED_FRIENDSHIP // TC1 gives nested classes access rights as any other member +# define BOOST_NO_USING_TEMPLATE +# define BOOST_NO_TWO_PHASE_NAME_LOOKUP +// Temporary hack, until specific MPL preprocessed headers are generated +# define BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS + +// CodeGear has not yet completely implemented value-initialization, for +// example for array types, as I reported in 2010: Embarcadero Report 83751, +// "Value-initialization: arrays should have each element value-initialized", +// http://qc.embarcadero.com/wc/qcmain.aspx?d=83751 +// Last checked version: Embarcadero C++ 6.21 +// See also: http://www.boost.org/libs/utility/value_init.htm#compiler_issues +// (Niels Dekker, LKEB, April 2010) +# define BOOST_NO_COMPLETE_VALUE_INITIALIZATION + +# if defined(NDEBUG) && defined(__cplusplus) + // fix broken so that Boost.test works: +# include +# undef strcmp +# endif + // fix broken errno declaration: +# include +# ifndef errno +# define errno errno +# endif + +#endif + +// Reportedly, #pragma once is supported since C++ Builder 2010 +#if (__CODEGEARC__ >= 0x620) +# define BOOST_HAS_PRAGMA_ONCE +#endif + +#define BOOST_NO_FENV_H + +// +// C++0x macros: +// +#if (__CODEGEARC__ <= 0x620) +#define BOOST_NO_CXX11_STATIC_ASSERT +#else +#define BOOST_HAS_STATIC_ASSERT +#endif +#define BOOST_HAS_CHAR16_T +#define BOOST_HAS_CHAR32_T +#define BOOST_HAS_LONG_LONG +// #define BOOST_HAS_ALIGNOF +#define BOOST_HAS_DECLTYPE +#define BOOST_HAS_EXPLICIT_CONVERSION_OPS +// #define BOOST_HAS_RVALUE_REFS +#define BOOST_HAS_SCOPED_ENUM +// #define BOOST_HAS_STATIC_ASSERT +#define BOOST_HAS_STD_TYPE_TRAITS + +#define BOOST_NO_CXX11_AUTO_DECLARATIONS +#define BOOST_NO_CXX11_AUTO_MULTIDECLARATIONS +#define BOOST_NO_CXX11_CONSTEXPR +#define BOOST_NO_CXX11_DEFAULTED_FUNCTIONS +#define BOOST_NO_CXX11_DELETED_FUNCTIONS +#define BOOST_NO_CXX11_EXTERN_TEMPLATE +#define BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS +#define BOOST_NO_CXX11_LAMBDAS +#define BOOST_NO_CXX11_LOCAL_CLASS_TEMPLATE_PARAMETERS +#define BOOST_NO_CXX11_NOEXCEPT +#define BOOST_NO_CXX11_NULLPTR +#define BOOST_NO_CXX11_RANGE_BASED_FOR +#define BOOST_NO_CXX11_RAW_LITERALS +#define BOOST_NO_CXX11_RVALUE_REFERENCES +#define BOOST_NO_SFINAE_EXPR +#define BOOST_NO_CXX11_SFINAE_EXPR +#define BOOST_NO_CXX11_TEMPLATE_ALIASES +#define BOOST_NO_CXX11_UNICODE_LITERALS +#define BOOST_NO_CXX11_VARIADIC_TEMPLATES +#define BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX +#define BOOST_NO_CXX11_USER_DEFINED_LITERALS +#define BOOST_NO_CXX11_ALIGNAS +#define BOOST_NO_CXX11_ALIGNOF +#define BOOST_NO_CXX11_TRAILING_RESULT_TYPES +#define BOOST_NO_CXX11_INLINE_NAMESPACES +#define BOOST_NO_CXX11_REF_QUALIFIERS +#define BOOST_NO_CXX11_FINAL +#define BOOST_NO_CXX11_OVERRIDE +#define BOOST_NO_CXX11_THREAD_LOCAL +#define BOOST_NO_CXX11_DECLTYPE_N3276 +#define BOOST_NO_CXX11_UNRESTRICTED_UNION + +// C++ 14: +#if !defined(__cpp_aggregate_nsdmi) || (__cpp_aggregate_nsdmi < 201304) +# define BOOST_NO_CXX14_AGGREGATE_NSDMI +#endif +#if !defined(__cpp_binary_literals) || (__cpp_binary_literals < 201304) +# define BOOST_NO_CXX14_BINARY_LITERALS +#endif +#if !defined(__cpp_constexpr) || (__cpp_constexpr < 201304) +# define BOOST_NO_CXX14_CONSTEXPR +#endif +#if !defined(__cpp_decltype_auto) || (__cpp_decltype_auto < 201304) +# define BOOST_NO_CXX14_DECLTYPE_AUTO +#endif +#if (__cplusplus < 201304) // There's no SD6 check for this.... +# define BOOST_NO_CXX14_DIGIT_SEPARATORS +#endif +#if !defined(__cpp_generic_lambdas) || (__cpp_generic_lambdas < 201304) +# define BOOST_NO_CXX14_GENERIC_LAMBDAS +#endif +#if !defined(__cpp_init_captures) || (__cpp_init_captures < 201304) +# define BOOST_NO_CXX14_INITIALIZED_LAMBDA_CAPTURES +#endif +#if !defined(__cpp_return_type_deduction) || (__cpp_return_type_deduction < 201304) +# define BOOST_NO_CXX14_RETURN_TYPE_DEDUCTION +#endif +#if !defined(__cpp_variable_templates) || (__cpp_variable_templates < 201304) +# define BOOST_NO_CXX14_VARIABLE_TEMPLATES +#endif + +// C++17 +#if !defined(__cpp_structured_bindings) || (__cpp_structured_bindings < 201606) +# define BOOST_NO_CXX17_STRUCTURED_BINDINGS +#endif + +#if !defined(__cpp_inline_variables) || (__cpp_inline_variables < 201606) +# define BOOST_NO_CXX17_INLINE_VARIABLES +#endif + +#if !defined(__cpp_fold_expressions) || (__cpp_fold_expressions < 201603) +# define BOOST_NO_CXX17_FOLD_EXPRESSIONS +#endif + +#if !defined(__cpp_if_constexpr) || (__cpp_if_constexpr < 201606) +# define BOOST_NO_CXX17_IF_CONSTEXPR +#endif + +// +// TR1 macros: +// +#define BOOST_HAS_TR1_HASH +#define BOOST_HAS_TR1_TYPE_TRAITS +#define BOOST_HAS_TR1_UNORDERED_MAP +#define BOOST_HAS_TR1_UNORDERED_SET + +#define BOOST_HAS_MACRO_USE_FACET + +#define BOOST_NO_CXX11_HDR_INITIALIZER_LIST + +// On non-Win32 platforms let the platform config figure this out: +#ifdef _WIN32 +# define BOOST_HAS_STDINT_H +#endif + +// +// __int64: +// +#if !defined(__STRICT_ANSI__) +# define BOOST_HAS_MS_INT64 +#endif +// +// check for exception handling support: +// +#if !defined(_CPPUNWIND) && !defined(BOOST_CPPUNWIND) && !defined(__EXCEPTIONS) && !defined(BOOST_NO_EXCEPTIONS) +# define BOOST_NO_EXCEPTIONS +#endif +// +// all versions have a : +// +#if !defined(__STRICT_ANSI__) +# define BOOST_HAS_DIRENT_H +#endif +// +// all versions support __declspec: +// +#if defined(__STRICT_ANSI__) +// config/platform/win32.hpp will define BOOST_SYMBOL_EXPORT, etc., unless already defined +# define BOOST_SYMBOL_EXPORT +#endif +// +// ABI fixing headers: +// +#ifndef BOOST_ABI_PREFIX +# define BOOST_ABI_PREFIX "boost/config/abi/borland_prefix.hpp" +#endif +#ifndef BOOST_ABI_SUFFIX +# define BOOST_ABI_SUFFIX "boost/config/abi/borland_suffix.hpp" +#endif +// +// Disable Win32 support in ANSI mode: +// +# pragma defineonoption BOOST_DISABLE_WIN32 -A +// +// MSVC compatibility mode does some nasty things: +// TODO: look up if this doesn't apply to the whole 12xx range +// +#if defined(_MSC_VER) && (_MSC_VER <= 1200) +# define BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP +# define BOOST_NO_VOID_RETURNS +#endif + +#define BOOST_COMPILER "CodeGear C++ version " BOOST_STRINGIZE(__CODEGEARC__) + +#endif // #if !defined(__clang__) diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/compiler/comeau.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/compiler/comeau.hpp new file mode 100644 index 0000000..ca80fac --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/compiler/comeau.hpp @@ -0,0 +1,59 @@ +// (C) Copyright John Maddock 2001. +// (C) Copyright Douglas Gregor 2001. +// (C) Copyright Peter Dimov 2001. +// (C) Copyright Aleksey Gurtovoy 2003. +// (C) Copyright Beman Dawes 2003. +// (C) Copyright Jens Maurer 2003. +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for most recent version. + +// Comeau C++ compiler setup: + +#include + +#if (__COMO_VERSION__ <= 4245) + +# if defined(_MSC_VER) && _MSC_VER <= 1300 +# if _MSC_VER > 100 + // only set this in non-strict mode: +# define BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP +# endif +# endif + +// Void returns don't work when emulating VC 6 (Peter Dimov) +// TODO: look up if this doesn't apply to the whole 12xx range +# if defined(_MSC_VER) && (_MSC_VER < 1300) +# define BOOST_NO_VOID_RETURNS +# endif + +#endif // version 4245 + +// +// enable __int64 support in VC emulation mode +// +# if defined(_MSC_VER) && (_MSC_VER >= 1200) +# define BOOST_HAS_MS_INT64 +# endif + +#define BOOST_COMPILER "Comeau compiler version " BOOST_STRINGIZE(__COMO_VERSION__) + +// +// versions check: +// we don't know Comeau prior to version 4245: +#if __COMO_VERSION__ < 4245 +# error "Compiler not configured - please reconfigure" +#endif +// +// last known and checked version is 4245: +#if (__COMO_VERSION__ > 4245) +# if defined(BOOST_ASSERT_CONFIG) +# error "boost: Unknown compiler version - please run the configure tests and report the results" +# endif +#endif + + + + diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/compiler/common_edg.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/compiler/common_edg.hpp new file mode 100644 index 0000000..dc04989 --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/compiler/common_edg.hpp @@ -0,0 +1,183 @@ +// (C) Copyright John Maddock 2001 - 2002. +// (C) Copyright Jens Maurer 2001. +// (C) Copyright David Abrahams 2002. +// (C) Copyright Aleksey Gurtovoy 2002. +// (C) Copyright Markus Schoepflin 2005. +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for most recent version. + +// +// Options common to all edg based compilers. +// +// This is included from within the individual compiler mini-configs. + +#ifndef __EDG_VERSION__ +# error This file requires that __EDG_VERSION__ be defined. +#endif + +#if (__EDG_VERSION__ <= 238) +# define BOOST_NO_INTEGRAL_INT64_T +# define BOOST_NO_SFINAE +#endif + +#if (__EDG_VERSION__ <= 240) +# define BOOST_NO_VOID_RETURNS +#endif + +#if (__EDG_VERSION__ <= 241) && !defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP) +# define BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP +#endif + +#if (__EDG_VERSION__ <= 244) && !defined(BOOST_NO_TEMPLATE_TEMPLATES) +# define BOOST_NO_TEMPLATE_TEMPLATES +#endif + +#if (__EDG_VERSION__ < 300) && !defined(BOOST_NO_IS_ABSTRACT) +# define BOOST_NO_IS_ABSTRACT +#endif + +#if (__EDG_VERSION__ <= 303) && !defined(BOOST_FUNCTION_SCOPE_USING_DECLARATION_BREAKS_ADL) +# define BOOST_FUNCTION_SCOPE_USING_DECLARATION_BREAKS_ADL +#endif + +// See also kai.hpp which checks a Kai-specific symbol for EH +# if !defined(__KCC) && !defined(__EXCEPTIONS) && !defined(BOOST_NO_EXCEPTIONS) +# define BOOST_NO_EXCEPTIONS +# endif + +# if !defined(__NO_LONG_LONG) +# define BOOST_HAS_LONG_LONG +# else +# define BOOST_NO_LONG_LONG +# endif + +// Not sure what version was the first to support #pragma once, but +// different EDG-based compilers (e.g. Intel) supported it for ages. +// Add a proper version check if it causes problems. +#define BOOST_HAS_PRAGMA_ONCE + +// +// C++0x features +// +// See above for BOOST_NO_LONG_LONG +// +#if (__EDG_VERSION__ < 310) +# define BOOST_NO_CXX11_EXTERN_TEMPLATE +#endif +#if (__EDG_VERSION__ <= 310) +// No support for initializer lists +# define BOOST_NO_CXX11_HDR_INITIALIZER_LIST +#endif +#if (__EDG_VERSION__ < 400) +# define BOOST_NO_CXX11_VARIADIC_MACROS +#endif + +#define BOOST_NO_CXX11_AUTO_DECLARATIONS +#define BOOST_NO_CXX11_AUTO_MULTIDECLARATIONS +#define BOOST_NO_CXX11_DEFAULTED_FUNCTIONS +#define BOOST_NO_CXX11_DELETED_FUNCTIONS +#define BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS +#define BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS +#define BOOST_NO_CXX11_LOCAL_CLASS_TEMPLATE_PARAMETERS +#define BOOST_NO_CXX11_NOEXCEPT +#define BOOST_NO_CXX11_NULLPTR +#define BOOST_NO_CXX11_RVALUE_REFERENCES +#define BOOST_NO_CXX11_SCOPED_ENUMS +#define BOOST_NO_SFINAE_EXPR +#define BOOST_NO_CXX11_SFINAE_EXPR +#define BOOST_NO_CXX11_STATIC_ASSERT +#define BOOST_NO_CXX11_TEMPLATE_ALIASES +#define BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX +#define BOOST_NO_CXX11_ALIGNAS +#define BOOST_NO_CXX11_ALIGNOF +#define BOOST_NO_CXX11_TRAILING_RESULT_TYPES +#define BOOST_NO_CXX11_INLINE_NAMESPACES +#define BOOST_NO_CXX11_REF_QUALIFIERS +#define BOOST_NO_CXX11_FINAL +#define BOOST_NO_CXX11_OVERRIDE +#define BOOST_NO_CXX11_THREAD_LOCAL +#define BOOST_NO_CXX11_UNRESTRICTED_UNION + +//__cpp_decltype 200707 possibly? +#define BOOST_NO_CXX11_DECLTYPE +#define BOOST_NO_CXX11_DECLTYPE_N3276 + +#if !defined(__cpp_unicode_characters) || (__cpp_unicode_characters < 200704) +# define BOOST_NO_CXX11_CHAR16_T +# define BOOST_NO_CXX11_CHAR32_T +#endif +#if !defined(__cpp_unicode_literals) || (__cpp_unicode_literals < 200710) +# define BOOST_NO_CXX11_UNICODE_LITERALS +#endif +#if !defined(__cpp_user_defined_literals) || (__cpp_user_defined_literals < 200809) +# define BOOST_NO_CXX11_USER_DEFINED_LITERALS +#endif +#if !defined(__cpp_variadic_templates) || (__cpp_variadic_templates < 200704) +# define BOOST_NO_CXX11_VARIADIC_TEMPLATES +#endif +#if !defined(__cpp_constexpr) || (__cpp_constexpr < 200907) +# define BOOST_NO_CXX11_CONSTEXPR +#endif +#if !defined(__cpp_lambdas) || (__cpp_lambdas < 200907) +# define BOOST_NO_CXX11_LAMBDAS +#endif +#if !defined(__cpp_range_based_for) || (__cpp_range_based_for < 200710) +# define BOOST_NO_CXX11_RANGE_BASED_FOR +#endif +#if !defined(__cpp_raw_strings) || (__cpp_raw_strings < 200610) +# define BOOST_NO_CXX11_RAW_LITERALS +#endif + + +// C++ 14: +#if !defined(__cpp_aggregate_nsdmi) || (__cpp_aggregate_nsdmi < 201304) +# define BOOST_NO_CXX14_AGGREGATE_NSDMI +#endif +#if !defined(__cpp_binary_literals) || (__cpp_binary_literals < 201304) +# define BOOST_NO_CXX14_BINARY_LITERALS +#endif +#if !defined(__cpp_constexpr) || (__cpp_constexpr < 201304) +# define BOOST_NO_CXX14_CONSTEXPR +#endif +#if !defined(__cpp_decltype_auto) || (__cpp_decltype_auto < 201304) +# define BOOST_NO_CXX14_DECLTYPE_AUTO +#endif +#if (__cplusplus < 201304) // There's no SD6 check for this.... +# define BOOST_NO_CXX14_DIGIT_SEPARATORS +#endif +#if !defined(__cpp_generic_lambdas) || (__cpp_generic_lambdas < 201304) +# define BOOST_NO_CXX14_GENERIC_LAMBDAS +#endif +#if !defined(__cpp_init_captures) || (__cpp_init_captures < 201304) +# define BOOST_NO_CXX14_INITIALIZED_LAMBDA_CAPTURES +#endif +#if !defined(__cpp_return_type_deduction) || (__cpp_return_type_deduction < 201304) +# define BOOST_NO_CXX14_RETURN_TYPE_DEDUCTION +#endif +#if !defined(__cpp_variable_templates) || (__cpp_variable_templates < 201304) +# define BOOST_NO_CXX14_VARIABLE_TEMPLATES +#endif + +// C++17 +#if !defined(__cpp_structured_bindings) || (__cpp_structured_bindings < 201606) +# define BOOST_NO_CXX17_STRUCTURED_BINDINGS +#endif +#if !defined(__cpp_inline_variables) || (__cpp_inline_variables < 201606) +# define BOOST_NO_CXX17_INLINE_VARIABLES +#endif +#if !defined(__cpp_fold_expressions) || (__cpp_fold_expressions < 201603) +# define BOOST_NO_CXX17_FOLD_EXPRESSIONS +#endif + +#if !defined(__cpp_if_constexpr) || (__cpp_if_constexpr < 201606) +# define BOOST_NO_CXX17_IF_CONSTEXPR +#endif + +#ifdef c_plusplus +// EDG has "long long" in non-strict mode +// However, some libraries have insufficient "long long" support +// #define BOOST_HAS_LONG_LONG +#endif diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/compiler/compaq_cxx.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/compiler/compaq_cxx.hpp new file mode 100644 index 0000000..4d6b8ab --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/compiler/compaq_cxx.hpp @@ -0,0 +1,19 @@ +// (C) Copyright John Maddock 2001 - 2003. +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for most recent version. + +// Tru64 C++ compiler setup (now HP): + +#define BOOST_COMPILER "HP Tru64 C++ " BOOST_STRINGIZE(__DECCXX_VER) + +#include + +// +// versions check: +// Nothing to do here? + + + diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/compiler/cray.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/compiler/cray.hpp new file mode 100644 index 0000000..e40fd05 --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/compiler/cray.hpp @@ -0,0 +1,446 @@ +// Copyright 2011 John Maddock +// Copyright 2013, 2017-2018 Cray, Inc. +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for most recent version. + +// Cray C++ compiler setup. +// +// There are a few parameters that affect the macros defined in this file: +// +// - What version of CCE (Cray Compiling Environment) are we running? This +// comes from the '_RELEASE_MAJOR', '_RELEASE_MINOR', and +// '_RELEASE_PATCHLEVEL' macros. +// - What C++ standards conformance level are we using (e.g. '-h +// std=c++14')? This comes from the '__cplusplus' macro. +// - Are we using GCC extensions ('-h gnu' or '-h nognu')? If we have '-h +// gnu' then CCE emulates GCC, and the macros '__GNUC__', +// '__GNUC_MINOR__', and '__GNUC_PATCHLEVEL__' are defined. +// +// This file is organized as follows: +// +// - Verify that the combination of parameters listed above is supported. +// If we have an unsupported combination, we abort with '#error'. +// - Establish baseline values for all Boost macros. +// - Apply changes to the baseline macros based on compiler version. These +// changes are cummulative so each version section only describes the +// changes since the previous version. +// - Within each version section, we may also apply changes based on +// other parameters (i.e. C++ standards conformance level and GCC +// extensions). +// +// To test changes to this file: +// +// ``` +// module load cce/8.6.5 # Pick the version you want to test. +// cd boost/libs/config/test/all +// b2 -j 8 toolset=cray cxxstd=03 cxxstd=11 cxxstd=14 cxxstd-dialect=gnu linkflags=-lrt +// ``` +// Note: Using 'cxxstd-dialect=iso' is not supported at this time (the +// tests run, but many tests fail). +// +// Note: 'linkflags=-lrt' is needed in Cray Linux Environment. Otherwise +// you get an 'undefined reference to clock_gettime' error. +// +// Note: If a test '*_fail.cpp' file compiles, but fails to run, then it is +// reported as a defect. However, this is not actually a defect. This is an +// area where the test system is somewhat broken. Tests that are failing +// because of this problem are noted in the comments. +// +// Pay attention to the macro definitions for the macros you wish to +// modify. For example, only macros categorized as compiler macros should +// appear in this file; platform macros should not appear in this file. +// Also, some macros have to be defined to specific values; it is not +// always enough to define or undefine a macro. +// +// Macro definitions are available in the source code at: +// +// `boost/libs/config/doc/html/boost_config/boost_macro_reference.html` +// +// Macro definitions are also available online at: +// +// http://www.boost.org/doc/libs/master/libs/config/doc/html/boost_config/boost_macro_reference.html +// +// Typically, if you enable a feature, and the tests pass, then you have +// nothing to worry about. However, it's sometimes hard to figure out if a +// disabled feature needs to stay disabled. To get a list of disabled +// features, run 'b2' in 'boost/libs/config/checks'. These are the macros +// you should pay attention to (in addition to macros that cause test +// failures). + +//// +//// Front matter +//// + +// In a developer build of the Cray compiler (i.e. a compiler built by a +// Cray employee), the release patch level is reported as "x". This gives +// versions that look like e.g. "8.6.x". +// +// To accomplish this, the the Cray compiler preprocessor inserts: +// +// #define _RELEASE_PATCHLEVEL x +// +// If we are using a developer build of the compiler, we want to use the +// configuration macros for the most recent patch level of the release. To +// accomplish this, we'll pretend that _RELEASE_PATCHLEVEL is 99. +// +// However, it's difficult to detect if _RELEASE_PATCHLEVEL is x. We must +// consider that the x will be expanded if x is defined as a macro +// elsewhere. For example, imagine if someone put "-D x=3" on the command +// line, and _RELEASE_PATCHLEVEL is x. Then _RELEASE_PATCHLEVEL would +// expand to 3, and we could not distinguish it from an actual +// _RELEASE_PATCHLEVEL of 3. This problem only affects developer builds; in +// production builds, _RELEASE_PATCHLEVEL is always an integer. +// +// IMPORTANT: In developer builds, if x is defined as a macro, you will get +// an incorrect configuration. The behavior in this case is undefined. +// +// Even if x is not defined, we have to use some trickery to detect if +// _RELEASE_PATCHLEVEL is x. First we define BOOST_CRAY_x to some arbitrary +// magic value, 9867657. Then we use BOOST_CRAY_APPEND to append the +// expanded value of _RELEASE_PATCHLEVEL to the string "BOOST_CRAY_". +// +// - If _RELEASE_PATCHLEVEL is undefined, we get "BOOST_CRAY_". +// - If _RELEASE_PATCHLEVEL is 5, we get "BOOST_CRAY_5". +// - If _RELEASE_PATCHLEVEL is x (and x is not defined) we get +// "BOOST_CRAY_x": +// +// Then we check if BOOST_CRAY_x is equal to the output of +// BOOST_CRAY_APPEND. In other words, the output of BOOST_CRAY_APPEND is +// treated as a macro name, and expanded again. If we can safely assume +// that BOOST_CRAY_ is not a macro defined as our magic number, and +// BOOST_CRAY_5 is not a macro defined as our magic number, then the only +// way the equality test can pass is if _RELEASE_PATCHLEVEL expands to x. +// +// So, that is how we detect if we are using a developer build of the Cray +// compiler. + +#define BOOST_CRAY_x 9867657 // Arbitrary number +#define BOOST_CRAY_APPEND(MACRO) BOOST_CRAY_APPEND_INTERNAL(MACRO) +#define BOOST_CRAY_APPEND_INTERNAL(MACRO) BOOST_CRAY_##MACRO + +#if BOOST_CRAY_x == BOOST_CRAY_APPEND(_RELEASE_PATCHLEVEL) + + // This is a developer build. + // + // - _RELEASE_PATCHLEVEL is defined as x, and x is not defined as a macro. + + // Pretend _RELEASE_PATCHLEVEL is 99, so we get the configuration for the + // most recent patch level in this release. + + #define BOOST_CRAY_VERSION (_RELEASE_MAJOR * 10000 + _RELEASE_MINOR * 100 + 99) + +#else + + // This is a production build. + // + // _RELEASE_PATCHLEVEL is not defined as x, or x is defined as a macro. + + #define BOOST_CRAY_VERSION (_RELEASE_MAJOR * 10000 + _RELEASE_MINOR * 100 + _RELEASE_PATCHLEVEL) + +#endif // BOOST_CRAY_x == BOOST_CRAY_APPEND(_RELEASE_PATCHLEVEL) + +#undef BOOST_CRAY_APPEND_INTERNAL +#undef BOOST_CRAY_APPEND +#undef BOOST_CRAY_x + + +#ifdef __GNUC__ +# define BOOST_GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) +#endif + +#ifndef BOOST_COMPILER +# define BOOST_COMPILER "Cray C++ version " BOOST_STRINGIZE(_RELEASE_MAJOR) "." BOOST_STRINGIZE(_RELEASE_MINOR) "." BOOST_STRINGIZE(_RELEASE_PATCHLEVEL) +#endif + +// Since the Cray compiler defines '__GNUC__', we have to emulate some +// additional GCC macros in order to make everything work. +// +// FIXME: Perhaps Cray should fix the compiler to define these additional +// macros for GCC emulation? + +#if __cplusplus >= 201103L && defined(__GNUC__) && !defined(__GXX_EXPERIMENTAL_CXX0X__) +# define __GXX_EXPERIMENTAL_CXX0X__ 1 +#endif + +//// +//// Parameter validation +//// + +// FIXME: Do we really need to support compilers before 8.5? Do they pass +// the Boost.Config tests? + +#if BOOST_CRAY_VERSION < 80000 +# error "Boost is not configured for Cray compilers prior to version 8, please try the configure script." +#endif + +// We only support recent EDG based compilers. + +#ifndef __EDG__ +# error "Unsupported Cray compiler, please try running the configure script." +#endif + +//// +//// Baseline values +//// + +#include + +#define BOOST_HAS_NRVO +#define BOOST_NO_COMPLETE_VALUE_INITIALIZATION +#define BOOST_NO_CXX11_AUTO_DECLARATIONS +#define BOOST_NO_CXX11_AUTO_MULTIDECLARATIONS +#define BOOST_NO_CXX11_CHAR16_T +#define BOOST_NO_CXX11_CHAR32_T +#define BOOST_NO_CXX11_CONSTEXPR +#define BOOST_NO_CXX11_DECLTYPE +#define BOOST_NO_CXX11_DECLTYPE_N3276 +#define BOOST_NO_CXX11_DEFAULTED_FUNCTIONS +#define BOOST_NO_CXX11_DELETED_FUNCTIONS +#define BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS +#define BOOST_NO_CXX11_FINAL +#define BOOST_NO_CXX11_OVERRIDE +#define BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS +#define BOOST_NO_CXX11_LAMBDAS +#define BOOST_NO_CXX11_LOCAL_CLASS_TEMPLATE_PARAMETERS +#define BOOST_NO_CXX11_NOEXCEPT +#define BOOST_NO_CXX11_NULLPTR +#define BOOST_NO_CXX11_RANGE_BASED_FOR +#define BOOST_NO_CXX11_RAW_LITERALS +#define BOOST_NO_CXX11_REF_QUALIFIERS +#define BOOST_NO_CXX11_RVALUE_REFERENCES +#define BOOST_NO_CXX11_SCOPED_ENUMS +#define BOOST_NO_CXX11_SFINAE_EXPR +#define BOOST_NO_CXX11_STATIC_ASSERT +#define BOOST_NO_CXX11_TEMPLATE_ALIASES +#define BOOST_NO_CXX11_THREAD_LOCAL +#define BOOST_NO_CXX11_UNICODE_LITERALS +#define BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX +#define BOOST_NO_CXX11_USER_DEFINED_LITERALS +#define BOOST_NO_CXX11_VARIADIC_MACROS +#define BOOST_NO_CXX11_VARIADIC_TEMPLATES +#define BOOST_NO_CXX11_UNRESTRICTED_UNION +#define BOOST_NO_SFINAE_EXPR +#define BOOST_NO_TWO_PHASE_NAME_LOOKUP + +//#define BOOST_BCB_PARTIAL_SPECIALIZATION_BUG +#define BOOST_MATH_DISABLE_STD_FPCLASSIFY +//#define BOOST_HAS_FPCLASSIFY + +#define BOOST_SP_USE_PTHREADS +#define BOOST_AC_USE_PTHREADS + +// +// Everything that follows is working around what are thought to be +// compiler shortcomings. Revist all of these regularly. +// + +//#define BOOST_USE_ENUM_STATIC_ASSERT +//#define BOOST_BUGGY_INTEGRAL_CONSTANT_EXPRESSIONS //(this may be implied by the previous #define + +// These constants should be provided by the compiler. + +#ifndef __ATOMIC_RELAXED +#define __ATOMIC_RELAXED 0 +#define __ATOMIC_CONSUME 1 +#define __ATOMIC_ACQUIRE 2 +#define __ATOMIC_RELEASE 3 +#define __ATOMIC_ACQ_REL 4 +#define __ATOMIC_SEQ_CST 5 +#endif + +//// +//// Version changes +//// + +// +// 8.5.0 +// + +#if BOOST_CRAY_VERSION >= 80500 + +#if __cplusplus >= 201103L + +#undef BOOST_HAS_NRVO +#undef BOOST_NO_COMPLETE_VALUE_INITIALIZATION +#undef BOOST_NO_CXX11_AUTO_DECLARATIONS +#undef BOOST_NO_CXX11_AUTO_MULTIDECLARATIONS +#undef BOOST_NO_CXX11_CHAR16_T +#undef BOOST_NO_CXX11_CHAR32_T +#undef BOOST_NO_CXX11_CONSTEXPR +#undef BOOST_NO_CXX11_DECLTYPE +#undef BOOST_NO_CXX11_DECLTYPE_N3276 +#undef BOOST_NO_CXX11_DEFAULTED_FUNCTIONS +#undef BOOST_NO_CXX11_DELETED_FUNCTIONS +#undef BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS +#undef BOOST_NO_CXX11_FINAL +#undef BOOST_NO_CXX11_OVERRIDE +#undef BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS +#undef BOOST_NO_CXX11_LAMBDAS +#undef BOOST_NO_CXX11_LOCAL_CLASS_TEMPLATE_PARAMETERS +#undef BOOST_NO_CXX11_NOEXCEPT +#undef BOOST_NO_CXX11_NULLPTR +#undef BOOST_NO_CXX11_RANGE_BASED_FOR +#undef BOOST_NO_CXX11_RAW_LITERALS +#undef BOOST_NO_CXX11_REF_QUALIFIERS +#undef BOOST_NO_CXX11_RVALUE_REFERENCES +#undef BOOST_NO_CXX11_SCOPED_ENUMS +#undef BOOST_NO_CXX11_SFINAE_EXPR +#undef BOOST_NO_CXX11_STATIC_ASSERT +#undef BOOST_NO_CXX11_TEMPLATE_ALIASES +#undef BOOST_NO_CXX11_THREAD_LOCAL +#undef BOOST_NO_CXX11_UNICODE_LITERALS +#undef BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX +#undef BOOST_NO_CXX11_USER_DEFINED_LITERALS +#undef BOOST_NO_CXX11_VARIADIC_MACROS +#undef BOOST_NO_CXX11_VARIADIC_TEMPLATES +#undef BOOST_NO_CXX11_UNRESTRICTED_UNION +#undef BOOST_NO_SFINAE_EXPR +#undef BOOST_NO_TWO_PHASE_NAME_LOOKUP +#undef BOOST_MATH_DISABLE_STD_FPCLASSIFY +#undef BOOST_SP_USE_PTHREADS +#undef BOOST_AC_USE_PTHREADS + +#define BOOST_HAS_VARIADIC_TMPL +#define BOOST_HAS_UNISTD_H +#define BOOST_HAS_TR1_COMPLEX_INVERSE_TRIG +#define BOOST_HAS_TR1_COMPLEX_OVERLOADS +#define BOOST_HAS_STDINT_H +#define BOOST_HAS_STATIC_ASSERT +#define BOOST_HAS_SIGACTION +#define BOOST_HAS_SCHED_YIELD +#define BOOST_HAS_RVALUE_REFS +#define BOOST_HAS_PTHREADS +#define BOOST_HAS_PTHREAD_YIELD +#define BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE +#define BOOST_HAS_PARTIAL_STD_ALLOCATOR +#define BOOST_HAS_NRVO +#define BOOST_HAS_NL_TYPES_H +#define BOOST_HAS_NANOSLEEP +#define BOOST_NO_CXX11_SMART_PTR +#define BOOST_NO_CXX11_HDR_FUNCTIONAL +#define BOOST_NO_CXX14_CONSTEXPR +#define BOOST_HAS_LONG_LONG +#define BOOST_HAS_FLOAT128 + +#if __cplusplus < 201402L +#define BOOST_NO_CXX11_DECLTYPE_N3276 +#endif // __cplusplus < 201402L + +#endif // __cplusplus >= 201103L + +#endif // BOOST_CRAY_VERSION >= 80500 + +// +// 8.6.4 +// (versions prior to 8.6.5 do not define _RELEASE_PATCHLEVEL) +// + +#if BOOST_CRAY_VERSION >= 80600 + +#if __cplusplus >= 199711L +#define BOOST_HAS_FLOAT128 +#define BOOST_HAS_PTHREAD_YIELD // This is a platform macro, but it improves test results. +#define BOOST_NO_COMPLETE_VALUE_INITIALIZATION // This is correct. Test compiles, but fails to run. +#undef BOOST_NO_CXX11_CHAR16_T +#undef BOOST_NO_CXX11_CHAR32_T +#undef BOOST_NO_CXX11_INLINE_NAMESPACES +#undef BOOST_NO_CXX11_FINAL +#undef BOOST_NO_CXX11_OVERRIDE +#undef BOOST_NO_CXX11_FIXED_LENGTH_VARIADIC_TEMPLATE_EXPANSION_PACKS +#undef BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS +#define BOOST_NO_CXX11_SFINAE_EXPR // This is correct, even though '*_fail.cpp' test fails. +#undef BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX +#undef BOOST_NO_CXX11_VARIADIC_MACROS +#undef BOOST_NO_CXX11_VARIADIC_TEMPLATES +// 'BOOST_NO_DEDUCED_TYPENAME' test is broken. The test files are enabled / +// disabled with an '#ifdef BOOST_DEDUCED_TYPENAME'. However, +// 'boost/libs/config/include/boost/config/detail/suffix.hpp' ensures that +// 'BOOST_DEDUCED_TYPENAME' is always defined (the value it is defined as +// depends on 'BOOST_NO_DEDUCED_TYPENAME'). So, modifying +// 'BOOST_NO_DEDUCED_TYPENAME' has no effect on which tests are run. +// +// The 'no_ded_typename_pass.cpp' test should always compile and run +// successfully, because 'BOOST_DEDUCED_TYPENAME' must always have an +// appropriate value (it's not just something that you turn on or off). +// Therefore, if you wish to test changes to 'BOOST_NO_DEDUCED_TYPENAME', +// you have to modify 'no_ded_typename_pass.cpp' to unconditionally include +// 'boost_no_ded_typename.ipp'. +#undef BOOST_NO_DEDUCED_TYPENAME // This is correct. Test is broken. +#undef BOOST_NO_SFINAE_EXPR +#undef BOOST_NO_TWO_PHASE_NAME_LOOKUP +#endif // __cplusplus >= 199711L + +#if __cplusplus >= 201103L +#undef BOOST_NO_CXX11_ALIGNAS +#undef BOOST_NO_CXX11_ALIGNOF +#undef BOOST_NO_CXX11_DECLTYPE_N3276 +#define BOOST_NO_CXX11_HDR_ATOMIC +#undef BOOST_NO_CXX11_HDR_FUNCTIONAL +#define BOOST_NO_CXX11_HDR_REGEX // This is correct. Test compiles, but fails to run. +#undef BOOST_NO_CXX11_SFINAE_EXPR +#undef BOOST_NO_CXX11_SMART_PTR +#undef BOOST_NO_CXX11_TRAILING_RESULT_TYPES +#endif // __cplusplus >= 201103L + +#if __cplusplus >= 201402L +#undef BOOST_NO_CXX14_CONSTEXPR +#define BOOST_NO_CXX14_DIGIT_SEPARATORS +#endif // __cplusplus == 201402L + +#endif // BOOST_CRAY_VERSION >= 80600 + +// +// 8.6.5 +// (no change from 8.6.4) +// + +// +// 8.7.0 +// + +#if BOOST_CRAY_VERSION >= 80700 + +#if __cplusplus >= 199711L +#endif // __cplusplus >= 199711L + +#if __cplusplus >= 201103L +#undef BOOST_NO_CXX11_HDR_ATOMIC +#undef BOOST_NO_CXX11_HDR_REGEX +#endif // __cplusplus >= 201103L + +#if __cplusplus >= 201402L +#endif // __cplusplus == 201402L + +#endif // BOOST_CRAY_VERSION >= 80700 + +// +// Next release +// + +#if BOOST_CRAY_VERSION > 80799 + +#if __cplusplus >= 199711L +#endif // __cplusplus >= 199711L + +#if __cplusplus >= 201103L +#endif // __cplusplus >= 201103L + +#if __cplusplus >= 201402L +#endif // __cplusplus == 201402L + +#endif // BOOST_CRAY_VERSION > 80799 + +//// +//// Remove temporary macros +//// + +// I've commented out some '#undef' statements to signify that we purposely +// want to keep certain macros. + +//#undef __GXX_EXPERIMENTAL_CXX0X__ +//#undef BOOST_COMPILER +#undef BOOST_GCC_VERSION +#undef BOOST_CRAY_VERSION diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/compiler/diab.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/compiler/diab.hpp new file mode 100644 index 0000000..943db83 --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/compiler/diab.hpp @@ -0,0 +1,26 @@ +// (C) Copyright Brian Kuhl 2016. +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// Check this is a recent EDG based compiler, otherwise we don't support it here: + + +#ifndef __EDG_VERSION__ +# error "Unknown Diab compiler version - please run the configure tests and report the results" +#endif + +#include "boost/config/compiler/common_edg.hpp" + +#define BOOST_NO_TWO_PHASE_NAME_LOOKUP +#define BOOST_BUGGY_INTEGRAL_CONSTANT_EXPRESSIONS + +#define BOOST_MPL_CFG_NO_HAS_XXX_TEMPLATE +#define BOOST_LOG_NO_MEMBER_TEMPLATE_FRIENDS +#define BOOST_REGEX_NO_EXTERNAL_TEMPLATES + +#define BOOST_NO_CXX11_HDR_INITIALIZER_LIST +#define BOOST_NO_CXX11_HDR_CODECVT +#define BOOST_NO_CXX11_NUMERIC_LIMITS + +#define BOOST_COMPILER "Wind River Diab " BOOST_STRINGIZE(__VERSION_NUMBER__) diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/compiler/digitalmars.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/compiler/digitalmars.hpp new file mode 100644 index 0000000..bb56ff6 --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/compiler/digitalmars.hpp @@ -0,0 +1,143 @@ +// Copyright (C) Christof Meerwald 2003 +// Copyright (C) Dan Watkins 2003 +// +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// Digital Mars C++ compiler setup: +#define BOOST_COMPILER __DMC_VERSION_STRING__ + +#define BOOST_HAS_LONG_LONG +#define BOOST_HAS_PRAGMA_ONCE + +#if !defined(BOOST_STRICT_CONFIG) +#define BOOST_NO_MEMBER_TEMPLATE_FRIENDS +#define BOOST_NO_OPERATORS_IN_NAMESPACE +#define BOOST_NO_UNREACHABLE_RETURN_DETECTION +#define BOOST_NO_SFINAE +#define BOOST_NO_USING_TEMPLATE +#define BOOST_FUNCTION_SCOPE_USING_DECLARATION_BREAKS_ADL +#endif + +// +// has macros: +#define BOOST_HAS_DIRENT_H +#define BOOST_HAS_STDINT_H +#define BOOST_HAS_WINTHREADS + +#if (__DMC__ >= 0x847) +#define BOOST_HAS_EXPM1 +#define BOOST_HAS_LOG1P +#endif + +// +// Is this really the best way to detect whether the std lib is in namespace std? +// +#ifdef __cplusplus +#include +#endif +#if !defined(__STL_IMPORT_VENDOR_CSTD) && !defined(_STLP_IMPORT_VENDOR_CSTD) +# define BOOST_NO_STDC_NAMESPACE +#endif + + +// check for exception handling support: +#if !defined(_CPPUNWIND) && !defined(BOOST_NO_EXCEPTIONS) +# define BOOST_NO_EXCEPTIONS +#endif + +// +// C++0x features +// +#define BOOST_NO_CXX11_AUTO_DECLARATIONS +#define BOOST_NO_CXX11_AUTO_MULTIDECLARATIONS +#define BOOST_NO_CXX11_CHAR16_T +#define BOOST_NO_CXX11_CHAR32_T +#define BOOST_NO_CXX11_CONSTEXPR +#define BOOST_NO_CXX11_DECLTYPE +#define BOOST_NO_CXX11_DECLTYPE_N3276 +#define BOOST_NO_CXX11_DEFAULTED_FUNCTIONS +#define BOOST_NO_CXX11_DELETED_FUNCTIONS +#define BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS +#define BOOST_NO_CXX11_EXTERN_TEMPLATE +#define BOOST_NO_CXX11_HDR_INITIALIZER_LIST +#define BOOST_NO_CXX11_LAMBDAS +#define BOOST_NO_CXX11_LOCAL_CLASS_TEMPLATE_PARAMETERS +#define BOOST_NO_CXX11_NOEXCEPT +#define BOOST_NO_CXX11_NULLPTR +#define BOOST_NO_CXX11_RANGE_BASED_FOR +#define BOOST_NO_CXX11_RAW_LITERALS +#define BOOST_NO_CXX11_RVALUE_REFERENCES +#define BOOST_NO_CXX11_SCOPED_ENUMS +#define BOOST_NO_SFINAE_EXPR +#define BOOST_NO_CXX11_SFINAE_EXPR +#define BOOST_NO_CXX11_STATIC_ASSERT +#define BOOST_NO_CXX11_TEMPLATE_ALIASES +#define BOOST_NO_CXX11_UNICODE_LITERALS +#define BOOST_NO_CXX11_VARIADIC_TEMPLATES +#define BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX +#define BOOST_NO_CXX11_USER_DEFINED_LITERALS +#define BOOST_NO_CXX11_ALIGNAS +#define BOOST_NO_CXX11_ALIGNOF +#define BOOST_NO_CXX11_TRAILING_RESULT_TYPES +#define BOOST_NO_CXX11_INLINE_NAMESPACES +#define BOOST_NO_CXX11_REF_QUALIFIERS +#define BOOST_NO_CXX11_FINAL +#define BOOST_NO_CXX11_OVERRIDE +#define BOOST_NO_CXX11_THREAD_LOCAL +#define BOOST_NO_CXX11_UNRESTRICTED_UNION + +// C++ 14: +#if !defined(__cpp_aggregate_nsdmi) || (__cpp_aggregate_nsdmi < 201304) +# define BOOST_NO_CXX14_AGGREGATE_NSDMI +#endif +#if !defined(__cpp_binary_literals) || (__cpp_binary_literals < 201304) +# define BOOST_NO_CXX14_BINARY_LITERALS +#endif +#if !defined(__cpp_constexpr) || (__cpp_constexpr < 201304) +# define BOOST_NO_CXX14_CONSTEXPR +#endif +#if !defined(__cpp_decltype_auto) || (__cpp_decltype_auto < 201304) +# define BOOST_NO_CXX14_DECLTYPE_AUTO +#endif +#if (__cplusplus < 201304) // There's no SD6 check for this.... +# define BOOST_NO_CXX14_DIGIT_SEPARATORS +#endif +#if !defined(__cpp_generic_lambdas) || (__cpp_generic_lambdas < 201304) +# define BOOST_NO_CXX14_GENERIC_LAMBDAS +#endif +#if !defined(__cpp_init_captures) || (__cpp_init_captures < 201304) +# define BOOST_NO_CXX14_INITIALIZED_LAMBDA_CAPTURES +#endif +#if !defined(__cpp_return_type_deduction) || (__cpp_return_type_deduction < 201304) +# define BOOST_NO_CXX14_RETURN_TYPE_DEDUCTION +#endif +#if !defined(__cpp_variable_templates) || (__cpp_variable_templates < 201304) +# define BOOST_NO_CXX14_VARIABLE_TEMPLATES +#endif + +// C++17 +#if !defined(__cpp_structured_bindings) || (__cpp_structured_bindings < 201606) +# define BOOST_NO_CXX17_STRUCTURED_BINDINGS +#endif +#if !defined(__cpp_inline_variables) || (__cpp_inline_variables < 201606) +# define BOOST_NO_CXX17_INLINE_VARIABLES +#endif +#if !defined(__cpp_fold_expressions) || (__cpp_fold_expressions < 201603) +# define BOOST_NO_CXX17_FOLD_EXPRESSIONS +#endif +#if !defined(__cpp_if_constexpr) || (__cpp_if_constexpr < 201606) +# define BOOST_NO_CXX17_IF_CONSTEXPR +#endif + +#if (__DMC__ <= 0x840) +#error "Compiler not supported or configured - please reconfigure" +#endif +// +// last known and checked version is ...: +#if (__DMC__ > 0x848) +# if defined(BOOST_ASSERT_CONFIG) +# error "boost: Unknown compiler version - please run the configure tests and report the results" +# endif +#endif diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/compiler/gcc.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/compiler/gcc.hpp new file mode 100644 index 0000000..2f1fe55 --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/compiler/gcc.hpp @@ -0,0 +1,383 @@ +// (C) Copyright John Maddock 2001 - 2003. +// (C) Copyright Darin Adler 2001 - 2002. +// (C) Copyright Jens Maurer 2001 - 2002. +// (C) Copyright Beman Dawes 2001 - 2003. +// (C) Copyright Douglas Gregor 2002. +// (C) Copyright David Abrahams 2002 - 2003. +// (C) Copyright Synge Todo 2003. +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for most recent version. + +// GNU C++ compiler setup. + +// +// Define BOOST_GCC so we know this is "real" GCC and not some pretender: +// +#define BOOST_GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) +#if !defined(__CUDACC__) +#define BOOST_GCC BOOST_GCC_VERSION +#endif + +#if defined(__GXX_EXPERIMENTAL_CXX0X__) || (__cplusplus >= 201103L) +# define BOOST_GCC_CXX11 +#endif + +#if __GNUC__ == 3 +# if defined (__PATHSCALE__) +# define BOOST_NO_TWO_PHASE_NAME_LOOKUP +# define BOOST_NO_IS_ABSTRACT +# endif + +# if __GNUC_MINOR__ < 4 +# define BOOST_NO_IS_ABSTRACT +# endif +# define BOOST_NO_CXX11_EXTERN_TEMPLATE +#endif +#if __GNUC__ < 4 +// +// All problems to gcc-3.x and earlier here: +// +#define BOOST_NO_TWO_PHASE_NAME_LOOKUP +# ifdef __OPEN64__ +# define BOOST_NO_IS_ABSTRACT +# endif +#endif + +// GCC prior to 3.4 had #pragma once too but it didn't work well with filesystem links +#if BOOST_GCC_VERSION >= 30400 +#define BOOST_HAS_PRAGMA_ONCE +#endif + +#if BOOST_GCC_VERSION < 40400 +// Previous versions of GCC did not completely implement value-initialization: +// GCC Bug 30111, "Value-initialization of POD base class doesn't initialize +// members", reported by Jonathan Wakely in 2006, +// http://gcc.gnu.org/bugzilla/show_bug.cgi?id=30111 (fixed for GCC 4.4) +// GCC Bug 33916, "Default constructor fails to initialize array members", +// reported by Michael Elizabeth Chastain in 2007, +// http://gcc.gnu.org/bugzilla/show_bug.cgi?id=33916 (fixed for GCC 4.2.4) +// See also: http://www.boost.org/libs/utility/value_init.htm#compiler_issues +#define BOOST_NO_COMPLETE_VALUE_INITIALIZATION +#endif + +#if !defined(__EXCEPTIONS) && !defined(BOOST_NO_EXCEPTIONS) +# define BOOST_NO_EXCEPTIONS +#endif + + +// +// Threading support: Turn this on unconditionally here (except for +// those platforms where we can know for sure). It will get turned off again +// later if no threading API is detected. +// +#if !defined(__MINGW32__) && !defined(linux) && !defined(__linux) && !defined(__linux__) +# define BOOST_HAS_THREADS +#endif + +// +// gcc has "long long" +// Except on Darwin with standard compliance enabled (-pedantic) +// Apple gcc helpfully defines this macro we can query +// +#if !defined(__DARWIN_NO_LONG_LONG) +# define BOOST_HAS_LONG_LONG +#endif + +// +// gcc implements the named return value optimization since version 3.1 +// +#define BOOST_HAS_NRVO + +// Branch prediction hints +#define BOOST_LIKELY(x) __builtin_expect(x, 1) +#define BOOST_UNLIKELY(x) __builtin_expect(x, 0) + +// +// Dynamic shared object (DSO) and dynamic-link library (DLL) support +// +#if __GNUC__ >= 4 +# if defined(_WIN32) || defined(__WIN32__) || defined(WIN32) || defined(__CYGWIN__) + // All Win32 development environments, including 64-bit Windows and MinGW, define + // _WIN32 or one of its variant spellings. Note that Cygwin is a POSIX environment, + // so does not define _WIN32 or its variants, but still supports dllexport/dllimport. +# define BOOST_HAS_DECLSPEC +# define BOOST_SYMBOL_EXPORT __attribute__((__dllexport__)) +# define BOOST_SYMBOL_IMPORT __attribute__((__dllimport__)) +# else +# define BOOST_SYMBOL_EXPORT __attribute__((__visibility__("default"))) +# define BOOST_SYMBOL_IMPORT +# endif +# define BOOST_SYMBOL_VISIBLE __attribute__((__visibility__("default"))) +#else +// config/platform/win32.hpp will define BOOST_SYMBOL_EXPORT, etc., unless already defined +# define BOOST_SYMBOL_EXPORT +#endif + +// +// RTTI and typeinfo detection is possible post gcc-4.3: +// +#if BOOST_GCC_VERSION > 40300 +# ifndef __GXX_RTTI +# ifndef BOOST_NO_TYPEID +# define BOOST_NO_TYPEID +# endif +# ifndef BOOST_NO_RTTI +# define BOOST_NO_RTTI +# endif +# endif +#endif + +// +// Recent GCC versions have __int128 when in 64-bit mode. +// +// We disable this if the compiler is really nvcc with C++03 as it +// doesn't actually support __int128 as of CUDA_VERSION=7500 +// even though it defines __SIZEOF_INT128__. +// See https://svn.boost.org/trac/boost/ticket/8048 +// https://svn.boost.org/trac/boost/ticket/11852 +// Only re-enable this for nvcc if you're absolutely sure +// of the circumstances under which it's supported: +// +#if defined(__CUDACC__) +# if defined(BOOST_GCC_CXX11) +# define BOOST_NVCC_CXX11 +# else +# define BOOST_NVCC_CXX03 +# endif +#endif + +#if defined(__SIZEOF_INT128__) && !defined(BOOST_NVCC_CXX03) +# define BOOST_HAS_INT128 +#endif +// +// Recent GCC versions have a __float128 native type, we need to +// include a std lib header to detect this - not ideal, but we'll +// be including later anyway when we select the std lib. +// +// Nevertheless, as of CUDA 7.5, using __float128 with the host +// compiler in pre-C++11 mode is still not supported. +// See https://svn.boost.org/trac/boost/ticket/11852 +// +#ifdef __cplusplus +#include +#else +#include +#endif +#if defined(_GLIBCXX_USE_FLOAT128) && !defined(__STRICT_ANSI__) && !defined(BOOST_NVCC_CXX03) +# define BOOST_HAS_FLOAT128 +#endif + +// C++0x features in 4.3.n and later +// +#if (BOOST_GCC_VERSION >= 40300) && defined(BOOST_GCC_CXX11) +// C++0x features are only enabled when -std=c++0x or -std=gnu++0x are +// passed on the command line, which in turn defines +// __GXX_EXPERIMENTAL_CXX0X__. +# define BOOST_HAS_DECLTYPE +# define BOOST_HAS_RVALUE_REFS +# define BOOST_HAS_STATIC_ASSERT +# define BOOST_HAS_VARIADIC_TMPL +#else +# define BOOST_NO_CXX11_DECLTYPE +# define BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS +# define BOOST_NO_CXX11_RVALUE_REFERENCES +# define BOOST_NO_CXX11_STATIC_ASSERT +#endif + +// C++0x features in 4.4.n and later +// +#if (BOOST_GCC_VERSION < 40400) || !defined(BOOST_GCC_CXX11) +# define BOOST_NO_CXX11_AUTO_DECLARATIONS +# define BOOST_NO_CXX11_AUTO_MULTIDECLARATIONS +# define BOOST_NO_CXX11_CHAR16_T +# define BOOST_NO_CXX11_CHAR32_T +# define BOOST_NO_CXX11_HDR_INITIALIZER_LIST +# define BOOST_NO_CXX11_DEFAULTED_FUNCTIONS +# define BOOST_NO_CXX11_DELETED_FUNCTIONS +# define BOOST_NO_CXX11_TRAILING_RESULT_TYPES +# define BOOST_NO_CXX11_INLINE_NAMESPACES +# define BOOST_NO_CXX11_VARIADIC_TEMPLATES +#endif + +#if BOOST_GCC_VERSION < 40500 +# define BOOST_NO_SFINAE_EXPR +#endif + +// GCC 4.5 forbids declaration of defaulted functions in private or protected sections +#if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ == 5) || !defined(BOOST_GCC_CXX11) +# define BOOST_NO_CXX11_NON_PUBLIC_DEFAULTED_FUNCTIONS +#endif + +// C++0x features in 4.5.0 and later +// +#if (BOOST_GCC_VERSION < 40500) || !defined(BOOST_GCC_CXX11) +# define BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS +# define BOOST_NO_CXX11_LAMBDAS +# define BOOST_NO_CXX11_LOCAL_CLASS_TEMPLATE_PARAMETERS +# define BOOST_NO_CXX11_RAW_LITERALS +# define BOOST_NO_CXX11_UNICODE_LITERALS +# define BOOST_NO_CXX11_ALIGNOF +#endif + +// C++0x features in 4.5.1 and later +// +#if (BOOST_GCC_VERSION < 40501) || !defined(BOOST_GCC_CXX11) +// scoped enums have a serious bug in 4.4.0, so define BOOST_NO_CXX11_SCOPED_ENUMS before 4.5.1 +// See http://gcc.gnu.org/bugzilla/show_bug.cgi?id=38064 +# define BOOST_NO_CXX11_SCOPED_ENUMS +#endif + +// C++0x features in 4.6.n and later +// +#if (BOOST_GCC_VERSION < 40600) || !defined(BOOST_GCC_CXX11) +#define BOOST_NO_CXX11_DEFAULTED_MOVES +#define BOOST_NO_CXX11_NOEXCEPT +#define BOOST_NO_CXX11_NULLPTR +#define BOOST_NO_CXX11_RANGE_BASED_FOR +#define BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX +#endif + +// C++0x features in 4.7.n and later +// +#if (BOOST_GCC_VERSION < 40700) || !defined(BOOST_GCC_CXX11) +// Note that while constexpr is partly supported in gcc-4.6 it's a +// pre-std version with several bugs: +# define BOOST_NO_CXX11_CONSTEXPR +# define BOOST_NO_CXX11_FINAL +# define BOOST_NO_CXX11_TEMPLATE_ALIASES +# define BOOST_NO_CXX11_USER_DEFINED_LITERALS +# define BOOST_NO_CXX11_FIXED_LENGTH_VARIADIC_TEMPLATE_EXPANSION_PACKS +# define BOOST_NO_CXX11_OVERRIDE +#endif + +// C++0x features in 4.8.n and later +// +#if (BOOST_GCC_VERSION < 40800) || !defined(BOOST_GCC_CXX11) +# define BOOST_NO_CXX11_THREAD_LOCAL +# define BOOST_NO_CXX11_SFINAE_EXPR +#endif + +// C++0x features in 4.8.1 and later +// +#if (BOOST_GCC_VERSION < 40801) || !defined(BOOST_GCC_CXX11) +# define BOOST_NO_CXX11_DECLTYPE_N3276 +# define BOOST_NO_CXX11_REF_QUALIFIERS +# define BOOST_NO_CXX14_BINARY_LITERALS +#endif + +// C++0x features in 4.9.n and later +// +#if (BOOST_GCC_VERSION < 40900) || !defined(BOOST_GCC_CXX11) +// Although alignas support is added in gcc 4.8, it does not accept +// dependent constant expressions as an argument until gcc 4.9. +# define BOOST_NO_CXX11_ALIGNAS +#endif + +// C++0x features in 5.1 and later +// +#if (BOOST_GCC_VERSION < 50100) || !defined(BOOST_GCC_CXX11) +# define BOOST_NO_CXX11_UNRESTRICTED_UNION +#endif + +// C++14 features in 4.9.0 and later +// +#if (BOOST_GCC_VERSION < 40900) || (__cplusplus < 201300) +# define BOOST_NO_CXX14_RETURN_TYPE_DEDUCTION +# define BOOST_NO_CXX14_GENERIC_LAMBDAS +# define BOOST_NO_CXX14_DIGIT_SEPARATORS +# define BOOST_NO_CXX14_DECLTYPE_AUTO +# if !((BOOST_GCC_VERSION >= 40801) && (BOOST_GCC_VERSION < 40900) && defined(BOOST_GCC_CXX11)) +# define BOOST_NO_CXX14_INITIALIZED_LAMBDA_CAPTURES +# endif +#endif + + +// C++ 14: +#if !defined(__cpp_aggregate_nsdmi) || (__cpp_aggregate_nsdmi < 201304) +# define BOOST_NO_CXX14_AGGREGATE_NSDMI +#endif +#if !defined(__cpp_constexpr) || (__cpp_constexpr < 201304) +# define BOOST_NO_CXX14_CONSTEXPR +#endif +#if (BOOST_GCC_VERSION < 50200) || !defined(__cpp_variable_templates) || (__cpp_variable_templates < 201304) +# define BOOST_NO_CXX14_VARIABLE_TEMPLATES +#endif + +// C++17 +#if !defined(__cpp_structured_bindings) || (__cpp_structured_bindings < 201606) +# define BOOST_NO_CXX17_STRUCTURED_BINDINGS +#endif +#if !defined(__cpp_inline_variables) || (__cpp_inline_variables < 201606) +# define BOOST_NO_CXX17_INLINE_VARIABLES +#endif +#if !defined(__cpp_fold_expressions) || (__cpp_fold_expressions < 201603) +# define BOOST_NO_CXX17_FOLD_EXPRESSIONS +#endif +#if !defined(__cpp_if_constexpr) || (__cpp_if_constexpr < 201606) +# define BOOST_NO_CXX17_IF_CONSTEXPR +#endif + +#if __GNUC__ >= 7 +# define BOOST_FALLTHROUGH __attribute__((fallthrough)) +#endif + +#if (__GNUC__ < 11) && defined(__MINGW32__) && !defined(__MINGW64__) +// thread_local was broken on mingw for all 32bit compiler releases prior to 11.x, see +// https://sourceforge.net/p/mingw-w64/bugs/527/ +// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83562 +// Not setting this causes program termination on thread exit. +#define BOOST_NO_CXX11_THREAD_LOCAL +#endif + +// +// Unused attribute: +#if __GNUC__ >= 4 +# define BOOST_ATTRIBUTE_UNUSED __attribute__((__unused__)) +#endif + +// Type aliasing hint. Supported since gcc 3.3. +#define BOOST_MAY_ALIAS __attribute__((__may_alias__)) + +// Unreachable code markup +#if BOOST_GCC_VERSION >= 40500 +#define BOOST_UNREACHABLE_RETURN(x) __builtin_unreachable(); +#endif + +// Deprecated symbol markup +#if BOOST_GCC_VERSION >= 40500 +#define BOOST_DEPRECATED(msg) __attribute__((deprecated(msg))) +#else +#define BOOST_DEPRECATED(msg) __attribute__((deprecated)) +#endif + +#ifndef BOOST_COMPILER +# define BOOST_COMPILER "GNU C++ version " __VERSION__ +#endif + +// ConceptGCC compiler: +// http://www.generic-programming.org/software/ConceptGCC/ +#ifdef __GXX_CONCEPTS__ +# define BOOST_HAS_CONCEPTS +# define BOOST_COMPILER "ConceptGCC version " __VERSION__ +#endif + +// versions check: +// we don't know gcc prior to version 3.30: +#if (BOOST_GCC_VERSION < 30300) +# error "Compiler not configured - please reconfigure" +#endif +// +// last known and checked version is 8.1: +#if (BOOST_GCC_VERSION > 80100) +# if defined(BOOST_ASSERT_CONFIG) +# error "Boost.Config is older than your compiler - please check for an updated Boost release." +# else +// we don't emit warnings here anymore since there are no defect macros defined for +// gcc post 3.4, so any failures are gcc regressions... +//# warning "boost: Unknown compiler version - please run the configure tests and report the results" +# endif +#endif + diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/compiler/gcc_xml.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/compiler/gcc_xml.hpp new file mode 100644 index 0000000..75cac44 --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/compiler/gcc_xml.hpp @@ -0,0 +1,114 @@ +// (C) Copyright John Maddock 2006. +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for most recent version. + +// GCC-XML C++ compiler setup: + +# if !defined(__GCCXML_GNUC__) || ((__GCCXML_GNUC__ <= 3) && (__GCCXML_GNUC_MINOR__ <= 3)) +# define BOOST_NO_IS_ABSTRACT +# endif + +// +// Threading support: Turn this on unconditionally here (except for +// those platforms where we can know for sure). It will get turned off again +// later if no threading API is detected. +// +#if !defined(__MINGW32__) && !defined(_MSC_VER) && !defined(linux) && !defined(__linux) && !defined(__linux__) +# define BOOST_HAS_THREADS +#endif + +// +// gcc has "long long" +// +#define BOOST_HAS_LONG_LONG + +// C++0x features: +// +# define BOOST_NO_CXX11_CONSTEXPR +# define BOOST_NO_CXX11_NULLPTR +# define BOOST_NO_CXX11_TEMPLATE_ALIASES +# define BOOST_NO_CXX11_DECLTYPE +# define BOOST_NO_CXX11_DECLTYPE_N3276 +# define BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS +# define BOOST_NO_CXX11_RVALUE_REFERENCES +# define BOOST_NO_CXX11_STATIC_ASSERT +# define BOOST_NO_CXX11_VARIADIC_TEMPLATES +# define BOOST_NO_CXX11_VARIADIC_MACROS +# define BOOST_NO_CXX11_AUTO_DECLARATIONS +# define BOOST_NO_CXX11_AUTO_MULTIDECLARATIONS +# define BOOST_NO_CXX11_CHAR16_T +# define BOOST_NO_CXX11_CHAR32_T +# define BOOST_NO_CXX11_DEFAULTED_FUNCTIONS +# define BOOST_NO_CXX11_DELETED_FUNCTIONS +# define BOOST_NO_CXX11_HDR_INITIALIZER_LIST +# define BOOST_NO_CXX11_SCOPED_ENUMS +# define BOOST_NO_SFINAE_EXPR +# define BOOST_NO_CXX11_SFINAE_EXPR +# define BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS +# define BOOST_NO_CXX11_LAMBDAS +# define BOOST_NO_CXX11_LOCAL_CLASS_TEMPLATE_PARAMETERS +# define BOOST_NO_CXX11_RANGE_BASED_FOR +# define BOOST_NO_CXX11_RAW_LITERALS +# define BOOST_NO_CXX11_UNICODE_LITERALS +# define BOOST_NO_CXX11_NOEXCEPT +# define BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX +# define BOOST_NO_CXX11_USER_DEFINED_LITERALS +# define BOOST_NO_CXX11_ALIGNAS +# define BOOST_NO_CXX11_ALIGNOF +# define BOOST_NO_CXX11_TRAILING_RESULT_TYPES +# define BOOST_NO_CXX11_INLINE_NAMESPACES +# define BOOST_NO_CXX11_REF_QUALIFIERS +# define BOOST_NO_CXX11_FINAL +# define BOOST_NO_CXX11_OVERRIDE +# define BOOST_NO_CXX11_THREAD_LOCAL +# define BOOST_NO_CXX11_UNRESTRICTED_UNION + +// C++ 14: +#if !defined(__cpp_aggregate_nsdmi) || (__cpp_aggregate_nsdmi < 201304) +# define BOOST_NO_CXX14_AGGREGATE_NSDMI +#endif +#if !defined(__cpp_binary_literals) || (__cpp_binary_literals < 201304) +# define BOOST_NO_CXX14_BINARY_LITERALS +#endif +#if !defined(__cpp_constexpr) || (__cpp_constexpr < 201304) +# define BOOST_NO_CXX14_CONSTEXPR +#endif +#if !defined(__cpp_decltype_auto) || (__cpp_decltype_auto < 201304) +# define BOOST_NO_CXX14_DECLTYPE_AUTO +#endif +#if (__cplusplus < 201304) // There's no SD6 check for this.... +# define BOOST_NO_CXX14_DIGIT_SEPARATORS +#endif +#if !defined(__cpp_generic_lambdas) || (__cpp_generic_lambdas < 201304) +# define BOOST_NO_CXX14_GENERIC_LAMBDAS +#endif +#if !defined(__cpp_init_captures) || (__cpp_init_captures < 201304) +# define BOOST_NO_CXX14_INITIALIZED_LAMBDA_CAPTURES +#endif +#if !defined(__cpp_return_type_deduction) || (__cpp_return_type_deduction < 201304) +# define BOOST_NO_CXX14_RETURN_TYPE_DEDUCTION +#endif +#if !defined(__cpp_variable_templates) || (__cpp_variable_templates < 201304) +# define BOOST_NO_CXX14_VARIABLE_TEMPLATES +#endif + +// C++17 +#if !defined(__cpp_structured_bindings) || (__cpp_structured_bindings < 201606) +# define BOOST_NO_CXX17_STRUCTURED_BINDINGS +#endif +#if !defined(__cpp_inline_variables) || (__cpp_inline_variables < 201606) +# define BOOST_NO_CXX17_INLINE_VARIABLES +#endif +#if !defined(__cpp_fold_expressions) || (__cpp_fold_expressions < 201603) +# define BOOST_NO_CXX17_FOLD_EXPRESSIONS +#endif +#if !defined(__cpp_if_constexpr) || (__cpp_if_constexpr < 201606) +# define BOOST_NO_CXX17_IF_CONSTEXPR +#endif + +#define BOOST_COMPILER "GCC-XML C++ version " __GCCXML__ + + diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/compiler/greenhills.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/compiler/greenhills.hpp new file mode 100644 index 0000000..39112c2 --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/compiler/greenhills.hpp @@ -0,0 +1,28 @@ +// (C) Copyright John Maddock 2001. +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for most recent version. + +// Greenhills C++ compiler setup: + +#define BOOST_COMPILER "Greenhills C++ version " BOOST_STRINGIZE(__ghs) + +#include + +// +// versions check: +// we don't support Greenhills prior to version 0: +#if __ghs < 0 +# error "Compiler not supported or configured - please reconfigure" +#endif +// +// last known and checked version is 0: +#if (__ghs > 0) +# if defined(BOOST_ASSERT_CONFIG) +# error "boost: Unknown compiler version - please run the configure tests and report the results" +# endif +#endif + + diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/compiler/hp_acc.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/compiler/hp_acc.hpp new file mode 100644 index 0000000..2563632 --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/compiler/hp_acc.hpp @@ -0,0 +1,149 @@ +// (C) Copyright John Maddock 2001 - 2003. +// (C) Copyright Jens Maurer 2001 - 2003. +// (C) Copyright Aleksey Gurtovoy 2002. +// (C) Copyright David Abrahams 2002 - 2003. +// (C) Copyright Toon Knapen 2003. +// (C) Copyright Boris Gubenko 2006 - 2007. +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for most recent version. + +// HP aCC C++ compiler setup: + +#if defined(__EDG__) +#include +#endif + +#if (__HP_aCC <= 33100) +# define BOOST_NO_INTEGRAL_INT64_T +# define BOOST_NO_OPERATORS_IN_NAMESPACE +# if !defined(_NAMESPACE_STD) +# define BOOST_NO_STD_LOCALE +# define BOOST_NO_STRINGSTREAM +# endif +#endif + +#if (__HP_aCC <= 33300) +// member templates are sufficiently broken that we disable them for now +# define BOOST_NO_MEMBER_TEMPLATES +# define BOOST_NO_DEPENDENT_NESTED_DERIVATIONS +# define BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE +#endif + +#if (__HP_aCC <= 38000) +# define BOOST_NO_TWO_PHASE_NAME_LOOKUP +#endif + +#if (__HP_aCC > 50000) && (__HP_aCC < 60000) +# define BOOST_NO_UNREACHABLE_RETURN_DETECTION +# define BOOST_NO_TEMPLATE_TEMPLATES +# define BOOST_NO_SWPRINTF +# define BOOST_NO_DEPENDENT_TYPES_IN_TEMPLATE_VALUE_PARAMETERS +# define BOOST_NO_IS_ABSTRACT +# define BOOST_NO_MEMBER_TEMPLATE_FRIENDS +#endif + +// optional features rather than defects: +#if (__HP_aCC >= 33900) +# define BOOST_HAS_LONG_LONG +# define BOOST_HAS_PARTIAL_STD_ALLOCATOR +#endif + +#if (__HP_aCC >= 50000 ) && (__HP_aCC <= 53800 ) || (__HP_aCC < 31300 ) +# define BOOST_NO_MEMBER_TEMPLATE_KEYWORD +#endif + +// This macro should not be defined when compiling in strict ansi +// mode, but, currently, we don't have the ability to determine +// what standard mode we are compiling with. Some future version +// of aCC6 compiler will provide predefined macros reflecting the +// compilation options, including the standard mode. +#if (__HP_aCC >= 60000) || ((__HP_aCC > 38000) && defined(__hpxstd98)) +# define BOOST_NO_TWO_PHASE_NAME_LOOKUP +#endif + +#define BOOST_COMPILER "HP aCC version " BOOST_STRINGIZE(__HP_aCC) + +// +// versions check: +// we don't support HP aCC prior to version 33000: +#if __HP_aCC < 33000 +# error "Compiler not supported or configured - please reconfigure" +#endif + +// +// Extended checks for supporting aCC on PA-RISC +#if __HP_aCC > 30000 && __HP_aCC < 50000 +# if __HP_aCC < 38000 + // versions prior to version A.03.80 not supported +# error "Compiler version not supported - version A.03.80 or higher is required" +# elif !defined(__hpxstd98) + // must compile using the option +hpxstd98 with version A.03.80 and above +# error "Compiler option '+hpxstd98' is required for proper support" +# endif //PA-RISC +#endif + +// +// C++0x features +// +// See boost\config\suffix.hpp for BOOST_NO_LONG_LONG +// +#if !defined(__EDG__) + +#define BOOST_NO_CXX11_AUTO_DECLARATIONS +#define BOOST_NO_CXX11_AUTO_MULTIDECLARATIONS +#define BOOST_NO_CXX11_CHAR16_T +#define BOOST_NO_CXX11_CHAR32_T +#define BOOST_NO_CXX11_CONSTEXPR +#define BOOST_NO_CXX11_DECLTYPE +#define BOOST_NO_CXX11_DECLTYPE_N3276 +#define BOOST_NO_CXX11_DEFAULTED_FUNCTIONS +#define BOOST_NO_CXX11_DELETED_FUNCTIONS +#define BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS +#define BOOST_NO_CXX11_EXTERN_TEMPLATE +#define BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS +#define BOOST_NO_CXX11_HDR_INITIALIZER_LIST +#define BOOST_NO_CXX11_LAMBDAS +#define BOOST_NO_CXX11_LOCAL_CLASS_TEMPLATE_PARAMETERS +#define BOOST_NO_CXX11_NOEXCEPT +#define BOOST_NO_CXX11_NULLPTR +#define BOOST_NO_CXX11_RANGE_BASED_FOR +#define BOOST_NO_CXX11_RAW_LITERALS +#define BOOST_NO_CXX11_RVALUE_REFERENCES +#define BOOST_NO_CXX11_SCOPED_ENUMS +#define BOOST_NO_SFINAE_EXPR +#define BOOST_NO_CXX11_SFINAE_EXPR +#define BOOST_NO_CXX11_STATIC_ASSERT +#define BOOST_NO_CXX11_TEMPLATE_ALIASES +#define BOOST_NO_CXX11_UNICODE_LITERALS +#define BOOST_NO_CXX11_VARIADIC_TEMPLATES +#define BOOST_NO_CXX11_USER_DEFINED_LITERALS +#define BOOST_NO_CXX11_ALIGNAS +#define BOOST_NO_CXX11_ALIGNOF +#define BOOST_NO_CXX11_TRAILING_RESULT_TYPES +#define BOOST_NO_CXX11_INLINE_NAMESPACES +#define BOOST_NO_CXX11_REF_QUALIFIERS +#define BOOST_NO_CXX11_THREAD_LOCAL +#define BOOST_NO_CXX11_UNRESTRICTED_UNION + +/* + See https://forums13.itrc.hp.com/service/forums/questionanswer.do?threadId=1443331 and + https://forums13.itrc.hp.com/service/forums/questionanswer.do?threadId=1443436 +*/ + +#if (__HP_aCC < 62500) || !defined(HP_CXX0x_SOURCE) + #define BOOST_NO_CXX11_VARIADIC_MACROS +#endif + +#endif + +// +// last known and checked version for HP-UX/ia64 is 61300 +// last known and checked version for PA-RISC is 38000 +#if ((__HP_aCC > 61300) || ((__HP_aCC > 38000) && defined(__hpxstd98))) +# if defined(BOOST_ASSERT_CONFIG) +# error "boost: Unknown compiler version - please run the configure tests and report the results" +# endif +#endif diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/compiler/intel.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/compiler/intel.hpp new file mode 100644 index 0000000..6a34397 --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/compiler/intel.hpp @@ -0,0 +1,577 @@ +// (C) Copyright John Maddock 2001-8. +// (C) Copyright Peter Dimov 2001. +// (C) Copyright Jens Maurer 2001. +// (C) Copyright David Abrahams 2002 - 2003. +// (C) Copyright Aleksey Gurtovoy 2002 - 2003. +// (C) Copyright Guillaume Melquiond 2002 - 2003. +// (C) Copyright Beman Dawes 2003. +// (C) Copyright Martin Wille 2003. +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for most recent version. + +// Intel compiler setup: + +#if defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 1500) && (defined(_MSC_VER) || defined(__GNUC__)) + +#ifdef _MSC_VER + +#include + +#undef BOOST_MSVC +#undef BOOST_MSVC_FULL_VER + +#if (__INTEL_COMPILER >= 1500) && (_MSC_VER >= 1900) +// +// These appear to be supported, even though VC++ may not support them: +// +#define BOOST_HAS_EXPM1 +#define BOOST_HAS_LOG1P +#undef BOOST_NO_CXX14_BINARY_LITERALS +// This one may be a little risky to enable?? +#undef BOOST_NO_SFINAE_EXPR + +#endif + +#if (__INTEL_COMPILER <= 1600) && !defined(BOOST_NO_CXX14_VARIABLE_TEMPLATES) +# define BOOST_NO_CXX14_VARIABLE_TEMPLATES +#endif + +#else // defined(_MSC_VER) + +#include + +#undef BOOST_GCC_VERSION +#undef BOOST_GCC_CXX11 +#undef BOOST_GCC +#undef BOOST_FALLTHROUGH + +// Broken in all versions up to 17 (newer versions not tested) +#if (__INTEL_COMPILER <= 1700) && !defined(BOOST_NO_CXX14_CONSTEXPR) +# define BOOST_NO_CXX14_CONSTEXPR +#endif + +#if (__INTEL_COMPILER >= 1800) && (__cplusplus >= 201703) +# define BOOST_FALLTHROUGH [[fallthrough]] +#endif + +#endif // defined(_MSC_VER) + +#undef BOOST_COMPILER + +#if defined(__INTEL_COMPILER) +#if __INTEL_COMPILER == 9999 +# define BOOST_INTEL_CXX_VERSION 1200 // Intel bug in 12.1. +#else +# define BOOST_INTEL_CXX_VERSION __INTEL_COMPILER +#endif +#elif defined(__ICL) +# define BOOST_INTEL_CXX_VERSION __ICL +#elif defined(__ICC) +# define BOOST_INTEL_CXX_VERSION __ICC +#elif defined(__ECC) +# define BOOST_INTEL_CXX_VERSION __ECC +#endif + +// Flags determined by comparing output of 'icpc -dM -E' with and without '-std=c++0x' +#if (!(defined(_WIN32) || defined(_WIN64)) && defined(__STDC_HOSTED__) && (__STDC_HOSTED__ && (BOOST_INTEL_CXX_VERSION <= 1200))) || defined(__GXX_EXPERIMENTAL_CPP0X__) || defined(__GXX_EXPERIMENTAL_CXX0X__) +# define BOOST_INTEL_STDCXX0X +#endif +#if defined(_MSC_VER) && (_MSC_VER >= 1600) +# define BOOST_INTEL_STDCXX0X +#endif + +#ifdef __GNUC__ +# define BOOST_INTEL_GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) +#endif + +#if !defined(BOOST_COMPILER) +# if defined(BOOST_INTEL_STDCXX0X) +# define BOOST_COMPILER "Intel C++ C++0x mode version " BOOST_STRINGIZE(BOOST_INTEL_CXX_VERSION) +# else +# define BOOST_COMPILER "Intel C++ version " BOOST_STRINGIZE(BOOST_INTEL_CXX_VERSION) +# endif +#endif + +#define BOOST_INTEL BOOST_INTEL_CXX_VERSION + +#if defined(_WIN32) || defined(_WIN64) +# define BOOST_INTEL_WIN BOOST_INTEL +#else +# define BOOST_INTEL_LINUX BOOST_INTEL +#endif + +#else // defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 1500) && (defined(_MSC_VER) || defined(__GNUC__)) + +#include + +#if defined(__INTEL_COMPILER) +#if __INTEL_COMPILER == 9999 +# define BOOST_INTEL_CXX_VERSION 1200 // Intel bug in 12.1. +#else +# define BOOST_INTEL_CXX_VERSION __INTEL_COMPILER +#endif +#elif defined(__ICL) +# define BOOST_INTEL_CXX_VERSION __ICL +#elif defined(__ICC) +# define BOOST_INTEL_CXX_VERSION __ICC +#elif defined(__ECC) +# define BOOST_INTEL_CXX_VERSION __ECC +#endif + +// Flags determined by comparing output of 'icpc -dM -E' with and without '-std=c++0x' +#if (!(defined(_WIN32) || defined(_WIN64)) && defined(__STDC_HOSTED__) && (__STDC_HOSTED__ && (BOOST_INTEL_CXX_VERSION <= 1200))) || defined(__GXX_EXPERIMENTAL_CPP0X__) || defined(__GXX_EXPERIMENTAL_CXX0X__) +# define BOOST_INTEL_STDCXX0X +#endif +#if defined(_MSC_VER) && (_MSC_VER >= 1600) +# define BOOST_INTEL_STDCXX0X +#endif + +#ifdef __GNUC__ +# define BOOST_INTEL_GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) +#endif + +#if !defined(BOOST_COMPILER) +# if defined(BOOST_INTEL_STDCXX0X) +# define BOOST_COMPILER "Intel C++ C++0x mode version " BOOST_STRINGIZE(BOOST_INTEL_CXX_VERSION) +# else +# define BOOST_COMPILER "Intel C++ version " BOOST_STRINGIZE(BOOST_INTEL_CXX_VERSION) +# endif +#endif + +#define BOOST_INTEL BOOST_INTEL_CXX_VERSION + +#if defined(_WIN32) || defined(_WIN64) +# define BOOST_INTEL_WIN BOOST_INTEL +#else +# define BOOST_INTEL_LINUX BOOST_INTEL +#endif + +#if (BOOST_INTEL_CXX_VERSION <= 600) + +# if defined(_MSC_VER) && (_MSC_VER <= 1300) // added check for <= VC 7 (Peter Dimov) + +// Boost libraries assume strong standard conformance unless otherwise +// indicated by a config macro. As configured by Intel, the EDG front-end +// requires certain compiler options be set to achieve that strong conformance. +// Particularly /Qoption,c,--arg_dep_lookup (reported by Kirk Klobe & Thomas Witt) +// and /Zc:wchar_t,forScope. See boost-root/tools/build/intel-win32-tools.jam for +// details as they apply to particular versions of the compiler. When the +// compiler does not predefine a macro indicating if an option has been set, +// this config file simply assumes the option has been set. +// Thus BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP will not be defined, even if +// the compiler option is not enabled. + +# define BOOST_NO_SWPRINTF +# endif + +// Void returns, 64 bit integrals don't work when emulating VC 6 (Peter Dimov) + +# if defined(_MSC_VER) && (_MSC_VER <= 1200) +# define BOOST_NO_VOID_RETURNS +# define BOOST_NO_INTEGRAL_INT64_T +# endif + +#endif + +#if (BOOST_INTEL_CXX_VERSION <= 710) && defined(_WIN32) +# define BOOST_NO_POINTER_TO_MEMBER_TEMPLATE_PARAMETERS +#endif + +// See http://aspn.activestate.com/ASPN/Mail/Message/boost/1614864 +#if BOOST_INTEL_CXX_VERSION < 600 +# define BOOST_NO_INTRINSIC_WCHAR_T +#else +// We should test the macro _WCHAR_T_DEFINED to check if the compiler +// supports wchar_t natively. *BUT* there is a problem here: the standard +// headers define this macro if they typedef wchar_t. Anyway, we're lucky +// because they define it without a value, while Intel C++ defines it +// to 1. So we can check its value to see if the macro was defined natively +// or not. +// Under UNIX, the situation is exactly the same, but the macro _WCHAR_T +// is used instead. +# if ((_WCHAR_T_DEFINED + 0) == 0) && ((_WCHAR_T + 0) == 0) +# define BOOST_NO_INTRINSIC_WCHAR_T +# endif +#endif + +#if defined(__GNUC__) && !defined(BOOST_FUNCTION_SCOPE_USING_DECLARATION_BREAKS_ADL) +// +// Figure out when Intel is emulating this gcc bug +// (All Intel versions prior to 9.0.26, and versions +// later than that if they are set up to emulate gcc 3.2 +// or earlier): +// +# if ((__GNUC__ == 3) && (__GNUC_MINOR__ <= 2)) || (BOOST_INTEL < 900) || (__INTEL_COMPILER_BUILD_DATE < 20050912) +# define BOOST_FUNCTION_SCOPE_USING_DECLARATION_BREAKS_ADL +# endif +#endif +#if (defined(__GNUC__) && (__GNUC__ < 4)) || (defined(_WIN32) && (BOOST_INTEL_CXX_VERSION <= 1200)) || (BOOST_INTEL_CXX_VERSION <= 1200) +// GCC or VC emulation: +#define BOOST_NO_TWO_PHASE_NAME_LOOKUP +#endif +// +// Verify that we have actually got BOOST_NO_INTRINSIC_WCHAR_T +// set correctly, if we don't do this now, we will get errors later +// in type_traits code among other things, getting this correct +// for the Intel compiler is actually remarkably fragile and tricky: +// +#ifdef __cplusplus +#if defined(BOOST_NO_INTRINSIC_WCHAR_T) +#include +template< typename T > struct assert_no_intrinsic_wchar_t; +template<> struct assert_no_intrinsic_wchar_t { typedef void type; }; +// if you see an error here then you need to unset BOOST_NO_INTRINSIC_WCHAR_T +// where it is defined above: +typedef assert_no_intrinsic_wchar_t::type assert_no_intrinsic_wchar_t_; +#else +template< typename T > struct assert_intrinsic_wchar_t; +template<> struct assert_intrinsic_wchar_t {}; +// if you see an error here then define BOOST_NO_INTRINSIC_WCHAR_T on the command line: +template<> struct assert_intrinsic_wchar_t {}; +#endif +#endif + +#if defined(_MSC_VER) && (_MSC_VER+0 >= 1000) +# if _MSC_VER >= 1200 +# define BOOST_HAS_MS_INT64 +# endif +# define BOOST_NO_SWPRINTF +# define BOOST_NO_TWO_PHASE_NAME_LOOKUP +#elif defined(_WIN32) +# define BOOST_DISABLE_WIN32 +#endif + +// I checked version 6.0 build 020312Z, it implements the NRVO. +// Correct this as you find out which version of the compiler +// implemented the NRVO first. (Daniel Frey) +#if (BOOST_INTEL_CXX_VERSION >= 600) +# define BOOST_HAS_NRVO +#endif + +// Branch prediction hints +// I'm not sure 8.0 was the first version to support these builtins, +// update the condition if the version is not accurate. (Andrey Semashev) +#if defined(__GNUC__) && BOOST_INTEL_CXX_VERSION >= 800 +#define BOOST_LIKELY(x) __builtin_expect(x, 1) +#define BOOST_UNLIKELY(x) __builtin_expect(x, 0) +#endif + +// RTTI +// __RTTI is the EDG macro +// __INTEL_RTTI__ is the Intel macro +// __GXX_RTTI is the g++ macro +// _CPPRTTI is the MSVC++ macro +#if !defined(__RTTI) && !defined(__INTEL_RTTI__) && !defined(__GXX_RTTI) && !defined(_CPPRTTI) + +#if !defined(BOOST_NO_RTTI) +# define BOOST_NO_RTTI +#endif + +// in MS mode, static typeid works even when RTTI is off +#if !defined(_MSC_VER) && !defined(BOOST_NO_TYPEID) +# define BOOST_NO_TYPEID +#endif + +#endif + +// +// versions check: +// we don't support Intel prior to version 6.0: +#if BOOST_INTEL_CXX_VERSION < 600 +# error "Compiler not supported or configured - please reconfigure" +#endif + +// Intel on MacOS requires +#if defined(__APPLE__) && defined(__INTEL_COMPILER) +# define BOOST_NO_TWO_PHASE_NAME_LOOKUP +#endif + +// Intel on Altix Itanium +#if defined(__itanium__) && defined(__INTEL_COMPILER) +# define BOOST_NO_TWO_PHASE_NAME_LOOKUP +#endif + +// +// An attempt to value-initialize a pointer-to-member may trigger an +// internal error on Intel <= 11.1 (last checked version), as was +// reported by John Maddock, Intel support issue 589832, May 2010. +// Moreover, according to test results from Huang-Vista-x86_32_intel, +// intel-vc9-win-11.1 may leave a non-POD array uninitialized, in some +// cases when it should be value-initialized. +// (Niels Dekker, LKEB, May 2010) +// Apparently Intel 12.1 (compiler version number 9999 !!) has the same issue (compiler regression). +#if defined(__INTEL_COMPILER) +# if (__INTEL_COMPILER <= 1110) || (__INTEL_COMPILER == 9999) || (defined(_WIN32) && (__INTEL_COMPILER < 1600)) +# define BOOST_NO_COMPLETE_VALUE_INITIALIZATION +# endif +#endif + +// +// Dynamic shared object (DSO) and dynamic-link library (DLL) support +// +#if defined(__GNUC__) && (__GNUC__ >= 4) +# define BOOST_SYMBOL_EXPORT __attribute__((visibility("default"))) +# define BOOST_SYMBOL_IMPORT +# define BOOST_SYMBOL_VISIBLE __attribute__((visibility("default"))) +#endif + +// Type aliasing hint +#if defined(__GNUC__) && (BOOST_INTEL_CXX_VERSION >= 1300) +# define BOOST_MAY_ALIAS __attribute__((__may_alias__)) +#endif + +// +// C++0x features +// For each feature we need to check both the Intel compiler version, +// and the version of MSVC or GCC that we are emulating. +// See http://software.intel.com/en-us/articles/c0x-features-supported-by-intel-c-compiler/ +// for a list of which features were implemented in which Intel releases. +// +#if defined(BOOST_INTEL_STDCXX0X) +// BOOST_NO_CXX11_CONSTEXPR: +#if (BOOST_INTEL_CXX_VERSION >= 1500) && (!defined(BOOST_INTEL_GCC_VERSION) || (BOOST_INTEL_GCC_VERSION >= 40600)) && !defined(_MSC_VER) +// Available in earlier Intel versions, but fail our tests: +# undef BOOST_NO_CXX11_CONSTEXPR +#endif +// BOOST_NO_CXX11_NULLPTR: +#if (BOOST_INTEL_CXX_VERSION >= 1210) && (!defined(BOOST_INTEL_GCC_VERSION) || (BOOST_INTEL_GCC_VERSION >= 40600)) && (!defined(_MSC_VER) || (_MSC_VER >= 1600)) +# undef BOOST_NO_CXX11_NULLPTR +#endif +// BOOST_NO_CXX11_TEMPLATE_ALIASES +#if (BOOST_INTEL_CXX_VERSION >= 1210) && (!defined(BOOST_INTEL_GCC_VERSION) || (BOOST_INTEL_GCC_VERSION >= 40700)) && (!defined(_MSC_VER) || (_MSC_FULL_VER >= 180020827)) +# undef BOOST_NO_CXX11_TEMPLATE_ALIASES +#endif + +// BOOST_NO_CXX11_DECLTYPE +#if (BOOST_INTEL_CXX_VERSION >= 1200) && (!defined(BOOST_INTEL_GCC_VERSION) || (BOOST_INTEL_GCC_VERSION >= 40300)) && (!defined(_MSC_VER) || (_MSC_VER >= 1600)) +# undef BOOST_NO_CXX11_DECLTYPE +#endif + +// BOOST_NO_CXX11_DECLTYPE_N3276 +#if (BOOST_INTEL_CXX_VERSION >= 1500) && (!defined(BOOST_INTEL_GCC_VERSION) || (BOOST_INTEL_GCC_VERSION >= 40800)) && (!defined(_MSC_VER) || (_MSC_FULL_VER >= 180020827)) +# undef BOOST_NO_CXX11_DECLTYPE_N3276 +#endif + +// BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS +#if (BOOST_INTEL_CXX_VERSION >= 1200) && (!defined(BOOST_INTEL_GCC_VERSION) || (BOOST_INTEL_GCC_VERSION >= 40300)) && (!defined(_MSC_VER) || (_MSC_FULL_VER >= 180020827)) +# undef BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS +#endif + +// BOOST_NO_CXX11_RVALUE_REFERENCES +#if (BOOST_INTEL_CXX_VERSION >= 1300) && (!defined(BOOST_INTEL_GCC_VERSION) || (BOOST_INTEL_GCC_VERSION >= 40300)) && (!defined(_MSC_VER) || (_MSC_VER >= 1600)) +// This is available from earlier Intel versions, but breaks Filesystem and other libraries: +# undef BOOST_NO_CXX11_RVALUE_REFERENCES +#endif + +// BOOST_NO_CXX11_STATIC_ASSERT +#if (BOOST_INTEL_CXX_VERSION >= 1110) && (!defined(BOOST_INTEL_GCC_VERSION) || (BOOST_INTEL_GCC_VERSION >= 40300)) && (!defined(_MSC_VER) || (_MSC_VER >= 1600)) +# undef BOOST_NO_CXX11_STATIC_ASSERT +#endif + +// BOOST_NO_CXX11_VARIADIC_TEMPLATES +#if (BOOST_INTEL_CXX_VERSION >= 1200) && (!defined(BOOST_INTEL_GCC_VERSION) || (BOOST_INTEL_GCC_VERSION >= 40400)) && (!defined(_MSC_VER) || (_MSC_FULL_VER >= 180020827)) +# undef BOOST_NO_CXX11_VARIADIC_TEMPLATES +#endif + +// BOOST_NO_CXX11_VARIADIC_MACROS +#if (BOOST_INTEL_CXX_VERSION >= 1200) && (!defined(BOOST_INTEL_GCC_VERSION) || (BOOST_INTEL_GCC_VERSION >= 40200)) && (!defined(_MSC_VER) || (_MSC_VER >= 1400)) +# undef BOOST_NO_CXX11_VARIADIC_MACROS +#endif + +// BOOST_NO_CXX11_AUTO_DECLARATIONS +#if (BOOST_INTEL_CXX_VERSION >= 1200) && (!defined(BOOST_INTEL_GCC_VERSION) || (BOOST_INTEL_GCC_VERSION >= 40400)) && (!defined(_MSC_VER) || (_MSC_VER >= 1600)) +# undef BOOST_NO_CXX11_AUTO_DECLARATIONS +#endif + +// BOOST_NO_CXX11_AUTO_MULTIDECLARATIONS +#if (BOOST_INTEL_CXX_VERSION >= 1200) && (!defined(BOOST_INTEL_GCC_VERSION) || (BOOST_INTEL_GCC_VERSION >= 40400)) && (!defined(_MSC_VER) || (_MSC_VER >= 1600)) +# undef BOOST_NO_CXX11_AUTO_MULTIDECLARATIONS +#endif + +// BOOST_NO_CXX11_CHAR16_T +#if (BOOST_INTEL_CXX_VERSION >= 1400) && (!defined(BOOST_INTEL_GCC_VERSION) || (BOOST_INTEL_GCC_VERSION >= 40400)) && (!defined(_MSC_VER) || (_MSC_VER >= 9999)) +# undef BOOST_NO_CXX11_CHAR16_T +#endif + +// BOOST_NO_CXX11_CHAR32_T +#if (BOOST_INTEL_CXX_VERSION >= 1400) && (!defined(BOOST_INTEL_GCC_VERSION) || (BOOST_INTEL_GCC_VERSION >= 40400)) && (!defined(_MSC_VER) || (_MSC_VER >= 9999)) +# undef BOOST_NO_CXX11_CHAR32_T +#endif + +// BOOST_NO_CXX11_DEFAULTED_FUNCTIONS +#if (BOOST_INTEL_CXX_VERSION >= 1200) && (!defined(BOOST_INTEL_GCC_VERSION) || (BOOST_INTEL_GCC_VERSION >= 40400)) && (!defined(_MSC_VER) || (_MSC_FULL_VER >= 180020827)) +# undef BOOST_NO_CXX11_DEFAULTED_FUNCTIONS +#endif + +// BOOST_NO_CXX11_DELETED_FUNCTIONS +#if (BOOST_INTEL_CXX_VERSION >= 1200) && (!defined(BOOST_INTEL_GCC_VERSION) || (BOOST_INTEL_GCC_VERSION >= 40400)) && (!defined(_MSC_VER) || (_MSC_FULL_VER >= 180020827)) +# undef BOOST_NO_CXX11_DELETED_FUNCTIONS +#endif + +// BOOST_NO_CXX11_HDR_INITIALIZER_LIST +#if (BOOST_INTEL_CXX_VERSION >= 1400) && (!defined(BOOST_INTEL_GCC_VERSION) || (BOOST_INTEL_GCC_VERSION >= 40400)) && (!defined(_MSC_VER) || (_MSC_VER >= 1700)) +# undef BOOST_NO_CXX11_HDR_INITIALIZER_LIST +#endif + +// BOOST_NO_CXX11_SCOPED_ENUMS +#if (BOOST_INTEL_CXX_VERSION >= 1400) && (!defined(BOOST_INTEL_GCC_VERSION) || (BOOST_INTEL_GCC_VERSION >= 40501)) && (!defined(_MSC_VER) || (_MSC_VER >= 1700)) +// This is available but broken in earlier Intel releases. +# undef BOOST_NO_CXX11_SCOPED_ENUMS +#endif + +// BOOST_NO_SFINAE_EXPR +#if (BOOST_INTEL_CXX_VERSION >= 1200) && (!defined(BOOST_INTEL_GCC_VERSION) || (BOOST_INTEL_GCC_VERSION >= 40500)) && (!defined(_MSC_VER) || (_MSC_VER >= 9999)) +# undef BOOST_NO_SFINAE_EXPR +#endif + +// BOOST_NO_CXX11_SFINAE_EXPR +#if (BOOST_INTEL_CXX_VERSION >= 1500) && (!defined(BOOST_INTEL_GCC_VERSION) || (BOOST_INTEL_GCC_VERSION >= 40800)) && !defined(_MSC_VER) +# undef BOOST_NO_CXX11_SFINAE_EXPR +#endif + +// BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS +#if (BOOST_INTEL_CXX_VERSION >= 1500) && (!defined(BOOST_INTEL_GCC_VERSION) || (BOOST_INTEL_GCC_VERSION >= 40500)) && (!defined(_MSC_VER) || (_MSC_FULL_VER >= 180020827)) +// This is available in earlier Intel releases, but breaks Multiprecision: +# undef BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS +#endif + +// BOOST_NO_CXX11_LAMBDAS +#if (BOOST_INTEL_CXX_VERSION >= 1200) && (!defined(BOOST_INTEL_GCC_VERSION) || (BOOST_INTEL_GCC_VERSION >= 40500)) && (!defined(_MSC_VER) || (_MSC_VER >= 1600)) +# undef BOOST_NO_CXX11_LAMBDAS +#endif + +// BOOST_NO_CXX11_LOCAL_CLASS_TEMPLATE_PARAMETERS +#if (BOOST_INTEL_CXX_VERSION >= 1200) && (!defined(BOOST_INTEL_GCC_VERSION) || (BOOST_INTEL_GCC_VERSION >= 40500)) +# undef BOOST_NO_CXX11_LOCAL_CLASS_TEMPLATE_PARAMETERS +#endif + +// BOOST_NO_CXX11_RANGE_BASED_FOR +#if (BOOST_INTEL_CXX_VERSION >= 1400) && (!defined(BOOST_INTEL_GCC_VERSION) || (BOOST_INTEL_GCC_VERSION >= 40600)) && (!defined(_MSC_VER) || (_MSC_VER >= 1700)) +# undef BOOST_NO_CXX11_RANGE_BASED_FOR +#endif + +// BOOST_NO_CXX11_RAW_LITERALS +#if (BOOST_INTEL_CXX_VERSION >= 1400) && (!defined(BOOST_INTEL_GCC_VERSION) || (BOOST_INTEL_GCC_VERSION >= 40500)) && (!defined(_MSC_VER) || (_MSC_FULL_VER >= 180020827)) +# undef BOOST_NO_CXX11_RAW_LITERALS +#endif + +// BOOST_NO_CXX11_UNICODE_LITERALS +#if (BOOST_INTEL_CXX_VERSION >= 1400) && (!defined(BOOST_INTEL_GCC_VERSION) || (BOOST_INTEL_GCC_VERSION >= 40500)) && (!defined(_MSC_VER) || (_MSC_VER >= 9999)) +# undef BOOST_NO_CXX11_UNICODE_LITERALS +#endif + +// BOOST_NO_CXX11_NOEXCEPT +#if (BOOST_INTEL_CXX_VERSION >= 1500) && (!defined(BOOST_INTEL_GCC_VERSION) || (BOOST_INTEL_GCC_VERSION >= 40600)) && (!defined(_MSC_VER) || (_MSC_VER >= 9999)) +// Available in earlier Intel release, but generates errors when used with +// conditional exception specifications, for example in multiprecision: +# undef BOOST_NO_CXX11_NOEXCEPT +#endif + +// BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX +#if (BOOST_INTEL_CXX_VERSION >= 1400) && (!defined(BOOST_INTEL_GCC_VERSION) || (BOOST_INTEL_GCC_VERSION >= 40600)) && (!defined(_MSC_VER) || (_MSC_VER >= 9999)) +# undef BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX +#endif + +// BOOST_NO_CXX11_USER_DEFINED_LITERALS +#if (BOOST_INTEL_CXX_VERSION >= 1500) && (!defined(BOOST_INTEL_GCC_VERSION) || (BOOST_INTEL_GCC_VERSION >= 40700)) && (!defined(_MSC_VER) || (_MSC_FULL_VER >= 190021730)) +# undef BOOST_NO_CXX11_USER_DEFINED_LITERALS +#endif + +// BOOST_NO_CXX11_ALIGNAS +#if (BOOST_INTEL_CXX_VERSION >= 1500) && (!defined(BOOST_INTEL_GCC_VERSION) || (BOOST_INTEL_GCC_VERSION >= 40800)) && (!defined(_MSC_VER) || (_MSC_FULL_VER >= 190021730)) +# undef BOOST_NO_CXX11_ALIGNAS +# undef BOOST_NO_CXX11_ALIGNOF +#endif + +// BOOST_NO_CXX11_TRAILING_RESULT_TYPES +#if (BOOST_INTEL_CXX_VERSION >= 1200) && (!defined(BOOST_INTEL_GCC_VERSION) || (BOOST_INTEL_GCC_VERSION >= 40400)) && (!defined(_MSC_VER) || (_MSC_FULL_VER >= 180020827)) +# undef BOOST_NO_CXX11_TRAILING_RESULT_TYPES +#endif + +// BOOST_NO_CXX11_INLINE_NAMESPACES +#if (BOOST_INTEL_CXX_VERSION >= 1400) && (!defined(BOOST_INTEL_GCC_VERSION) || (BOOST_INTEL_GCC_VERSION >= 40400)) && (!defined(_MSC_VER) || (_MSC_FULL_VER >= 190021730)) +# undef BOOST_NO_CXX11_INLINE_NAMESPACES +#endif + +// BOOST_NO_CXX11_REF_QUALIFIERS +#if (BOOST_INTEL_CXX_VERSION >= 1400) && (!defined(BOOST_INTEL_GCC_VERSION) || (BOOST_INTEL_GCC_VERSION >= 40800)) && (!defined(_MSC_VER) || (_MSC_FULL_VER >= 190021730)) +# undef BOOST_NO_CXX11_REF_QUALIFIERS +#endif + +// BOOST_NO_CXX11_FINAL +// BOOST_NO_CXX11_OVERRIDE +#if (BOOST_INTEL_CXX_VERSION >= 1400) && (!defined(BOOST_INTEL_GCC_VERSION) || (BOOST_INTEL_GCC_VERSION >= 40700)) && (!defined(_MSC_VER) || (_MSC_VER >= 1700)) +# undef BOOST_NO_CXX11_FINAL +# undef BOOST_NO_CXX11_OVERRIDE +#endif + +// BOOST_NO_CXX11_UNRESTRICTED_UNION +#if (BOOST_INTEL_CXX_VERSION >= 1400) && (!defined(BOOST_INTEL_GCC_VERSION) || (BOOST_INTEL_GCC_VERSION >= 50100)) && (!defined(_MSC_VER)) +# undef BOOST_NO_CXX11_UNRESTRICTED_UNION +#endif + +#endif // defined(BOOST_INTEL_STDCXX0X) + +// +// Broken in all versions up to 15: +#define BOOST_NO_CXX11_FIXED_LENGTH_VARIADIC_TEMPLATE_EXPANSION_PACKS + +#if defined(BOOST_INTEL_STDCXX0X) && (BOOST_INTEL_CXX_VERSION <= 1310) +# define BOOST_NO_CXX11_HDR_FUTURE +# define BOOST_NO_CXX11_HDR_INITIALIZER_LIST +#endif + +#if defined(BOOST_INTEL_STDCXX0X) && (BOOST_INTEL_CXX_VERSION == 1400) +// A regression in Intel's compiler means that seems to be broken in this release as well as : +# define BOOST_NO_CXX11_HDR_FUTURE +# define BOOST_NO_CXX11_HDR_TUPLE +#endif + +#if (BOOST_INTEL_CXX_VERSION < 1200) +// +// fenv.h appears not to work with Intel prior to 12.0: +// +# define BOOST_NO_FENV_H +#endif + +// Intel 13.10 fails to access defaulted functions of a base class declared in private or protected sections, +// producing the following errors: +// error #453: protected function "..." (declared at ...") is not accessible through a "..." pointer or object +#if (BOOST_INTEL_CXX_VERSION <= 1310) +# define BOOST_NO_CXX11_NON_PUBLIC_DEFAULTED_FUNCTIONS +#endif + +#if defined(_MSC_VER) && (_MSC_VER >= 1600) +# define BOOST_HAS_STDINT_H +#endif + +#if defined(__CUDACC__) +# if defined(BOOST_GCC_CXX11) +# define BOOST_NVCC_CXX11 +# else +# define BOOST_NVCC_CXX03 +# endif +#endif + +#if defined(__LP64__) && defined(__GNUC__) && (BOOST_INTEL_CXX_VERSION >= 1310) && !defined(BOOST_NVCC_CXX03) +# define BOOST_HAS_INT128 +#endif + +#endif // defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 1500) && (defined(_MSC_VER) || defined(__GNUC__)) +// +// last known and checked version: +#if (BOOST_INTEL_CXX_VERSION > 1700) +# if defined(BOOST_ASSERT_CONFIG) +# error "Boost.Config is older than your compiler - please check for an updated Boost release." +# elif defined(_MSC_VER) +// +// We don't emit this warning any more, since we have so few +// defect macros set anyway (just the one). +// +//# pragma message("boost: Unknown compiler version - please run the configure tests and report the results") +# endif +#endif + diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/compiler/kai.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/compiler/kai.hpp new file mode 100644 index 0000000..0b22ec1 --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/compiler/kai.hpp @@ -0,0 +1,33 @@ +// (C) Copyright John Maddock 2001. +// (C) Copyright David Abrahams 2002. +// (C) Copyright Aleksey Gurtovoy 2002. +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for most recent version. + +// Kai C++ compiler setup: + +#include + +# if (__KCC_VERSION <= 4001) || !defined(BOOST_STRICT_CONFIG) + // at least on Sun, the contents of is not in namespace std +# define BOOST_NO_STDC_NAMESPACE +# endif + +// see also common_edg.hpp which needs a special check for __KCC +# if !defined(_EXCEPTIONS) && !defined(BOOST_NO_EXCEPTIONS) +# define BOOST_NO_EXCEPTIONS +# endif + +// +// last known and checked version is 4001: +#if (__KCC_VERSION > 4001) +# if defined(BOOST_ASSERT_CONFIG) +# error "boost: Unknown compiler version - please run the configure tests and report the results" +# endif +#endif + + + diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/compiler/metrowerks.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/compiler/metrowerks.hpp new file mode 100644 index 0000000..448ab67 --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/compiler/metrowerks.hpp @@ -0,0 +1,198 @@ +// (C) Copyright John Maddock 2001. +// (C) Copyright Darin Adler 2001. +// (C) Copyright Peter Dimov 2001. +// (C) Copyright David Abrahams 2001 - 2002. +// (C) Copyright Beman Dawes 2001 - 2003. +// (C) Copyright Stefan Slapeta 2004. +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for most recent version. + +// Metrowerks C++ compiler setup: + +// locale support is disabled when linking with the dynamic runtime +# ifdef _MSL_NO_LOCALE +# define BOOST_NO_STD_LOCALE +# endif + +# if __MWERKS__ <= 0x2301 // 5.3 +# define BOOST_NO_FUNCTION_TEMPLATE_ORDERING +# define BOOST_NO_POINTER_TO_MEMBER_CONST +# define BOOST_NO_DEPENDENT_TYPES_IN_TEMPLATE_VALUE_PARAMETERS +# define BOOST_NO_MEMBER_TEMPLATE_KEYWORD +# endif + +# if __MWERKS__ <= 0x2401 // 6.2 +//# define BOOST_NO_FUNCTION_TEMPLATE_ORDERING +# endif + +# if(__MWERKS__ <= 0x2407) // 7.x +# define BOOST_NO_MEMBER_FUNCTION_SPECIALIZATIONS +# define BOOST_NO_UNREACHABLE_RETURN_DETECTION +# endif + +# if(__MWERKS__ <= 0x3003) // 8.x +# define BOOST_NO_SFINAE +# endif + +// the "|| !defined(BOOST_STRICT_CONFIG)" part should apply to the last +// tested version *only*: +# if(__MWERKS__ <= 0x3207) || !defined(BOOST_STRICT_CONFIG) // 9.6 +# define BOOST_NO_MEMBER_TEMPLATE_FRIENDS +# define BOOST_NO_IS_ABSTRACT +# endif + +#if !__option(wchar_type) +# define BOOST_NO_INTRINSIC_WCHAR_T +#endif + +#if !__option(exceptions) && !defined(BOOST_NO_EXCEPTIONS) +# define BOOST_NO_EXCEPTIONS +#endif + +#if (__INTEL__ && _WIN32) || (__POWERPC__ && macintosh) +# if __MWERKS__ == 0x3000 +# define BOOST_COMPILER_VERSION 8.0 +# elif __MWERKS__ == 0x3001 +# define BOOST_COMPILER_VERSION 8.1 +# elif __MWERKS__ == 0x3002 +# define BOOST_COMPILER_VERSION 8.2 +# elif __MWERKS__ == 0x3003 +# define BOOST_COMPILER_VERSION 8.3 +# elif __MWERKS__ == 0x3200 +# define BOOST_COMPILER_VERSION 9.0 +# elif __MWERKS__ == 0x3201 +# define BOOST_COMPILER_VERSION 9.1 +# elif __MWERKS__ == 0x3202 +# define BOOST_COMPILER_VERSION 9.2 +# elif __MWERKS__ == 0x3204 +# define BOOST_COMPILER_VERSION 9.3 +# elif __MWERKS__ == 0x3205 +# define BOOST_COMPILER_VERSION 9.4 +# elif __MWERKS__ == 0x3206 +# define BOOST_COMPILER_VERSION 9.5 +# elif __MWERKS__ == 0x3207 +# define BOOST_COMPILER_VERSION 9.6 +# else +# define BOOST_COMPILER_VERSION __MWERKS__ +# endif +#else +# define BOOST_COMPILER_VERSION __MWERKS__ +#endif + +// +// C++0x features +// +// See boost\config\suffix.hpp for BOOST_NO_LONG_LONG +// +#if __MWERKS__ > 0x3206 && __option(rvalue_refs) +# define BOOST_HAS_RVALUE_REFS +#else +# define BOOST_NO_CXX11_RVALUE_REFERENCES +#endif +#define BOOST_NO_CXX11_AUTO_DECLARATIONS +#define BOOST_NO_CXX11_AUTO_MULTIDECLARATIONS +#define BOOST_NO_CXX11_CHAR16_T +#define BOOST_NO_CXX11_CHAR32_T +#define BOOST_NO_CXX11_CONSTEXPR +#define BOOST_NO_CXX11_DECLTYPE +#define BOOST_NO_CXX11_DECLTYPE_N3276 +#define BOOST_NO_CXX11_DEFAULTED_FUNCTIONS +#define BOOST_NO_CXX11_DELETED_FUNCTIONS +#define BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS +#define BOOST_NO_CXX11_EXTERN_TEMPLATE +#define BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS +#define BOOST_NO_CXX11_HDR_INITIALIZER_LIST +#define BOOST_NO_CXX11_LAMBDAS +#define BOOST_NO_CXX11_LOCAL_CLASS_TEMPLATE_PARAMETERS +#define BOOST_NO_CXX11_NOEXCEPT +#define BOOST_NO_CXX11_NULLPTR +#define BOOST_NO_CXX11_RANGE_BASED_FOR +#define BOOST_NO_CXX11_RAW_LITERALS +#define BOOST_NO_CXX11_SCOPED_ENUMS +#define BOOST_NO_SFINAE_EXPR +#define BOOST_NO_CXX11_SFINAE_EXPR +#define BOOST_NO_CXX11_STATIC_ASSERT +#define BOOST_NO_CXX11_TEMPLATE_ALIASES +#define BOOST_NO_CXX11_UNICODE_LITERALS +#define BOOST_NO_CXX11_VARIADIC_TEMPLATES +#define BOOST_NO_CXX11_VARIADIC_MACROS +#define BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX +#define BOOST_NO_CXX11_USER_DEFINED_LITERALS +#define BOOST_NO_CXX11_ALIGNAS +#define BOOST_NO_CXX11_ALIGNOF +#define BOOST_NO_CXX11_TRAILING_RESULT_TYPES +#define BOOST_NO_CXX11_INLINE_NAMESPACES +#define BOOST_NO_CXX11_REF_QUALIFIERS +#define BOOST_NO_CXX11_FINAL +#define BOOST_NO_CXX11_OVERRIDE +#define BOOST_NO_CXX11_THREAD_LOCAL +#define BOOST_NO_CXX11_UNRESTRICTED_UNION + +// C++ 14: +#if !defined(__cpp_aggregate_nsdmi) || (__cpp_aggregate_nsdmi < 201304) +# define BOOST_NO_CXX14_AGGREGATE_NSDMI +#endif +#if !defined(__cpp_binary_literals) || (__cpp_binary_literals < 201304) +# define BOOST_NO_CXX14_BINARY_LITERALS +#endif +#if !defined(__cpp_constexpr) || (__cpp_constexpr < 201304) +# define BOOST_NO_CXX14_CONSTEXPR +#endif +#if !defined(__cpp_decltype_auto) || (__cpp_decltype_auto < 201304) +# define BOOST_NO_CXX14_DECLTYPE_AUTO +#endif +#if (__cplusplus < 201304) // There's no SD6 check for this.... +# define BOOST_NO_CXX14_DIGIT_SEPARATORS +#endif +#if !defined(__cpp_generic_lambdas) || (__cpp_generic_lambdas < 201304) +# define BOOST_NO_CXX14_GENERIC_LAMBDAS +#endif +#if !defined(__cpp_init_captures) || (__cpp_init_captures < 201304) +# define BOOST_NO_CXX14_INITIALIZED_LAMBDA_CAPTURES +#endif +#if !defined(__cpp_return_type_deduction) || (__cpp_return_type_deduction < 201304) +# define BOOST_NO_CXX14_RETURN_TYPE_DEDUCTION +#endif +#if !defined(__cpp_variable_templates) || (__cpp_variable_templates < 201304) +# define BOOST_NO_CXX14_VARIABLE_TEMPLATES +#endif + +// C++17 +#if !defined(__cpp_structured_bindings) || (__cpp_structured_bindings < 201606) +# define BOOST_NO_CXX17_STRUCTURED_BINDINGS +#endif +#if !defined(__cpp_inline_variables) || (__cpp_inline_variables < 201606) +# define BOOST_NO_CXX17_INLINE_VARIABLES +#endif +#if !defined(__cpp_fold_expressions) || (__cpp_fold_expressions < 201603) +# define BOOST_NO_CXX17_FOLD_EXPRESSIONS +#endif +#if !defined(__cpp_if_constexpr) || (__cpp_if_constexpr < 201606) +# define BOOST_NO_CXX17_IF_CONSTEXPR +#endif + +#define BOOST_COMPILER "Metrowerks CodeWarrior C++ version " BOOST_STRINGIZE(BOOST_COMPILER_VERSION) + +// +// versions check: +// we don't support Metrowerks prior to version 5.3: +#if __MWERKS__ < 0x2301 +# error "Compiler not supported or configured - please reconfigure" +#endif +// +// last known and checked version: +#if (__MWERKS__ > 0x3205) +# if defined(BOOST_ASSERT_CONFIG) +# error "boost: Unknown compiler version - please run the configure tests and report the results" +# endif +#endif + + + + + + + diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/compiler/mpw.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/compiler/mpw.hpp new file mode 100644 index 0000000..8433f37 --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/compiler/mpw.hpp @@ -0,0 +1,140 @@ +// (C) Copyright John Maddock 2001 - 2002. +// (C) Copyright Aleksey Gurtovoy 2002. +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for most recent version. + +// MPW C++ compilers setup: + +# if defined(__SC__) +# define BOOST_COMPILER "MPW SCpp version " BOOST_STRINGIZE(__SC__) +# elif defined(__MRC__) +# define BOOST_COMPILER "MPW MrCpp version " BOOST_STRINGIZE(__MRC__) +# else +# error "Using MPW compiler configuration by mistake. Please update." +# endif + +// +// MPW 8.90: +// +#if (MPW_CPLUS <= 0x890) || !defined(BOOST_STRICT_CONFIG) +# define BOOST_NO_CV_SPECIALIZATIONS +# define BOOST_NO_DEPENDENT_NESTED_DERIVATIONS +# define BOOST_NO_DEPENDENT_TYPES_IN_TEMPLATE_VALUE_PARAMETERS +# define BOOST_NO_INCLASS_MEMBER_INITIALIZATION +# define BOOST_NO_INTRINSIC_WCHAR_T +# define BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +# define BOOST_NO_USING_TEMPLATE + +# define BOOST_NO_CWCHAR +# define BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS + +# define BOOST_NO_STD_ALLOCATOR /* actually a bug with const reference overloading */ + +#endif + +// +// C++0x features +// +// See boost\config\suffix.hpp for BOOST_NO_LONG_LONG +// +#define BOOST_NO_CXX11_AUTO_DECLARATIONS +#define BOOST_NO_CXX11_AUTO_MULTIDECLARATIONS +#define BOOST_NO_CXX11_CHAR16_T +#define BOOST_NO_CXX11_CHAR32_T +#define BOOST_NO_CXX11_CONSTEXPR +#define BOOST_NO_CXX11_DECLTYPE +#define BOOST_NO_CXX11_DECLTYPE_N3276 +#define BOOST_NO_CXX11_DEFAULTED_FUNCTIONS +#define BOOST_NO_CXX11_DELETED_FUNCTIONS +#define BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS +#define BOOST_NO_CXX11_EXTERN_TEMPLATE +#define BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS +#define BOOST_NO_CXX11_HDR_INITIALIZER_LIST +#define BOOST_NO_CXX11_LAMBDAS +#define BOOST_NO_CXX11_LOCAL_CLASS_TEMPLATE_PARAMETERS +#define BOOST_NO_CXX11_NOEXCEPT +#define BOOST_NO_CXX11_NULLPTR +#define BOOST_NO_CXX11_RANGE_BASED_FOR +#define BOOST_NO_CXX11_RAW_LITERALS +#define BOOST_NO_CXX11_RVALUE_REFERENCES +#define BOOST_NO_CXX11_SCOPED_ENUMS +#define BOOST_NO_SFINAE_EXPR +#define BOOST_NO_CXX11_SFINAE_EXPR +#define BOOST_NO_CXX11_STATIC_ASSERT +#define BOOST_NO_CXX11_TEMPLATE_ALIASES +#define BOOST_NO_CXX11_UNICODE_LITERALS +#define BOOST_NO_CXX11_VARIADIC_TEMPLATES +#define BOOST_NO_CXX11_VARIADIC_MACROS +#define BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX +#define BOOST_NO_CXX11_USER_DEFINED_LITERALS +#define BOOST_NO_CXX11_ALIGNAS +#define BOOST_NO_CXX11_ALIGNOF +#define BOOST_NO_CXX11_TRAILING_RESULT_TYPES +#define BOOST_NO_CXX11_INLINE_NAMESPACES +#define BOOST_NO_CXX11_REF_QUALIFIERS +#define BOOST_NO_CXX11_FINAL +#define BOOST_NO_CXX11_OVERRIDE +#define BOOST_NO_CXX11_THREAD_LOCAL +#define BOOST_NO_CXX11_UNRESTRICTED_UNION + +// C++ 14: +#if !defined(__cpp_aggregate_nsdmi) || (__cpp_aggregate_nsdmi < 201304) +# define BOOST_NO_CXX14_AGGREGATE_NSDMI +#endif +#if !defined(__cpp_binary_literals) || (__cpp_binary_literals < 201304) +# define BOOST_NO_CXX14_BINARY_LITERALS +#endif +#if !defined(__cpp_constexpr) || (__cpp_constexpr < 201304) +# define BOOST_NO_CXX14_CONSTEXPR +#endif +#if !defined(__cpp_decltype_auto) || (__cpp_decltype_auto < 201304) +# define BOOST_NO_CXX14_DECLTYPE_AUTO +#endif +#if (__cplusplus < 201304) // There's no SD6 check for this.... +# define BOOST_NO_CXX14_DIGIT_SEPARATORS +#endif +#if !defined(__cpp_generic_lambdas) || (__cpp_generic_lambdas < 201304) +# define BOOST_NO_CXX14_GENERIC_LAMBDAS +#endif +#if !defined(__cpp_init_captures) || (__cpp_init_captures < 201304) +# define BOOST_NO_CXX14_INITIALIZED_LAMBDA_CAPTURES +#endif +#if !defined(__cpp_return_type_deduction) || (__cpp_return_type_deduction < 201304) +# define BOOST_NO_CXX14_RETURN_TYPE_DEDUCTION +#endif +#if !defined(__cpp_variable_templates) || (__cpp_variable_templates < 201304) +# define BOOST_NO_CXX14_VARIABLE_TEMPLATES +#endif + +// C++17 +#if !defined(__cpp_structured_bindings) || (__cpp_structured_bindings < 201606) +# define BOOST_NO_CXX17_STRUCTURED_BINDINGS +#endif +#if !defined(__cpp_inline_variables) || (__cpp_inline_variables < 201606) +# define BOOST_NO_CXX17_INLINE_VARIABLES +#endif +#if !defined(__cpp_fold_expressions) || (__cpp_fold_expressions < 201603) +# define BOOST_NO_CXX17_FOLD_EXPRESSIONS +#endif +#if !defined(__cpp_if_constexpr) || (__cpp_if_constexpr < 201606) +# define BOOST_NO_CXX17_IF_CONSTEXPR +#endif + +// +// versions check: +// we don't support MPW prior to version 8.9: +#if MPW_CPLUS < 0x890 +# error "Compiler not supported or configured - please reconfigure" +#endif +// +// last known and checked version is 0x890: +#if (MPW_CPLUS > 0x890) +# if defined(BOOST_ASSERT_CONFIG) +# error "boost: Unknown compiler version - please run the configure tests and report the results" +# endif +#endif + + diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/compiler/nvcc.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/compiler/nvcc.hpp new file mode 100644 index 0000000..419dd72 --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/compiler/nvcc.hpp @@ -0,0 +1,61 @@ +// (C) Copyright Eric Jourdanneau, Joel Falcou 2010 +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for most recent version. + +// NVIDIA CUDA C++ compiler setup + +#ifndef BOOST_COMPILER +# define BOOST_COMPILER "NVIDIA CUDA C++ Compiler" +#endif + +#if defined(__CUDACC_VER_MAJOR__) && defined(__CUDACC_VER_MINOR__) && defined(__CUDACC_VER_BUILD__) +# define BOOST_CUDA_VERSION (__CUDACC_VER_MAJOR__ * 1000000 + __CUDACC_VER_MINOR__ * 10000 + __CUDACC_VER_BUILD__) +#else +// We don't really know what the CUDA version is, but it's definitely before 7.5: +# define BOOST_CUDA_VERSION 7000000 +#endif + +// NVIDIA Specific support +// BOOST_GPU_ENABLED : Flag a function or a method as being enabled on the host and device +#define BOOST_GPU_ENABLED __host__ __device__ + +#if !defined(__clang__) || defined(__NVCC__) +// A bug in version 7.0 of CUDA prevents use of variadic templates in some occasions +// https://svn.boost.org/trac/boost/ticket/11897 +// This is fixed in 7.5. As the following version macro was introduced in 7.5 an existance +// check is enough to detect versions < 7.5 +#if BOOST_CUDA_VERSION < 7050000 +# define BOOST_NO_CXX11_VARIADIC_TEMPLATES +#endif +// The same bug is back again in 8.0: +#if (BOOST_CUDA_VERSION > 8000000) && (BOOST_CUDA_VERSION < 8010000) +# define BOOST_NO_CXX11_VARIADIC_TEMPLATES +#endif +// CUDA (8.0) has no constexpr support in msvc mode: +#if defined(_MSC_VER) && (BOOST_CUDA_VERSION < 9000000) +# define BOOST_NO_CXX11_CONSTEXPR +#endif + +#endif + +#ifdef __CUDACC__ +// +// When compiing .cu files, there's a bunch of stuff that doesn't work with msvc: +// +#if defined(_MSC_VER) +# define BOOST_NO_CXX14_DIGIT_SEPARATORS +# define BOOST_NO_CXX11_UNICODE_LITERALS +#endif +// +// And this one effects the NVCC front end, +// See https://svn.boost.org/trac/boost/ticket/13049 +// +#if (BOOST_CUDA_VERSION >= 8000000) && (BOOST_CUDA_VERSION < 8010000) +# define BOOST_NO_CXX11_NOEXCEPT +#endif + +#endif + diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/compiler/pathscale.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/compiler/pathscale.hpp new file mode 100644 index 0000000..5348cf7 --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/compiler/pathscale.hpp @@ -0,0 +1,138 @@ +// (C) Copyright Bryce Lelbach 2011 + +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for most recent version. + +// PathScale EKOPath C++ Compiler + +#ifndef BOOST_COMPILER +# define BOOST_COMPILER "PathScale EKOPath C++ Compiler version " __PATHSCALE__ +#endif + +#if __PATHCC__ >= 6 +// PathCC is based on clang, and supports the __has_*() builtins used +// to detect features in clang.hpp. Since the clang toolset is much +// better maintained, it is more convenient to reuse its definitions. +# include "boost/config/compiler/clang.hpp" +#elif __PATHCC__ >= 4 +# define BOOST_MSVC6_MEMBER_TEMPLATES +# define BOOST_HAS_UNISTD_H +# define BOOST_HAS_STDINT_H +# define BOOST_HAS_SIGACTION +# define BOOST_HAS_SCHED_YIELD +# define BOOST_HAS_THREADS +# define BOOST_HAS_PTHREADS +# define BOOST_HAS_PTHREAD_YIELD +# define BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE +# define BOOST_HAS_PARTIAL_STD_ALLOCATOR +# define BOOST_HAS_NRVO +# define BOOST_HAS_NL_TYPES_H +# define BOOST_HAS_NANOSLEEP +# define BOOST_HAS_LONG_LONG +# define BOOST_HAS_LOG1P +# define BOOST_HAS_GETTIMEOFDAY +# define BOOST_HAS_EXPM1 +# define BOOST_HAS_DIRENT_H +# define BOOST_HAS_CLOCK_GETTIME +# define BOOST_NO_CXX11_VARIADIC_TEMPLATES +# define BOOST_NO_CXX11_UNICODE_LITERALS +# define BOOST_NO_CXX11_TEMPLATE_ALIASES +# define BOOST_NO_CXX11_STATIC_ASSERT +# define BOOST_NO_SFINAE_EXPR +# define BOOST_NO_CXX11_SFINAE_EXPR +# define BOOST_NO_CXX11_SCOPED_ENUMS +# define BOOST_NO_CXX11_RVALUE_REFERENCES +# define BOOST_NO_CXX11_RANGE_BASED_FOR +# define BOOST_NO_CXX11_RAW_LITERALS +# define BOOST_NO_CXX11_NULLPTR +# define BOOST_NO_CXX11_NUMERIC_LIMITS +# define BOOST_NO_CXX11_NOEXCEPT +# define BOOST_NO_CXX11_LAMBDAS +# define BOOST_NO_CXX11_LOCAL_CLASS_TEMPLATE_PARAMETERS +# define BOOST_NO_MS_INT64_NUMERIC_LIMITS +# define BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS +# define BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS +# define BOOST_NO_CXX11_DELETED_FUNCTIONS +# define BOOST_NO_CXX11_DEFAULTED_FUNCTIONS +# define BOOST_NO_CXX11_DECLTYPE +# define BOOST_NO_CXX11_DECLTYPE_N3276 +# define BOOST_NO_CXX11_CONSTEXPR +# define BOOST_NO_COMPLETE_VALUE_INITIALIZATION +# define BOOST_NO_CXX11_CHAR32_T +# define BOOST_NO_CXX11_CHAR16_T +# define BOOST_NO_CXX11_AUTO_MULTIDECLARATIONS +# define BOOST_NO_CXX11_AUTO_DECLARATIONS +# define BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX +# define BOOST_NO_CXX11_HDR_UNORDERED_SET +# define BOOST_NO_CXX11_HDR_UNORDERED_MAP +# define BOOST_NO_CXX11_HDR_TYPEINDEX +# define BOOST_NO_CXX11_HDR_TUPLE +# define BOOST_NO_CXX11_HDR_THREAD +# define BOOST_NO_CXX11_HDR_SYSTEM_ERROR +# define BOOST_NO_CXX11_HDR_REGEX +# define BOOST_NO_CXX11_HDR_RATIO +# define BOOST_NO_CXX11_HDR_RANDOM +# define BOOST_NO_CXX11_HDR_MUTEX +# define BOOST_NO_CXX11_HDR_INITIALIZER_LIST +# define BOOST_NO_CXX11_HDR_FUTURE +# define BOOST_NO_CXX11_HDR_FORWARD_LIST +# define BOOST_NO_CXX11_HDR_CONDITION_VARIABLE +# define BOOST_NO_CXX11_HDR_CODECVT +# define BOOST_NO_CXX11_HDR_CHRONO +# define BOOST_NO_CXX11_USER_DEFINED_LITERALS +# define BOOST_NO_CXX11_ALIGNAS +# define BOOST_NO_CXX11_ALIGNOF +# define BOOST_NO_CXX11_TRAILING_RESULT_TYPES +# define BOOST_NO_CXX11_INLINE_NAMESPACES +# define BOOST_NO_CXX11_REF_QUALIFIERS +# define BOOST_NO_CXX11_FINAL +# define BOOST_NO_CXX11_OVERRIDE +# define BOOST_NO_CXX11_THREAD_LOCAL +# define BOOST_NO_CXX11_UNRESTRICTED_UNION + +// C++ 14: +#if !defined(__cpp_aggregate_nsdmi) || (__cpp_aggregate_nsdmi < 201304) +# define BOOST_NO_CXX14_AGGREGATE_NSDMI +#endif +#if !defined(__cpp_binary_literals) || (__cpp_binary_literals < 201304) +# define BOOST_NO_CXX14_BINARY_LITERALS +#endif +#if !defined(__cpp_constexpr) || (__cpp_constexpr < 201304) +# define BOOST_NO_CXX14_CONSTEXPR +#endif +#if !defined(__cpp_decltype_auto) || (__cpp_decltype_auto < 201304) +# define BOOST_NO_CXX14_DECLTYPE_AUTO +#endif +#if (__cplusplus < 201304) // There's no SD6 check for this.... +# define BOOST_NO_CXX14_DIGIT_SEPARATORS +#endif +#if !defined(__cpp_generic_lambdas) || (__cpp_generic_lambdas < 201304) +# define BOOST_NO_CXX14_GENERIC_LAMBDAS +#endif +#if !defined(__cpp_init_captures) || (__cpp_init_captures < 201304) +# define BOOST_NO_CXX14_INITIALIZED_LAMBDA_CAPTURES +#endif +#if !defined(__cpp_return_type_deduction) || (__cpp_return_type_deduction < 201304) +# define BOOST_NO_CXX14_RETURN_TYPE_DEDUCTION +#endif +#if !defined(__cpp_variable_templates) || (__cpp_variable_templates < 201304) +# define BOOST_NO_CXX14_VARIABLE_TEMPLATES +#endif + +// C++17 +#if !defined(__cpp_structured_bindings) || (__cpp_structured_bindings < 201606) +# define BOOST_NO_CXX17_STRUCTURED_BINDINGS +#endif +#if !defined(__cpp_inline_variables) || (__cpp_inline_variables < 201606) +# define BOOST_NO_CXX17_INLINE_VARIABLES +#endif +#if !defined(__cpp_fold_expressions) || (__cpp_fold_expressions < 201603) +# define BOOST_NO_CXX17_FOLD_EXPRESSIONS +#endif +#if !defined(__cpp_if_constexpr) || (__cpp_if_constexpr < 201606) +# define BOOST_NO_CXX17_IF_CONSTEXPR +#endif +#endif diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/compiler/pgi.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/compiler/pgi.hpp new file mode 100644 index 0000000..4e909d8 --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/compiler/pgi.hpp @@ -0,0 +1,23 @@ +// (C) Copyright Noel Belcourt 2007. +// Copyright 2017, NVIDIA CORPORATION. +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for most recent version. + +// PGI C++ compiler setup: + +#define BOOST_COMPILER_VERSION __PGIC__##__PGIC_MINOR__ +#define BOOST_COMPILER "PGI compiler version " BOOST_STRINGIZE(BOOST_COMPILER_VERSION) + +// PGI is mostly GNU compatible. So start with that. +#include + +// Now adjust for things that are different. + +// __float128 is a typedef, not a distinct type. +#undef BOOST_HAS_FLOAT128 + +// __int128 is not supported. +#undef BOOST_HAS_INT128 diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/compiler/sgi_mipspro.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/compiler/sgi_mipspro.hpp new file mode 100644 index 0000000..54433c9 --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/compiler/sgi_mipspro.hpp @@ -0,0 +1,29 @@ +// (C) Copyright John Maddock 2001 - 2002. +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for most recent version. + +// SGI C++ compiler setup: + +#define BOOST_COMPILER "SGI Irix compiler version " BOOST_STRINGIZE(_COMPILER_VERSION) + +#include + +// +// Threading support: +// Turn this on unconditionally here, it will get turned off again later +// if no threading API is detected. +// +#define BOOST_HAS_THREADS +#define BOOST_NO_TWO_PHASE_NAME_LOOKUP + +#undef BOOST_NO_SWPRINTF +#undef BOOST_DEDUCED_TYPENAME + +// +// version check: +// probably nothing to do here? + + diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/compiler/sunpro_cc.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/compiler/sunpro_cc.hpp new file mode 100644 index 0000000..490dc76 --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/compiler/sunpro_cc.hpp @@ -0,0 +1,222 @@ +// (C) Copyright John Maddock 2001. +// (C) Copyright Jens Maurer 2001 - 2003. +// (C) Copyright Peter Dimov 2002. +// (C) Copyright Aleksey Gurtovoy 2002 - 2003. +// (C) Copyright David Abrahams 2002. +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for most recent version. + +// Sun C++ compiler setup: + +# if __SUNPRO_CC <= 0x500 +# define BOOST_NO_MEMBER_TEMPLATES +# define BOOST_NO_FUNCTION_TEMPLATE_ORDERING +# endif + +# if (__SUNPRO_CC <= 0x520) + // + // Sunpro 5.2 and earler: + // + // although sunpro 5.2 supports the syntax for + // inline initialization it often gets the value + // wrong, especially where the value is computed + // from other constants (J Maddock 6th May 2001) +# define BOOST_NO_INCLASS_MEMBER_INITIALIZATION + + // Although sunpro 5.2 supports the syntax for + // partial specialization, it often seems to + // bind to the wrong specialization. Better + // to disable it until suppport becomes more stable + // (J Maddock 6th May 2001). +# define BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +# endif + +# if (__SUNPRO_CC <= 0x530) + // Requesting debug info (-g) with Boost.Python results + // in an internal compiler error for "static const" + // initialized in-class. + // >> Assertion: (../links/dbg_cstabs.cc, line 611) + // while processing ../test.cpp at line 0. + // (Jens Maurer according to Gottfried Ganssauge 04 Mar 2002) +# define BOOST_NO_INCLASS_MEMBER_INITIALIZATION + + // SunPro 5.3 has better support for partial specialization, + // but breaks when compiling std::less > + // (Jens Maurer 4 Nov 2001). + + // std::less specialization fixed as reported by George + // Heintzelman; partial specialization re-enabled + // (Peter Dimov 17 Jan 2002) + +//# define BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + + // integral constant expressions with 64 bit numbers fail +# define BOOST_NO_INTEGRAL_INT64_T +# endif + +# if (__SUNPRO_CC < 0x570) +# define BOOST_NO_TEMPLATE_TEMPLATES + // see http://lists.boost.org/MailArchives/boost/msg47184.php + // and http://lists.boost.org/MailArchives/boost/msg47220.php +# define BOOST_NO_INCLASS_MEMBER_INITIALIZATION +# define BOOST_NO_SFINAE +# define BOOST_NO_ARRAY_TYPE_SPECIALIZATIONS +# endif +# if (__SUNPRO_CC <= 0x580) +# define BOOST_NO_IS_ABSTRACT +# endif + +# if (__SUNPRO_CC <= 0x5100) + // Sun 5.10 may not correctly value-initialize objects of + // some user defined types, as was reported in April 2010 + // (CR 6947016), and confirmed by Steve Clamage. + // (Niels Dekker, LKEB, May 2010). +# define BOOST_NO_COMPLETE_VALUE_INITIALIZATION +# endif + +// +// Dynamic shared object (DSO) and dynamic-link library (DLL) support +// +#if __SUNPRO_CC > 0x500 +# define BOOST_SYMBOL_EXPORT __global +# define BOOST_SYMBOL_IMPORT __global +# define BOOST_SYMBOL_VISIBLE __global +#endif + +// Deprecated symbol markup +// Oracle Studio 12.4 supports deprecated attribute with a message; this is the first release that supports the attribute. +#if (__SUNPRO_CC >= 0x5130) +#define BOOST_DEPRECATED(msg) __attribute__((deprecated(msg))) +#endif + +#if (__SUNPRO_CC < 0x5130) +// C++03 features in 12.4: +#define BOOST_NO_TWO_PHASE_NAME_LOOKUP +#define BOOST_NO_SFINAE_EXPR +#define BOOST_NO_ADL_BARRIER +#define BOOST_NO_CXX11_VARIADIC_MACROS +#endif + +#if (__SUNPRO_CC < 0x5130) || (__cplusplus < 201100) +// C++11 only featuires in 12.4: +#define BOOST_NO_CXX11_AUTO_DECLARATIONS +#define BOOST_NO_CXX11_AUTO_MULTIDECLARATIONS +#define BOOST_NO_CXX11_CHAR16_T +#define BOOST_NO_CXX11_CHAR32_T +#define BOOST_NO_CXX11_CONSTEXPR +#define BOOST_NO_CXX11_DECLTYPE +#define BOOST_NO_CXX11_DEFAULTED_FUNCTIONS +#define BOOST_NO_CXX11_DELETED_FUNCTIONS +#define BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS +#define BOOST_NO_CXX11_EXTERN_TEMPLATE +#define BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS +#define BOOST_NO_CXX11_HDR_INITIALIZER_LIST +#define BOOST_NO_CXX11_LAMBDAS +#define BOOST_NO_CXX11_LOCAL_CLASS_TEMPLATE_PARAMETERS +#define BOOST_NO_CXX11_NOEXCEPT +#define BOOST_NO_CXX11_NULLPTR +#define BOOST_NO_CXX11_RANGE_BASED_FOR +#define BOOST_NO_CXX11_RAW_LITERALS +#define BOOST_NO_CXX11_RVALUE_REFERENCES +#define BOOST_NO_CXX11_SCOPED_ENUMS +#define BOOST_NO_CXX11_STATIC_ASSERT +#define BOOST_NO_CXX11_TEMPLATE_ALIASES +#define BOOST_NO_CXX11_UNICODE_LITERALS +#define BOOST_NO_CXX11_ALIGNAS +#define BOOST_NO_CXX11_ALIGNOF +#define BOOST_NO_CXX11_TRAILING_RESULT_TYPES +#define BOOST_NO_CXX11_INLINE_NAMESPACES +#define BOOST_NO_CXX11_FINAL +#define BOOST_NO_CXX11_OVERRIDE +#define BOOST_NO_CXX11_UNRESTRICTED_UNION +#endif + +#if (__SUNPRO_CC < 0x5140) || (__cplusplus < 201103) +#define BOOST_NO_CXX11_VARIADIC_TEMPLATES +#define BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX +#define BOOST_NO_CXX11_FIXED_LENGTH_VARIADIC_TEMPLATE_EXPANSION_PACKS +#define BOOST_NO_CXX11_DECLTYPE_N3276 +#define BOOST_NO_CXX11_USER_DEFINED_LITERALS +#define BOOST_NO_CXX11_REF_QUALIFIERS +#define BOOST_NO_CXX11_THREAD_LOCAL +#endif + +#define BOOST_NO_COMPLETE_VALUE_INITIALIZATION +// +// C++0x features +// +# define BOOST_HAS_LONG_LONG + +#define BOOST_NO_CXX11_SFINAE_EXPR + +// C++ 14: +#if !defined(__cpp_aggregate_nsdmi) || (__cpp_aggregate_nsdmi < 201304) +# define BOOST_NO_CXX14_AGGREGATE_NSDMI +#endif +#if !defined(__cpp_binary_literals) || (__cpp_binary_literals < 201304) +# define BOOST_NO_CXX14_BINARY_LITERALS +#endif +#if !defined(__cpp_constexpr) || (__cpp_constexpr < 201304) +# define BOOST_NO_CXX14_CONSTEXPR +#endif +#if !defined(__cpp_decltype_auto) || (__cpp_decltype_auto < 201304) || (__cplusplus < 201402L) +# define BOOST_NO_CXX14_DECLTYPE_AUTO +#endif +#if (__cplusplus < 201304) // There's no SD6 check for this.... +# define BOOST_NO_CXX14_DIGIT_SEPARATORS +#endif +#if !defined(__cpp_generic_lambdas) || (__cpp_generic_lambdas < 201304) +# define BOOST_NO_CXX14_GENERIC_LAMBDAS +#endif +#if !defined(__cpp_init_captures) || (__cpp_init_captures < 201304) +# define BOOST_NO_CXX14_INITIALIZED_LAMBDA_CAPTURES +#endif +#if !defined(__cpp_return_type_deduction) || (__cpp_return_type_deduction < 201304) +# define BOOST_NO_CXX14_RETURN_TYPE_DEDUCTION +#endif +#if !defined(__cpp_variable_templates) || (__cpp_variable_templates < 201304) +# define BOOST_NO_CXX14_VARIABLE_TEMPLATES +#endif + +// C++17 +#if !defined(__cpp_structured_bindings) || (__cpp_structured_bindings < 201606) +# define BOOST_NO_CXX17_STRUCTURED_BINDINGS +#endif +#if !defined(__cpp_inline_variables) || (__cpp_inline_variables < 201606) +# define BOOST_NO_CXX17_INLINE_VARIABLES +#endif +#if !defined(__cpp_fold_expressions) || (__cpp_fold_expressions < 201603) +# define BOOST_NO_CXX17_FOLD_EXPRESSIONS +#endif +#if !defined(__cpp_if_constexpr) || (__cpp_if_constexpr < 201606) +# define BOOST_NO_CXX17_IF_CONSTEXPR +#endif + +// Turn on threading support for Solaris 12. +// Ticket #11972 +#if (__SUNPRO_CC >= 0x5140) && defined(__SunOS_5_12) && !defined(BOOST_HAS_THREADS) +# define BOOST_HAS_THREADS +#endif + +// +// Version +// + +#define BOOST_COMPILER "Sun compiler version " BOOST_STRINGIZE(__SUNPRO_CC) + +// +// versions check: +// we don't support sunpro prior to version 4: +#if __SUNPRO_CC < 0x400 +#error "Compiler not supported or configured - please reconfigure" +#endif +// +// last known and checked version: +#if (__SUNPRO_CC > 0x5150) +# if defined(BOOST_ASSERT_CONFIG) +# error "Boost.Config is older than your compiler - please check for an updated Boost release." +# endif +#endif diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/compiler/vacpp.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/compiler/vacpp.hpp new file mode 100644 index 0000000..9cfa1ad --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/compiler/vacpp.hpp @@ -0,0 +1,186 @@ +// (C) Copyright John Maddock 2001 - 2003. +// (C) Copyright Toon Knapen 2001 - 2003. +// (C) Copyright Lie-Quan Lee 2001. +// (C) Copyright Markus Schoepflin 2002 - 2003. +// (C) Copyright Beman Dawes 2002 - 2003. +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for most recent version. + +// Visual Age (IBM) C++ compiler setup: + +#if __IBMCPP__ <= 501 +# define BOOST_NO_MEMBER_TEMPLATE_FRIENDS +# define BOOST_NO_MEMBER_FUNCTION_SPECIALIZATIONS +#endif + +#if (__IBMCPP__ <= 502) +// Actually the compiler supports inclass member initialization but it +// requires a definition for the class member and it doesn't recognize +// it as an integral constant expression when used as a template argument. +# define BOOST_NO_INCLASS_MEMBER_INITIALIZATION +# define BOOST_NO_INTEGRAL_INT64_T +# define BOOST_NO_MEMBER_TEMPLATE_KEYWORD +#endif + +#if (__IBMCPP__ <= 600) || !defined(BOOST_STRICT_CONFIG) +# define BOOST_NO_POINTER_TO_MEMBER_TEMPLATE_PARAMETERS +#endif + +#if (__IBMCPP__ <= 1110) +// XL C++ V11.1 and earlier versions may not always value-initialize +// a temporary object T(), when T is a non-POD aggregate class type. +// Michael Wong (IBM Canada Ltd) has confirmed this issue and gave it +// high priority. -- Niels Dekker (LKEB), May 2010. +# define BOOST_NO_COMPLETE_VALUE_INITIALIZATION +#endif + +// +// On AIX thread support seems to be indicated by _THREAD_SAFE: +// +#ifdef _THREAD_SAFE +# define BOOST_HAS_THREADS +#endif + +#define BOOST_COMPILER "IBM Visual Age version " BOOST_STRINGIZE(__IBMCPP__) + +// +// versions check: +// we don't support Visual age prior to version 5: +#if __IBMCPP__ < 500 +#error "Compiler not supported or configured - please reconfigure" +#endif +// +// last known and checked version is 1210: +#if (__IBMCPP__ > 1210) +# if defined(BOOST_ASSERT_CONFIG) +# error "boost: Unknown compiler version - please run the configure tests and report the results" +# endif +#endif + +// Some versions of the compiler have issues with default arguments on partial specializations +#if __IBMCPP__ <= 1010 +#define BOOST_NO_PARTIAL_SPECIALIZATION_IMPLICIT_DEFAULT_ARGS +#endif + +// Type aliasing hint. Supported since XL C++ 13.1 +#if (__IBMCPP__ >= 1310) +# define BOOST_MAY_ALIAS __attribute__((__may_alias__)) +#endif + +// +// C++0x features +// +// See boost\config\suffix.hpp for BOOST_NO_LONG_LONG +// +#if ! __IBMCPP_AUTO_TYPEDEDUCTION +# define BOOST_NO_CXX11_AUTO_DECLARATIONS +# define BOOST_NO_CXX11_AUTO_MULTIDECLARATIONS +#endif +#if ! __IBMCPP_UTF_LITERAL__ +# define BOOST_NO_CXX11_CHAR16_T +# define BOOST_NO_CXX11_CHAR32_T +#endif +#if ! __IBMCPP_CONSTEXPR +# define BOOST_NO_CXX11_CONSTEXPR +#endif +#if ! __IBMCPP_DECLTYPE +# define BOOST_NO_CXX11_DECLTYPE +#else +# define BOOST_HAS_DECLTYPE +#endif +#define BOOST_NO_CXX11_DECLTYPE_N3276 +#define BOOST_NO_CXX11_DEFAULTED_FUNCTIONS +#define BOOST_NO_CXX11_DELETED_FUNCTIONS +#if ! __IBMCPP_EXPLICIT_CONVERSION_OPERATORS +# define BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS +#endif +#if ! __IBMCPP_EXTERN_TEMPLATE +# define BOOST_NO_CXX11_EXTERN_TEMPLATE +#endif +#if ! __IBMCPP_VARIADIC_TEMPLATES +// not enabled separately at this time +# define BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS +#endif +#define BOOST_NO_CXX11_HDR_INITIALIZER_LIST +#define BOOST_NO_CXX11_LAMBDAS +#define BOOST_NO_CXX11_LOCAL_CLASS_TEMPLATE_PARAMETERS +#define BOOST_NO_CXX11_NOEXCEPT +#define BOOST_NO_CXX11_NULLPTR +#define BOOST_NO_CXX11_RANGE_BASED_FOR +#define BOOST_NO_CXX11_RAW_LITERALS +#define BOOST_NO_CXX11_USER_DEFINED_LITERALS +#if ! __IBMCPP_RVALUE_REFERENCES +# define BOOST_NO_CXX11_RVALUE_REFERENCES +#endif +#if ! __IBMCPP_SCOPED_ENUM +# define BOOST_NO_CXX11_SCOPED_ENUMS +#endif +#define BOOST_NO_SFINAE_EXPR +#define BOOST_NO_CXX11_SFINAE_EXPR +#define BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX +#if ! __IBMCPP_STATIC_ASSERT +# define BOOST_NO_CXX11_STATIC_ASSERT +#endif +#define BOOST_NO_CXX11_TEMPLATE_ALIASES +#define BOOST_NO_CXX11_UNICODE_LITERALS +#if ! __IBMCPP_VARIADIC_TEMPLATES +# define BOOST_NO_CXX11_VARIADIC_TEMPLATES +#endif +#if ! __C99_MACRO_WITH_VA_ARGS +# define BOOST_NO_CXX11_VARIADIC_MACROS +#endif +#define BOOST_NO_CXX11_ALIGNAS +#define BOOST_NO_CXX11_ALIGNOF +#define BOOST_NO_CXX11_TRAILING_RESULT_TYPES +#define BOOST_NO_CXX11_INLINE_NAMESPACES +#define BOOST_NO_CXX11_REF_QUALIFIERS +#define BOOST_NO_CXX11_FINAL +#define BOOST_NO_CXX11_OVERRIDE +#define BOOST_NO_CXX11_THREAD_LOCAL +#define BOOST_NO_CXX11_UNRESTRICTED_UNION + +// C++ 14: +#if !defined(__cpp_aggregate_nsdmi) || (__cpp_aggregate_nsdmi < 201304) +# define BOOST_NO_CXX14_AGGREGATE_NSDMI +#endif +#if !defined(__cpp_binary_literals) || (__cpp_binary_literals < 201304) +# define BOOST_NO_CXX14_BINARY_LITERALS +#endif +#if !defined(__cpp_constexpr) || (__cpp_constexpr < 201304) +# define BOOST_NO_CXX14_CONSTEXPR +#endif +#if !defined(__cpp_decltype_auto) || (__cpp_decltype_auto < 201304) +# define BOOST_NO_CXX14_DECLTYPE_AUTO +#endif +#if (__cplusplus < 201304) // There's no SD6 check for this.... +# define BOOST_NO_CXX14_DIGIT_SEPARATORS +#endif +#if !defined(__cpp_generic_lambdas) || (__cpp_generic_lambdas < 201304) +# define BOOST_NO_CXX14_GENERIC_LAMBDAS +#endif +#if !defined(__cpp_init_captures) || (__cpp_init_captures < 201304) +# define BOOST_NO_CXX14_INITIALIZED_LAMBDA_CAPTURES +#endif +#if !defined(__cpp_return_type_deduction) || (__cpp_return_type_deduction < 201304) +# define BOOST_NO_CXX14_RETURN_TYPE_DEDUCTION +#endif +#if !defined(__cpp_variable_templates) || (__cpp_variable_templates < 201304) +# define BOOST_NO_CXX14_VARIABLE_TEMPLATES +#endif + +// C++17 +#if !defined(__cpp_structured_bindings) || (__cpp_structured_bindings < 201606) +# define BOOST_NO_CXX17_STRUCTURED_BINDINGS +#endif +#if !defined(__cpp_inline_variables) || (__cpp_inline_variables < 201606) +# define BOOST_NO_CXX17_INLINE_VARIABLES +#endif +#if !defined(__cpp_fold_expressions) || (__cpp_fold_expressions < 201603) +# define BOOST_NO_CXX17_FOLD_EXPRESSIONS +#endif +#if !defined(__cpp_if_constexpr) || (__cpp_if_constexpr < 201606) +# define BOOST_NO_CXX17_IF_CONSTEXPR +#endif diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/compiler/visualc.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/compiler/visualc.hpp new file mode 100644 index 0000000..c0ada09 --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/compiler/visualc.hpp @@ -0,0 +1,395 @@ +// (C) Copyright John Maddock 2001 - 2003. +// (C) Copyright Darin Adler 2001 - 2002. +// (C) Copyright Peter Dimov 2001. +// (C) Copyright Aleksey Gurtovoy 2002. +// (C) Copyright David Abrahams 2002 - 2003. +// (C) Copyright Beman Dawes 2002 - 2003. +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for most recent version. +// +// Microsoft Visual C++ compiler setup: +// +// We need to be careful with the checks in this file, as contrary +// to popular belief there are versions with _MSC_VER with the final +// digit non-zero (mainly the MIPS cross compiler). +// +// So we either test _MSC_VER >= XXXX or else _MSC_VER < XXXX. +// No other comparisons (==, >, or <=) are safe. +// + +#define BOOST_MSVC _MSC_VER + +// +// Helper macro BOOST_MSVC_FULL_VER for use in Boost code: +// +#if _MSC_FULL_VER > 100000000 +# define BOOST_MSVC_FULL_VER _MSC_FULL_VER +#else +# define BOOST_MSVC_FULL_VER (_MSC_FULL_VER * 10) +#endif + +// Attempt to suppress VC6 warnings about the length of decorated names (obsolete): +#pragma warning( disable : 4503 ) // warning: decorated name length exceeded + +#define BOOST_HAS_PRAGMA_ONCE + +// +// versions check: +// we don't support Visual C++ prior to version 7.1: +#if _MSC_VER < 1310 +# error "Compiler not supported or configured - please reconfigure" +#endif + +// VS2005 (VC8) docs: __assume has been in Visual C++ for multiple releases +#define BOOST_UNREACHABLE_RETURN(x) __assume(0); + +#if _MSC_FULL_VER < 180020827 +# define BOOST_NO_FENV_H +#endif + +#if _MSC_VER < 1400 +// although a conforming signature for swprint exists in VC7.1 +// it appears not to actually work: +# define BOOST_NO_SWPRINTF +// Our extern template tests also fail for this compiler: +# define BOOST_NO_CXX11_EXTERN_TEMPLATE +// Variadic macros do not exist for VC7.1 and lower +# define BOOST_NO_CXX11_VARIADIC_MACROS +# define BOOST_NO_CXX11_LOCAL_CLASS_TEMPLATE_PARAMETERS +#endif + +#if _MSC_VER < 1500 // 140X == VC++ 8.0 +# define BOOST_NO_MEMBER_TEMPLATE_FRIENDS +#endif + +#if _MSC_VER < 1600 // 150X == VC++ 9.0 + // A bug in VC9: +# define BOOST_NO_ADL_BARRIER +#endif + + +#ifndef _NATIVE_WCHAR_T_DEFINED +# define BOOST_NO_INTRINSIC_WCHAR_T +#endif + +// +// check for exception handling support: +#if !defined(_CPPUNWIND) && !defined(BOOST_NO_EXCEPTIONS) +# define BOOST_NO_EXCEPTIONS +#endif + +// +// __int64 support: +// +#define BOOST_HAS_MS_INT64 +#if defined(_MSC_EXTENSIONS) || (_MSC_VER >= 1400) +# define BOOST_HAS_LONG_LONG +#else +# define BOOST_NO_LONG_LONG +#endif +#if (_MSC_VER >= 1400) && !defined(_DEBUG) +# define BOOST_HAS_NRVO +#endif +#if _MSC_VER >= 1600 // 160X == VC++ 10.0 +# define BOOST_HAS_PRAGMA_DETECT_MISMATCH +#endif +// +// disable Win32 API's if compiler extensions are +// turned off: +// +#if !defined(_MSC_EXTENSIONS) && !defined(BOOST_DISABLE_WIN32) +# define BOOST_DISABLE_WIN32 +#endif +#if !defined(_CPPRTTI) && !defined(BOOST_NO_RTTI) +# define BOOST_NO_RTTI +#endif + +// Deprecated symbol markup +#if (_MSC_VER >= 1400) +#define BOOST_DEPRECATED(msg) __declspec(deprecated(msg)) +#else +// MSVC 7.1 only supports the attribute without a message +#define BOOST_DEPRECATED(msg) __declspec(deprecated) +#endif + +// +// TR1 features: +// +#if (_MSC_VER >= 1700) && defined(_HAS_CXX17) && (_HAS_CXX17 > 0) +// # define BOOST_HAS_TR1_HASH // don't know if this is true yet. +// # define BOOST_HAS_TR1_TYPE_TRAITS // don't know if this is true yet. +# define BOOST_HAS_TR1_UNORDERED_MAP +# define BOOST_HAS_TR1_UNORDERED_SET +#endif + +// +// C++0x features +// +// See above for BOOST_NO_LONG_LONG + +// C++ features supported by VC++ 10 (aka 2010) +// +#if _MSC_VER < 1600 +# define BOOST_NO_CXX11_AUTO_DECLARATIONS +# define BOOST_NO_CXX11_AUTO_MULTIDECLARATIONS +# define BOOST_NO_CXX11_LAMBDAS +# define BOOST_NO_CXX11_RVALUE_REFERENCES +# define BOOST_NO_CXX11_STATIC_ASSERT +# define BOOST_NO_CXX11_NULLPTR +# define BOOST_NO_CXX11_DECLTYPE +#endif // _MSC_VER < 1600 + +#if _MSC_VER >= 1600 +# define BOOST_HAS_STDINT_H +#endif + +// C++11 features supported by VC++ 11 (aka 2012) +// +#if _MSC_VER < 1700 +# define BOOST_NO_CXX11_FINAL +# define BOOST_NO_CXX11_RANGE_BASED_FOR +# define BOOST_NO_CXX11_SCOPED_ENUMS +# define BOOST_NO_CXX11_OVERRIDE +#endif // _MSC_VER < 1700 + +// C++11 features supported by VC++ 12 (aka 2013). +// +#if _MSC_FULL_VER < 180020827 +# define BOOST_NO_CXX11_DEFAULTED_FUNCTIONS +# define BOOST_NO_CXX11_DELETED_FUNCTIONS +# define BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS +# define BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS +# define BOOST_NO_CXX11_RAW_LITERALS +# define BOOST_NO_CXX11_TEMPLATE_ALIASES +# define BOOST_NO_CXX11_TRAILING_RESULT_TYPES +# define BOOST_NO_CXX11_VARIADIC_TEMPLATES +# define BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX +# define BOOST_NO_CXX11_DECLTYPE_N3276 +#endif + +#if _MSC_FULL_VER >= 180020827 +#define BOOST_HAS_EXPM1 +#define BOOST_HAS_LOG1P +#endif + +// C++11 features supported by VC++ 14 (aka 2015) +// +#if (_MSC_FULL_VER < 190023026) +# define BOOST_NO_CXX11_NOEXCEPT +# define BOOST_NO_CXX11_DEFAULTED_MOVES +# define BOOST_NO_CXX11_REF_QUALIFIERS +# define BOOST_NO_CXX11_USER_DEFINED_LITERALS +# define BOOST_NO_CXX11_ALIGNAS +# define BOOST_NO_CXX11_ALIGNOF +# define BOOST_NO_CXX11_INLINE_NAMESPACES +# define BOOST_NO_CXX11_CHAR16_T +# define BOOST_NO_CXX11_CHAR32_T +# define BOOST_NO_CXX11_UNICODE_LITERALS +# define BOOST_NO_CXX14_DECLTYPE_AUTO +# define BOOST_NO_CXX14_INITIALIZED_LAMBDA_CAPTURES +# define BOOST_NO_CXX14_RETURN_TYPE_DEDUCTION +# define BOOST_NO_CXX14_BINARY_LITERALS +# define BOOST_NO_CXX14_GENERIC_LAMBDAS +# define BOOST_NO_CXX14_DIGIT_SEPARATORS +# define BOOST_NO_CXX11_THREAD_LOCAL +# define BOOST_NO_CXX11_UNRESTRICTED_UNION +#endif +// C++11 features supported by VC++ 14 update 3 (aka 2015) +// +#if (_MSC_FULL_VER < 190024210) +# define BOOST_NO_CXX14_VARIABLE_TEMPLATES +# define BOOST_NO_SFINAE_EXPR +# define BOOST_NO_CXX11_CONSTEXPR +#endif + +// C++14 features supported by VC++ 14.1 (Visual Studio 2017) +// +#if (_MSC_VER < 1910) +# define BOOST_NO_CXX14_AGGREGATE_NSDMI +#endif + +// C++17 features supported by VC++ 14.1 (Visual Studio 2017) Update 3 +// +#if (_MSC_VER < 1911) || (_MSVC_LANG < 201703) +# define BOOST_NO_CXX17_STRUCTURED_BINDINGS +# define BOOST_NO_CXX17_IF_CONSTEXPR +// Let the defaults handle these now: +//# define BOOST_NO_CXX17_HDR_OPTIONAL +//# define BOOST_NO_CXX17_HDR_STRING_VIEW +#endif + +// MSVC including version 14 has not yet completely +// implemented value-initialization, as is reported: +// "VC++ does not value-initialize members of derived classes without +// user-declared constructor", reported in 2009 by Sylvester Hesp: +// https://connect.microsoft.com/VisualStudio/feedback/details/484295 +// "Presence of copy constructor breaks member class initialization", +// reported in 2009 by Alex Vakulenko: +// https://connect.microsoft.com/VisualStudio/feedback/details/499606 +// "Value-initialization in new-expression", reported in 2005 by +// Pavel Kuznetsov (MetaCommunications Engineering): +// https://connect.microsoft.com/VisualStudio/feedback/details/100744 +// Reported again by John Maddock in 2015 for VC14: +// https://connect.microsoft.com/VisualStudio/feedback/details/1582233/c-subobjects-still-not-value-initialized-correctly +// See also: http://www.boost.org/libs/utility/value_init.htm#compiler_issues +// (Niels Dekker, LKEB, May 2010) +// Still present in VC15.5, Dec 2017. +#define BOOST_NO_COMPLETE_VALUE_INITIALIZATION +// +// C++ 11: +// +// This is supported with /permissive- for 15.5 onwards, unfortunately we appear to have no way to tell +// if this is in effect or not, in any case nothing in Boost is currently using this, so we'll just go +// on defining it for now: +// +#if (_MSC_FULL_VER < 193030705) || (_MSVC_LANG < 202004) +# define BOOST_NO_TWO_PHASE_NAME_LOOKUP +#endif + +#if (_MSC_VER < 1912) || (_MSVC_LANG < 201402) +// Supported from msvc-15.5 onwards: +#define BOOST_NO_CXX11_SFINAE_EXPR +#endif +#if (_MSC_VER < 1915) || (_MSVC_LANG < 201402) +// C++ 14: +// Still gives internal compiler error for msvc-15.5: +# define BOOST_NO_CXX14_CONSTEXPR +#endif +// C++ 17: +#if (_MSC_VER < 1912) || (_MSVC_LANG < 201703) +#define BOOST_NO_CXX17_INLINE_VARIABLES +#define BOOST_NO_CXX17_FOLD_EXPRESSIONS +#endif + +// +// Things that don't work in clr mode: +// +#ifdef _M_CEE +#ifndef BOOST_NO_CXX11_THREAD_LOCAL +# define BOOST_NO_CXX11_THREAD_LOCAL +#endif +#if !defined(BOOST_NO_SFINAE_EXPR) && !defined(_MSVC_LANG) +# define BOOST_NO_SFINAE_EXPR +#endif +#ifndef BOOST_NO_CXX11_REF_QUALIFIERS +# define BOOST_NO_CXX11_REF_QUALIFIERS +#endif +#endif +#ifdef _M_CEE_PURE +#ifndef BOOST_NO_CXX11_CONSTEXPR +# define BOOST_NO_CXX11_CONSTEXPR +#endif +#endif + +// +// prefix and suffix headers: +// +#ifndef BOOST_ABI_PREFIX +# define BOOST_ABI_PREFIX "boost/config/abi/msvc_prefix.hpp" +#endif +#ifndef BOOST_ABI_SUFFIX +# define BOOST_ABI_SUFFIX "boost/config/abi/msvc_suffix.hpp" +#endif + +// +// Approximate compiler conformance version +// +#ifdef _MSVC_LANG +# define BOOST_CXX_VERSION _MSVC_LANG +#elif defined(_HAS_CXX17) +# define BOOST_CXX_VERSION 201703L +#elif BOOST_MSVC >= 1916 +# define BOOST_CXX_VERSION 201402L +#endif + +#if BOOST_CXX_VERSION >= 201703L +# define BOOST_ATTRIBUTE_UNUSED [[maybe_unused]] +#endif + +#ifndef BOOST_COMPILER +// TODO: +// these things are mostly bogus. 1200 means version 12.0 of the compiler. The +// artificial versions assigned to them only refer to the versions of some IDE +// these compilers have been shipped with, and even that is not all of it. Some +// were shipped with freely downloadable SDKs, others as crosscompilers in eVC. +// IOW, you can't use these 'versions' in any sensible way. Sorry. +# if defined(UNDER_CE) +# if _MSC_VER < 1400 + // Note: I'm not aware of any CE compiler with version 13xx +# if defined(BOOST_ASSERT_CONFIG) +# error "boost: Unknown EVC++ compiler version - please run the configure tests and report the results" +# else +# pragma message("boost: Unknown EVC++ compiler version - please run the configure tests and report the results") +# endif +# elif _MSC_VER < 1500 +# define BOOST_COMPILER_VERSION evc8 +# elif _MSC_VER < 1600 +# define BOOST_COMPILER_VERSION evc9 +# elif _MSC_VER < 1700 +# define BOOST_COMPILER_VERSION evc10 +# elif _MSC_VER < 1800 +# define BOOST_COMPILER_VERSION evc11 +# elif _MSC_VER < 1900 +# define BOOST_COMPILER_VERSION evc12 +# elif _MSC_VER < 2000 +# define BOOST_COMPILER_VERSION evc14 +# else +# if defined(BOOST_ASSERT_CONFIG) +# error "boost: Unknown EVC++ compiler version - please run the configure tests and report the results" +# else +# pragma message("boost: Unknown EVC++ compiler version - please run the configure tests and report the results") +# endif +# endif +# else +# if _MSC_VER < 1200 + // Note: Versions up to 10.0 aren't supported. +# define BOOST_COMPILER_VERSION 5.0 +# elif _MSC_VER < 1300 +# define BOOST_COMPILER_VERSION 6.0 +# elif _MSC_VER < 1310 +# define BOOST_COMPILER_VERSION 7.0 +# elif _MSC_VER < 1400 +# define BOOST_COMPILER_VERSION 7.1 +# elif _MSC_VER < 1500 +# define BOOST_COMPILER_VERSION 8.0 +# elif _MSC_VER < 1600 +# define BOOST_COMPILER_VERSION 9.0 +# elif _MSC_VER < 1700 +# define BOOST_COMPILER_VERSION 10.0 +# elif _MSC_VER < 1800 +# define BOOST_COMPILER_VERSION 11.0 +# elif _MSC_VER < 1900 +# define BOOST_COMPILER_VERSION 12.0 +# elif _MSC_VER < 1910 +# define BOOST_COMPILER_VERSION 14.0 +# elif _MSC_VER < 1920 +# define BOOST_COMPILER_VERSION 14.1 +# elif _MSC_VER < 1930 +# define BOOST_COMPILER_VERSION 14.2 +# elif _MSC_VER < 1940 +# define BOOST_COMPILER_VERSION 14.3 +# else +# define BOOST_COMPILER_VERSION _MSC_VER +# endif +# endif + +# define BOOST_COMPILER "Microsoft Visual C++ version " BOOST_STRINGIZE(BOOST_COMPILER_VERSION) +#endif + +#include + +// +// last known and checked version is 19.3x (VS2022): +#if (_MSC_VER >= 1940) +# if defined(BOOST_ASSERT_CONFIG) +# error "Boost.Config is older than your current compiler version." +# elif !defined(BOOST_CONFIG_SUPPRESS_OUTDATED_MESSAGE) + // + // Disabled as of March 2018 - the pace of VS releases is hard to keep up with + // and in any case, we have relatively few defect macros defined now. + // BOOST_PRAGMA_MESSAGE("Info: Boost.Config is older than your compiler version - probably nothing bad will happen - but you may wish to look for an updated Boost version. Define BOOST_CONFIG_SUPPRESS_OUTDATED_MESSAGE to suppress this message.") +# endif +#endif diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/compiler/xlcpp.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/compiler/xlcpp.hpp new file mode 100644 index 0000000..99b8b24 --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/compiler/xlcpp.hpp @@ -0,0 +1,299 @@ +// (C) Copyright Douglas Gregor 2010 +// +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for most recent version. + +// compiler setup for IBM XL C/C++ for Linux (Little Endian) based on clang. + +#define BOOST_HAS_PRAGMA_ONCE + +// Detecting `-fms-extension` compiler flag assuming that _MSC_VER defined when that flag is used. +#if defined (_MSC_VER) && (__clang_major__ > 3 || (__clang_major__ == 3 && __clang_minor__ >= 4)) +# define BOOST_HAS_PRAGMA_DETECT_MISMATCH +#endif + +// When compiling with clang before __has_extension was defined, +// even if one writes 'defined(__has_extension) && __has_extension(xxx)', +// clang reports a compiler error. So the only workaround found is: + +#ifndef __has_extension +#define __has_extension __has_feature +#endif + +#ifndef __has_cpp_attribute +#define __has_cpp_attribute(x) 0 +#endif + +#if !__has_feature(cxx_exceptions) && !defined(BOOST_NO_EXCEPTIONS) +# define BOOST_NO_EXCEPTIONS +#endif + +#if !__has_feature(cxx_rtti) && !defined(BOOST_NO_RTTI) +# define BOOST_NO_RTTI +#endif + +#if !__has_feature(cxx_rtti) && !defined(BOOST_NO_TYPEID) +# define BOOST_NO_TYPEID +#endif + +#if defined(__int64) && !defined(__GNUC__) +# define BOOST_HAS_MS_INT64 +#endif + +#define BOOST_HAS_NRVO + +// Branch prediction hints +#if defined(__has_builtin) +#if __has_builtin(__builtin_expect) +#define BOOST_LIKELY(x) __builtin_expect(x, 1) +#define BOOST_UNLIKELY(x) __builtin_expect(x, 0) +#endif +#endif + +// Clang supports "long long" in all compilation modes. +#define BOOST_HAS_LONG_LONG + +// +// Dynamic shared object (DSO) and dynamic-link library (DLL) support +// +#if !defined(_WIN32) && !defined(__WIN32__) && !defined(WIN32) +# define BOOST_SYMBOL_EXPORT __attribute__((__visibility__("default"))) +# define BOOST_SYMBOL_IMPORT +# define BOOST_SYMBOL_VISIBLE __attribute__((__visibility__("default"))) +#endif + +// +// The BOOST_FALLTHROUGH macro can be used to annotate implicit fall-through +// between switch labels. +// +#if __cplusplus >= 201103L && defined(__has_warning) +# if __has_feature(cxx_attributes) && __has_warning("-Wimplicit-fallthrough") +# define BOOST_FALLTHROUGH [[clang::fallthrough]] +# endif +#endif + +#if !__has_feature(cxx_auto_type) +# define BOOST_NO_CXX11_AUTO_DECLARATIONS +# define BOOST_NO_CXX11_AUTO_MULTIDECLARATIONS +#endif + +// +// Currently clang on Windows using VC++ RTL does not support C++11's char16_t or char32_t +// +#if defined(_MSC_VER) || !(defined(__GXX_EXPERIMENTAL_CXX0X__) || __cplusplus >= 201103L) +# define BOOST_NO_CXX11_CHAR16_T +# define BOOST_NO_CXX11_CHAR32_T +#endif + +#if !__has_feature(cxx_constexpr) +# define BOOST_NO_CXX11_CONSTEXPR +#endif + +#if !__has_feature(cxx_decltype) +# define BOOST_NO_CXX11_DECLTYPE +#endif + +#if !__has_feature(cxx_decltype_incomplete_return_types) +# define BOOST_NO_CXX11_DECLTYPE_N3276 +#endif + +#if !__has_feature(cxx_defaulted_functions) +# define BOOST_NO_CXX11_DEFAULTED_FUNCTIONS +#endif + +#if !__has_feature(cxx_deleted_functions) +# define BOOST_NO_CXX11_DELETED_FUNCTIONS +#endif + +#if !__has_feature(cxx_explicit_conversions) +# define BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS +#endif + +#if !__has_feature(cxx_default_function_template_args) +# define BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS +#endif + +#if !__has_feature(cxx_generalized_initializers) +# define BOOST_NO_CXX11_HDR_INITIALIZER_LIST +#endif + +#if !__has_feature(cxx_lambdas) +# define BOOST_NO_CXX11_LAMBDAS +#endif + +#if !__has_feature(cxx_local_type_template_args) +# define BOOST_NO_CXX11_LOCAL_CLASS_TEMPLATE_PARAMETERS +#endif + +#if !__has_feature(cxx_noexcept) +# define BOOST_NO_CXX11_NOEXCEPT +#endif + +#if !__has_feature(cxx_nullptr) +# define BOOST_NO_CXX11_NULLPTR +#endif + +#if !__has_feature(cxx_range_for) +# define BOOST_NO_CXX11_RANGE_BASED_FOR +#endif + +#if !__has_feature(cxx_raw_string_literals) +# define BOOST_NO_CXX11_RAW_LITERALS +#endif + +#if !__has_feature(cxx_reference_qualified_functions) +# define BOOST_NO_CXX11_REF_QUALIFIERS +#endif + +#if !__has_feature(cxx_generalized_initializers) +# define BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX +#endif + +#if !__has_feature(cxx_rvalue_references) +# define BOOST_NO_CXX11_RVALUE_REFERENCES +#endif + +#if !__has_feature(cxx_strong_enums) +# define BOOST_NO_CXX11_SCOPED_ENUMS +#endif + +#if !__has_feature(cxx_static_assert) +# define BOOST_NO_CXX11_STATIC_ASSERT +#endif + +#if !__has_feature(cxx_alias_templates) +# define BOOST_NO_CXX11_TEMPLATE_ALIASES +#endif + +#if !__has_feature(cxx_unicode_literals) +# define BOOST_NO_CXX11_UNICODE_LITERALS +#endif + +#if !__has_feature(cxx_variadic_templates) +# define BOOST_NO_CXX11_VARIADIC_TEMPLATES +#endif + +#if !__has_feature(cxx_user_literals) +# define BOOST_NO_CXX11_USER_DEFINED_LITERALS +#endif + +#if !__has_feature(cxx_alignas) +# define BOOST_NO_CXX11_ALIGNAS +#endif + +#if !__has_feature(cxx_alignof) +# define BOOST_NO_CXX11_ALIGNOF +#endif + +#if !__has_feature(cxx_trailing_return) +# define BOOST_NO_CXX11_TRAILING_RESULT_TYPES +#endif + +#if !__has_feature(cxx_inline_namespaces) +# define BOOST_NO_CXX11_INLINE_NAMESPACES +#endif + +#if !__has_feature(cxx_override_control) +# define BOOST_NO_CXX11_FINAL +# define BOOST_NO_CXX11_OVERRIDE +#endif + +#if !__has_feature(cxx_unrestricted_unions) +# define BOOST_NO_CXX11_UNRESTRICTED_UNION +#endif + +#if !(__has_feature(__cxx_binary_literals__) || __has_extension(__cxx_binary_literals__)) +# define BOOST_NO_CXX14_BINARY_LITERALS +#endif + +#if !__has_feature(__cxx_decltype_auto__) +# define BOOST_NO_CXX14_DECLTYPE_AUTO +#endif + +#if !__has_feature(__cxx_aggregate_nsdmi__) +# define BOOST_NO_CXX14_AGGREGATE_NSDMI +#endif + +#if !__has_feature(__cxx_init_captures__) +# define BOOST_NO_CXX14_INITIALIZED_LAMBDA_CAPTURES +#endif + +#if !__has_feature(__cxx_generic_lambdas__) +# define BOOST_NO_CXX14_GENERIC_LAMBDAS +#endif + +// clang < 3.5 has a defect with dependent type, like following. +// +// template +// constexpr typename enable_if >::type foo(T &) +// { } // error: no return statement in constexpr function +// +// This issue also affects C++11 mode, but C++11 constexpr requires return stmt. +// Therefore we don't care such case. +// +// Note that we can't check Clang version directly as the numbering system changes depending who's +// creating the Clang release (see https://github.com/boostorg/config/pull/39#issuecomment-59927873) +// so instead verify that we have a feature that was introduced at the same time as working C++14 +// constexpr (generic lambda's in this case): +// +#if !__has_feature(__cxx_generic_lambdas__) || !__has_feature(__cxx_relaxed_constexpr__) +# define BOOST_NO_CXX14_CONSTEXPR +#endif + +#if !__has_feature(__cxx_return_type_deduction__) +# define BOOST_NO_CXX14_RETURN_TYPE_DEDUCTION +#endif + +#if !__has_feature(__cxx_variable_templates__) +# define BOOST_NO_CXX14_VARIABLE_TEMPLATES +#endif + +#if !defined(__cpp_structured_bindings) || (__cpp_structured_bindings < 201606) +# define BOOST_NO_CXX17_STRUCTURED_BINDINGS +#endif + +#if !defined(__cpp_if_constexpr) || (__cpp_if_constexpr < 201606) +# define BOOST_NO_CXX17_IF_CONSTEXPR +#endif + +// Clang 3.9+ in c++1z +#if !__has_cpp_attribute(fallthrough) || __cplusplus < 201406L +# define BOOST_NO_CXX17_INLINE_VARIABLES +# define BOOST_NO_CXX17_FOLD_EXPRESSIONS +#endif + +#if !__has_feature(cxx_thread_local) +# define BOOST_NO_CXX11_THREAD_LOCAL +#endif + +#if __cplusplus < 201400 +// All versions with __cplusplus above this value seem to support this: +# define BOOST_NO_CXX14_DIGIT_SEPARATORS +#endif + +// Deprecated symbol markup +#if __has_attribute(deprecated) +#define BOOST_DEPRECATED(msg) __attribute__((deprecated(msg))) +#endif + +// Unused attribute: +#if defined(__GNUC__) && (__GNUC__ >= 4) +# define BOOST_ATTRIBUTE_UNUSED __attribute__((unused)) +#endif + +// Type aliasing hint. +#if __has_attribute(__may_alias__) +# define BOOST_MAY_ALIAS __attribute__((__may_alias__)) +#endif + +#ifndef BOOST_COMPILER +# define BOOST_COMPILER "Clang version " __clang_version__ +#endif + +// Macro used to identify the Clang compiler. +#define BOOST_CLANG 1 + +#define BOOST_CLANG_VERSION (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/compiler/xlcpp_zos.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/compiler/xlcpp_zos.hpp new file mode 100644 index 0000000..9a177f1 --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/compiler/xlcpp_zos.hpp @@ -0,0 +1,173 @@ +// Copyright (c) 2017 Dynatrace +// +// Distributed under the Boost Software License, Version 1.0. +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt + +// See http://www.boost.org for most recent version. + +// Compiler setup for IBM z/OS XL C/C++ compiler. + +// Oldest compiler version currently supported is 2.1 (V2R1) +#if !defined(__IBMCPP__) || !defined(__COMPILER_VER__) || __COMPILER_VER__ < 0x42010000 +# error "Compiler not supported or configured - please reconfigure" +#endif + +#if __COMPILER_VER__ > 0x42010000 +# if defined(BOOST_ASSERT_CONFIG) +# error "Unknown compiler version - please run the configure tests and report the results" +# endif +#endif + +#define BOOST_COMPILER "IBM z/OS XL C/C++ version " BOOST_STRINGIZE(__COMPILER_VER__) +#define BOOST_XLCPP_ZOS __COMPILER_VER__ + +// ------------------------------------- + +#include // For __UU, __C99, __TR1, ... + +#if !defined(__IBMCPP_DEFAULTED_AND_DELETED_FUNCTIONS) +# define BOOST_NO_CXX11_DELETED_FUNCTIONS +# define BOOST_NO_CXX11_DEFAULTED_FUNCTIONS +# define BOOST_NO_CXX11_NON_PUBLIC_DEFAULTED_FUNCTIONS +#endif + +// ------------------------------------- + +#if defined(__UU) || defined(__C99) || defined(__TR1) +# define BOOST_HAS_LOG1P +# define BOOST_HAS_EXPM1 +#endif + +#if defined(__C99) || defined(__TR1) +# define BOOST_HAS_STDINT_H +#else +# define BOOST_NO_FENV_H +#endif + +// ------------------------------------- + +#define BOOST_HAS_NRVO + +#if !defined(__RTTI_ALL__) +# define BOOST_NO_RTTI +#endif + +#if !defined(_CPPUNWIND) && !defined(__EXCEPTIONS) +# define BOOST_NO_EXCEPTIONS +#endif + +#if defined(_LONG_LONG) || defined(__IBMCPP_C99_LONG_LONG) || defined(__LL) +# define BOOST_HAS_LONG_LONG +#else +# define BOOST_NO_LONG_LONG +#endif + +#if defined(_LONG_LONG) || defined(__IBMCPP_C99_LONG_LONG) || defined(__LL) || defined(_LP64) +# define BOOST_HAS_MS_INT64 +#endif + +#define BOOST_NO_SFINAE_EXPR +#define BOOST_NO_CXX11_SFINAE_EXPR + +#if defined(__IBMCPP_VARIADIC_TEMPLATES) +# define BOOST_HAS_VARIADIC_TMPL +#else +# define BOOST_NO_CXX11_VARIADIC_TEMPLATES +# define BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS +#endif + +#if defined(__IBMCPP_STATIC_ASSERT) +# define BOOST_HAS_STATIC_ASSERT +#else +# define BOOST_NO_CXX11_STATIC_ASSERT +#endif + +#if defined(__IBMCPP_RVALUE_REFERENCES) +# define BOOST_HAS_RVALUE_REFS +#else +# define BOOST_NO_CXX11_RVALUE_REFERENCES +#endif + +#if !defined(__IBMCPP_SCOPED_ENUM) +# define BOOST_NO_CXX11_SCOPED_ENUMS +#endif + +#define BOOST_NO_CXX11_FIXED_LENGTH_VARIADIC_TEMPLATE_EXPANSION_PACKS +#define BOOST_NO_CXX11_TEMPLATE_ALIASES +#define BOOST_NO_CXX11_LOCAL_CLASS_TEMPLATE_PARAMETERS + +#if !defined(__IBMCPP_EXPLICIT_CONVERSION_OPERATORS) +# define BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS +#endif + +#if !defined(__IBMCPP_DECLTYPE) +# define BOOST_NO_CXX11_DECLTYPE +#else +# define BOOST_HAS_DECLTYPE +#endif +#define BOOST_NO_CXX11_DECLTYPE_N3276 + +#if !defined(__IBMCPP_INLINE_NAMESPACE) +# define BOOST_NO_CXX11_INLINE_NAMESPACES +#endif + +#if !defined(__IBMCPP_AUTO_TYPEDEDUCTION) +# define BOOST_NO_CXX11_AUTO_MULTIDECLARATIONS +# define BOOST_NO_CXX11_AUTO_DECLARATIONS +# define BOOST_NO_CXX11_TRAILING_RESULT_TYPES +#endif + +#if !defined(__IBM_CHAR32_T__) +# define BOOST_NO_CXX11_CHAR32_T +#endif +#if !defined(__IBM_CHAR16_T__) +# define BOOST_NO_CXX11_CHAR16_T +#endif + +#if !defined(__IBMCPP_CONSTEXPR) +# define BOOST_NO_CXX11_CONSTEXPR +#endif + +#define BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX +#define BOOST_NO_CXX11_UNICODE_LITERALS +#define BOOST_NO_CXX11_RAW_LITERALS +#define BOOST_NO_CXX11_RANGE_BASED_FOR +#define BOOST_NO_CXX11_NULLPTR +#define BOOST_NO_CXX11_NOEXCEPT +#define BOOST_NO_CXX11_LAMBDAS +#define BOOST_NO_CXX11_USER_DEFINED_LITERALS +#define BOOST_NO_CXX11_THREAD_LOCAL +#define BOOST_NO_CXX11_REF_QUALIFIERS +#define BOOST_NO_CXX11_FINAL +#define BOOST_NO_CXX11_OVERRIDE +#define BOOST_NO_CXX11_ALIGNAS +#define BOOST_NO_CXX11_ALIGNOF +#define BOOST_NO_CXX11_UNRESTRICTED_UNION +#define BOOST_NO_CXX14_VARIABLE_TEMPLATES +#define BOOST_NO_CXX14_RETURN_TYPE_DEDUCTION +#define BOOST_NO_CXX14_AGGREGATE_NSDMI +#define BOOST_NO_CXX14_INITIALIZED_LAMBDA_CAPTURES +#define BOOST_NO_CXX14_GENERIC_LAMBDAS +#define BOOST_NO_CXX14_DIGIT_SEPARATORS +#define BOOST_NO_CXX14_DECLTYPE_AUTO +#define BOOST_NO_CXX14_CONSTEXPR +#define BOOST_NO_CXX14_BINARY_LITERALS +#define BOOST_NO_CXX17_STRUCTURED_BINDINGS +#define BOOST_NO_CXX17_INLINE_VARIABLES +#define BOOST_NO_CXX17_FOLD_EXPRESSIONS +#define BOOST_NO_CXX17_IF_CONSTEXPR + +// ------------------------------------- + +#if defined(__IBM_ATTRIBUTES) +# define BOOST_FORCEINLINE inline __attribute__ ((__always_inline__)) +# define BOOST_NOINLINE __attribute__ ((__noinline__)) +# define BOOST_MAY_ALIAS __attribute__((__may_alias__)) +// No BOOST_ALIGNMENT - explicit alignment support is broken (V2R1). +#endif + +extern "builtin" long __builtin_expect(long, long); + +#define BOOST_LIKELY(x) __builtin_expect((x) && true, 1) +#define BOOST_UNLIKELY(x) __builtin_expect((x) && true, 0) diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/detail/cxx_composite.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/detail/cxx_composite.hpp new file mode 100644 index 0000000..9c2c01e --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/detail/cxx_composite.hpp @@ -0,0 +1,217 @@ +// This file was automatically generated on Fri Oct 13 19:09:38 2023 +// by libs/config/tools/generate.cpp +// Copyright John Maddock 2002-21. +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org/libs/config for the most recent version.// +// Revision $Id$ +// + +#if defined(BOOST_NO_ADL_BARRIER)\ + || defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)\ + || defined(BOOST_NO_ARRAY_TYPE_SPECIALIZATIONS)\ + || defined(BOOST_NO_COMPLETE_VALUE_INITIALIZATION)\ + || defined(BOOST_NO_CTYPE_FUNCTIONS)\ + || defined(BOOST_NO_CV_SPECIALIZATIONS)\ + || defined(BOOST_NO_CV_VOID_SPECIALIZATIONS)\ + || defined(BOOST_NO_CWCHAR)\ + || defined(BOOST_NO_CWCTYPE)\ + || defined(BOOST_NO_DEPENDENT_NESTED_DERIVATIONS)\ + || defined(BOOST_NO_DEPENDENT_TYPES_IN_TEMPLATE_VALUE_PARAMETERS)\ + || defined(BOOST_NO_EXCEPTIONS)\ + || defined(BOOST_NO_EXCEPTION_STD_NAMESPACE)\ + || defined(BOOST_NO_EXPLICIT_FUNCTION_TEMPLATE_ARGUMENTS)\ + || defined(BOOST_NO_FENV_H)\ + || defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING)\ + || defined(BOOST_NO_FUNCTION_TYPE_SPECIALIZATIONS)\ + || defined(BOOST_NO_INCLASS_MEMBER_INITIALIZATION)\ + || defined(BOOST_NO_INTEGRAL_INT64_T)\ + || defined(BOOST_NO_INTRINSIC_WCHAR_T)\ + || defined(BOOST_NO_IOSFWD)\ + || defined(BOOST_NO_IOSTREAM)\ + || defined(BOOST_NO_IS_ABSTRACT)\ + || defined(BOOST_NO_LIMITS)\ + || defined(BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS)\ + || defined(BOOST_NO_LONG_LONG)\ + || defined(BOOST_NO_LONG_LONG_NUMERIC_LIMITS)\ + || defined(BOOST_NO_MEMBER_FUNCTION_SPECIALIZATIONS)\ + || defined(BOOST_NO_MEMBER_TEMPLATES)\ + || defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)\ + || defined(BOOST_NO_MEMBER_TEMPLATE_KEYWORD)\ + || defined(BOOST_NO_NESTED_FRIENDSHIP)\ + || defined(BOOST_NO_OPERATORS_IN_NAMESPACE)\ + || defined(BOOST_NO_PARTIAL_SPECIALIZATION_IMPLICIT_DEFAULT_ARGS)\ + || defined(BOOST_NO_POINTER_TO_MEMBER_CONST)\ + || defined(BOOST_NO_POINTER_TO_MEMBER_TEMPLATE_PARAMETERS)\ + || defined(BOOST_NO_PRIVATE_IN_AGGREGATE)\ + || defined(BOOST_NO_RESTRICT_REFERENCES)\ + || defined(BOOST_NO_RTTI)\ + || defined(BOOST_NO_SFINAE)\ + || defined(BOOST_NO_SFINAE_EXPR)\ + || defined(BOOST_NO_STDC_NAMESPACE)\ + || defined(BOOST_NO_STD_ALLOCATOR)\ + || defined(BOOST_NO_STD_DISTANCE)\ + || defined(BOOST_NO_STD_ITERATOR)\ + || defined(BOOST_NO_STD_ITERATOR_TRAITS)\ + || defined(BOOST_NO_STD_LOCALE)\ + || defined(BOOST_NO_STD_MESSAGES)\ + || defined(BOOST_NO_STD_MIN_MAX)\ + || defined(BOOST_NO_STD_OUTPUT_ITERATOR_ASSIGN)\ + || defined(BOOST_NO_STD_TYPEINFO)\ + || defined(BOOST_NO_STD_USE_FACET)\ + || defined(BOOST_NO_STD_WSTREAMBUF)\ + || defined(BOOST_NO_STD_WSTRING)\ + || defined(BOOST_NO_STRINGSTREAM)\ + || defined(BOOST_NO_TEMPLATED_IOSTREAMS)\ + || defined(BOOST_NO_TEMPLATED_ITERATOR_CONSTRUCTORS)\ + || defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)\ + || defined(BOOST_NO_TEMPLATE_TEMPLATES)\ + || defined(BOOST_NO_TWO_PHASE_NAME_LOOKUP)\ + || defined(BOOST_NO_TYPEID)\ + || defined(BOOST_NO_TYPENAME_WITH_CTOR)\ + || defined(BOOST_NO_UNREACHABLE_RETURN_DETECTION)\ + || defined(BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE)\ + || defined(BOOST_NO_USING_TEMPLATE)\ + || defined(BOOST_NO_VOID_RETURNS) +# define BOOST_NO_CXX03 +#endif + +#if defined(BOOST_NO_CXX03)\ + || defined(BOOST_NO_CXX11_ADDRESSOF)\ + || defined(BOOST_NO_CXX11_ALIGNAS)\ + || defined(BOOST_NO_CXX11_ALIGNOF)\ + || defined(BOOST_NO_CXX11_ALLOCATOR)\ + || defined(BOOST_NO_CXX11_AUTO_DECLARATIONS)\ + || defined(BOOST_NO_CXX11_AUTO_MULTIDECLARATIONS)\ + || defined(BOOST_NO_CXX11_CHAR16_T)\ + || defined(BOOST_NO_CXX11_CHAR32_T)\ + || defined(BOOST_NO_CXX11_CONSTEXPR)\ + || defined(BOOST_NO_CXX11_DECLTYPE)\ + || defined(BOOST_NO_CXX11_DECLTYPE_N3276)\ + || defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS)\ + || defined(BOOST_NO_CXX11_DEFAULTED_MOVES)\ + || defined(BOOST_NO_CXX11_DELETED_FUNCTIONS)\ + || defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS)\ + || defined(BOOST_NO_CXX11_EXTERN_TEMPLATE)\ + || defined(BOOST_NO_CXX11_FINAL)\ + || defined(BOOST_NO_CXX11_FIXED_LENGTH_VARIADIC_TEMPLATE_EXPANSION_PACKS)\ + || defined(BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS)\ + || defined(BOOST_NO_CXX11_HDR_ARRAY)\ + || defined(BOOST_NO_CXX11_HDR_ATOMIC)\ + || defined(BOOST_NO_CXX11_HDR_CHRONO)\ + || defined(BOOST_NO_CXX11_HDR_CONDITION_VARIABLE)\ + || defined(BOOST_NO_CXX11_HDR_EXCEPTION)\ + || defined(BOOST_NO_CXX11_HDR_FORWARD_LIST)\ + || defined(BOOST_NO_CXX11_HDR_FUNCTIONAL)\ + || defined(BOOST_NO_CXX11_HDR_FUTURE)\ + || defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)\ + || defined(BOOST_NO_CXX11_HDR_MUTEX)\ + || defined(BOOST_NO_CXX11_HDR_RANDOM)\ + || defined(BOOST_NO_CXX11_HDR_RATIO)\ + || defined(BOOST_NO_CXX11_HDR_REGEX)\ + || defined(BOOST_NO_CXX11_HDR_SYSTEM_ERROR)\ + || defined(BOOST_NO_CXX11_HDR_THREAD)\ + || defined(BOOST_NO_CXX11_HDR_TUPLE)\ + || defined(BOOST_NO_CXX11_HDR_TYPEINDEX)\ + || defined(BOOST_NO_CXX11_HDR_TYPE_TRAITS)\ + || defined(BOOST_NO_CXX11_HDR_UNORDERED_MAP)\ + || defined(BOOST_NO_CXX11_HDR_UNORDERED_SET)\ + || defined(BOOST_NO_CXX11_INLINE_NAMESPACES)\ + || defined(BOOST_NO_CXX11_LAMBDAS)\ + || defined(BOOST_NO_CXX11_LOCAL_CLASS_TEMPLATE_PARAMETERS)\ + || defined(BOOST_NO_CXX11_NOEXCEPT)\ + || defined(BOOST_NO_CXX11_NON_PUBLIC_DEFAULTED_FUNCTIONS)\ + || defined(BOOST_NO_CXX11_NULLPTR)\ + || defined(BOOST_NO_CXX11_NUMERIC_LIMITS)\ + || defined(BOOST_NO_CXX11_OVERRIDE)\ + || defined(BOOST_NO_CXX11_POINTER_TRAITS)\ + || defined(BOOST_NO_CXX11_RANGE_BASED_FOR)\ + || defined(BOOST_NO_CXX11_RAW_LITERALS)\ + || defined(BOOST_NO_CXX11_REF_QUALIFIERS)\ + || defined(BOOST_NO_CXX11_RVALUE_REFERENCES)\ + || defined(BOOST_NO_CXX11_SCOPED_ENUMS)\ + || defined(BOOST_NO_CXX11_SFINAE_EXPR)\ + || defined(BOOST_NO_CXX11_SMART_PTR)\ + || defined(BOOST_NO_CXX11_STATIC_ASSERT)\ + || defined(BOOST_NO_CXX11_STD_ALIGN)\ + || defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)\ + || defined(BOOST_NO_CXX11_THREAD_LOCAL)\ + || defined(BOOST_NO_CXX11_TRAILING_RESULT_TYPES)\ + || defined(BOOST_NO_CXX11_UNICODE_LITERALS)\ + || defined(BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX)\ + || defined(BOOST_NO_CXX11_UNRESTRICTED_UNION)\ + || defined(BOOST_NO_CXX11_USER_DEFINED_LITERALS)\ + || defined(BOOST_NO_CXX11_VARIADIC_MACROS)\ + || defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) +# define BOOST_NO_CXX11 +#endif + +#if defined(BOOST_NO_CXX11)\ + || defined(BOOST_NO_CXX14_AGGREGATE_NSDMI)\ + || defined(BOOST_NO_CXX14_BINARY_LITERALS)\ + || defined(BOOST_NO_CXX14_CONSTEXPR)\ + || defined(BOOST_NO_CXX14_DECLTYPE_AUTO)\ + || defined(BOOST_NO_CXX14_DIGIT_SEPARATORS)\ + || defined(BOOST_NO_CXX14_GENERIC_LAMBDAS)\ + || defined(BOOST_NO_CXX14_HDR_SHARED_MUTEX)\ + || defined(BOOST_NO_CXX14_INITIALIZED_LAMBDA_CAPTURES)\ + || defined(BOOST_NO_CXX14_RETURN_TYPE_DEDUCTION)\ + || defined(BOOST_NO_CXX14_STD_EXCHANGE)\ + || defined(BOOST_NO_CXX14_VARIABLE_TEMPLATES) +# define BOOST_NO_CXX14 +#endif + +#if defined(BOOST_NO_CXX14)\ + || defined(BOOST_NO_CXX17_DEDUCTION_GUIDES)\ + || defined(BOOST_NO_CXX17_FOLD_EXPRESSIONS)\ + || defined(BOOST_NO_CXX17_HDR_ANY)\ + || defined(BOOST_NO_CXX17_HDR_CHARCONV)\ + || defined(BOOST_NO_CXX17_HDR_EXECUTION)\ + || defined(BOOST_NO_CXX17_HDR_FILESYSTEM)\ + || defined(BOOST_NO_CXX17_HDR_MEMORY_RESOURCE)\ + || defined(BOOST_NO_CXX17_HDR_OPTIONAL)\ + || defined(BOOST_NO_CXX17_HDR_STRING_VIEW)\ + || defined(BOOST_NO_CXX17_HDR_VARIANT)\ + || defined(BOOST_NO_CXX17_IF_CONSTEXPR)\ + || defined(BOOST_NO_CXX17_INLINE_VARIABLES)\ + || defined(BOOST_NO_CXX17_ITERATOR_TRAITS)\ + || defined(BOOST_NO_CXX17_STD_APPLY)\ + || defined(BOOST_NO_CXX17_STD_INVOKE)\ + || defined(BOOST_NO_CXX17_STRUCTURED_BINDINGS) +# define BOOST_NO_CXX17 +#endif + +#if defined(BOOST_NO_CXX17)\ + || defined(BOOST_NO_CXX20_HDR_BARRIER)\ + || defined(BOOST_NO_CXX20_HDR_BIT)\ + || defined(BOOST_NO_CXX20_HDR_COMPARE)\ + || defined(BOOST_NO_CXX20_HDR_CONCEPTS)\ + || defined(BOOST_NO_CXX20_HDR_COROUTINE)\ + || defined(BOOST_NO_CXX20_HDR_FORMAT)\ + || defined(BOOST_NO_CXX20_HDR_LATCH)\ + || defined(BOOST_NO_CXX20_HDR_NUMBERS)\ + || defined(BOOST_NO_CXX20_HDR_RANGES)\ + || defined(BOOST_NO_CXX20_HDR_SEMAPHORE)\ + || defined(BOOST_NO_CXX20_HDR_SOURCE_LOCATION)\ + || defined(BOOST_NO_CXX20_HDR_SPAN)\ + || defined(BOOST_NO_CXX20_HDR_STOP_TOKEN)\ + || defined(BOOST_NO_CXX20_HDR_SYNCSTREAM)\ + || defined(BOOST_NO_CXX20_HDR_VERSION) +# define BOOST_NO_CXX20 +#endif + +#if defined(BOOST_NO_CXX20)\ + || defined(BOOST_NO_CXX23_HDR_EXPECTED)\ + || defined(BOOST_NO_CXX23_HDR_FLAT_MAP)\ + || defined(BOOST_NO_CXX23_HDR_FLAT_SET)\ + || defined(BOOST_NO_CXX23_HDR_GENERATOR)\ + || defined(BOOST_NO_CXX23_HDR_MDSPAN)\ + || defined(BOOST_NO_CXX23_HDR_PRINT)\ + || defined(BOOST_NO_CXX23_HDR_SPANSTREAM)\ + || defined(BOOST_NO_CXX23_HDR_STACKTRACE)\ + || defined(BOOST_NO_CXX23_HDR_STDFLOAT) +# define BOOST_NO_CXX23 +#endif + diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/detail/posix_features.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/detail/posix_features.hpp new file mode 100644 index 0000000..d129547 --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/detail/posix_features.hpp @@ -0,0 +1,95 @@ +// (C) Copyright John Maddock 2001 - 2003. +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + + +// See http://www.boost.org for most recent version. + +// All POSIX feature tests go in this file, +// Note that we test _POSIX_C_SOURCE and _XOPEN_SOURCE as well +// _POSIX_VERSION and _XOPEN_VERSION: on some systems POSIX API's +// may be present but none-functional unless _POSIX_C_SOURCE and +// _XOPEN_SOURCE have been defined to the right value (it's up +// to the user to do this *before* including any header, although +// in most cases the compiler will do this for you). + +# if defined(BOOST_HAS_UNISTD_H) +# include + + // XOpen has , but is this the correct version check? +# if defined(_XOPEN_VERSION) && (_XOPEN_VERSION >= 3) +# define BOOST_HAS_NL_TYPES_H +# endif + + // POSIX version 6 requires +# if defined(_POSIX_VERSION) && (_POSIX_VERSION >= 200100) +# define BOOST_HAS_STDINT_H +# endif + + // POSIX version 2 requires +# if defined(_POSIX_VERSION) && (_POSIX_VERSION >= 199009L) +# define BOOST_HAS_DIRENT_H +# endif + + // POSIX version 3 requires to have sigaction: +# if defined(_POSIX_VERSION) && (_POSIX_VERSION >= 199506L) +# define BOOST_HAS_SIGACTION +# endif + // POSIX defines _POSIX_THREADS > 0 for pthread support, + // however some platforms define _POSIX_THREADS without + // a value, hence the (_POSIX_THREADS+0 >= 0) check. + // Strictly speaking this may catch platforms with a + // non-functioning stub , but such occurrences should + // occur very rarely if at all. +# if defined(_POSIX_THREADS) && (_POSIX_THREADS+0 >= 0) && !defined(BOOST_HAS_WINTHREADS) && !defined(BOOST_HAS_MPTASKS) +# define BOOST_HAS_PTHREADS +# endif + + // BOOST_HAS_NANOSLEEP: + // This is predicated on _POSIX_TIMERS or _XOPEN_REALTIME: +# if (defined(_POSIX_TIMERS) && (_POSIX_TIMERS+0 >= 0)) \ + || (defined(_XOPEN_REALTIME) && (_XOPEN_REALTIME+0 >= 0)) +# define BOOST_HAS_NANOSLEEP +# endif + + // BOOST_HAS_CLOCK_GETTIME: + // This is predicated on _POSIX_TIMERS (also on _XOPEN_REALTIME + // but at least one platform - linux - defines that flag without + // defining clock_gettime): +# if (defined(_POSIX_TIMERS) && (_POSIX_TIMERS+0 >= 0)) +# define BOOST_HAS_CLOCK_GETTIME +# endif + + // BOOST_HAS_SCHED_YIELD: + // This is predicated on _POSIX_PRIORITY_SCHEDULING or + // on _POSIX_THREAD_PRIORITY_SCHEDULING or on _XOPEN_REALTIME. +# if defined(_POSIX_PRIORITY_SCHEDULING) && (_POSIX_PRIORITY_SCHEDULING+0 > 0)\ + || (defined(_POSIX_THREAD_PRIORITY_SCHEDULING) && (_POSIX_THREAD_PRIORITY_SCHEDULING+0 > 0))\ + || (defined(_XOPEN_REALTIME) && (_XOPEN_REALTIME+0 >= 0)) +# define BOOST_HAS_SCHED_YIELD +# endif + + // BOOST_HAS_GETTIMEOFDAY: + // BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE: + // These are predicated on _XOPEN_VERSION, and appears to be first released + // in issue 4, version 2 (_XOPEN_VERSION > 500). + // Likewise for the functions log1p and expm1. +# if defined(_XOPEN_VERSION) && (_XOPEN_VERSION+0 >= 500) +# define BOOST_HAS_GETTIMEOFDAY +# if defined(_XOPEN_SOURCE) && (_XOPEN_SOURCE+0 >= 500) +# define BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE +# endif +# ifndef BOOST_HAS_LOG1P +# define BOOST_HAS_LOG1P +# endif +# ifndef BOOST_HAS_EXPM1 +# define BOOST_HAS_EXPM1 +# endif +# endif + +# endif + + + + diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/detail/select_compiler_config.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/detail/select_compiler_config.hpp new file mode 100644 index 0000000..c3d99e1 --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/detail/select_compiler_config.hpp @@ -0,0 +1,157 @@ +// Boost compiler configuration selection header file + +// (C) Copyright John Maddock 2001 - 2003. +// (C) Copyright Martin Wille 2003. +// (C) Copyright Guillaume Melquiond 2003. +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org/ for most recent version. + +// locate which compiler we are using and define +// BOOST_COMPILER_CONFIG as needed: + +#if defined __CUDACC__ +// NVIDIA CUDA C++ compiler for GPU +# include "boost/config/compiler/nvcc.hpp" + +#endif + +#if defined(__GCCXML__) +// GCC-XML emulates other compilers, it has to appear first here! +# define BOOST_COMPILER_CONFIG "boost/config/compiler/gcc_xml.hpp" + +#elif defined(_CRAYC) +// EDG based Cray compiler: +# define BOOST_COMPILER_CONFIG "boost/config/compiler/cray.hpp" + +#elif defined __COMO__ +// Comeau C++ +# define BOOST_COMPILER_CONFIG "boost/config/compiler/comeau.hpp" + +#elif defined(__PATHSCALE__) && (__PATHCC__ >= 4) +// PathScale EKOPath compiler (has to come before clang and gcc) +# define BOOST_COMPILER_CONFIG "boost/config/compiler/pathscale.hpp" + +#elif defined(__INTEL_COMPILER) || defined(__ICL) || defined(__ICC) || defined(__ECC) +// Intel +# define BOOST_COMPILER_CONFIG "boost/config/compiler/intel.hpp" + +#elif defined __clang__ && !defined(__ibmxl__) && !defined(__CODEGEARC__) +// Clang C++ emulates GCC, so it has to appear early. +# define BOOST_COMPILER_CONFIG "boost/config/compiler/clang.hpp" + +#elif defined __DMC__ +// Digital Mars C++ +# define BOOST_COMPILER_CONFIG "boost/config/compiler/digitalmars.hpp" + +#elif defined __DCC__ +// Wind River Diab C++ +# define BOOST_COMPILER_CONFIG "boost/config/compiler/diab.hpp" + +#elif defined(__PGI) +// Portland Group Inc. +# define BOOST_COMPILER_CONFIG "boost/config/compiler/pgi.hpp" + +# elif defined(__GNUC__) && !defined(__ibmxl__) +// GNU C++: +# define BOOST_COMPILER_CONFIG "boost/config/compiler/gcc.hpp" + +#elif defined __KCC +// Kai C++ +# define BOOST_COMPILER_CONFIG "boost/config/compiler/kai.hpp" + +#elif defined __sgi +// SGI MIPSpro C++ +# define BOOST_COMPILER_CONFIG "boost/config/compiler/sgi_mipspro.hpp" + +#elif defined __DECCXX +// Compaq Tru64 Unix cxx +# define BOOST_COMPILER_CONFIG "boost/config/compiler/compaq_cxx.hpp" + +#elif defined __ghs +// Greenhills C++ +# define BOOST_COMPILER_CONFIG "boost/config/compiler/greenhills.hpp" + +#elif defined __CODEGEARC__ +// CodeGear - must be checked for before Borland +# define BOOST_COMPILER_CONFIG "boost/config/compiler/codegear.hpp" + +#elif defined __BORLANDC__ +// Borland +# define BOOST_COMPILER_CONFIG "boost/config/compiler/borland.hpp" + +#elif defined __MWERKS__ +// Metrowerks CodeWarrior +# define BOOST_COMPILER_CONFIG "boost/config/compiler/metrowerks.hpp" + +#elif defined __SUNPRO_CC +// Sun Workshop Compiler C++ +# define BOOST_COMPILER_CONFIG "boost/config/compiler/sunpro_cc.hpp" + +#elif defined __HP_aCC +// HP aCC +# define BOOST_COMPILER_CONFIG "boost/config/compiler/hp_acc.hpp" + +#elif defined(__MRC__) || defined(__SC__) +// MPW MrCpp or SCpp +# define BOOST_COMPILER_CONFIG "boost/config/compiler/mpw.hpp" + +#elif defined(__IBMCPP__) && defined(__COMPILER_VER__) && defined(__MVS__) +// IBM z/OS XL C/C++ +# define BOOST_COMPILER_CONFIG "boost/config/compiler/xlcpp_zos.hpp" + +#elif defined(__ibmxl__) +// IBM XL C/C++ for Linux (Little Endian) +# define BOOST_COMPILER_CONFIG "boost/config/compiler/xlcpp.hpp" + +#elif defined(__IBMCPP__) +// IBM Visual Age or IBM XL C/C++ for Linux (Big Endian) +# define BOOST_COMPILER_CONFIG "boost/config/compiler/vacpp.hpp" + +#elif defined _MSC_VER +// Microsoft Visual C++ +// +// Must remain the last #elif since some other vendors (Metrowerks, for +// example) also #define _MSC_VER +# define BOOST_COMPILER_CONFIG "boost/config/compiler/visualc.hpp" + +#elif defined (BOOST_ASSERT_CONFIG) +// this must come last - generate an error if we don't +// recognise the compiler: +# error "Unknown compiler - please configure (http://www.boost.org/libs/config/config.htm#configuring) and report the results to the main boost mailing list (http://www.boost.org/more/mailing_lists.htm#main)" + +#endif + +#if 0 +// +// This section allows dependency scanners to find all the headers we *might* include: +// +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#endif + diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/detail/select_platform_config.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/detail/select_platform_config.hpp new file mode 100644 index 0000000..dbff74a --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/detail/select_platform_config.hpp @@ -0,0 +1,147 @@ +// Boost compiler configuration selection header file + +// (C) Copyright John Maddock 2001 - 2002. +// (C) Copyright Jens Maurer 2001. +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for most recent version. + +// locate which platform we are on and define BOOST_PLATFORM_CONFIG as needed. +// Note that we define the headers to include using "header_name" not +// in order to prevent macro expansion within the header +// name (for example "linux" is a macro on linux systems). + +#if (defined(linux) || defined(__linux) || defined(__linux__) || defined(__GNU__) || defined(__GLIBC__)) && !defined(_CRAYC) +// linux, also other platforms (Hurd etc) that use GLIBC, should these really have their own config headers though? +# define BOOST_PLATFORM_CONFIG "boost/config/platform/linux.hpp" + +#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) +// BSD: +# define BOOST_PLATFORM_CONFIG "boost/config/platform/bsd.hpp" + +#elif defined(sun) || defined(__sun) +// solaris: +# define BOOST_PLATFORM_CONFIG "boost/config/platform/solaris.hpp" + +#elif defined(__sgi) +// SGI Irix: +# define BOOST_PLATFORM_CONFIG "boost/config/platform/irix.hpp" + +#elif defined(__hpux) +// hp unix: +# define BOOST_PLATFORM_CONFIG "boost/config/platform/hpux.hpp" + +#elif defined(__CYGWIN__) +// cygwin is not win32: +# define BOOST_PLATFORM_CONFIG "boost/config/platform/cygwin.hpp" + +#elif defined(_WIN32) || defined(__WIN32__) || defined(WIN32) +// win32: +# define BOOST_PLATFORM_CONFIG "boost/config/platform/win32.hpp" + +#elif defined(__HAIKU__) +// Haiku +# define BOOST_PLATFORM_CONFIG "boost/config/platform/haiku.hpp" + +#elif defined(__BEOS__) +// BeOS +# define BOOST_PLATFORM_CONFIG "boost/config/platform/beos.hpp" + +#elif defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__) +// MacOS +# define BOOST_PLATFORM_CONFIG "boost/config/platform/macos.hpp" + +#elif defined(__TOS_MVS__) +// IBM z/OS +# define BOOST_PLATFORM_CONFIG "boost/config/platform/zos.hpp" + +#elif defined(__IBMCPP__) || defined(_AIX) +// IBM AIX +# define BOOST_PLATFORM_CONFIG "boost/config/platform/aix.hpp" + +#elif defined(__amigaos__) +// AmigaOS +# define BOOST_PLATFORM_CONFIG "boost/config/platform/amigaos.hpp" + +#elif defined(__QNXNTO__) +// QNX: +# define BOOST_PLATFORM_CONFIG "boost/config/platform/qnxnto.hpp" + +#elif defined(__VXWORKS__) +// vxWorks: +# define BOOST_PLATFORM_CONFIG "boost/config/platform/vxworks.hpp" + +#elif defined(__SYMBIAN32__) +// Symbian: +# define BOOST_PLATFORM_CONFIG "boost/config/platform/symbian.hpp" + +#elif defined(_CRAYC) +// Cray: +# define BOOST_PLATFORM_CONFIG "boost/config/platform/cray.hpp" + +#elif defined(__VMS) +// VMS: +# define BOOST_PLATFORM_CONFIG "boost/config/platform/vms.hpp" + +#elif defined(__CloudABI__) +// Nuxi CloudABI: +# define BOOST_PLATFORM_CONFIG "boost/config/platform/cloudabi.hpp" + +#elif defined (__wasm__) +// Web assembly: +# define BOOST_PLATFORM_CONFIG "boost/config/platform/wasm.hpp" + +#else + +# if defined(unix) \ + || defined(__unix) \ + || defined(_XOPEN_SOURCE) \ + || defined(_POSIX_SOURCE) + + // generic unix platform: + +# ifndef BOOST_HAS_UNISTD_H +# define BOOST_HAS_UNISTD_H +# endif + +# include + +# endif + +# if defined (BOOST_ASSERT_CONFIG) + // this must come last - generate an error if we don't + // recognise the platform: +# error "Unknown platform - please configure and report the results to boost.org" +# endif + +#endif + +#if 0 +// +// This section allows dependency scanners to find all the files we *might* include: +// +# include "boost/config/platform/linux.hpp" +# include "boost/config/platform/bsd.hpp" +# include "boost/config/platform/solaris.hpp" +# include "boost/config/platform/irix.hpp" +# include "boost/config/platform/hpux.hpp" +# include "boost/config/platform/cygwin.hpp" +# include "boost/config/platform/win32.hpp" +# include "boost/config/platform/beos.hpp" +# include "boost/config/platform/macos.hpp" +# include "boost/config/platform/zos.hpp" +# include "boost/config/platform/aix.hpp" +# include "boost/config/platform/amigaos.hpp" +# include "boost/config/platform/qnxnto.hpp" +# include "boost/config/platform/vxworks.hpp" +# include "boost/config/platform/symbian.hpp" +# include "boost/config/platform/cray.hpp" +# include "boost/config/platform/vms.hpp" +# include + + + +#endif + diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/detail/select_stdlib_config.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/detail/select_stdlib_config.hpp new file mode 100644 index 0000000..1a09dda --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/detail/select_stdlib_config.hpp @@ -0,0 +1,121 @@ +// Boost compiler configuration selection header file + +// (C) Copyright John Maddock 2001 - 2003. +// (C) Copyright Jens Maurer 2001 - 2002. +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + + +// See http://www.boost.org for most recent version. + +// locate which std lib we are using and define BOOST_STDLIB_CONFIG as needed: + +// First, check if __has_include is available and include can be located, +// otherwise include to determine if some version of STLport is in use as the std lib +// (do not rely on this header being included since users can short-circuit this header +// if they know whose std lib they are using.) +#if defined(__cplusplus) && defined(__has_include) +# if __has_include() +// It should be safe to include `` when it is present without checking +// the actual C++ language version as it consists solely of macro definitions. +// [version.syn] p1: The header supplies implementation-dependent +// information about the C++ standard library (e.g., version number and release date). +# include +# else +# include +# endif +#elif defined(__cplusplus) +# include +#else +# include +#endif + +#if defined(__SGI_STL_PORT) || defined(_STLPORT_VERSION) +// STLPort library; this _must_ come first, otherwise since +// STLport typically sits on top of some other library, we +// can end up detecting that first rather than STLport: +# define BOOST_STDLIB_CONFIG "boost/config/stdlib/stlport.hpp" + +#else + +// If our std lib was not some version of STLport, and has not otherwise +// been detected, then include as it is about +// the smallest of the std lib headers that includes real C++ stuff. +// Some std libs do not include their C++-related macros in +// so this additional include makes sure we get those definitions. +// Note: do not rely on this header being included since users can short-circuit this +// #include if they know whose std lib they are using. +#if !defined(__LIBCOMO__) && !defined(__STD_RWCOMPILER_H__) && !defined(_RWSTD_VER)\ + && !defined(_LIBCPP_VERSION) && !defined(__GLIBCPP__) && !defined(__GLIBCXX__)\ + && !defined(__STL_CONFIG_H) && !defined(__MSL_CPP__) && !defined(__IBMCPP__)\ + && !defined(MSIPL_COMPILE_H) && !defined(_YVALS) && !defined(_CPPLIB_VER) +#include +#endif + +#if defined(__LIBCOMO__) +// Comeau STL: +#define BOOST_STDLIB_CONFIG "boost/config/stdlib/libcomo.hpp" + +#elif defined(__STD_RWCOMPILER_H__) || defined(_RWSTD_VER) +// Rogue Wave library: +# define BOOST_STDLIB_CONFIG "boost/config/stdlib/roguewave.hpp" + +#elif defined(_LIBCPP_VERSION) +// libc++ +# define BOOST_STDLIB_CONFIG "boost/config/stdlib/libcpp.hpp" + +#elif defined(__GLIBCPP__) || defined(__GLIBCXX__) +// GNU libstdc++ 3 +# define BOOST_STDLIB_CONFIG "boost/config/stdlib/libstdcpp3.hpp" + +#elif defined(__STL_CONFIG_H) +// generic SGI STL +# define BOOST_STDLIB_CONFIG "boost/config/stdlib/sgi.hpp" + +#elif defined(__MSL_CPP__) +// MSL standard lib: +# define BOOST_STDLIB_CONFIG "boost/config/stdlib/msl.hpp" + +#elif defined(__IBMCPP__) && defined(__COMPILER_VER__) && defined(__MVS__) +// IBM z/OS XL C/C++ +# define BOOST_STDLIB_CONFIG "boost/config/stdlib/xlcpp_zos.hpp" + +#elif defined(__IBMCPP__) +// take the default VACPP std lib +# define BOOST_STDLIB_CONFIG "boost/config/stdlib/vacpp.hpp" + +#elif defined(MSIPL_COMPILE_H) +// Modena C++ standard library +# define BOOST_STDLIB_CONFIG "boost/config/stdlib/modena.hpp" + +#elif (defined(_YVALS) && !defined(__IBMCPP__)) || defined(_CPPLIB_VER) +// Dinkumware Library (this has to appear after any possible replacement libraries): +# define BOOST_STDLIB_CONFIG "boost/config/stdlib/dinkumware.hpp" + +#elif defined (BOOST_ASSERT_CONFIG) +// this must come last - generate an error if we don't +// recognise the library: +# error "Unknown standard library - please configure and report the results to boost.org" + +#endif + +#endif + +#if 0 +// +// This section allows dependency scanners to find all the files we *might* include: +// +# include "boost/config/stdlib/stlport.hpp" +# include "boost/config/stdlib/libcomo.hpp" +# include "boost/config/stdlib/roguewave.hpp" +# include "boost/config/stdlib/libcpp.hpp" +# include "boost/config/stdlib/libstdcpp3.hpp" +# include "boost/config/stdlib/sgi.hpp" +# include "boost/config/stdlib/msl.hpp" +# include "boost/config/stdlib/xlcpp_zos.hpp" +# include "boost/config/stdlib/vacpp.hpp" +# include "boost/config/stdlib/modena.hpp" +# include "boost/config/stdlib/dinkumware.hpp" +#endif + diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/detail/suffix.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/detail/suffix.hpp new file mode 100644 index 0000000..2650510 --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/detail/suffix.hpp @@ -0,0 +1,1334 @@ +// Boost config.hpp configuration header file ------------------------------// +// boostinspect:ndprecated_macros -- tell the inspect tool to ignore this file + +// Copyright (c) 2001-2003 John Maddock +// Copyright (c) 2001 Darin Adler +// Copyright (c) 2001 Peter Dimov +// Copyright (c) 2002 Bill Kempf +// Copyright (c) 2002 Jens Maurer +// Copyright (c) 2002-2003 David Abrahams +// Copyright (c) 2003 Gennaro Prota +// Copyright (c) 2003 Eric Friedman +// Copyright (c) 2010 Eric Jourdanneau, Joel Falcou +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org/ for most recent version. + +// Boost config.hpp policy and rationale documentation has been moved to +// http://www.boost.org/libs/config/ +// +// This file is intended to be stable, and relatively unchanging. +// It should contain boilerplate code only - no compiler specific +// code unless it is unavoidable - no changes unless unavoidable. + +#ifndef BOOST_CONFIG_SUFFIX_HPP +#define BOOST_CONFIG_SUFFIX_HPP + +#if defined(__GNUC__) && (__GNUC__ >= 4) +// +// Some GCC-4.x versions issue warnings even when __extension__ is used, +// so use this as a workaround: +// +#pragma GCC system_header +#endif + +// +// ensure that visibility macros are always defined, thus simplifying use +// +#ifndef BOOST_SYMBOL_EXPORT +# define BOOST_SYMBOL_EXPORT +#endif +#ifndef BOOST_SYMBOL_IMPORT +# define BOOST_SYMBOL_IMPORT +#endif +#ifndef BOOST_SYMBOL_VISIBLE +# define BOOST_SYMBOL_VISIBLE +#endif + +// +// disable explicitly enforced visibility +// +#if defined(BOOST_DISABLE_EXPLICIT_SYMBOL_VISIBILITY) + +#undef BOOST_SYMBOL_EXPORT +#define BOOST_SYMBOL_EXPORT + +#undef BOOST_SYMBOL_IMPORT +#define BOOST_SYMBOL_IMPORT + +#undef BOOST_SYMBOL_VISIBLE +#define BOOST_SYMBOL_VISIBLE + +#endif + +// +// look for long long by looking for the appropriate macros in . +// Note that we use limits.h rather than climits for maximal portability, +// remember that since these just declare a bunch of macros, there should be +// no namespace issues from this. +// +#if !defined(BOOST_HAS_LONG_LONG) && !defined(BOOST_NO_LONG_LONG) \ + && !defined(BOOST_MSVC) && !defined(BOOST_BORLANDC) +# include +# if (defined(ULLONG_MAX) || defined(ULONG_LONG_MAX) || defined(ULONGLONG_MAX)) +# define BOOST_HAS_LONG_LONG +# else +# define BOOST_NO_LONG_LONG +# endif +#endif + +// GCC 3.x will clean up all of those nasty macro definitions that +// BOOST_NO_CTYPE_FUNCTIONS is intended to help work around, so undefine +// it under GCC 3.x. +#if defined(__GNUC__) && (__GNUC__ >= 3) && defined(BOOST_NO_CTYPE_FUNCTIONS) +# undef BOOST_NO_CTYPE_FUNCTIONS +#endif + +// +// Assume any extensions are in namespace std:: unless stated otherwise: +// +# ifndef BOOST_STD_EXTENSION_NAMESPACE +# define BOOST_STD_EXTENSION_NAMESPACE std +# endif + +// +// If cv-qualified specializations are not allowed, then neither are cv-void ones: +// +# if defined(BOOST_NO_CV_SPECIALIZATIONS) \ + && !defined(BOOST_NO_CV_VOID_SPECIALIZATIONS) +# define BOOST_NO_CV_VOID_SPECIALIZATIONS +# endif + +// +// If there is no numeric_limits template, then it can't have any compile time +// constants either! +// +# if defined(BOOST_NO_LIMITS) \ + && !defined(BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS) +# define BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS +# define BOOST_NO_MS_INT64_NUMERIC_LIMITS +# define BOOST_NO_LONG_LONG_NUMERIC_LIMITS +# endif + +// +// if there is no long long then there is no specialisation +// for numeric_limits either: +// +#if !defined(BOOST_HAS_LONG_LONG) && !defined(BOOST_NO_LONG_LONG_NUMERIC_LIMITS) +# define BOOST_NO_LONG_LONG_NUMERIC_LIMITS +#endif + +// +// if there is no __int64 then there is no specialisation +// for numeric_limits<__int64> either: +// +#if !defined(BOOST_HAS_MS_INT64) && !defined(BOOST_NO_MS_INT64_NUMERIC_LIMITS) +# define BOOST_NO_MS_INT64_NUMERIC_LIMITS +#endif + +// +// if member templates are supported then so is the +// VC6 subset of member templates: +// +# if !defined(BOOST_NO_MEMBER_TEMPLATES) \ + && !defined(BOOST_MSVC6_MEMBER_TEMPLATES) +# define BOOST_MSVC6_MEMBER_TEMPLATES +# endif + +// +// Without partial specialization, can't test for partial specialisation bugs: +// +# if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) \ + && !defined(BOOST_BCB_PARTIAL_SPECIALIZATION_BUG) +# define BOOST_BCB_PARTIAL_SPECIALIZATION_BUG +# endif + +// +// Without partial specialization, we can't have array-type partial specialisations: +// +# if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) \ + && !defined(BOOST_NO_ARRAY_TYPE_SPECIALIZATIONS) +# define BOOST_NO_ARRAY_TYPE_SPECIALIZATIONS +# endif + +// +// Without partial specialization, std::iterator_traits can't work: +// +# if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) \ + && !defined(BOOST_NO_STD_ITERATOR_TRAITS) +# define BOOST_NO_STD_ITERATOR_TRAITS +# endif + +// +// Without partial specialization, partial +// specialization with default args won't work either: +// +# if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) \ + && !defined(BOOST_NO_PARTIAL_SPECIALIZATION_IMPLICIT_DEFAULT_ARGS) +# define BOOST_NO_PARTIAL_SPECIALIZATION_IMPLICIT_DEFAULT_ARGS +# endif + +// +// Without member template support, we can't have template constructors +// in the standard library either: +// +# if defined(BOOST_NO_MEMBER_TEMPLATES) \ + && !defined(BOOST_MSVC6_MEMBER_TEMPLATES) \ + && !defined(BOOST_NO_TEMPLATED_ITERATOR_CONSTRUCTORS) +# define BOOST_NO_TEMPLATED_ITERATOR_CONSTRUCTORS +# endif + +// +// Without member template support, we can't have a conforming +// std::allocator template either: +// +# if defined(BOOST_NO_MEMBER_TEMPLATES) \ + && !defined(BOOST_MSVC6_MEMBER_TEMPLATES) \ + && !defined(BOOST_NO_STD_ALLOCATOR) +# define BOOST_NO_STD_ALLOCATOR +# endif + +// +// without ADL support then using declarations will break ADL as well: +// +#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP) && !defined(BOOST_FUNCTION_SCOPE_USING_DECLARATION_BREAKS_ADL) +# define BOOST_FUNCTION_SCOPE_USING_DECLARATION_BREAKS_ADL +#endif + +// +// Without typeid support we have no dynamic RTTI either: +// +#if defined(BOOST_NO_TYPEID) && !defined(BOOST_NO_RTTI) +# define BOOST_NO_RTTI +#endif + +// +// If we have a standard allocator, then we have a partial one as well: +// +#if !defined(BOOST_NO_STD_ALLOCATOR) +# define BOOST_HAS_PARTIAL_STD_ALLOCATOR +#endif + +// +// We can't have a working std::use_facet if there is no std::locale: +// +# if defined(BOOST_NO_STD_LOCALE) && !defined(BOOST_NO_STD_USE_FACET) +# define BOOST_NO_STD_USE_FACET +# endif + +// +// We can't have a std::messages facet if there is no std::locale: +// +# if defined(BOOST_NO_STD_LOCALE) && !defined(BOOST_NO_STD_MESSAGES) +# define BOOST_NO_STD_MESSAGES +# endif + +// +// We can't have a working std::wstreambuf if there is no std::locale: +// +# if defined(BOOST_NO_STD_LOCALE) && !defined(BOOST_NO_STD_WSTREAMBUF) +# define BOOST_NO_STD_WSTREAMBUF +# endif + +// +// We can't have a if there is no : +// +# if defined(BOOST_NO_CWCHAR) && !defined(BOOST_NO_CWCTYPE) +# define BOOST_NO_CWCTYPE +# endif + +// +// We can't have a swprintf if there is no : +// +# if defined(BOOST_NO_CWCHAR) && !defined(BOOST_NO_SWPRINTF) +# define BOOST_NO_SWPRINTF +# endif + +// +// If Win32 support is turned off, then we must turn off +// threading support also, unless there is some other +// thread API enabled: +// +#if defined(BOOST_DISABLE_WIN32) && defined(_WIN32) \ + && !defined(BOOST_DISABLE_THREADS) && !defined(BOOST_HAS_PTHREADS) +# define BOOST_DISABLE_THREADS +#endif + +// +// Turn on threading support if the compiler thinks that it's in +// multithreaded mode. We put this here because there are only a +// limited number of macros that identify this (if there's any missing +// from here then add to the appropriate compiler section): +// +#if (defined(__MT__) || defined(_MT) || defined(_REENTRANT) \ + || defined(_PTHREADS) || defined(__APPLE__) || defined(__DragonFly__)) \ + && !defined(BOOST_HAS_THREADS) +# define BOOST_HAS_THREADS +#endif + +// +// Turn threading support off if BOOST_DISABLE_THREADS is defined: +// +#if defined(BOOST_DISABLE_THREADS) && defined(BOOST_HAS_THREADS) +# undef BOOST_HAS_THREADS +#endif + +// +// Turn threading support off if we don't recognise the threading API: +// +#if defined(BOOST_HAS_THREADS) && !defined(BOOST_HAS_PTHREADS)\ + && !defined(BOOST_HAS_WINTHREADS) && !defined(BOOST_HAS_BETHREADS)\ + && !defined(BOOST_HAS_MPTASKS) +# undef BOOST_HAS_THREADS +#endif + +// +// Turn threading detail macros off if we don't (want to) use threading +// +#ifndef BOOST_HAS_THREADS +# undef BOOST_HAS_PTHREADS +# undef BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE +# undef BOOST_HAS_PTHREAD_YIELD +# undef BOOST_HAS_PTHREAD_DELAY_NP +# undef BOOST_HAS_WINTHREADS +# undef BOOST_HAS_BETHREADS +# undef BOOST_HAS_MPTASKS +#endif + +// +// If the compiler claims to be C99 conformant, then it had better +// have a : +// +# if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901) +# define BOOST_HAS_STDINT_H +# ifndef BOOST_HAS_LOG1P +# define BOOST_HAS_LOG1P +# endif +# ifndef BOOST_HAS_EXPM1 +# define BOOST_HAS_EXPM1 +# endif +# endif + +// +// Define BOOST_NO_SLIST and BOOST_NO_HASH if required. +// Note that this is for backwards compatibility only. +// +# if !defined(BOOST_HAS_SLIST) && !defined(BOOST_NO_SLIST) +# define BOOST_NO_SLIST +# endif + +# if !defined(BOOST_HAS_HASH) && !defined(BOOST_NO_HASH) +# define BOOST_NO_HASH +# endif + +// +// Set BOOST_SLIST_HEADER if not set already: +// +#if defined(BOOST_HAS_SLIST) && !defined(BOOST_SLIST_HEADER) +# define BOOST_SLIST_HEADER +#endif + +// +// Set BOOST_HASH_SET_HEADER if not set already: +// +#if defined(BOOST_HAS_HASH) && !defined(BOOST_HASH_SET_HEADER) +# define BOOST_HASH_SET_HEADER +#endif + +// +// Set BOOST_HASH_MAP_HEADER if not set already: +// +#if defined(BOOST_HAS_HASH) && !defined(BOOST_HASH_MAP_HEADER) +# define BOOST_HASH_MAP_HEADER +#endif + +// BOOST_HAS_ABI_HEADERS +// This macro gets set if we have headers that fix the ABI, +// and prevent ODR violations when linking to external libraries: +#if defined(BOOST_ABI_PREFIX) && defined(BOOST_ABI_SUFFIX) && !defined(BOOST_HAS_ABI_HEADERS) +# define BOOST_HAS_ABI_HEADERS +#endif + +#if defined(BOOST_HAS_ABI_HEADERS) && defined(BOOST_DISABLE_ABI_HEADERS) +# undef BOOST_HAS_ABI_HEADERS +#endif + +// BOOST_NO_STDC_NAMESPACE workaround --------------------------------------// +// Because std::size_t usage is so common, even in boost headers which do not +// otherwise use the C library, the workaround is included here so +// that ugly workaround code need not appear in many other boost headers. +// NOTE WELL: This is a workaround for non-conforming compilers; +// must still be #included in the usual places so that inclusion +// works as expected with standard conforming compilers. The resulting +// double inclusion of is harmless. + +# if defined(BOOST_NO_STDC_NAMESPACE) && defined(__cplusplus) +# include + namespace std { using ::ptrdiff_t; using ::size_t; } +# endif + +// Workaround for the unfortunate min/max macros defined by some platform headers + +#define BOOST_PREVENT_MACRO_SUBSTITUTION + +#ifndef BOOST_USING_STD_MIN +# define BOOST_USING_STD_MIN() using std::min +#endif + +#ifndef BOOST_USING_STD_MAX +# define BOOST_USING_STD_MAX() using std::max +#endif + +// BOOST_NO_STD_MIN_MAX workaround -----------------------------------------// + +# if defined(BOOST_NO_STD_MIN_MAX) && defined(__cplusplus) + +namespace std { + template + inline const _Tp& min BOOST_PREVENT_MACRO_SUBSTITUTION (const _Tp& __a, const _Tp& __b) { + return __b < __a ? __b : __a; + } + template + inline const _Tp& max BOOST_PREVENT_MACRO_SUBSTITUTION (const _Tp& __a, const _Tp& __b) { + return __a < __b ? __b : __a; + } +} + +# endif + +// BOOST_STATIC_CONSTANT workaround --------------------------------------- // +// On compilers which don't allow in-class initialization of static integral +// constant members, we must use enums as a workaround if we want the constants +// to be available at compile-time. This macro gives us a convenient way to +// declare such constants. + +# ifdef BOOST_NO_INCLASS_MEMBER_INITIALIZATION +# define BOOST_STATIC_CONSTANT(type, assignment) enum { assignment } +# else +# define BOOST_STATIC_CONSTANT(type, assignment) static const type assignment +# endif + +// BOOST_USE_FACET / HAS_FACET workaround ----------------------------------// +// When the standard library does not have a conforming std::use_facet there +// are various workarounds available, but they differ from library to library. +// The same problem occurs with has_facet. +// These macros provide a consistent way to access a locale's facets. +// Usage: +// replace +// std::use_facet(loc); +// with +// BOOST_USE_FACET(Type, loc); +// Note do not add a std:: prefix to the front of BOOST_USE_FACET! +// Use for BOOST_HAS_FACET is analogous. + +#if defined(BOOST_NO_STD_USE_FACET) +# ifdef BOOST_HAS_TWO_ARG_USE_FACET +# define BOOST_USE_FACET(Type, loc) std::use_facet(loc, static_cast(0)) +# define BOOST_HAS_FACET(Type, loc) std::has_facet(loc, static_cast(0)) +# elif defined(BOOST_HAS_MACRO_USE_FACET) +# define BOOST_USE_FACET(Type, loc) std::_USE(loc, Type) +# define BOOST_HAS_FACET(Type, loc) std::_HAS(loc, Type) +# elif defined(BOOST_HAS_STLP_USE_FACET) +# define BOOST_USE_FACET(Type, loc) (*std::_Use_facet(loc)) +# define BOOST_HAS_FACET(Type, loc) std::has_facet< Type >(loc) +# endif +#else +# define BOOST_USE_FACET(Type, loc) std::use_facet< Type >(loc) +# define BOOST_HAS_FACET(Type, loc) std::has_facet< Type >(loc) +#endif + +// BOOST_NESTED_TEMPLATE workaround ------------------------------------------// +// Member templates are supported by some compilers even though they can't use +// the A::template member syntax, as a workaround replace: +// +// typedef typename A::template rebind binder; +// +// with: +// +// typedef typename A::BOOST_NESTED_TEMPLATE rebind binder; + +#ifndef BOOST_NO_MEMBER_TEMPLATE_KEYWORD +# define BOOST_NESTED_TEMPLATE template +#else +# define BOOST_NESTED_TEMPLATE +#endif + +// BOOST_UNREACHABLE_RETURN(x) workaround -------------------------------------// +// Normally evaluates to nothing, unless BOOST_NO_UNREACHABLE_RETURN_DETECTION +// is defined, in which case it evaluates to return x; Use when you have a return +// statement that can never be reached. + +#ifndef BOOST_UNREACHABLE_RETURN +# ifdef BOOST_NO_UNREACHABLE_RETURN_DETECTION +# define BOOST_UNREACHABLE_RETURN(x) return x; +# else +# define BOOST_UNREACHABLE_RETURN(x) +# endif +#endif + +// BOOST_DEDUCED_TYPENAME workaround ------------------------------------------// +// +// Some compilers don't support the use of `typename' for dependent +// types in deduced contexts, e.g. +// +// template void f(T, typename T::type); +// ^^^^^^^^ +// Replace these declarations with: +// +// template void f(T, BOOST_DEDUCED_TYPENAME T::type); + +#ifndef BOOST_NO_DEDUCED_TYPENAME +# define BOOST_DEDUCED_TYPENAME typename +#else +# define BOOST_DEDUCED_TYPENAME +#endif + +#ifndef BOOST_NO_TYPENAME_WITH_CTOR +# define BOOST_CTOR_TYPENAME typename +#else +# define BOOST_CTOR_TYPENAME +#endif + +// +// If we're on a CUDA device (note DEVICE not HOST, irrespective of compiler) then disable __int128 and __float128 support if present: +// +#if defined(__CUDA_ARCH__) && defined(BOOST_HAS_FLOAT128) +# undef BOOST_HAS_FLOAT128 +#endif +#if defined(__CUDA_ARCH__) && defined(BOOST_HAS_INT128) +# undef BOOST_HAS_INT128 +#endif + +// long long workaround ------------------------------------------// +// On gcc (and maybe other compilers?) long long is alway supported +// but it's use may generate either warnings (with -ansi), or errors +// (with -pedantic -ansi) unless it's use is prefixed by __extension__ +// +#if defined(BOOST_HAS_LONG_LONG) && defined(__cplusplus) +namespace boost{ +# ifdef __GNUC__ + __extension__ typedef long long long_long_type; + __extension__ typedef unsigned long long ulong_long_type; +# else + typedef long long long_long_type; + typedef unsigned long long ulong_long_type; +# endif +} +#endif +// same again for __int128: +#if defined(BOOST_HAS_INT128) && defined(__cplusplus) +namespace boost{ +# ifdef __GNUC__ + __extension__ typedef __int128 int128_type; + __extension__ typedef unsigned __int128 uint128_type; +# else + typedef __int128 int128_type; + typedef unsigned __int128 uint128_type; +# endif +} +#endif +// same again for __float128: +#if defined(BOOST_HAS_FLOAT128) && defined(__cplusplus) +namespace boost { +# ifdef __GNUC__ + __extension__ typedef __float128 float128_type; +# else + typedef __float128 float128_type; +# endif +} +#endif + +// BOOST_[APPEND_]EXPLICIT_TEMPLATE_[NON_]TYPE macros --------------------------// + +// These macros are obsolete. Port away and remove. + +# define BOOST_EXPLICIT_TEMPLATE_TYPE(t) +# define BOOST_EXPLICIT_TEMPLATE_TYPE_SPEC(t) +# define BOOST_EXPLICIT_TEMPLATE_NON_TYPE(t, v) +# define BOOST_EXPLICIT_TEMPLATE_NON_TYPE_SPEC(t, v) + +# define BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(t) +# define BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE_SPEC(t) +# define BOOST_APPEND_EXPLICIT_TEMPLATE_NON_TYPE(t, v) +# define BOOST_APPEND_EXPLICIT_TEMPLATE_NON_TYPE_SPEC(t, v) + +// When BOOST_NO_STD_TYPEINFO is defined, we can just import +// the global definition into std namespace, +// see https://svn.boost.org/trac10/ticket/4115 +#if defined(BOOST_NO_STD_TYPEINFO) && defined(__cplusplus) && defined(BOOST_MSVC) +#include +namespace std{ using ::type_info; } +// Since we do now have typeinfo, undef the macro: +#undef BOOST_NO_STD_TYPEINFO +#endif + +// ---------------------------------------------------------------------------// + +// Helper macro BOOST_STRINGIZE: +// Helper macro BOOST_JOIN: + +#include + +// +// Set some default values for compiler/library/platform names. +// These are for debugging config setup only: +// +# ifndef BOOST_COMPILER +# define BOOST_COMPILER "Unknown ISO C++ Compiler" +# endif +# ifndef BOOST_STDLIB +# define BOOST_STDLIB "Unknown ISO standard library" +# endif +# ifndef BOOST_PLATFORM +# if defined(unix) || defined(__unix) || defined(_XOPEN_SOURCE) \ + || defined(_POSIX_SOURCE) +# define BOOST_PLATFORM "Generic Unix" +# else +# define BOOST_PLATFORM "Unknown" +# endif +# endif + +// +// Set some default values GPU support +// +# ifndef BOOST_GPU_ENABLED +# define BOOST_GPU_ENABLED +# endif + +// BOOST_RESTRICT ---------------------------------------------// +// Macro to use in place of 'restrict' keyword variants +#if !defined(BOOST_RESTRICT) +# if defined(_MSC_VER) +# define BOOST_RESTRICT __restrict +# if !defined(BOOST_NO_RESTRICT_REFERENCES) && (_MSC_FULL_VER < 190023026) +# define BOOST_NO_RESTRICT_REFERENCES +# endif +# elif defined(__GNUC__) && __GNUC__ > 3 + // Clang also defines __GNUC__ (as 4) +# define BOOST_RESTRICT __restrict__ +# else +# define BOOST_RESTRICT +# if !defined(BOOST_NO_RESTRICT_REFERENCES) +# define BOOST_NO_RESTRICT_REFERENCES +# endif +# endif +#endif + +// BOOST_MAY_ALIAS -----------------------------------------------// +// The macro expands to an attribute to mark a type that is allowed to alias other types. +// The macro is defined in the compiler-specific headers. +#if !defined(BOOST_MAY_ALIAS) +# define BOOST_NO_MAY_ALIAS +# define BOOST_MAY_ALIAS +#endif + +// BOOST_FORCEINLINE ---------------------------------------------// +// Macro to use in place of 'inline' to force a function to be inline +#if !defined(BOOST_FORCEINLINE) +# if defined(_MSC_VER) +# define BOOST_FORCEINLINE __forceinline +# elif defined(__GNUC__) && __GNUC__ > 3 + // Clang also defines __GNUC__ (as 4) +# define BOOST_FORCEINLINE inline __attribute__ ((__always_inline__)) +# else +# define BOOST_FORCEINLINE inline +# endif +#endif + +// BOOST_NOINLINE ---------------------------------------------// +// Macro to use in place of 'inline' to prevent a function to be inlined +#if !defined(BOOST_NOINLINE) +# if defined(_MSC_VER) +# define BOOST_NOINLINE __declspec(noinline) +# elif defined(__GNUC__) && __GNUC__ > 3 + // Clang also defines __GNUC__ (as 4) +# if defined(__CUDACC__) + // nvcc doesn't always parse __noinline__, + // see: https://svn.boost.org/trac/boost/ticket/9392 +# define BOOST_NOINLINE __attribute__ ((noinline)) +# elif defined(__HIP__) + // See https://github.com/boostorg/config/issues/392 +# define BOOST_NOINLINE __attribute__ ((noinline)) +# else +# define BOOST_NOINLINE __attribute__ ((__noinline__)) +# endif +# else +# define BOOST_NOINLINE +# endif +#endif + +// BOOST_NORETURN ---------------------------------------------// +// Macro to use before a function declaration/definition to designate +// the function as not returning normally (i.e. with a return statement +// or by leaving the function scope, if the function return type is void). +#if !defined(BOOST_NORETURN) +# if defined(_MSC_VER) +# define BOOST_NORETURN __declspec(noreturn) +# elif defined(__GNUC__) || defined(__CODEGEARC__) && defined(__clang__) +# define BOOST_NORETURN __attribute__ ((__noreturn__)) +# elif defined(__has_attribute) && defined(__SUNPRO_CC) && (__SUNPRO_CC > 0x5130) +# if __has_attribute(noreturn) +# define BOOST_NORETURN [[noreturn]] +# endif +# elif defined(__has_cpp_attribute) +# if __has_cpp_attribute(noreturn) +# define BOOST_NORETURN [[noreturn]] +# endif +# endif +#endif + +#if !defined(BOOST_NORETURN) +# define BOOST_NO_NORETURN +# define BOOST_NORETURN +#endif + +// BOOST_DEPRECATED -------------------------------------------// +// The macro can be used to mark deprecated symbols, such as functions, objects and types. +// Any code that uses these symbols will produce warnings, possibly with a message specified +// as an argument. The warnings can be suppressed by defining BOOST_ALLOW_DEPRECATED_SYMBOLS +// or BOOST_ALLOW_DEPRECATED. +#if !defined(BOOST_DEPRECATED) && __cplusplus >= 201402 +#define BOOST_DEPRECATED(msg) [[deprecated(msg)]] +#endif + +#if defined(BOOST_ALLOW_DEPRECATED_SYMBOLS) || defined(BOOST_ALLOW_DEPRECATED) +#undef BOOST_DEPRECATED +#endif + +#if !defined(BOOST_DEPRECATED) +#define BOOST_DEPRECATED(msg) +#endif + +// Branch prediction hints +// These macros are intended to wrap conditional expressions that yield true or false +// +// if (BOOST_LIKELY(var == 10)) +// { +// // the most probable code here +// } +// +#if !defined(BOOST_LIKELY) +# define BOOST_LIKELY(x) x +#endif +#if !defined(BOOST_UNLIKELY) +# define BOOST_UNLIKELY(x) x +#endif + +#if !defined(BOOST_NO_CXX11_OVERRIDE) +# define BOOST_OVERRIDE override +#else +# define BOOST_OVERRIDE +#endif + +// Type and data alignment specification +// +#if !defined(BOOST_ALIGNMENT) +# if !defined(BOOST_NO_CXX11_ALIGNAS) +# define BOOST_ALIGNMENT(x) alignas(x) +# elif defined(_MSC_VER) +# define BOOST_ALIGNMENT(x) __declspec(align(x)) +# elif defined(__GNUC__) +# define BOOST_ALIGNMENT(x) __attribute__ ((__aligned__(x))) +# else +# define BOOST_NO_ALIGNMENT +# define BOOST_ALIGNMENT(x) +# endif +#endif + +// Lack of non-public defaulted functions is implied by the lack of any defaulted functions +#if !defined(BOOST_NO_CXX11_NON_PUBLIC_DEFAULTED_FUNCTIONS) && defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS) +# define BOOST_NO_CXX11_NON_PUBLIC_DEFAULTED_FUNCTIONS +#endif + +// Lack of defaulted moves is implied by the lack of either rvalue references or any defaulted functions +#if !defined(BOOST_NO_CXX11_DEFAULTED_MOVES) && (defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS) || defined(BOOST_NO_CXX11_RVALUE_REFERENCES)) +# define BOOST_NO_CXX11_DEFAULTED_MOVES +#endif + +// Defaulted and deleted function declaration helpers +// These macros are intended to be inside a class definition. +// BOOST_DEFAULTED_FUNCTION accepts the function declaration and its +// body, which will be used if the compiler doesn't support defaulted functions. +// BOOST_DELETED_FUNCTION only accepts the function declaration. It +// will expand to a private function declaration, if the compiler doesn't support +// deleted functions. Because of this it is recommended to use BOOST_DELETED_FUNCTION +// in the end of the class definition. +// +// class my_class +// { +// public: +// // Default-constructible +// BOOST_DEFAULTED_FUNCTION(my_class(), {}) +// // Copying prohibited +// BOOST_DELETED_FUNCTION(my_class(my_class const&)) +// BOOST_DELETED_FUNCTION(my_class& operator= (my_class const&)) +// }; +// +#if !(defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS) || defined(BOOST_NO_CXX11_NON_PUBLIC_DEFAULTED_FUNCTIONS)) +# define BOOST_DEFAULTED_FUNCTION(fun, body) fun = default; +#else +# define BOOST_DEFAULTED_FUNCTION(fun, body) fun body +#endif + +#if !defined(BOOST_NO_CXX11_DELETED_FUNCTIONS) +# define BOOST_DELETED_FUNCTION(fun) fun = delete; +#else +# define BOOST_DELETED_FUNCTION(fun) private: fun; +#endif + +// +// Set BOOST_NO_DECLTYPE_N3276 when BOOST_NO_DECLTYPE is defined +// +#if defined(BOOST_NO_CXX11_DECLTYPE) && !defined(BOOST_NO_CXX11_DECLTYPE_N3276) +#define BOOST_NO_CXX11_DECLTYPE_N3276 BOOST_NO_CXX11_DECLTYPE +#endif + +// -------------------- Deprecated macros for 1.50 --------------------------- +// These will go away in a future release + +// Use BOOST_NO_CXX11_HDR_UNORDERED_SET or BOOST_NO_CXX11_HDR_UNORDERED_MAP +// instead of BOOST_NO_STD_UNORDERED +#if defined(BOOST_NO_CXX11_HDR_UNORDERED_MAP) || defined (BOOST_NO_CXX11_HDR_UNORDERED_SET) +# ifndef BOOST_NO_CXX11_STD_UNORDERED +# define BOOST_NO_CXX11_STD_UNORDERED +# endif +#endif + +// Use BOOST_NO_CXX11_HDR_INITIALIZER_LIST instead of BOOST_NO_INITIALIZER_LISTS +#if defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) && !defined(BOOST_NO_INITIALIZER_LISTS) +# define BOOST_NO_INITIALIZER_LISTS +#endif + +// Use BOOST_NO_CXX11_HDR_ARRAY instead of BOOST_NO_0X_HDR_ARRAY +#if defined(BOOST_NO_CXX11_HDR_ARRAY) && !defined(BOOST_NO_0X_HDR_ARRAY) +# define BOOST_NO_0X_HDR_ARRAY +#endif +// Use BOOST_NO_CXX11_HDR_CHRONO instead of BOOST_NO_0X_HDR_CHRONO +#if defined(BOOST_NO_CXX11_HDR_CHRONO) && !defined(BOOST_NO_0X_HDR_CHRONO) +# define BOOST_NO_0X_HDR_CHRONO +#endif +// Use BOOST_NO_CXX11_HDR_CODECVT instead of BOOST_NO_0X_HDR_CODECVT +#if defined(BOOST_NO_CXX11_HDR_CODECVT) && !defined(BOOST_NO_0X_HDR_CODECVT) +# define BOOST_NO_0X_HDR_CODECVT +#endif +// Use BOOST_NO_CXX11_HDR_CONDITION_VARIABLE instead of BOOST_NO_0X_HDR_CONDITION_VARIABLE +#if defined(BOOST_NO_CXX11_HDR_CONDITION_VARIABLE) && !defined(BOOST_NO_0X_HDR_CONDITION_VARIABLE) +# define BOOST_NO_0X_HDR_CONDITION_VARIABLE +#endif +// Use BOOST_NO_CXX11_HDR_FORWARD_LIST instead of BOOST_NO_0X_HDR_FORWARD_LIST +#if defined(BOOST_NO_CXX11_HDR_FORWARD_LIST) && !defined(BOOST_NO_0X_HDR_FORWARD_LIST) +# define BOOST_NO_0X_HDR_FORWARD_LIST +#endif +// Use BOOST_NO_CXX11_HDR_FUTURE instead of BOOST_NO_0X_HDR_FUTURE +#if defined(BOOST_NO_CXX11_HDR_FUTURE) && !defined(BOOST_NO_0X_HDR_FUTURE) +# define BOOST_NO_0X_HDR_FUTURE +#endif + +// Use BOOST_NO_CXX11_HDR_INITIALIZER_LIST +// instead of BOOST_NO_0X_HDR_INITIALIZER_LIST or BOOST_NO_INITIALIZER_LISTS +#ifdef BOOST_NO_CXX11_HDR_INITIALIZER_LIST +# ifndef BOOST_NO_0X_HDR_INITIALIZER_LIST +# define BOOST_NO_0X_HDR_INITIALIZER_LIST +# endif +# ifndef BOOST_NO_INITIALIZER_LISTS +# define BOOST_NO_INITIALIZER_LISTS +# endif +#endif + +// Use BOOST_NO_CXX11_HDR_MUTEX instead of BOOST_NO_0X_HDR_MUTEX +#if defined(BOOST_NO_CXX11_HDR_MUTEX) && !defined(BOOST_NO_0X_HDR_MUTEX) +# define BOOST_NO_0X_HDR_MUTEX +#endif +// Use BOOST_NO_CXX11_HDR_RANDOM instead of BOOST_NO_0X_HDR_RANDOM +#if defined(BOOST_NO_CXX11_HDR_RANDOM) && !defined(BOOST_NO_0X_HDR_RANDOM) +# define BOOST_NO_0X_HDR_RANDOM +#endif +// Use BOOST_NO_CXX11_HDR_RATIO instead of BOOST_NO_0X_HDR_RATIO +#if defined(BOOST_NO_CXX11_HDR_RATIO) && !defined(BOOST_NO_0X_HDR_RATIO) +# define BOOST_NO_0X_HDR_RATIO +#endif +// Use BOOST_NO_CXX11_HDR_REGEX instead of BOOST_NO_0X_HDR_REGEX +#if defined(BOOST_NO_CXX11_HDR_REGEX) && !defined(BOOST_NO_0X_HDR_REGEX) +# define BOOST_NO_0X_HDR_REGEX +#endif +// Use BOOST_NO_CXX11_HDR_SYSTEM_ERROR instead of BOOST_NO_0X_HDR_SYSTEM_ERROR +#if defined(BOOST_NO_CXX11_HDR_SYSTEM_ERROR) && !defined(BOOST_NO_0X_HDR_SYSTEM_ERROR) +# define BOOST_NO_0X_HDR_SYSTEM_ERROR +#endif +// Use BOOST_NO_CXX11_HDR_THREAD instead of BOOST_NO_0X_HDR_THREAD +#if defined(BOOST_NO_CXX11_HDR_THREAD) && !defined(BOOST_NO_0X_HDR_THREAD) +# define BOOST_NO_0X_HDR_THREAD +#endif +// Use BOOST_NO_CXX11_HDR_TUPLE instead of BOOST_NO_0X_HDR_TUPLE +#if defined(BOOST_NO_CXX11_HDR_TUPLE) && !defined(BOOST_NO_0X_HDR_TUPLE) +# define BOOST_NO_0X_HDR_TUPLE +#endif +// Use BOOST_NO_CXX11_HDR_TYPE_TRAITS instead of BOOST_NO_0X_HDR_TYPE_TRAITS +#if defined(BOOST_NO_CXX11_HDR_TYPE_TRAITS) && !defined(BOOST_NO_0X_HDR_TYPE_TRAITS) +# define BOOST_NO_0X_HDR_TYPE_TRAITS +#endif +// Use BOOST_NO_CXX11_HDR_TYPEINDEX instead of BOOST_NO_0X_HDR_TYPEINDEX +#if defined(BOOST_NO_CXX11_HDR_TYPEINDEX) && !defined(BOOST_NO_0X_HDR_TYPEINDEX) +# define BOOST_NO_0X_HDR_TYPEINDEX +#endif +// Use BOOST_NO_CXX11_HDR_UNORDERED_MAP instead of BOOST_NO_0X_HDR_UNORDERED_MAP +#if defined(BOOST_NO_CXX11_HDR_UNORDERED_MAP) && !defined(BOOST_NO_0X_HDR_UNORDERED_MAP) +# define BOOST_NO_0X_HDR_UNORDERED_MAP +#endif +// Use BOOST_NO_CXX11_HDR_UNORDERED_SET instead of BOOST_NO_0X_HDR_UNORDERED_SET +#if defined(BOOST_NO_CXX11_HDR_UNORDERED_SET) && !defined(BOOST_NO_0X_HDR_UNORDERED_SET) +# define BOOST_NO_0X_HDR_UNORDERED_SET +#endif + +// ------------------ End of deprecated macros for 1.50 --------------------------- + +// -------------------- Deprecated macros for 1.51 --------------------------- +// These will go away in a future release + +// Use BOOST_NO_CXX11_AUTO_DECLARATIONS instead of BOOST_NO_AUTO_DECLARATIONS +#if defined(BOOST_NO_CXX11_AUTO_DECLARATIONS) && !defined(BOOST_NO_AUTO_DECLARATIONS) +# define BOOST_NO_AUTO_DECLARATIONS +#endif +// Use BOOST_NO_CXX11_AUTO_MULTIDECLARATIONS instead of BOOST_NO_AUTO_MULTIDECLARATIONS +#if defined(BOOST_NO_CXX11_AUTO_MULTIDECLARATIONS) && !defined(BOOST_NO_AUTO_MULTIDECLARATIONS) +# define BOOST_NO_AUTO_MULTIDECLARATIONS +#endif +// Use BOOST_NO_CXX11_CHAR16_T instead of BOOST_NO_CHAR16_T +#if defined(BOOST_NO_CXX11_CHAR16_T) && !defined(BOOST_NO_CHAR16_T) +# define BOOST_NO_CHAR16_T +#endif +// Use BOOST_NO_CXX11_CHAR32_T instead of BOOST_NO_CHAR32_T +#if defined(BOOST_NO_CXX11_CHAR32_T) && !defined(BOOST_NO_CHAR32_T) +# define BOOST_NO_CHAR32_T +#endif +// Use BOOST_NO_CXX11_TEMPLATE_ALIASES instead of BOOST_NO_TEMPLATE_ALIASES +#if defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) && !defined(BOOST_NO_TEMPLATE_ALIASES) +# define BOOST_NO_TEMPLATE_ALIASES +#endif +// Use BOOST_NO_CXX11_CONSTEXPR instead of BOOST_NO_CONSTEXPR +#if defined(BOOST_NO_CXX11_CONSTEXPR) && !defined(BOOST_NO_CONSTEXPR) +# define BOOST_NO_CONSTEXPR +#endif +// Use BOOST_NO_CXX11_DECLTYPE_N3276 instead of BOOST_NO_DECLTYPE_N3276 +#if defined(BOOST_NO_CXX11_DECLTYPE_N3276) && !defined(BOOST_NO_DECLTYPE_N3276) +# define BOOST_NO_DECLTYPE_N3276 +#endif +// Use BOOST_NO_CXX11_DECLTYPE instead of BOOST_NO_DECLTYPE +#if defined(BOOST_NO_CXX11_DECLTYPE) && !defined(BOOST_NO_DECLTYPE) +# define BOOST_NO_DECLTYPE +#endif +// Use BOOST_NO_CXX11_DEFAULTED_FUNCTIONS instead of BOOST_NO_DEFAULTED_FUNCTIONS +#if defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS) && !defined(BOOST_NO_DEFAULTED_FUNCTIONS) +# define BOOST_NO_DEFAULTED_FUNCTIONS +#endif +// Use BOOST_NO_CXX11_DELETED_FUNCTIONS instead of BOOST_NO_DELETED_FUNCTIONS +#if defined(BOOST_NO_CXX11_DELETED_FUNCTIONS) && !defined(BOOST_NO_DELETED_FUNCTIONS) +# define BOOST_NO_DELETED_FUNCTIONS +#endif +// Use BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS instead of BOOST_NO_EXPLICIT_CONVERSION_OPERATORS +#if defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS) && !defined(BOOST_NO_EXPLICIT_CONVERSION_OPERATORS) +# define BOOST_NO_EXPLICIT_CONVERSION_OPERATORS +#endif +// Use BOOST_NO_CXX11_EXTERN_TEMPLATE instead of BOOST_NO_EXTERN_TEMPLATE +#if defined(BOOST_NO_CXX11_EXTERN_TEMPLATE) && !defined(BOOST_NO_EXTERN_TEMPLATE) +# define BOOST_NO_EXTERN_TEMPLATE +#endif +// Use BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS instead of BOOST_NO_FUNCTION_TEMPLATE_DEFAULT_ARGS +#if defined(BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS) && !defined(BOOST_NO_FUNCTION_TEMPLATE_DEFAULT_ARGS) +# define BOOST_NO_FUNCTION_TEMPLATE_DEFAULT_ARGS +#endif +// Use BOOST_NO_CXX11_LAMBDAS instead of BOOST_NO_LAMBDAS +#if defined(BOOST_NO_CXX11_LAMBDAS) && !defined(BOOST_NO_LAMBDAS) +# define BOOST_NO_LAMBDAS +#endif +// Use BOOST_NO_CXX11_LOCAL_CLASS_TEMPLATE_PARAMETERS instead of BOOST_NO_LOCAL_CLASS_TEMPLATE_PARAMETERS +#if defined(BOOST_NO_CXX11_LOCAL_CLASS_TEMPLATE_PARAMETERS) && !defined(BOOST_NO_LOCAL_CLASS_TEMPLATE_PARAMETERS) +# define BOOST_NO_LOCAL_CLASS_TEMPLATE_PARAMETERS +#endif +// Use BOOST_NO_CXX11_NOEXCEPT instead of BOOST_NO_NOEXCEPT +#if defined(BOOST_NO_CXX11_NOEXCEPT) && !defined(BOOST_NO_NOEXCEPT) +# define BOOST_NO_NOEXCEPT +#endif +// Use BOOST_NO_CXX11_NULLPTR instead of BOOST_NO_NULLPTR +#if defined(BOOST_NO_CXX11_NULLPTR) && !defined(BOOST_NO_NULLPTR) +# define BOOST_NO_NULLPTR +#endif +// Use BOOST_NO_CXX11_RAW_LITERALS instead of BOOST_NO_RAW_LITERALS +#if defined(BOOST_NO_CXX11_RAW_LITERALS) && !defined(BOOST_NO_RAW_LITERALS) +# define BOOST_NO_RAW_LITERALS +#endif +// Use BOOST_NO_CXX11_RVALUE_REFERENCES instead of BOOST_NO_RVALUE_REFERENCES +#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_NO_RVALUE_REFERENCES) +# define BOOST_NO_RVALUE_REFERENCES +#endif +// Use BOOST_NO_CXX11_SCOPED_ENUMS instead of BOOST_NO_SCOPED_ENUMS +#if defined(BOOST_NO_CXX11_SCOPED_ENUMS) && !defined(BOOST_NO_SCOPED_ENUMS) +# define BOOST_NO_SCOPED_ENUMS +#endif +// Use BOOST_NO_CXX11_STATIC_ASSERT instead of BOOST_NO_STATIC_ASSERT +#if defined(BOOST_NO_CXX11_STATIC_ASSERT) && !defined(BOOST_NO_STATIC_ASSERT) +# define BOOST_NO_STATIC_ASSERT +#endif +// Use BOOST_NO_CXX11_STD_UNORDERED instead of BOOST_NO_STD_UNORDERED +#if defined(BOOST_NO_CXX11_STD_UNORDERED) && !defined(BOOST_NO_STD_UNORDERED) +# define BOOST_NO_STD_UNORDERED +#endif +// Use BOOST_NO_CXX11_UNICODE_LITERALS instead of BOOST_NO_UNICODE_LITERALS +#if defined(BOOST_NO_CXX11_UNICODE_LITERALS) && !defined(BOOST_NO_UNICODE_LITERALS) +# define BOOST_NO_UNICODE_LITERALS +#endif +// Use BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX instead of BOOST_NO_UNIFIED_INITIALIZATION_SYNTAX +#if defined(BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX) && !defined(BOOST_NO_UNIFIED_INITIALIZATION_SYNTAX) +# define BOOST_NO_UNIFIED_INITIALIZATION_SYNTAX +#endif +// Use BOOST_NO_CXX11_VARIADIC_TEMPLATES instead of BOOST_NO_VARIADIC_TEMPLATES +#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_NO_VARIADIC_TEMPLATES) +# define BOOST_NO_VARIADIC_TEMPLATES +#endif +// Use BOOST_NO_CXX11_VARIADIC_MACROS instead of BOOST_NO_VARIADIC_MACROS +#if defined(BOOST_NO_CXX11_VARIADIC_MACROS) && !defined(BOOST_NO_VARIADIC_MACROS) +# define BOOST_NO_VARIADIC_MACROS +#endif +// Use BOOST_NO_CXX11_NUMERIC_LIMITS instead of BOOST_NO_NUMERIC_LIMITS_LOWEST +#if defined(BOOST_NO_CXX11_NUMERIC_LIMITS) && !defined(BOOST_NO_NUMERIC_LIMITS_LOWEST) +# define BOOST_NO_NUMERIC_LIMITS_LOWEST +#endif +// ------------------ End of deprecated macros for 1.51 --------------------------- + + +// +// Helper macro for marking types and methods final +// +#if !defined(BOOST_NO_CXX11_FINAL) +# define BOOST_FINAL final +#else +# define BOOST_FINAL +#endif + +// +// Helper macros BOOST_NOEXCEPT, BOOST_NOEXCEPT_IF, BOOST_NOEXCEPT_EXPR +// These aid the transition to C++11 while still supporting C++03 compilers +// +#ifdef BOOST_NO_CXX11_NOEXCEPT +# define BOOST_NOEXCEPT +# define BOOST_NOEXCEPT_OR_NOTHROW throw() +# define BOOST_NOEXCEPT_IF(Predicate) +# define BOOST_NOEXCEPT_EXPR(Expression) false +#else +# define BOOST_NOEXCEPT noexcept +# define BOOST_NOEXCEPT_OR_NOTHROW noexcept +# define BOOST_NOEXCEPT_IF(Predicate) noexcept((Predicate)) +# define BOOST_NOEXCEPT_EXPR(Expression) noexcept((Expression)) +#endif +// +// Helper macro BOOST_FALLTHROUGH +// Fallback definition of BOOST_FALLTHROUGH macro used to mark intended +// fall-through between case labels in a switch statement. We use a definition +// that requires a semicolon after it to avoid at least one type of misuse even +// on unsupported compilers. +// +#ifndef BOOST_FALLTHROUGH +# define BOOST_FALLTHROUGH ((void)0) +#endif + +// +// constexpr workarounds +// +#if defined(BOOST_NO_CXX11_CONSTEXPR) +#define BOOST_CONSTEXPR +#define BOOST_CONSTEXPR_OR_CONST const +#else +#define BOOST_CONSTEXPR constexpr +#define BOOST_CONSTEXPR_OR_CONST constexpr +#endif +#if defined(BOOST_NO_CXX14_CONSTEXPR) +#define BOOST_CXX14_CONSTEXPR +#else +#define BOOST_CXX14_CONSTEXPR constexpr +#endif +#if !defined(BOOST_NO_CXX17_STRUCTURED_BINDINGS) && defined(BOOST_NO_CXX11_HDR_TUPLE) +# define BOOST_NO_CXX17_STRUCTURED_BINDINGS +#endif + +// +// C++17 inline variables +// +#if !defined(BOOST_NO_CXX17_INLINE_VARIABLES) +#define BOOST_INLINE_VARIABLE inline +#else +#define BOOST_INLINE_VARIABLE +#endif +// +// C++17 if constexpr +// +#if !defined(BOOST_NO_CXX17_IF_CONSTEXPR) +# define BOOST_IF_CONSTEXPR if constexpr +#else +# define BOOST_IF_CONSTEXPR if +#endif + +#define BOOST_INLINE_CONSTEXPR BOOST_INLINE_VARIABLE BOOST_CONSTEXPR_OR_CONST + +// +// Unused variable/typedef workarounds: +// +#ifndef BOOST_ATTRIBUTE_UNUSED +# if defined(__has_attribute) && defined(__SUNPRO_CC) && (__SUNPRO_CC > 0x5130) +# if __has_attribute(maybe_unused) +# define BOOST_ATTRIBUTE_UNUSED [[maybe_unused]] +# endif +# elif defined(__has_cpp_attribute) +# if __has_cpp_attribute(maybe_unused) +# define BOOST_ATTRIBUTE_UNUSED [[maybe_unused]] +# endif +# endif +#endif + +#ifndef BOOST_ATTRIBUTE_UNUSED +# define BOOST_ATTRIBUTE_UNUSED +#endif + +// +// [[nodiscard]]: +// +#if defined(__has_attribute) && defined(__SUNPRO_CC) && (__SUNPRO_CC > 0x5130) +#if __has_attribute(nodiscard) +# define BOOST_ATTRIBUTE_NODISCARD [[nodiscard]] +#endif +#if __has_attribute(no_unique_address) +# define BOOST_ATTRIBUTE_NO_UNIQUE_ADDRESS [[no_unique_address]] +#endif +#elif defined(__has_cpp_attribute) +// clang-6 accepts [[nodiscard]] with -std=c++14, but warns about it -pedantic +#if __has_cpp_attribute(nodiscard) && !(defined(__clang__) && (__cplusplus < 201703L)) && !(defined(__GNUC__) && (__cplusplus < 201100)) +# define BOOST_ATTRIBUTE_NODISCARD [[nodiscard]] +#endif +#if __has_cpp_attribute(no_unique_address) && !(defined(__GNUC__) && (__cplusplus < 201100)) +# define BOOST_ATTRIBUTE_NO_UNIQUE_ADDRESS [[no_unique_address]] +#endif +#endif +#ifndef BOOST_ATTRIBUTE_NODISCARD +# define BOOST_ATTRIBUTE_NODISCARD +#endif +#ifndef BOOST_ATTRIBUTE_NO_UNIQUE_ADDRESS +# define BOOST_ATTRIBUTE_NO_UNIQUE_ADDRESS +#endif + +#define BOOST_STATIC_CONSTEXPR static BOOST_CONSTEXPR_OR_CONST + +#if !defined(BOOST_NO_CXX11_NULLPTR) +# define BOOST_NULLPTR nullptr +#else +# define BOOST_NULLPTR 0 +#endif + +// +// Set BOOST_HAS_STATIC_ASSERT when BOOST_NO_CXX11_STATIC_ASSERT is not defined +// +#if !defined(BOOST_NO_CXX11_STATIC_ASSERT) && !defined(BOOST_HAS_STATIC_ASSERT) +# define BOOST_HAS_STATIC_ASSERT +#endif + +// +// Set BOOST_HAS_RVALUE_REFS when BOOST_NO_CXX11_RVALUE_REFERENCES is not defined +// +#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_HAS_RVALUE_REFS) +#define BOOST_HAS_RVALUE_REFS +#endif + +// +// Set BOOST_HAS_VARIADIC_TMPL when BOOST_NO_CXX11_VARIADIC_TEMPLATES is not defined +// +#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_HAS_VARIADIC_TMPL) +#define BOOST_HAS_VARIADIC_TMPL +#endif +// +// Set BOOST_NO_CXX11_FIXED_LENGTH_VARIADIC_TEMPLATE_EXPANSION_PACKS when +// BOOST_NO_CXX11_VARIADIC_TEMPLATES is set: +// +#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_FIXED_LENGTH_VARIADIC_TEMPLATE_EXPANSION_PACKS) +# define BOOST_NO_CXX11_FIXED_LENGTH_VARIADIC_TEMPLATE_EXPANSION_PACKS +#endif + +// This is a catch all case for obsolete compilers / std libs: +#if !defined(_YVALS) && !defined(_CPPLIB_VER) // msvc std lib already configured +#if (!defined(__has_include) || (__cplusplus < 201700)) +# define BOOST_NO_CXX17_HDR_OPTIONAL +# define BOOST_NO_CXX17_HDR_STRING_VIEW +# define BOOST_NO_CXX17_HDR_VARIANT +# define BOOST_NO_CXX17_HDR_ANY +# define BOOST_NO_CXX17_HDR_MEMORY_RESOURCE +# define BOOST_NO_CXX17_HDR_CHARCONV +# define BOOST_NO_CXX17_HDR_EXECUTION +# define BOOST_NO_CXX17_HDR_FILESYSTEM +#else +#if !__has_include() +# define BOOST_NO_CXX17_HDR_OPTIONAL +#endif +#if !__has_include() +# define BOOST_NO_CXX17_HDR_STRING_VIEW +#endif +#if !__has_include() +# define BOOST_NO_CXX17_HDR_VARIANT +#endif +#if !__has_include() +# define BOOST_NO_CXX17_HDR_ANY +#endif +#if !__has_include() +# define BOOST_NO_CXX17_HDR_MEMORY_RESOURCE +#endif +#if !__has_include() +# define BOOST_NO_CXX17_HDR_CHARCONV +#endif +#if !__has_include() +# define BOOST_NO_CXX17_HDR_EXECUTION +#endif +#if !__has_include() +# define BOOST_NO_CXX17_HDR_FILESYSTEM +#endif +#endif +#endif +// +// Define the std level that the compiler claims to support: +// +#ifndef BOOST_CXX_VERSION +# define BOOST_CXX_VERSION __cplusplus +#endif + +#if (!defined(__has_include) || (BOOST_CXX_VERSION < 201704)) +# define BOOST_NO_CXX20_HDR_BARRIER +# define BOOST_NO_CXX20_HDR_FORMAT +# define BOOST_NO_CXX20_HDR_SOURCE_LOCATION +# define BOOST_NO_CXX20_HDR_BIT +# define BOOST_NO_CXX20_HDR_LATCH +# define BOOST_NO_CXX20_HDR_SPAN +# define BOOST_NO_CXX20_HDR_COMPARE +# define BOOST_NO_CXX20_HDR_NUMBERS +# define BOOST_NO_CXX20_HDR_STOP_TOKEN +# define BOOST_NO_CXX20_HDR_CONCEPTS +# define BOOST_NO_CXX20_HDR_RANGES +# define BOOST_NO_CXX20_HDR_SYNCSTREAM +# define BOOST_NO_CXX20_HDR_COROUTINE +# define BOOST_NO_CXX20_HDR_SEMAPHORE +#else +#if (!__has_include() || !defined(__cpp_lib_barrier) || (__cpp_lib_barrier < 201907L)) && !defined(BOOST_NO_CXX20_HDR_BARRIER) +# define BOOST_NO_CXX20_HDR_BARRIER +#endif +#if (!__has_include() || !defined(__cpp_lib_format) || (__cpp_lib_format < 201907L)) && !defined(BOOST_NO_CXX20_HDR_FORMAT) +# define BOOST_NO_CXX20_HDR_FORMAT +#endif +#if (!__has_include() || !defined(__cpp_lib_source_location) || (__cpp_lib_source_location < 201907L)) && !defined(BOOST_NO_CXX20_HDR_SOURCE_LOCATION) +# define BOOST_NO_CXX20_HDR_SOURCE_LOCATION +#endif +#if (!__has_include() || !defined(__cpp_lib_bit_cast) || (__cpp_lib_bit_cast < 201806L) || !defined(__cpp_lib_bitops) || (__cpp_lib_bitops < 201907L) || !defined(__cpp_lib_endian) || (__cpp_lib_endian < 201907L)) && !defined(BOOST_NO_CXX20_HDR_BIT) +# define BOOST_NO_CXX20_HDR_BIT +#endif +#if (!__has_include() || !defined(__cpp_lib_latch) || (__cpp_lib_latch < 201907L)) && !defined(BOOST_NO_CXX20_HDR_LATCH) +# define BOOST_NO_CXX20_HDR_LATCH +#endif +#if (!__has_include() || !defined(__cpp_lib_span) || (__cpp_lib_span < 202002L)) && !defined(BOOST_NO_CXX20_HDR_SPAN) +# define BOOST_NO_CXX20_HDR_SPAN +#endif +#if (!__has_include() || !defined(__cpp_lib_three_way_comparison) || (__cpp_lib_three_way_comparison < 201907L)) && !defined(BOOST_NO_CXX20_HDR_COMPARE) +# define BOOST_NO_CXX20_HDR_COMPARE +#endif +#if (!__has_include() || !defined(__cpp_lib_math_constants) || (__cpp_lib_math_constants < 201907L)) && !defined(BOOST_NO_CXX20_HDR_NUMBERS) +# define BOOST_NO_CXX20_HDR_NUMBERS +#endif +#if (!__has_include() || !defined(__cpp_lib_jthread) || (__cpp_lib_jthread < 201911L)) && !defined(BOOST_NO_CXX20_HDR_STOP_TOKEN) +# define BOOST_NO_CXX20_HDR_STOP_TOKEN +#endif +#if (!__has_include() || !defined(__cpp_lib_concepts) || (__cpp_lib_concepts < 202002L)) && !defined(_YVALS) && !defined(_CPPLIB_VER) && !defined(BOOST_NO_CXX20_HDR_CONCEPTS) +# define BOOST_NO_CXX20_HDR_CONCEPTS +#endif +#if (!__has_include() || !defined(__cpp_lib_ranges) || (__cpp_lib_ranges < 201911L)) && !defined(BOOST_NO_CXX20_HDR_RANGES) +# define BOOST_NO_CXX20_HDR_RANGES +#endif +#if (!__has_include() || !defined(__cpp_lib_syncbuf) || (__cpp_lib_syncbuf < 201803L)) && !defined(BOOST_NO_CXX20_HDR_SYNCSTREAM) +# define BOOST_NO_CXX20_HDR_SYNCSTREAM +#endif +#if (!__has_include() || !defined(__cpp_lib_coroutine) || (__cpp_lib_coroutine < 201902L)) && !defined(BOOST_NO_CXX20_HDR_COROUTINE) +# define BOOST_NO_CXX20_HDR_COROUTINE +#endif +#if (!__has_include() || !defined(__cpp_lib_semaphore) || (__cpp_lib_semaphore < 201907L)) && !defined(BOOST_NO_CXX20_HDR_SEMAPHORE) +# define BOOST_NO_CXX20_HDR_SEMAPHORE +#endif +#endif + +#if (!defined(__has_include) || (BOOST_CXX_VERSION < 202003L)) +# define BOOST_NO_CXX23_HDR_EXPECTED +# define BOOST_NO_CXX23_HDR_FLAT_MAP +# define BOOST_NO_CXX23_HDR_FLAT_SET +# define BOOST_NO_CXX23_HDR_GENERATOR +# define BOOST_NO_CXX23_HDR_MDSPAN +# define BOOST_NO_CXX23_HDR_PRINT +# define BOOST_NO_CXX23_HDR_SPANSTREAM +# define BOOST_NO_CXX23_HDR_STACKTRACE +# define BOOST_NO_CXX23_HDR_STDFLOAT +#else +#if (!__has_include() || !defined(__cpp_lib_expected) || (__cpp_lib_expected < 202211L)) && !defined(BOOST_NO_CXX23_HDR_EXPECTED) +# define BOOST_NO_CXX23_HDR_EXPECTED +#endif +#if (!__has_include() || !defined(__cpp_lib_flat_map) || (__cpp_lib_flat_map < 202207L)) && !defined(BOOST_NO_CXX23_HDR_FLAT_MAP) +# define BOOST_NO_CXX23_HDR_FLAT_MAP +#endif +#if (!__has_include() || !defined(__cpp_lib_flat_set) || (__cpp_lib_flat_set < 202207L)) && !defined(BOOST_NO_CXX23_HDR_FLAT_SET) +# define BOOST_NO_CXX23_HDR_FLAT_SET +#endif +#if (!__has_include() || !defined(__cpp_lib_generator) || (__cpp_lib_generator < 202207L)) && !defined(BOOST_NO_CXX23_HDR_GENERATOR) +# define BOOST_NO_CXX23_HDR_GENERATOR +#endif +#if (!__has_include() || !defined(__cpp_lib_mdspan) || (__cpp_lib_mdspan < 202207L)) && !defined(BOOST_NO_CXX23_HDR_MDSPAN) +# define BOOST_NO_CXX23_HDR_MDSPAN +#endif +#if (!__has_include() || !defined(__cpp_lib_print) || (__cpp_lib_print < 202207L)) && !defined(BOOST_NO_CXX23_HDR_PRINT) +# define BOOST_NO_CXX23_HDR_PRINT +#endif +#if (!__has_include() || !defined(__cpp_lib_spanstream) || (__cpp_lib_spanstream < 202106L)) && !defined(BOOST_NO_CXX23_HDR_SPANSTREAM) +# define BOOST_NO_CXX23_HDR_SPANSTREAM +#endif +#if (!__has_include() || !defined(__cpp_lib_stacktrace) || (__cpp_lib_stacktrace < 202011L)) && !defined(BOOST_NO_CXX23_HDR_STACKTRACE) +# define BOOST_NO_CXX23_HDR_STACKTRACE +#endif +#if !__has_include() && !defined(BOOST_NO_CXX23_HDR_STDFLOAT) +# define BOOST_NO_CXX23_HDR_STDFLOAT +#endif +#endif + +#if defined(__cplusplus) && defined(__has_include) +#if !__has_include() +# define BOOST_NO_CXX20_HDR_VERSION +#else +// For convenience, this is always included: +# include +#endif +#else +# define BOOST_NO_CXX20_HDR_VERSION +#endif + +#if defined(BOOST_MSVC) +#if (BOOST_MSVC < 1914) || (_MSVC_LANG < 201703) +# define BOOST_NO_CXX17_DEDUCTION_GUIDES +#endif +#elif !defined(__cpp_deduction_guides) || (__cpp_deduction_guides < 201606) +# define BOOST_NO_CXX17_DEDUCTION_GUIDES +#endif + +// +// Define composite agregate macros: +// +#include + +// +// Finish off with checks for macros that are depricated / no longer supported, +// if any of these are set then it's very likely that much of Boost will no +// longer work. So stop with a #error for now, but give the user a chance +// to continue at their own risk if they really want to: +// +#if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(BOOST_CONFIG_ALLOW_DEPRECATED) +# error "You are using a compiler which lacks features which are now a minimum requirement in order to use Boost, define BOOST_CONFIG_ALLOW_DEPRECATED if you want to continue at your own risk!!!" +#endif + +#endif diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/header_deprecated.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/header_deprecated.hpp new file mode 100644 index 0000000..120b4b3 --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/header_deprecated.hpp @@ -0,0 +1,26 @@ +#ifndef BOOST_CONFIG_HEADER_DEPRECATED_HPP_INCLUDED +#define BOOST_CONFIG_HEADER_DEPRECATED_HPP_INCLUDED + +// Copyright 2017 Peter Dimov. +// +// Distributed under the Boost Software License, Version 1.0. +// +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt +// +// BOOST_HEADER_DEPRECATED("") +// +// Expands to the equivalent of +// BOOST_PRAGMA_MESSAGE("This header is deprecated. Use instead.") +// +// Note that this header is C compatible. + +#include + +#if defined(BOOST_ALLOW_DEPRECATED_HEADERS) || defined(BOOST_ALLOW_DEPRECATED) +# define BOOST_HEADER_DEPRECATED(a) +#else +# define BOOST_HEADER_DEPRECATED(a) BOOST_PRAGMA_MESSAGE("This header is deprecated. Use " a " instead.") +#endif + +#endif // BOOST_CONFIG_HEADER_DEPRECATED_HPP_INCLUDED diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/helper_macros.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/helper_macros.hpp new file mode 100644 index 0000000..3e79526 --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/helper_macros.hpp @@ -0,0 +1,37 @@ +#ifndef BOOST_CONFIG_HELPER_MACROS_HPP_INCLUDED +#define BOOST_CONFIG_HELPER_MACROS_HPP_INCLUDED + +// Copyright 2001 John Maddock. +// Copyright 2017 Peter Dimov. +// +// Distributed under the Boost Software License, Version 1.0. +// +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt +// +// BOOST_STRINGIZE(X) +// BOOST_JOIN(X, Y) +// +// Note that this header is C compatible. + +// +// Helper macro BOOST_STRINGIZE: +// Converts the parameter X to a string after macro replacement +// on X has been performed. +// +#define BOOST_STRINGIZE(X) BOOST_DO_STRINGIZE(X) +#define BOOST_DO_STRINGIZE(X) #X + +// +// Helper macro BOOST_JOIN: +// The following piece of macro magic joins the two +// arguments together, even when one of the arguments is +// itself a macro (see 16.3.1 in C++ standard). The key +// is that macro expansion of macro arguments does not +// occur in BOOST_DO_JOIN2 but does in BOOST_DO_JOIN. +// +#define BOOST_JOIN(X, Y) BOOST_DO_JOIN(X, Y) +#define BOOST_DO_JOIN(X, Y) BOOST_DO_JOIN2(X,Y) +#define BOOST_DO_JOIN2(X, Y) X##Y + +#endif // BOOST_CONFIG_HELPER_MACROS_HPP_INCLUDED diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/no_tr1/cmath.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/no_tr1/cmath.hpp new file mode 100644 index 0000000..d8268d8 --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/no_tr1/cmath.hpp @@ -0,0 +1,28 @@ +// (C) Copyright John Maddock 2008. +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// The aim of this header is just to include but to do +// so in a way that does not result in recursive inclusion of +// the Boost TR1 components if boost/tr1/tr1/cmath is in the +// include search path. We have to do this to avoid circular +// dependencies: +// + +#ifndef BOOST_CONFIG_CMATH +# define BOOST_CONFIG_CMATH + +# ifndef BOOST_TR1_NO_RECURSION +# define BOOST_TR1_NO_RECURSION +# define BOOST_CONFIG_NO_CMATH_RECURSION +# endif + +# include + +# ifdef BOOST_CONFIG_NO_CMATH_RECURSION +# undef BOOST_TR1_NO_RECURSION +# undef BOOST_CONFIG_NO_CMATH_RECURSION +# endif + +#endif diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/no_tr1/complex.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/no_tr1/complex.hpp new file mode 100644 index 0000000..ca20092 --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/no_tr1/complex.hpp @@ -0,0 +1,28 @@ +// (C) Copyright John Maddock 2005. +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// The aim of this header is just to include but to do +// so in a way that does not result in recursive inclusion of +// the Boost TR1 components if boost/tr1/tr1/complex is in the +// include search path. We have to do this to avoid circular +// dependencies: +// + +#ifndef BOOST_CONFIG_COMPLEX +# define BOOST_CONFIG_COMPLEX + +# ifndef BOOST_TR1_NO_RECURSION +# define BOOST_TR1_NO_RECURSION +# define BOOST_CONFIG_NO_COMPLEX_RECURSION +# endif + +# include + +# ifdef BOOST_CONFIG_NO_COMPLEX_RECURSION +# undef BOOST_TR1_NO_RECURSION +# undef BOOST_CONFIG_NO_COMPLEX_RECURSION +# endif + +#endif diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/no_tr1/functional.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/no_tr1/functional.hpp new file mode 100644 index 0000000..e395efc --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/no_tr1/functional.hpp @@ -0,0 +1,28 @@ +// (C) Copyright John Maddock 2005. +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// The aim of this header is just to include but to do +// so in a way that does not result in recursive inclusion of +// the Boost TR1 components if boost/tr1/tr1/functional is in the +// include search path. We have to do this to avoid circular +// dependencies: +// + +#ifndef BOOST_CONFIG_FUNCTIONAL +# define BOOST_CONFIG_FUNCTIONAL + +# ifndef BOOST_TR1_NO_RECURSION +# define BOOST_TR1_NO_RECURSION +# define BOOST_CONFIG_NO_FUNCTIONAL_RECURSION +# endif + +# include + +# ifdef BOOST_CONFIG_NO_FUNCTIONAL_RECURSION +# undef BOOST_TR1_NO_RECURSION +# undef BOOST_CONFIG_NO_FUNCTIONAL_RECURSION +# endif + +#endif diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/no_tr1/memory.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/no_tr1/memory.hpp new file mode 100644 index 0000000..2b5d208 --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/no_tr1/memory.hpp @@ -0,0 +1,28 @@ +// (C) Copyright John Maddock 2005. +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// The aim of this header is just to include but to do +// so in a way that does not result in recursive inclusion of +// the Boost TR1 components if boost/tr1/tr1/memory is in the +// include search path. We have to do this to avoid circular +// dependencies: +// + +#ifndef BOOST_CONFIG_MEMORY +# define BOOST_CONFIG_MEMORY + +# ifndef BOOST_TR1_NO_RECURSION +# define BOOST_TR1_NO_RECURSION +# define BOOST_CONFIG_NO_MEMORY_RECURSION +# endif + +# include + +# ifdef BOOST_CONFIG_NO_MEMORY_RECURSION +# undef BOOST_TR1_NO_RECURSION +# undef BOOST_CONFIG_NO_MEMORY_RECURSION +# endif + +#endif diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/no_tr1/utility.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/no_tr1/utility.hpp new file mode 100644 index 0000000..dea8f11 --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/no_tr1/utility.hpp @@ -0,0 +1,28 @@ +// (C) Copyright John Maddock 2005. +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// The aim of this header is just to include but to do +// so in a way that does not result in recursive inclusion of +// the Boost TR1 components if boost/tr1/tr1/utility is in the +// include search path. We have to do this to avoid circular +// dependencies: +// + +#ifndef BOOST_CONFIG_UTILITY +# define BOOST_CONFIG_UTILITY + +# ifndef BOOST_TR1_NO_RECURSION +# define BOOST_TR1_NO_RECURSION +# define BOOST_CONFIG_NO_UTILITY_RECURSION +# endif + +# include + +# ifdef BOOST_CONFIG_NO_UTILITY_RECURSION +# undef BOOST_TR1_NO_RECURSION +# undef BOOST_CONFIG_NO_UTILITY_RECURSION +# endif + +#endif diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/platform/aix.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/platform/aix.hpp new file mode 100644 index 0000000..a48e232 --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/platform/aix.hpp @@ -0,0 +1,33 @@ +// (C) Copyright John Maddock 2001 - 2002. +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for most recent version. + +// IBM/Aix specific config options: + +#define BOOST_PLATFORM "IBM Aix" + +#define BOOST_HAS_UNISTD_H +#define BOOST_HAS_NL_TYPES_H +#define BOOST_HAS_NANOSLEEP +#define BOOST_HAS_CLOCK_GETTIME + +// This needs support in "boost/cstdint.hpp" exactly like FreeBSD. +// This platform has header named which includes all +// the things needed. +#define BOOST_HAS_STDINT_H + +// Threading API's: +#define BOOST_HAS_PTHREADS +#define BOOST_HAS_PTHREAD_DELAY_NP +#define BOOST_HAS_SCHED_YIELD +//#define BOOST_HAS_PTHREAD_YIELD + +// boilerplate code: +#include + + + + diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/platform/amigaos.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/platform/amigaos.hpp new file mode 100644 index 0000000..34bcf41 --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/platform/amigaos.hpp @@ -0,0 +1,15 @@ +// (C) Copyright John Maddock 2002. +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for most recent version. + +#define BOOST_PLATFORM "AmigaOS" + +#define BOOST_DISABLE_THREADS +#define BOOST_NO_CWCHAR +#define BOOST_NO_STD_WSTRING +#define BOOST_NO_INTRINSIC_WCHAR_T + + diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/platform/beos.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/platform/beos.hpp new file mode 100644 index 0000000..6158c1c --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/platform/beos.hpp @@ -0,0 +1,26 @@ +// (C) Copyright John Maddock 2001. +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for most recent version. + +// BeOS specific config options: + +#define BOOST_PLATFORM "BeOS" + +#define BOOST_NO_CWCHAR +#define BOOST_NO_CWCTYPE +#define BOOST_HAS_UNISTD_H + +#define BOOST_HAS_BETHREADS + +#ifndef BOOST_DISABLE_THREADS +# define BOOST_HAS_THREADS +#endif + +// boilerplate code: +#include + + + diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/platform/bsd.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/platform/bsd.hpp new file mode 100644 index 0000000..ccc7eb0 --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/platform/bsd.hpp @@ -0,0 +1,83 @@ +// (C) Copyright John Maddock 2001 - 2003. +// (C) Copyright Darin Adler 2001. +// (C) Copyright Douglas Gregor 2002. +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for most recent version. + +// generic BSD config options: + +#if !defined(__FreeBSD__) && !defined(__NetBSD__) && !defined(__OpenBSD__) && !defined(__DragonFly__) +#error "This platform is not BSD" +#endif + +#ifdef __FreeBSD__ +#define BOOST_PLATFORM "FreeBSD " BOOST_STRINGIZE(__FreeBSD__) +#elif defined(__NetBSD__) +#define BOOST_PLATFORM "NetBSD " BOOST_STRINGIZE(__NetBSD__) +#elif defined(__OpenBSD__) +#define BOOST_PLATFORM "OpenBSD " BOOST_STRINGIZE(__OpenBSD__) +#elif defined(__DragonFly__) +#define BOOST_PLATFORM "DragonFly " BOOST_STRINGIZE(__DragonFly__) +#endif + +// +// is this the correct version check? +// FreeBSD has but does not +// advertise the fact in : +// +#if (defined(__FreeBSD__) && (__FreeBSD__ >= 3)) \ + || defined(__OpenBSD__) || defined(__DragonFly__) +# define BOOST_HAS_NL_TYPES_H +#endif + +// +// FreeBSD 3.x has pthreads support, but defines _POSIX_THREADS in +// and not in +// +#if (defined(__FreeBSD__) && (__FreeBSD__ <= 3))\ + || defined(__OpenBSD__) || defined(__DragonFly__) +# define BOOST_HAS_PTHREADS +#endif + +// +// No wide character support in the BSD header files: +// +#if defined(__NetBSD__) +#define __NetBSD_GCC__ (__GNUC__ * 1000000 \ + + __GNUC_MINOR__ * 1000 \ + + __GNUC_PATCHLEVEL__) +// XXX - the following is required until c++config.h +// defines _GLIBCXX_HAVE_SWPRINTF and friends +// or the preprocessor conditionals are removed +// from the cwchar header. +#define _GLIBCXX_HAVE_SWPRINTF 1 +#endif + +#if !((defined(__FreeBSD__) && (__FreeBSD__ >= 5)) \ + || (defined(__NetBSD_GCC__) && (__NetBSD_GCC__ >= 2095003)) \ + || defined(__OpenBSD__) || defined(__DragonFly__)) +# define BOOST_NO_CWCHAR +#endif +// +// The BSD has macros only, no functions: +// +#if !defined(__OpenBSD__) || defined(__DragonFly__) +# define BOOST_NO_CTYPE_FUNCTIONS +#endif + +// +// thread API's not auto detected: +// +#define BOOST_HAS_SCHED_YIELD +#define BOOST_HAS_NANOSLEEP +#define BOOST_HAS_GETTIMEOFDAY +#define BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE +#define BOOST_HAS_SIGACTION +#define BOOST_HAS_CLOCK_GETTIME + +// boilerplate code: +#define BOOST_HAS_UNISTD_H +#include diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/platform/cloudabi.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/platform/cloudabi.hpp new file mode 100644 index 0000000..bed7b63 --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/platform/cloudabi.hpp @@ -0,0 +1,18 @@ +// Copyright Nuxi, https://nuxi.nl/ 2015. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_PLATFORM "CloudABI" + +#define BOOST_HAS_DIRENT_H +#define BOOST_HAS_STDINT_H +#define BOOST_HAS_UNISTD_H + +#define BOOST_HAS_CLOCK_GETTIME +#define BOOST_HAS_EXPM1 +#define BOOST_HAS_GETTIMEOFDAY +#define BOOST_HAS_LOG1P +#define BOOST_HAS_NANOSLEEP +#define BOOST_HAS_PTHREADS +#define BOOST_HAS_SCHED_YIELD diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/platform/cray.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/platform/cray.hpp new file mode 100644 index 0000000..103e9c0 --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/platform/cray.hpp @@ -0,0 +1,18 @@ +// (C) Copyright John Maddock 2011. +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + + +// See http://www.boost.org for most recent version. + +// SGI Irix specific config options: + +#define BOOST_PLATFORM "Cray" + +// boilerplate code: +#define BOOST_HAS_UNISTD_H +#include + + + diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/platform/cygwin.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/platform/cygwin.hpp new file mode 100644 index 0000000..d0052d8 --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/platform/cygwin.hpp @@ -0,0 +1,71 @@ +// (C) Copyright John Maddock 2001 - 2003. +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for most recent version. + +// cygwin specific config options: + +#define BOOST_PLATFORM "Cygwin" +#define BOOST_HAS_DIRENT_H +#define BOOST_HAS_LOG1P +#define BOOST_HAS_EXPM1 + +// +// Threading API: +// See if we have POSIX threads, if we do use them, otherwise +// revert to native Win threads. +#define BOOST_HAS_UNISTD_H +#include +#if defined(_POSIX_THREADS) && (_POSIX_THREADS+0 >= 0) && !defined(BOOST_HAS_WINTHREADS) +# define BOOST_HAS_PTHREADS +# define BOOST_HAS_SCHED_YIELD +# define BOOST_HAS_GETTIMEOFDAY +# define BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE +//# define BOOST_HAS_SIGACTION +#else +# if !defined(BOOST_HAS_WINTHREADS) +# define BOOST_HAS_WINTHREADS +# endif +# define BOOST_HAS_FTIME +#endif + +// +// find out if we have a stdint.h, there should be a better way to do this: +// +#include +#ifdef _STDINT_H +#define BOOST_HAS_STDINT_H +#endif +#if __GNUC__ > 5 && !defined(BOOST_HAS_STDINT_H) +# define BOOST_HAS_STDINT_H +#endif + +#include +#if (CYGWIN_VERSION_API_MAJOR == 0 && CYGWIN_VERSION_API_MINOR < 231) +/// Cygwin has no fenv.h +#define BOOST_NO_FENV_H +#endif + +// Cygwin has it's own which breaks unless the correct compiler flags are used: +#ifndef BOOST_NO_CXX14_HDR_SHARED_MUTEX +#include +#if !(__XSI_VISIBLE >= 500 || __POSIX_VISIBLE >= 200112) +# define BOOST_NO_CXX14_HDR_SHARED_MUTEX +#endif +#endif + +// boilerplate code: +#include + +// +// Cygwin lies about XSI conformance, there is no nl_types.h: +// +#ifdef BOOST_HAS_NL_TYPES_H +# undef BOOST_HAS_NL_TYPES_H +#endif + + + + diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/platform/haiku.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/platform/haiku.hpp new file mode 100644 index 0000000..04244c5 --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/platform/haiku.hpp @@ -0,0 +1,31 @@ +// (C) Copyright Jessica Hamilton 2014. +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for most recent version. + +// Haiku specific config options: + +#define BOOST_PLATFORM "Haiku" + +#define BOOST_HAS_UNISTD_H +#define BOOST_HAS_STDINT_H + +#ifndef BOOST_DISABLE_THREADS +# define BOOST_HAS_THREADS +#endif + +#define BOOST_NO_CXX11_HDR_TYPE_TRAITS +#define BOOST_NO_CXX11_ATOMIC_SMART_PTR +#define BOOST_NO_CXX11_STATIC_ASSERT +#define BOOST_NO_CXX11_VARIADIC_MACROS + +// +// thread API's not auto detected: +// +#define BOOST_HAS_SCHED_YIELD +#define BOOST_HAS_GETTIMEOFDAY + +// boilerplate code: +#include diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/platform/hpux.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/platform/hpux.hpp new file mode 100644 index 0000000..222622e --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/platform/hpux.hpp @@ -0,0 +1,87 @@ +// (C) Copyright John Maddock 2001 - 2003. +// (C) Copyright Jens Maurer 2001 - 2003. +// (C) Copyright David Abrahams 2002. +// (C) Copyright Toon Knapen 2003. +// (C) Copyright Boris Gubenko 2006 - 2007. +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for most recent version. + +// hpux specific config options: + +#define BOOST_PLATFORM "HP-UX" + +// In principle, HP-UX has a nice under the name +// However, it has the following problem: +// Use of UINT32_C(0) results in "0u l" for the preprocessed source +// (verifyable with gcc 2.95.3) +#if (defined(__GNUC__) && (__GNUC__ >= 3)) || defined(__HP_aCC) +# define BOOST_HAS_STDINT_H +#endif + +#if !(defined(__HP_aCC) || !defined(_INCLUDE__STDC_A1_SOURCE)) +# define BOOST_NO_SWPRINTF +#endif +#if defined(__HP_aCC) && !defined(_INCLUDE__STDC_A1_SOURCE) +# define BOOST_NO_CWCTYPE +#endif + +#if defined(__GNUC__) +# if (__GNUC__ < 3) || ((__GNUC__ == 3) && (__GNUC_MINOR__ < 3)) + // GNU C on HP-UX does not support threads (checked up to gcc 3.3) +# define BOOST_DISABLE_THREADS +# elif !defined(BOOST_DISABLE_THREADS) + // threads supported from gcc-3.3 onwards: +# define BOOST_HAS_THREADS +# define BOOST_HAS_PTHREADS +# endif +#elif defined(__HP_aCC) && !defined(BOOST_DISABLE_THREADS) +# define BOOST_HAS_PTHREADS +#endif + +// boilerplate code: +#define BOOST_HAS_UNISTD_H +#include + +// the following are always available: +#ifndef BOOST_HAS_GETTIMEOFDAY +# define BOOST_HAS_GETTIMEOFDAY +#endif +#ifndef BOOST_HAS_SCHED_YIELD +# define BOOST_HAS_SCHED_YIELD +#endif +#ifndef BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE +# define BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE +#endif +#ifndef BOOST_HAS_NL_TYPES_H +# define BOOST_HAS_NL_TYPES_H +#endif +#ifndef BOOST_HAS_NANOSLEEP +# define BOOST_HAS_NANOSLEEP +#endif +#ifndef BOOST_HAS_GETTIMEOFDAY +# define BOOST_HAS_GETTIMEOFDAY +#endif +#ifndef BOOST_HAS_DIRENT_H +# define BOOST_HAS_DIRENT_H +#endif +#ifndef BOOST_HAS_CLOCK_GETTIME +# define BOOST_HAS_CLOCK_GETTIME +#endif +#ifndef BOOST_HAS_SIGACTION +# define BOOST_HAS_SIGACTION +#endif +#ifndef BOOST_HAS_NRVO +# ifndef __parisc +# define BOOST_HAS_NRVO +# endif +#endif +#ifndef BOOST_HAS_LOG1P +# define BOOST_HAS_LOG1P +#endif +#ifndef BOOST_HAS_EXPM1 +# define BOOST_HAS_EXPM1 +#endif + diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/platform/irix.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/platform/irix.hpp new file mode 100644 index 0000000..0acb651 --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/platform/irix.hpp @@ -0,0 +1,31 @@ +// (C) Copyright John Maddock 2001 - 2003. +// (C) Copyright Jens Maurer 2003. +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + + +// See http://www.boost.org for most recent version. + +// SGI Irix specific config options: + +#define BOOST_PLATFORM "SGI Irix" + +#define BOOST_NO_SWPRINTF +// +// these are not auto detected by POSIX feature tests: +// +#define BOOST_HAS_GETTIMEOFDAY +#define BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE + +#ifdef __GNUC__ + // GNU C on IRIX does not support threads (checked up to gcc 3.3) +# define BOOST_DISABLE_THREADS +#endif + +// boilerplate code: +#define BOOST_HAS_UNISTD_H +#include + + + diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/platform/linux.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/platform/linux.hpp new file mode 100644 index 0000000..c4eef8f --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/platform/linux.hpp @@ -0,0 +1,106 @@ +// (C) Copyright John Maddock 2001 - 2003. +// (C) Copyright Jens Maurer 2001 - 2003. +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for most recent version. + +// linux specific config options: + +#define BOOST_PLATFORM "linux" + +// make sure we have __GLIBC_PREREQ if available at all +#ifdef __cplusplus +#include +#else +#include +#endif + +// +// added to glibc 2.1.1 +// We can only test for 2.1 though: +// +#if defined(__GLIBC__) && ((__GLIBC__ > 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ >= 1))) + // defines int64_t unconditionally, but defines + // int64_t only if __GNUC__. Thus, assume a fully usable + // only when using GCC. Update 2017: this appears not to be the case for + // recent glibc releases, see bug report: https://svn.boost.org/trac/boost/ticket/13045 +# if defined(__GNUC__) || ((__GLIBC__ > 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ >= 5))) +# define BOOST_HAS_STDINT_H +# endif +#endif + +#if defined(__LIBCOMO__) + // + // como on linux doesn't have std:: c functions: + // NOTE: versions of libcomo prior to beta28 have octal version numbering, + // e.g. version 25 is 21 (dec) + // +# if __LIBCOMO_VERSION__ <= 20 +# define BOOST_NO_STDC_NAMESPACE +# endif + +# if __LIBCOMO_VERSION__ <= 21 +# define BOOST_NO_SWPRINTF +# endif + +#endif + +// +// If glibc is past version 2 then we definitely have +// gettimeofday, earlier versions may or may not have it: +// +#if defined(__GLIBC__) && (__GLIBC__ >= 2) +# define BOOST_HAS_GETTIMEOFDAY +#endif + +#ifdef __USE_POSIX199309 +# define BOOST_HAS_NANOSLEEP +#endif + +#if defined(__GLIBC__) && defined(__GLIBC_PREREQ) +// __GLIBC_PREREQ is available since 2.1.2 + + // swprintf is available since glibc 2.2.0 +# if !__GLIBC_PREREQ(2,2) || (!defined(__USE_ISOC99) && !defined(__USE_UNIX98)) +# define BOOST_NO_SWPRINTF +# endif +#else +# define BOOST_NO_SWPRINTF +#endif + +// boilerplate code: +#define BOOST_HAS_UNISTD_H +#include +#if defined(__USE_GNU) && !defined(__ANDROID__) && !defined(ANDROID) +#define BOOST_HAS_PTHREAD_YIELD +#endif + +#ifndef __GNUC__ +// +// if the compiler is not gcc we still need to be able to parse +// the GNU system headers, some of which (mainly ) +// use GNU specific extensions: +// +# ifndef __extension__ +# define __extension__ +# endif +# ifndef __const__ +# define __const__ const +# endif +# ifndef __volatile__ +# define __volatile__ volatile +# endif +# ifndef __signed__ +# define __signed__ signed +# endif +# ifndef __typeof__ +# define __typeof__ typeof +# endif +# ifndef __inline__ +# define __inline__ inline +# endif +#endif + + diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/platform/macos.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/platform/macos.hpp new file mode 100644 index 0000000..ed7dc15 --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/platform/macos.hpp @@ -0,0 +1,87 @@ +// (C) Copyright John Maddock 2001 - 2003. +// (C) Copyright Darin Adler 2001 - 2002. +// (C) Copyright Bill Kempf 2002. +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for most recent version. + +// Mac OS specific config options: + +#define BOOST_PLATFORM "Mac OS" + +#if __MACH__ && !defined(_MSL_USING_MSL_C) + +// Using the Mac OS X system BSD-style C library. + +# ifndef BOOST_HAS_UNISTD_H +# define BOOST_HAS_UNISTD_H +# endif +// +// Begin by including our boilerplate code for POSIX +// feature detection, this is safe even when using +// the MSL as Metrowerks supply their own +// to replace the platform-native BSD one. G++ users +// should also always be able to do this on MaxOS X. +// +# include +# ifndef BOOST_HAS_STDINT_H +# define BOOST_HAS_STDINT_H +# endif + +// +// BSD runtime has pthreads, sigaction, sched_yield and gettimeofday, +// of these only pthreads are advertised in , so set the +// other options explicitly: +// +# define BOOST_HAS_SCHED_YIELD +# define BOOST_HAS_GETTIMEOFDAY +# define BOOST_HAS_SIGACTION + +# if (__GNUC__ < 3) && !defined( __APPLE_CC__) + +// GCC strange "ignore std" mode works better if you pretend everything +// is in the std namespace, for the most part. + +# define BOOST_NO_STDC_NAMESPACE +# endif + +# if (__GNUC__ >= 4) + +// Both gcc and intel require these. +# define BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE +# define BOOST_HAS_NANOSLEEP + +# endif + +#else + +// Using the MSL C library. + +// We will eventually support threads in non-Carbon builds, but we do +// not support this yet. +# if ( defined(TARGET_API_MAC_CARBON) && TARGET_API_MAC_CARBON ) || ( defined(TARGET_CARBON) && TARGET_CARBON ) + +# if !defined(BOOST_HAS_PTHREADS) +// MPTasks support is deprecated/removed from Boost: +//# define BOOST_HAS_MPTASKS +# elif ( __dest_os == __mac_os_x ) +// We are doing a Carbon/Mach-O/MSL build which has pthreads, but only the +// gettimeofday and no posix. +# define BOOST_HAS_GETTIMEOFDAY +# endif + +#ifdef BOOST_HAS_PTHREADS +# define BOOST_HAS_THREADS +#endif + +// The remote call manager depends on this. +# define BOOST_BIND_ENABLE_PASCAL + +# endif + +#endif + + + diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/platform/qnxnto.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/platform/qnxnto.hpp new file mode 100644 index 0000000..d0298cb --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/platform/qnxnto.hpp @@ -0,0 +1,31 @@ +// (C) Copyright Jim Douglas 2005. +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for most recent version. + +// QNX specific config options: + +#define BOOST_PLATFORM "QNX" + +#define BOOST_HAS_UNISTD_H +#include + +// QNX claims XOpen version 5 compatibility, but doesn't have an nl_types.h +// or log1p and expm1: +#undef BOOST_HAS_NL_TYPES_H +#undef BOOST_HAS_LOG1P +#undef BOOST_HAS_EXPM1 + +#define BOOST_HAS_PTHREADS +#define BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE + +#define BOOST_HAS_GETTIMEOFDAY +#define BOOST_HAS_CLOCK_GETTIME +#define BOOST_HAS_NANOSLEEP + + + + + diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/platform/solaris.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/platform/solaris.hpp new file mode 100644 index 0000000..51ffe67 --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/platform/solaris.hpp @@ -0,0 +1,31 @@ +// (C) Copyright John Maddock 2001 - 2003. +// (C) Copyright Jens Maurer 2003. +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for most recent version. + +// sun specific config options: + +#define BOOST_PLATFORM "Sun Solaris" + +#define BOOST_HAS_GETTIMEOFDAY + +// boilerplate code: +#define BOOST_HAS_UNISTD_H +#include + +// +// pthreads don't actually work with gcc unless _PTHREADS is defined: +// +#if defined(__GNUC__) && defined(_POSIX_THREADS) && !defined(_PTHREADS) +# undef BOOST_HAS_PTHREADS +#endif + +#define BOOST_HAS_STDINT_H +#define BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE +#define BOOST_HAS_LOG1P +#define BOOST_HAS_EXPM1 + + diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/platform/symbian.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/platform/symbian.hpp new file mode 100644 index 0000000..f814d00 --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/platform/symbian.hpp @@ -0,0 +1,97 @@ +// (C) Copyright Yuriy Krasnoschek 2009. +// (C) Copyright John Maddock 2001 - 2003. +// (C) Copyright Jens Maurer 2001 - 2003. +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for most recent version. + +// symbian specific config options: + + +#define BOOST_PLATFORM "Symbian" +#define BOOST_SYMBIAN 1 + + +#if defined(__S60_3X__) +// Open C / C++ plugin was introdused in this SDK, earlier versions don't have CRT / STL +# define BOOST_S60_3rd_EDITION_FP2_OR_LATER_SDK +// make sure we have __GLIBC_PREREQ if available at all +#ifdef __cplusplus +#include +#else +#include +#endif// boilerplate code: +# define BOOST_HAS_UNISTD_H +# include +// S60 SDK defines _POSIX_VERSION as POSIX.1 +# ifndef BOOST_HAS_STDINT_H +# define BOOST_HAS_STDINT_H +# endif +# ifndef BOOST_HAS_GETTIMEOFDAY +# define BOOST_HAS_GETTIMEOFDAY +# endif +# ifndef BOOST_HAS_DIRENT_H +# define BOOST_HAS_DIRENT_H +# endif +# ifndef BOOST_HAS_SIGACTION +# define BOOST_HAS_SIGACTION +# endif +# ifndef BOOST_HAS_PTHREADS +# define BOOST_HAS_PTHREADS +# endif +# ifndef BOOST_HAS_NANOSLEEP +# define BOOST_HAS_NANOSLEEP +# endif +# ifndef BOOST_HAS_SCHED_YIELD +# define BOOST_HAS_SCHED_YIELD +# endif +# ifndef BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE +# define BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE +# endif +# ifndef BOOST_HAS_LOG1P +# define BOOST_HAS_LOG1P +# endif +# ifndef BOOST_HAS_EXPM1 +# define BOOST_HAS_EXPM1 +# endif +# ifndef BOOST_POSIX_API +# define BOOST_POSIX_API +# endif +// endianess support +# include +// Symbian SDK provides _BYTE_ORDER instead of __BYTE_ORDER +# ifndef __LITTLE_ENDIAN +# ifdef _LITTLE_ENDIAN +# define __LITTLE_ENDIAN _LITTLE_ENDIAN +# else +# define __LITTLE_ENDIAN 1234 +# endif +# endif +# ifndef __BIG_ENDIAN +# ifdef _BIG_ENDIAN +# define __BIG_ENDIAN _BIG_ENDIAN +# else +# define __BIG_ENDIAN 4321 +# endif +# endif +# ifndef __BYTE_ORDER +# define __BYTE_ORDER __LITTLE_ENDIAN // Symbian is LE +# endif +// Known limitations +# define BOOST_ASIO_DISABLE_SERIAL_PORT +# define BOOST_DATE_TIME_NO_LOCALE +# define BOOST_NO_STD_WSTRING +# define BOOST_EXCEPTION_DISABLE +# define BOOST_NO_EXCEPTIONS + +#else // TODO: More platform support e.g. UIQ +# error "Unsuppoted Symbian SDK" +#endif + +#if defined(__WINSCW__) && !defined(BOOST_DISABLE_WIN32) +# define BOOST_DISABLE_WIN32 // winscw defines WIN32 macro +#endif + + diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/platform/vms.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/platform/vms.hpp new file mode 100644 index 0000000..f70efcf --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/platform/vms.hpp @@ -0,0 +1,25 @@ +// (C) Copyright Artyom Beilis 2010. +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_CONFIG_PLATFORM_VMS_HPP +#define BOOST_CONFIG_PLATFORM_VMS_HPP + +#define BOOST_PLATFORM "OpenVMS" + +#undef BOOST_HAS_STDINT_H +#define BOOST_HAS_UNISTD_H +#define BOOST_HAS_NL_TYPES_H +#define BOOST_HAS_GETTIMEOFDAY +#define BOOST_HAS_DIRENT_H +#define BOOST_HAS_PTHREADS +#define BOOST_HAS_NANOSLEEP +#define BOOST_HAS_CLOCK_GETTIME +#define BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE +#define BOOST_HAS_LOG1P +#define BOOST_HAS_EXPM1 +#define BOOST_HAS_THREADS +#undef BOOST_HAS_SCHED_YIELD + +#endif diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/platform/vxworks.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/platform/vxworks.hpp new file mode 100644 index 0000000..0564b94 --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/platform/vxworks.hpp @@ -0,0 +1,422 @@ +// (C) Copyright Dustin Spicuzza 2009. +// Adapted to vxWorks 6.9 by Peter Brockamp 2012. +// Updated for VxWorks 7 by Brian Kuhl 2016 +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for most recent version. + +// Old versions of vxWorks (namely everything below 6.x) are +// absolutely unable to use boost. Old STLs and compilers +// like (GCC 2.96) . Do not even think of getting this to work, +// a miserable failure will be guaranteed! +// +// VxWorks supports C++ linkage in the kernel with +// DKMs (Downloadable Kernel Modules). But, until recently +// the kernel used a C89 library with no +// wide character support and no guarantee of ANSI C. +// Regardless of the C library the same Dinkum +// STL library is used in both contexts. +// +// Similarly the Dinkum abridged STL that supports the loosely specified +// embedded C++ standard has not been tested and is unlikely to work +// on anything but the simplest library. +// ==================================================================== +// +// Some important information regarding the usage of POSIX semaphores: +// ------------------------------------------------------------------- +// +// VxWorks as a real time operating system handles threads somewhat +// different from what "normal" OSes do, regarding their scheduling! +// This could lead to a scenario called "priority inversion" when using +// semaphores, see http://en.wikipedia.org/wiki/Priority_inversion. +// +// Now, VxWorks POSIX-semaphores for DKM's default to the usage of +// priority inverting semaphores, which is fine. On the other hand, +// for RTP's it defaults to using non priority inverting semaphores, +// which could easily pose a serious problem for a real time process. +// +// To change the default properties for POSIX-semaphores in VxWorks 7 +// enable core > CORE_USER Menu > DEFAULT_PTHREAD_PRIO_INHERIT +// +// In VxWorks 6.x so as to integrate with boost. +// - Edit the file +// installDir/vxworks-6.x/target/usr/src/posix/pthreadLib.c +// - Around line 917 there should be the definition of the default +// mutex attributes: +// +// LOCAL pthread_mutexattr_t defaultMutexAttr = +// { +// PTHREAD_INITIALIZED_OBJ, PTHREAD_PRIO_NONE, 0, +// PTHREAD_MUTEX_DEFAULT +// }; +// +// Here, replace PTHREAD_PRIO_NONE by PTHREAD_PRIO_INHERIT. +// - Around line 1236 there should be a definition for the function +// pthread_mutexattr_init(). A couple of lines below you should +// find a block of code like this: +// +// pAttr->mutexAttrStatus = PTHREAD_INITIALIZED_OBJ; +// pAttr->mutexAttrProtocol = PTHREAD_PRIO_NONE; +// pAttr->mutexAttrPrioceiling = 0; +// pAttr->mutexAttrType = PTHREAD_MUTEX_DEFAULT; +// +// Here again, replace PTHREAD_PRIO_NONE by PTHREAD_PRIO_INHERIT. +// - Finally, rebuild your VSB. This will rebuild the libraries +// with the changed properties. That's it! Now, using boost should +// no longer cause any problems with task deadlocks! +// +// ==================================================================== + +// Block out all versions before vxWorks 6.x, as these don't work: +// Include header with the vxWorks version information and query them +#include +#if !defined(_WRS_VXWORKS_MAJOR) || (_WRS_VXWORKS_MAJOR < 6) +# error "The vxWorks version you're using is so badly outdated,\ + it doesn't work at all with boost, sorry, no chance!" +#endif + +// Handle versions above 5.X but below 6.9 +#if (_WRS_VXWORKS_MAJOR == 6) && (_WRS_VXWORKS_MINOR < 9) +// TODO: Starting from what version does vxWorks work with boost? +// We can't reasonably insert a #warning "" as a user hint here, +// as this will show up with every file including some boost header, +// badly bugging the user... So for the time being we just leave it. +#endif + +// vxWorks specific config options: +// -------------------------------- +#define BOOST_PLATFORM "vxWorks" + + +// Generally available headers: +#define BOOST_HAS_UNISTD_H +#define BOOST_HAS_STDINT_H +#define BOOST_HAS_DIRENT_H +//#define BOOST_HAS_SLIST + +// vxWorks does not have installed an iconv-library by default, +// so unfortunately no Unicode support from scratch is available! +// Thus, instead it is suggested to switch to ICU, as this seems +// to be the most complete and portable option... +#ifndef BOOST_LOCALE_WITH_ICU + #define BOOST_LOCALE_WITH_ICU +#endif + +// Generally available functionality: +#define BOOST_HAS_THREADS +#define BOOST_HAS_NANOSLEEP +#define BOOST_HAS_GETTIMEOFDAY +#define BOOST_HAS_CLOCK_GETTIME +#define BOOST_HAS_MACRO_USE_FACET + +// Generally available threading API's: +#define BOOST_HAS_PTHREADS +#define BOOST_HAS_SCHED_YIELD +#define BOOST_HAS_SIGACTION + +// Functionality available for RTPs only: +#ifdef __RTP__ +# define BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE +# define BOOST_HAS_LOG1P +# define BOOST_HAS_EXPM1 +#endif + +// Functionality available for DKMs only: +#ifdef _WRS_KERNEL + // Luckily, at the moment there seems to be none! +#endif + +// These #defines allow detail/posix_features to work, since vxWorks doesn't +// #define them itself for DKMs (for RTPs on the contrary it does): +#ifdef _WRS_KERNEL +# ifndef _POSIX_TIMERS +# define _POSIX_TIMERS 1 +# endif +# ifndef _POSIX_THREADS +# define _POSIX_THREADS 1 +# endif +// no sysconf( _SC_PAGESIZE) in kernel +# define BOOST_THREAD_USES_GETPAGESIZE +#endif + +#if (_WRS_VXWORKS_MAJOR < 7) +// vxWorks-around: #defines CLOCKS_PER_SEC as sysClkRateGet() but +// miserably fails to #include the required to make +// sysClkRateGet() available! So we manually include it here. +# ifdef __RTP__ +# include +# include +# endif + +// vxWorks-around: In the macros INT32_C(), UINT32_C(), INT64_C() and +// UINT64_C() are defined erroneously, yielding not a signed/ +// unsigned long/long long type, but a signed/unsigned int/long +// type. Eventually this leads to compile errors in ratio_fwd.hpp, +// when trying to define several constants which do not fit into a +// long type! We correct them here by redefining. + +# include + +// Special behaviour for DKMs: + +// Some macro-magic to do the job +# define VX_JOIN(X, Y) VX_DO_JOIN(X, Y) +# define VX_DO_JOIN(X, Y) VX_DO_JOIN2(X, Y) +# define VX_DO_JOIN2(X, Y) X##Y + +// Correctly setup the macros +# undef INT32_C +# undef UINT32_C +# undef INT64_C +# undef UINT64_C +# define INT32_C(x) VX_JOIN(x, L) +# define UINT32_C(x) VX_JOIN(x, UL) +# define INT64_C(x) VX_JOIN(x, LL) +# define UINT64_C(x) VX_JOIN(x, ULL) + +// #include Libraries required for the following function adaption +# include +#endif // _WRS_VXWORKS_MAJOR < 7 + +#include +#include + +#if defined(_WRS_KERNEL) && (_CPPLIB_VER < 700) + // recent kernels use Dinkum clib v7.00+ + // with widechar but older kernels + // do not have the -header, + // but apparently they do have an intrinsic wchar_t meanwhile! +# define BOOST_NO_CWCHAR + + // Lots of wide-functions and -headers are unavailable for DKMs as well: +# define BOOST_NO_CWCTYPE +# define BOOST_NO_SWPRINTF +# define BOOST_NO_STD_WSTRING +# define BOOST_NO_STD_WSTREAMBUF +#endif + + +// Use C-linkage for the following helper functions +#ifdef __cplusplus +extern "C" { +#endif + +// vxWorks-around: The required functions getrlimit() and getrlimit() are missing. +// But we have the similar functions getprlimit() and setprlimit(), +// which may serve the purpose. +// Problem: The vxWorks-documentation regarding these functions +// doesn't deserve its name! It isn't documented what the first two +// parameters idtype and id mean, so we must fall back to an educated +// guess - null, argh... :-/ + +// TODO: getprlimit() and setprlimit() do exist for RTPs only, for whatever reason. +// Thus for DKMs there would have to be another implementation. +#if defined ( __RTP__) && (_WRS_VXWORKS_MAJOR < 7) + inline int getrlimit(int resource, struct rlimit *rlp){ + return getprlimit(0, 0, resource, rlp); + } + + inline int setrlimit(int resource, const struct rlimit *rlp){ + return setprlimit(0, 0, resource, const_cast(rlp)); + } +#endif + +// vxWorks has ftruncate() only, so we do simulate truncate(): +inline int truncate(const char *p, off_t l){ + int fd = open(p, O_WRONLY); + if (fd == -1){ + errno = EACCES; + return -1; + } + if (ftruncate(fd, l) == -1){ + close(fd); + errno = EACCES; + return -1; + } + return close(fd); +} + +#ifdef __GNUC__ +# define ___unused __attribute__((unused)) +#else +# define ___unused +#endif + +// Fake symlink handling by dummy functions: +inline int symlink(const char* path1 ___unused, const char* path2 ___unused){ + // vxWorks has no symlinks -> always return an error! + errno = EACCES; + return -1; +} + +inline ssize_t readlink(const char* path1 ___unused, char* path2 ___unused, size_t size ___unused){ + // vxWorks has no symlinks -> always return an error! + errno = EACCES; + return -1; +} + +#if (_WRS_VXWORKS_MAJOR < 7) + +inline int gettimeofday(struct timeval *tv, void * /*tzv*/) { + struct timespec ts; + clock_gettime(CLOCK_MONOTONIC, &ts); + tv->tv_sec = ts.tv_sec; + tv->tv_usec = ts.tv_nsec / 1000; + return 0; +} +#endif + +#ifdef __cplusplus +} // extern "C" +#endif + +/* + * moved to os/utils/unix/freind_h/times.h in VxWorks 7 + * to avoid conflict with MPL operator times + */ +#if (_WRS_VXWORKS_MAJOR < 7) +# ifdef __cplusplus + +// vxWorks provides neither struct tms nor function times()! +// We implement an empty dummy-function, simply setting the user +// and system time to the half of thew actual system ticks-value +// and the child user and system time to 0. +// Rather ugly but at least it suppresses compiler errors... +// Unfortunately, this of course *does* have an severe impact on +// dependant libraries, actually this is chrono only! Here it will +// not be possible to correctly use user and system times! But +// as vxWorks is lacking the ability to calculate user and system +// process times there seems to be no other possible solution. +struct tms{ + clock_t tms_utime; // User CPU time + clock_t tms_stime; // System CPU time + clock_t tms_cutime; // User CPU time of terminated child processes + clock_t tms_cstime; // System CPU time of terminated child processes +}; + + + inline clock_t times(struct tms *t){ + struct timespec ts; + clock_gettime(CLOCK_THREAD_CPUTIME_ID, &ts); + clock_t ticks(static_cast(static_cast(ts.tv_sec) * CLOCKS_PER_SEC + + static_cast(ts.tv_nsec) * CLOCKS_PER_SEC / 1000000.0)); + t->tms_utime = ticks/2U; + t->tms_stime = ticks/2U; + t->tms_cutime = 0; // vxWorks is lacking the concept of a child process! + t->tms_cstime = 0; // -> Set the wait times for childs to 0 + return ticks; +} + + +namespace std { + using ::times; +} +# endif // __cplusplus +#endif // _WRS_VXWORKS_MAJOR < 7 + + +#ifdef __cplusplus +extern "C" void bzero (void *, size_t); // FD_ZERO uses bzero() but doesn't include strings.h + +// Put the selfmade functions into the std-namespace, just in case +namespace std { +# ifdef __RTP__ + using ::getrlimit; + using ::setrlimit; +# endif + using ::truncate; + using ::symlink; + using ::readlink; +# if (_WRS_VXWORKS_MAJOR < 7) + using ::gettimeofday; +# endif +} +#endif // __cplusplus + +// Some more macro-magic: +// vxWorks-around: Some functions are not present or broken in vxWorks +// but may be patched to life via helper macros... + +// Include signal.h which might contain a typo to be corrected here +#include + +#if (_WRS_VXWORKS_MAJOR < 7) +# define getpagesize() sysconf(_SC_PAGESIZE) // getpagesize is deprecated anyway! +inline int lstat(p, b) { return stat(p, b); } // lstat() == stat(), as vxWorks has no symlinks! +#endif + +#ifndef S_ISSOCK +# define S_ISSOCK(mode) ((mode & S_IFMT) == S_IFSOCK) // Is file a socket? +#endif +#ifndef FPE_FLTINV +# define FPE_FLTINV (FPE_FLTSUB+1) // vxWorks has no FPE_FLTINV, so define one as a dummy +#endif +#if !defined(BUS_ADRALN) && defined(BUS_ADRALNR) +# define BUS_ADRALN BUS_ADRALNR // Correct a supposed typo in vxWorks' +#endif +typedef int locale_t; // locale_t is a POSIX-extension, currently not present in vxWorks! + +// #include boilerplate code: +#include + +// vxWorks lies about XSI conformance, there is no nl_types.h: +#undef BOOST_HAS_NL_TYPES_H + +// vxWorks 7 adds C++11 support +// however it is optional, and does not match exactly the support determined +// by examining the Dinkum STL version and GCC version (or ICC and DCC) +#if !( defined( _WRS_CONFIG_LANG_LIB_CPLUS_CPLUS_USER_2011) || defined(_WRS_CONFIG_LIBCPLUS_STD)) +# define BOOST_NO_CXX11_ADDRESSOF // C11 addressof operator on memory location +# define BOOST_NO_CXX11_ALLOCATOR +# define BOOST_NO_CXX11_ATOMIC_SMART_PTR +# define BOOST_NO_CXX11_NUMERIC_LIMITS // max_digits10 in test/../print_helper.hpp +# define BOOST_NO_CXX11_SMART_PTR +# define BOOST_NO_CXX11_STD_ALIGN + + +# define BOOST_NO_CXX11_HDR_ARRAY +# define BOOST_NO_CXX11_HDR_ATOMIC +# define BOOST_NO_CXX11_HDR_CHRONO +# define BOOST_NO_CXX11_HDR_CONDITION_VARIABLE +# define BOOST_NO_CXX11_HDR_FORWARD_LIST //serialization/test/test_list.cpp +# define BOOST_NO_CXX11_HDR_FUNCTIONAL +# define BOOST_NO_CXX11_HDR_FUTURE +# define BOOST_NO_CXX11_HDR_MUTEX +# define BOOST_NO_CXX11_HDR_RANDOM //math/../test_data.hpp +# define BOOST_NO_CXX11_HDR_RATIO +# define BOOST_NO_CXX11_HDR_REGEX +# define BOOST_NO_CXX14_HDR_SHARED_MUTEX +# define BOOST_NO_CXX11_HDR_SYSTEM_ERROR +# define BOOST_NO_CXX11_HDR_THREAD +# define BOOST_NO_CXX11_HDR_TYPEINDEX +# define BOOST_NO_CXX11_HDR_TYPE_TRAITS +# define BOOST_NO_CXX11_HDR_TUPLE +# define BOOST_NO_CXX11_HDR_UNORDERED_MAP +# define BOOST_NO_CXX11_HDR_UNORDERED_SET +#else +# ifndef BOOST_SYSTEM_NO_DEPRECATED +# define BOOST_SYSTEM_NO_DEPRECATED // workaround link error in spirit +# endif +#endif + + +// NONE is used in enums in lamda and other libraries +#undef NONE +// restrict is an iostreams class +#undef restrict +// affects some typeof tests +#undef V7 + +// use fake poll() from Unix layer in ASIO to get full functionality +// most libraries will use select() but this define allows 'iostream' functionality +// which is based on poll() only +#if (_WRS_VXWORKS_MAJOR > 6) +# ifndef BOOST_ASIO_HAS_POSIX_STREAM_DESCRIPTOR +# define BOOST_ASIO_HAS_POSIX_STREAM_DESCRIPTOR +# endif +#else +# define BOOST_ASIO_DISABLE_SERIAL_PORT +#endif + diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/platform/wasm.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/platform/wasm.hpp new file mode 100644 index 0000000..682b848 --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/platform/wasm.hpp @@ -0,0 +1,23 @@ +// (C) Copyright John Maddock 2020. +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for most recent version. + +// WASM specific config options: + +#define BOOST_PLATFORM "Wasm" + +#ifdef __has_include +#if __has_include() +# define BOOST_HAS_UNISTD_H +#endif +#endif + +// boilerplate code: +#include +// +// fenv lacks the C++11 macros: +// +#define BOOST_NO_FENV_H diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/platform/win32.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/platform/win32.hpp new file mode 100644 index 0000000..450158f --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/platform/win32.hpp @@ -0,0 +1,90 @@ +// (C) Copyright John Maddock 2001 - 2003. +// (C) Copyright Bill Kempf 2001. +// (C) Copyright Aleksey Gurtovoy 2003. +// (C) Copyright Rene Rivera 2005. +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for most recent version. + +// Win32 specific config options: + +#define BOOST_PLATFORM "Win32" + +// Get the information about the MinGW runtime, i.e. __MINGW32_*VERSION. +#if defined(__MINGW32__) +# include <_mingw.h> +#endif + +#if defined(__GNUC__) && !defined(BOOST_NO_SWPRINTF) +# define BOOST_NO_SWPRINTF +#endif + +// Default defines for BOOST_SYMBOL_EXPORT and BOOST_SYMBOL_IMPORT +// If a compiler doesn't support __declspec(dllexport)/__declspec(dllimport), +// its boost/config/compiler/ file must define BOOST_SYMBOL_EXPORT and +// BOOST_SYMBOL_IMPORT +#ifndef BOOST_SYMBOL_EXPORT +# define BOOST_HAS_DECLSPEC +# define BOOST_SYMBOL_EXPORT __declspec(dllexport) +# define BOOST_SYMBOL_IMPORT __declspec(dllimport) +#endif + +#if defined(__MINGW32__) && ((__MINGW32_MAJOR_VERSION > 2) || ((__MINGW32_MAJOR_VERSION == 2) && (__MINGW32_MINOR_VERSION >= 0))) +# define BOOST_HAS_STDINT_H +# ifndef __STDC_LIMIT_MACROS +# define __STDC_LIMIT_MACROS +# endif +# define BOOST_HAS_DIRENT_H +# define BOOST_HAS_UNISTD_H +#endif + +#if defined(__MINGW32__) && (__GNUC__ >= 4) +// Mingw has these functions but there are persistent problems +// with calls to these crashing, so disable for now: +//# define BOOST_HAS_EXPM1 +//# define BOOST_HAS_LOG1P +# define BOOST_HAS_GETTIMEOFDAY +#endif +// +// Win32 will normally be using native Win32 threads, +// but there is a pthread library avaliable as an option, +// we used to disable this when BOOST_DISABLE_WIN32 was +// defined but no longer - this should allow some +// files to be compiled in strict mode - while maintaining +// a consistent setting of BOOST_HAS_THREADS across +// all translation units (needed for shared_ptr etc). +// + +#ifndef BOOST_HAS_PTHREADS +# define BOOST_HAS_WINTHREADS +#endif + +// +// WinCE configuration: +// +#if defined(_WIN32_WCE) || defined(UNDER_CE) +# define BOOST_NO_ANSI_APIS +// Windows CE does not have a conforming signature for swprintf +# define BOOST_NO_SWPRINTF +#else +# define BOOST_HAS_GETSYSTEMTIMEASFILETIME +# define BOOST_HAS_THREADEX +# define BOOST_HAS_GETSYSTEMTIMEASFILETIME +#endif + +// +// Windows Runtime +// +#if defined(WINAPI_FAMILY) && \ + (WINAPI_FAMILY == WINAPI_FAMILY_APP || WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) +# define BOOST_NO_ANSI_APIS +#endif + +#ifndef BOOST_DISABLE_WIN32 +// WEK: Added +#define BOOST_HAS_FTIME +#define BOOST_WINDOWS 1 + +#endif diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/platform/zos.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/platform/zos.hpp new file mode 100644 index 0000000..fa77999 --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/platform/zos.hpp @@ -0,0 +1,32 @@ +// Copyright (c) 2017 Dynatrace +// +// Distributed under the Boost Software License, Version 1.0. +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt + +// See http://www.boost.org for most recent version. + +// Platform setup for IBM z/OS. + +#define BOOST_PLATFORM "IBM z/OS" + +#include // For __UU, __C99, __TR1, ... + +#if defined(__UU) +# define BOOST_HAS_GETTIMEOFDAY +#endif + +#if defined(_OPEN_THREADS) || defined(__SUSV3_THR) +# define BOOST_HAS_PTHREADS +# define BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE +# define BOOST_HAS_THREADS +#endif + +#if defined(__SUSV3) || defined(__SUSV3_THR) +# define BOOST_HAS_SCHED_YIELD +#endif + +#define BOOST_HAS_SIGACTION +#define BOOST_HAS_UNISTD_H +#define BOOST_HAS_DIRENT_H +#define BOOST_HAS_NL_TYPES_H diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/pragma_message.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/pragma_message.hpp new file mode 100644 index 0000000..b2c5ff2 --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/pragma_message.hpp @@ -0,0 +1,31 @@ +#ifndef BOOST_CONFIG_PRAGMA_MESSAGE_HPP_INCLUDED +#define BOOST_CONFIG_PRAGMA_MESSAGE_HPP_INCLUDED + +// Copyright 2017 Peter Dimov. +// +// Distributed under the Boost Software License, Version 1.0. +// +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt +// +// BOOST_PRAGMA_MESSAGE("message") +// +// Expands to the equivalent of #pragma message("message") +// +// Note that this header is C compatible. + +#include + +#if defined(BOOST_DISABLE_PRAGMA_MESSAGE) +# define BOOST_PRAGMA_MESSAGE(x) +#elif defined(__INTEL_COMPILER) +# define BOOST_PRAGMA_MESSAGE(x) __pragma(message(__FILE__ "(" BOOST_STRINGIZE(__LINE__) "): note: " x)) +#elif defined(__GNUC__) +# define BOOST_PRAGMA_MESSAGE(x) _Pragma(BOOST_STRINGIZE(message(x))) +#elif defined(_MSC_VER) +# define BOOST_PRAGMA_MESSAGE(x) __pragma(message(__FILE__ "(" BOOST_STRINGIZE(__LINE__) "): note: " x)) +#else +# define BOOST_PRAGMA_MESSAGE(x) +#endif + +#endif // BOOST_CONFIG_PRAGMA_MESSAGE_HPP_INCLUDED diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/requires_threads.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/requires_threads.hpp new file mode 100644 index 0000000..c23a2ce --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/requires_threads.hpp @@ -0,0 +1,92 @@ +// (C) Copyright John Maddock 2003. +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + + +#ifndef BOOST_CONFIG_REQUIRES_THREADS_HPP +#define BOOST_CONFIG_REQUIRES_THREADS_HPP + +#ifndef BOOST_CONFIG_HPP +# include +#endif + +#if defined(BOOST_DISABLE_THREADS) + +// +// special case to handle versions of gcc which don't currently support threads: +// +#if defined(__GNUC__) && ((__GNUC__ < 3) || (__GNUC_MINOR__ <= 3) || !defined(BOOST_STRICT_CONFIG)) +// +// this is checked up to gcc 3.3: +// +#if defined(__sgi) || defined(__hpux) +# error "Multi-threaded programs are not supported by gcc on HPUX or Irix (last checked with gcc 3.3)" +#endif + +#endif + +# error "Threading support unavaliable: it has been explicitly disabled with BOOST_DISABLE_THREADS" + +#elif !defined(BOOST_HAS_THREADS) + +# if defined __COMO__ +// Comeau C++ +# error "Compiler threading support is not turned on. Please set the correct command line options for threading: -D_MT (Windows) or -D_REENTRANT (Unix)" + +#elif defined(__INTEL_COMPILER) || defined(__ICL) || defined(__ICC) || defined(__ECC) +// Intel +#ifdef _WIN32 +# error "Compiler threading support is not turned on. Please set the correct command line options for threading: either /MT /MTd /MD or /MDd" +#else +# error "Compiler threading support is not turned on. Please set the correct command line options for threading: -openmp" +#endif + +# elif defined __GNUC__ +// GNU C++: +# error "Compiler threading support is not turned on. Please set the correct command line options for threading: -pthread (Linux), -pthreads (Solaris) or -mthreads (Mingw32)" + +#elif defined __sgi +// SGI MIPSpro C++ +# error "Compiler threading support is not turned on. Please set the correct command line options for threading: -D_SGI_MP_SOURCE" + +#elif defined __DECCXX +// Compaq Tru64 Unix cxx +# error "Compiler threading support is not turned on. Please set the correct command line options for threading: -pthread" + +#elif defined BOOST_BORLANDC +// Borland +# error "Compiler threading support is not turned on. Please set the correct command line options for threading: -tWM" + +#elif defined __MWERKS__ +// Metrowerks CodeWarrior +# error "Compiler threading support is not turned on. Please set the correct command line options for threading: either -runtime sm, -runtime smd, -runtime dm, or -runtime dmd" + +#elif defined __SUNPRO_CC +// Sun Workshop Compiler C++ +# error "Compiler threading support is not turned on. Please set the correct command line options for threading: -mt" + +#elif defined __HP_aCC +// HP aCC +# error "Compiler threading support is not turned on. Please set the correct command line options for threading: -mt" + +#elif defined(__IBMCPP__) +// IBM Visual Age +# error "Compiler threading support is not turned on. Please compile the code with the xlC_r compiler" + +#elif defined _MSC_VER +// Microsoft Visual C++ +// +// Must remain the last #elif since some other vendors (Metrowerks, for +// example) also #define _MSC_VER +# error "Compiler threading support is not turned on. Please set the correct command line options for threading: either /MT /MTd /MD or /MDd" + +#else + +# error "Compiler threading support is not turned on. Please consult your compiler's documentation for the appropriate options to use" + +#endif // compilers + +#endif // BOOST_HAS_THREADS + +#endif // BOOST_CONFIG_REQUIRES_THREADS_HPP diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/stdlib/dinkumware.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/stdlib/dinkumware.hpp new file mode 100644 index 0000000..46ffe09 --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/stdlib/dinkumware.hpp @@ -0,0 +1,324 @@ +// (C) Copyright John Maddock 2001 - 2003. +// (C) Copyright Jens Maurer 2001. +// (C) Copyright Peter Dimov 2001. +// (C) Copyright David Abrahams 2002. +// (C) Copyright Guillaume Melquiond 2003. +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for most recent version. + +// Dinkumware standard library config: + +#if !defined(_YVALS) && !defined(_CPPLIB_VER) +#include +#if !defined(_YVALS) && !defined(_CPPLIB_VER) +#error This is not the Dinkumware lib! +#endif +#endif + + +#if defined(_CPPLIB_VER) && (_CPPLIB_VER >= 306) + // full dinkumware 3.06 and above + // fully conforming provided the compiler supports it: +# if !(defined(_GLOBAL_USING) && (_GLOBAL_USING+0 > 0)) && !defined(BOOST_BORLANDC) && !defined(_STD) && !(defined(__ICC) && (__ICC >= 700)) // can be defined in yvals.h +# define BOOST_NO_STDC_NAMESPACE +# endif +# if !(defined(_HAS_MEMBER_TEMPLATES_REBIND) && (_HAS_MEMBER_TEMPLATES_REBIND+0 > 0)) && !(defined(_MSC_VER) && (_MSC_VER > 1300)) && defined(BOOST_MSVC) +# define BOOST_NO_STD_ALLOCATOR +# endif +# define BOOST_HAS_PARTIAL_STD_ALLOCATOR +# if defined(BOOST_MSVC) && (BOOST_MSVC < 1300) + // if this lib version is set up for vc6 then there is no std::use_facet: +# define BOOST_NO_STD_USE_FACET +# define BOOST_HAS_TWO_ARG_USE_FACET + // C lib functions aren't in namespace std either: +# define BOOST_NO_STDC_NAMESPACE + // and nor is +# define BOOST_NO_EXCEPTION_STD_NAMESPACE +# endif +// There's no numeric_limits support unless _LONGLONG is defined: +# if !defined(_LONGLONG) && (_CPPLIB_VER <= 310) +# define BOOST_NO_MS_INT64_NUMERIC_LIMITS +# endif +// 3.06 appears to have (non-sgi versions of) & , +// and no at all +#else +# define BOOST_MSVC_STD_ITERATOR 1 +# define BOOST_NO_STD_ITERATOR +# define BOOST_NO_TEMPLATED_ITERATOR_CONSTRUCTORS +# define BOOST_NO_STD_ALLOCATOR +# define BOOST_NO_STDC_NAMESPACE +# define BOOST_NO_STD_USE_FACET +# define BOOST_NO_STD_OUTPUT_ITERATOR_ASSIGN +# define BOOST_HAS_MACRO_USE_FACET +# ifndef _CPPLIB_VER + // Updated Dinkum library defines this, and provides + // its own min and max definitions, as does MTA version. +# ifndef __MTA__ +# define BOOST_NO_STD_MIN_MAX +# endif +# define BOOST_NO_MS_INT64_NUMERIC_LIMITS +# endif +#endif + +// +// std extension namespace is stdext for vc7.1 and later, +// the same applies to other compilers that sit on top +// of vc7.1 (Intel and Comeau): +// +#if defined(_MSC_VER) && (_MSC_VER >= 1310) && !defined(BOOST_BORLANDC) +# define BOOST_STD_EXTENSION_NAMESPACE stdext +#endif + + +#if (defined(_MSC_VER) && (_MSC_VER <= 1300) && !defined(BOOST_BORLANDC)) || !defined(_CPPLIB_VER) || (_CPPLIB_VER < 306) + // if we're using a dinkum lib that's + // been configured for VC6/7 then there is + // no iterator traits (true even for icl) +# define BOOST_NO_STD_ITERATOR_TRAITS +#endif + +#if defined(__ICL) && (__ICL < 800) && defined(_CPPLIB_VER) && (_CPPLIB_VER <= 310) +// Intel C++ chokes over any non-trivial use of +// this may be an overly restrictive define, but regex fails without it: +# define BOOST_NO_STD_LOCALE +#endif + +#if ((defined(BOOST_MSVC) && BOOST_MSVC >= 1400) || (defined(__clang__) && defined(_MSC_VER))) && (_MSC_VER < 1800) +// Fix for VC++ 8.0 on up ( I do not have a previous version to test ) +// or clang-cl. If exceptions are off you must manually include the +// header before including the header. Admittedly +// trying to use Boost libraries or the standard C++ libraries without +// exception support is not suggested but currently clang-cl ( v 3.4 ) +// does not support exceptions and must be compiled with exceptions off. +#if !_HAS_EXCEPTIONS +#include +#endif +#include +#if !_HAS_EXCEPTIONS +# define BOOST_NO_STD_TYPEINFO +#endif +#endif +#if defined(__ghs__) && !_HAS_NAMESPACE +# define BOOST_NO_STD_TYPEINFO +#endif + +// C++0x headers implemented in 520 (as shipped by Microsoft) +// +#if !defined(_CPPLIB_VER) || _CPPLIB_VER < 520 +# define BOOST_NO_CXX11_HDR_ARRAY +# define BOOST_NO_CXX11_HDR_CODECVT +# define BOOST_NO_CXX11_HDR_FORWARD_LIST +# define BOOST_NO_CXX11_HDR_INITIALIZER_LIST +# define BOOST_NO_CXX11_HDR_RANDOM +# define BOOST_NO_CXX11_HDR_REGEX +# define BOOST_NO_CXX11_HDR_SYSTEM_ERROR +# define BOOST_NO_CXX11_HDR_UNORDERED_MAP +# define BOOST_NO_CXX11_HDR_UNORDERED_SET +# define BOOST_NO_CXX11_HDR_TUPLE +# define BOOST_NO_CXX11_HDR_TYPEINDEX +# define BOOST_NO_CXX11_HDR_FUNCTIONAL +# define BOOST_NO_CXX11_NUMERIC_LIMITS +# define BOOST_NO_CXX11_SMART_PTR +#endif + +#if ((!defined(_HAS_TR1_IMPORTS) || (_HAS_TR1_IMPORTS+0 == 0)) && !defined(BOOST_NO_CXX11_HDR_TUPLE)) \ + && (!defined(_CPPLIB_VER) || _CPPLIB_VER < 610) +# define BOOST_NO_CXX11_HDR_TUPLE +#endif + +// C++0x headers implemented in 540 (as shipped by Microsoft) +// +#if !defined(_CPPLIB_VER) || _CPPLIB_VER < 540 +# define BOOST_NO_CXX11_HDR_TYPE_TRAITS +# define BOOST_NO_CXX11_HDR_CHRONO +# define BOOST_NO_CXX11_HDR_CONDITION_VARIABLE +# define BOOST_NO_CXX11_HDR_FUTURE +# define BOOST_NO_CXX11_HDR_MUTEX +# define BOOST_NO_CXX11_HDR_RATIO +# define BOOST_NO_CXX11_HDR_THREAD +# define BOOST_NO_CXX11_ATOMIC_SMART_PTR +# define BOOST_NO_CXX11_HDR_EXCEPTION +#endif + +// C++0x headers implemented in 610 (as shipped by Microsoft) +// +#if !defined(_CPPLIB_VER) || _CPPLIB_VER < 610 +# define BOOST_NO_CXX11_HDR_INITIALIZER_LIST +# define BOOST_NO_CXX11_HDR_ATOMIC +# define BOOST_NO_CXX11_ALLOCATOR +// 540 has std::align but it is not a conforming implementation +# define BOOST_NO_CXX11_STD_ALIGN +#endif + +// Before 650 std::pointer_traits has a broken rebind template +#if !defined(_CPPLIB_VER) || _CPPLIB_VER < 650 +# define BOOST_NO_CXX11_POINTER_TRAITS +#elif defined(BOOST_MSVC) && BOOST_MSVC < 1910 +# define BOOST_NO_CXX11_POINTER_TRAITS +#endif + +#if defined(__has_include) +#if !__has_include() +# define BOOST_NO_CXX14_HDR_SHARED_MUTEX +#elif (__cplusplus < 201402) && !defined(_MSC_VER) +# define BOOST_NO_CXX14_HDR_SHARED_MUTEX +#endif +#elif !defined(_CPPLIB_VER) || (_CPPLIB_VER < 650) +# define BOOST_NO_CXX14_HDR_SHARED_MUTEX +#endif + +// C++14 features +#if !defined(_CPPLIB_VER) || (_CPPLIB_VER < 650) +# define BOOST_NO_CXX14_STD_EXCHANGE +#endif + +// C++17 features +#if !defined(_CPPLIB_VER) || (_CPPLIB_VER < 650) \ + || ((!defined(BOOST_MSVC) || (BOOST_MSVC < 1910))) && (!defined(__clang__) || !defined(_MSC_VER) || (_MSC_VER < 1929))\ + || !defined(_HAS_CXX17) || (_HAS_CXX17 == 0) +# define BOOST_NO_CXX17_STD_APPLY +# define BOOST_NO_CXX17_ITERATOR_TRAITS +# define BOOST_NO_CXX17_HDR_STRING_VIEW +# define BOOST_NO_CXX17_HDR_OPTIONAL +# define BOOST_NO_CXX17_HDR_VARIANT +# define BOOST_NO_CXX17_HDR_ANY +# define BOOST_NO_CXX17_HDR_MEMORY_RESOURCE +# define BOOST_NO_CXX17_HDR_CHARCONV +# define BOOST_NO_CXX17_HDR_EXECUTION +# define BOOST_NO_CXX17_HDR_FILESYSTEM +#endif +#if !defined(_CPPLIB_VER) || (_CPPLIB_VER < 650) || !defined(_HAS_CXX17) || (_HAS_CXX17 == 0) || !defined(_MSVC_STL_UPDATE) || (_MSVC_STL_UPDATE < 201709) +# define BOOST_NO_CXX17_STD_INVOKE +#endif + +// C++20 features which aren't configured in suffix.hpp correctly: +#if !defined(_MSVC_STL_UPDATE) || (_MSVC_STL_UPDATE < 202008L) || !defined(_HAS_CXX20) || (_HAS_CXX20 == 0) +# define BOOST_NO_CXX20_HDR_CONCEPTS +#endif + +#if !(!defined(_CPPLIB_VER) || (_CPPLIB_VER < 650) || !defined(BOOST_MSVC) || (BOOST_MSVC < 1912) || !defined(_HAS_CXX17) || (_HAS_CXX17 == 0)) +// Deprecated std::iterator: +# define BOOST_NO_STD_ITERATOR +#endif + +#if defined(BOOST_INTEL) && (BOOST_INTEL <= 1400) +// Intel's compiler can't handle this header yet: +# define BOOST_NO_CXX11_HDR_ATOMIC +#endif + + +// 520..610 have std::addressof, but it doesn't support functions +// +#if !defined(_CPPLIB_VER) || _CPPLIB_VER < 650 +# define BOOST_NO_CXX11_ADDRESSOF +#endif + +// Bug specific to VC14, +// See https://connect.microsoft.com/VisualStudio/feedback/details/1348277/link-error-when-using-std-codecvt-utf8-utf16-char16-t +// and discussion here: http://blogs.msdn.com/b/vcblog/archive/2014/11/12/visual-studio-2015-preview-now-available.aspx?PageIndex=2 +#if defined(_CPPLIB_VER) && (_CPPLIB_VER == 650) && (!defined(_MSVC_STL_VERSION) || (_MSVC_STL_VERSION < 142)) +# define BOOST_NO_CXX11_HDR_CODECVT +#endif + +#if (_MSVC_LANG > 201700) && !defined(BOOST_NO_CXX11_HDR_CODECVT) +// +// is deprected as of C++17, and by default MSVC emits hard errors +// if you try to use it, so mark it as unavailable: +// +# define BOOST_NO_CXX11_HDR_CODECVT +#endif + +#if defined(_CPPLIB_VER) && (_CPPLIB_VER >= 650) +// If _HAS_AUTO_PTR_ETC is defined to 0, std::auto_ptr and std::random_shuffle are not available. +// See https://www.visualstudio.com/en-us/news/vs2015-vs.aspx#C++ +// and http://blogs.msdn.com/b/vcblog/archive/2015/06/19/c-11-14-17-features-in-vs-2015-rtm.aspx +# if defined(_HAS_AUTO_PTR_ETC) && (_HAS_AUTO_PTR_ETC == 0) +# define BOOST_NO_AUTO_PTR +# define BOOST_NO_CXX98_RANDOM_SHUFFLE +# define BOOST_NO_CXX98_FUNCTION_BASE +# define BOOST_NO_CXX98_BINDERS +# elif defined(_HAS_DEPRECATED_ADAPTOR_TYPEDEFS) && (_HAS_DEPRECATED_ADAPTOR_TYPEDEFS == 0) +# define BOOST_NO_CXX98_BINDERS +# endif +#endif +// +// Things deprecated in C++20: +// +#if defined(_HAS_CXX20) +# define BOOST_NO_CXX11_ATOMIC_SMART_PTR +#endif + + +// +// Things not supported by the CLR: +#ifdef _M_CEE +#ifndef BOOST_NO_CXX11_HDR_MUTEX +# define BOOST_NO_CXX11_HDR_MUTEX +#endif +#ifndef BOOST_NO_CXX11_HDR_ATOMIC +# define BOOST_NO_CXX11_HDR_ATOMIC +#endif +#ifndef BOOST_NO_CXX11_HDR_FUTURE +# define BOOST_NO_CXX11_HDR_FUTURE +#endif +#ifndef BOOST_NO_CXX11_HDR_CONDITION_VARIABLE +# define BOOST_NO_CXX11_HDR_CONDITION_VARIABLE +#endif +#ifndef BOOST_NO_CXX11_HDR_THREAD +# define BOOST_NO_CXX11_HDR_THREAD +#endif +#ifndef BOOST_NO_CXX14_HDR_SHARED_MUTEX +# define BOOST_NO_CXX14_HDR_SHARED_MUTEX +#endif +#ifndef BOOST_NO_CXX14_STD_EXCHANGE +# define BOOST_NO_CXX14_STD_EXCHANGE +#endif +#ifndef BOOST_NO_FENV_H +# define BOOST_NO_FENV_H +#endif +#endif + +#ifdef _CPPLIB_VER +# define BOOST_DINKUMWARE_STDLIB _CPPLIB_VER +#else +# define BOOST_DINKUMWARE_STDLIB 1 +#endif + +// BOOST_MSSTL_VERSION: as _MSVC_STL_VERSION, but for earlier releases as well + +#if defined(_MSVC_STL_VERSION) // VS2017 (14.1) and above +# define BOOST_MSSTL_VERSION _MSVC_STL_VERSION + +#elif defined(_CPPLIB_VER) && _CPPLIB_VER >= 650 // VS2015 (14.0) +# define BOOST_MSSTL_VERSION 140 + +#elif defined(_CPPLIB_VER) && _CPPLIB_VER >= 610 // VS2013 (12.0) +# define BOOST_MSSTL_VERSION 120 + +#elif defined(_CPPLIB_VER) && _CPPLIB_VER >= 540 // VS2012 (11.0) +# define BOOST_MSSTL_VERSION 110 + +#elif defined(_CPPLIB_VER) && _CPPLIB_VER >= 520 // VS2010 (10.0) +# define BOOST_MSSTL_VERSION 100 + +#elif defined(_CPPLIB_VER) && _CPPLIB_VER >= 505 // VS2008SP1 (9.0) +# define BOOST_MSSTL_VERSION 91 + +#elif defined(_CPPLIB_VER) && _CPPLIB_VER >= 503 // VS2008 (also 9.0) +# define BOOST_MSSTL_VERSION 90 + +#elif defined(_CPPLIB_VER) && _CPPLIB_VER >= 405 // VS2005 (8.0) +# define BOOST_MSSTL_VERSION 80 + +#endif + +// + +#ifdef _CPPLIB_VER +# define BOOST_STDLIB "Dinkumware standard library version " BOOST_STRINGIZE(_CPPLIB_VER) +#else +# define BOOST_STDLIB "Dinkumware standard library version 1.x" +#endif diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/stdlib/libcomo.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/stdlib/libcomo.hpp new file mode 100644 index 0000000..6a8a161 --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/stdlib/libcomo.hpp @@ -0,0 +1,93 @@ +// (C) Copyright John Maddock 2002 - 2003. +// (C) Copyright Jens Maurer 2002 - 2003. +// (C) Copyright Beman Dawes 2002 - 2003. +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for most recent version. + +// Comeau STL: + +#if !defined(__LIBCOMO__) +# include +# if !defined(__LIBCOMO__) +# error "This is not the Comeau STL!" +# endif +#endif + +// +// std::streambuf is non-standard +// NOTE: versions of libcomo prior to beta28 have octal version numbering, +// e.g. version 25 is 21 (dec) +#if __LIBCOMO_VERSION__ <= 22 +# define BOOST_NO_STD_WSTREAMBUF +#endif + +#if (__LIBCOMO_VERSION__ <= 31) && defined(_WIN32) +#define BOOST_NO_SWPRINTF +#endif + +#if __LIBCOMO_VERSION__ >= 31 +# define BOOST_HAS_HASH +# define BOOST_HAS_SLIST +#endif + +// C++0x headers not yet implemented +// +# define BOOST_NO_CXX11_HDR_ARRAY +# define BOOST_NO_CXX11_HDR_CHRONO +# define BOOST_NO_CXX11_HDR_CODECVT +# define BOOST_NO_CXX11_HDR_CONDITION_VARIABLE +# define BOOST_NO_CXX11_HDR_EXCEPTION +# define BOOST_NO_CXX11_HDR_FORWARD_LIST +# define BOOST_NO_CXX11_HDR_FUTURE +# define BOOST_NO_CXX11_HDR_INITIALIZER_LIST +# define BOOST_NO_CXX11_HDR_MUTEX +# define BOOST_NO_CXX11_HDR_RANDOM +# define BOOST_NO_CXX11_HDR_RATIO +# define BOOST_NO_CXX11_HDR_REGEX +# define BOOST_NO_CXX11_HDR_SYSTEM_ERROR +# define BOOST_NO_CXX11_HDR_THREAD +# define BOOST_NO_CXX11_HDR_TUPLE +# define BOOST_NO_CXX11_HDR_TYPE_TRAITS +# define BOOST_NO_CXX11_HDR_TYPEINDEX +# define BOOST_NO_CXX11_HDR_UNORDERED_MAP +# define BOOST_NO_CXX11_HDR_UNORDERED_SET +# define BOOST_NO_CXX11_NUMERIC_LIMITS +# define BOOST_NO_CXX11_ALLOCATOR +# define BOOST_NO_CXX11_POINTER_TRAITS +# define BOOST_NO_CXX11_ATOMIC_SMART_PTR +# define BOOST_NO_CXX11_SMART_PTR +# define BOOST_NO_CXX11_HDR_FUNCTIONAL +# define BOOST_NO_CXX11_HDR_ATOMIC +# define BOOST_NO_CXX11_STD_ALIGN +# define BOOST_NO_CXX11_ADDRESSOF + +#if defined(__has_include) +#if !__has_include() +# define BOOST_NO_CXX14_HDR_SHARED_MUTEX +#elif __cplusplus < 201402 +# define BOOST_NO_CXX14_HDR_SHARED_MUTEX +#endif +#else +# define BOOST_NO_CXX14_HDR_SHARED_MUTEX +#endif + +// C++14 features +# define BOOST_NO_CXX14_STD_EXCHANGE + +// C++17 features +# define BOOST_NO_CXX17_STD_APPLY +# define BOOST_NO_CXX17_STD_INVOKE +# define BOOST_NO_CXX17_ITERATOR_TRAITS + +// +// Intrinsic type_traits support. +// The SGI STL has it's own __type_traits class, which +// has intrinsic compiler support with SGI's compilers. +// Whatever map SGI style type traits to boost equivalents: +// +#define BOOST_HAS_SGI_TYPE_TRAITS + +#define BOOST_STDLIB "Comeau standard library " BOOST_STRINGIZE(__LIBCOMO_VERSION__) diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/stdlib/libcpp.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/stdlib/libcpp.hpp new file mode 100644 index 0000000..0e9f244 --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/stdlib/libcpp.hpp @@ -0,0 +1,180 @@ +// (C) Copyright Christopher Jefferson 2011. +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for most recent version. + +// config for libc++ +// Might need more in here later. + +#if !defined(_LIBCPP_VERSION) +# include +# if !defined(_LIBCPP_VERSION) +# error "This is not libc++!" +# endif +#endif + +#define BOOST_STDLIB "libc++ version " BOOST_STRINGIZE(_LIBCPP_VERSION) + +#define BOOST_HAS_THREADS + +#ifdef _LIBCPP_HAS_NO_VARIADICS +# define BOOST_NO_CXX11_HDR_TUPLE +#endif + +// BOOST_NO_CXX11_ALLOCATOR should imply no support for the C++11 +// allocator model. The C++11 allocator model requires a conforming +// std::allocator_traits which is only possible with C++11 template +// aliases since members rebind_alloc and rebind_traits require it. +#if defined(_LIBCPP_HAS_NO_TEMPLATE_ALIASES) +# define BOOST_NO_CXX11_ALLOCATOR +# define BOOST_NO_CXX11_POINTER_TRAITS +#endif + +#if __cplusplus < 201103 +// +// These two appear to be somewhat useable in C++03 mode, there may be others... +// +//# define BOOST_NO_CXX11_HDR_ARRAY +//# define BOOST_NO_CXX11_HDR_FORWARD_LIST + +# define BOOST_NO_CXX11_HDR_CODECVT +# define BOOST_NO_CXX11_HDR_CONDITION_VARIABLE +# define BOOST_NO_CXX11_HDR_EXCEPTION +# define BOOST_NO_CXX11_HDR_INITIALIZER_LIST +# define BOOST_NO_CXX11_HDR_MUTEX +# define BOOST_NO_CXX11_HDR_RANDOM +# define BOOST_NO_CXX11_HDR_RATIO +# define BOOST_NO_CXX11_HDR_REGEX +# define BOOST_NO_CXX11_HDR_SYSTEM_ERROR +# define BOOST_NO_CXX11_HDR_THREAD +# define BOOST_NO_CXX11_HDR_TUPLE +# define BOOST_NO_CXX11_HDR_TYPEINDEX +# define BOOST_NO_CXX11_HDR_UNORDERED_MAP +# define BOOST_NO_CXX11_HDR_UNORDERED_SET +# define BOOST_NO_CXX11_NUMERIC_LIMITS +# define BOOST_NO_CXX11_ALLOCATOR +# define BOOST_NO_CXX11_POINTER_TRAITS +# define BOOST_NO_CXX11_SMART_PTR +# define BOOST_NO_CXX11_HDR_FUNCTIONAL +# define BOOST_NO_CXX11_STD_ALIGN +# define BOOST_NO_CXX11_ADDRESSOF +# define BOOST_NO_CXX11_HDR_ATOMIC +# define BOOST_NO_CXX11_ATOMIC_SMART_PTR +# define BOOST_NO_CXX11_HDR_CHRONO +# define BOOST_NO_CXX11_HDR_TYPE_TRAITS +# define BOOST_NO_CXX11_HDR_FUTURE +#elif _LIBCPP_VERSION < 3700 +// +// These appear to be unusable/incomplete so far: +// +# define BOOST_NO_CXX11_HDR_ATOMIC +# define BOOST_NO_CXX11_ATOMIC_SMART_PTR +# define BOOST_NO_CXX11_HDR_CHRONO +# define BOOST_NO_CXX11_HDR_TYPE_TRAITS +# define BOOST_NO_CXX11_HDR_FUTURE +#endif + + +#if _LIBCPP_VERSION < 3700 +// libc++ uses a non-standard messages_base +#define BOOST_NO_STD_MESSAGES +#endif + +// C++14 features +#if (_LIBCPP_VERSION < 3700) || (__cplusplus <= 201402L) +# define BOOST_NO_CXX14_STD_EXCHANGE +#endif + +// C++17 features +#if (_LIBCPP_VERSION < 4000) || (__cplusplus <= 201402L) +# define BOOST_NO_CXX17_STD_APPLY +# define BOOST_NO_CXX17_HDR_OPTIONAL +# define BOOST_NO_CXX17_HDR_STRING_VIEW +# define BOOST_NO_CXX17_HDR_VARIANT +#endif +#if (_LIBCPP_VERSION > 4000) && (__cplusplus > 201402L) && !defined(_LIBCPP_ENABLE_CXX17_REMOVED_AUTO_PTR) +# define BOOST_NO_AUTO_PTR +#endif +#if (_LIBCPP_VERSION > 4000) && (__cplusplus > 201402L) && !defined(_LIBCPP_ENABLE_CXX17_REMOVED_RANDOM_SHUFFLE) +# define BOOST_NO_CXX98_RANDOM_SHUFFLE +#endif +#if (_LIBCPP_VERSION > 4000) && (__cplusplus > 201402L) && !defined(_LIBCPP_ENABLE_CXX17_REMOVED_BINDERS) +# define BOOST_NO_CXX98_BINDERS +#endif + +#if defined(__cplusplus) && defined(__has_include) +#if __has_include() +#include + +#if !defined(__cpp_lib_execution) || (__cpp_lib_execution < 201603L) +# define BOOST_NO_CXX17_HDR_EXECUTION +#endif +#if !defined(__cpp_lib_invoke) || (__cpp_lib_invoke < 201411L) +#define BOOST_NO_CXX17_STD_INVOKE +#endif + +#if(_LIBCPP_VERSION < 9000) +// as_writable_bytes is missing. +# define BOOST_NO_CXX20_HDR_SPAN +#endif + +#else +#define BOOST_NO_CXX17_STD_INVOKE // Invoke support is incomplete (no invoke_result) +#define BOOST_NO_CXX17_HDR_EXECUTION +#endif +#else +#define BOOST_NO_CXX17_STD_INVOKE // Invoke support is incomplete (no invoke_result) +#define BOOST_NO_CXX17_HDR_EXECUTION +#endif + +#if _LIBCPP_VERSION < 10000 // What's the correct version check here? +#define BOOST_NO_CXX17_ITERATOR_TRAITS +#endif + +#if (_LIBCPP_VERSION <= 1101) && !defined(BOOST_NO_CXX11_THREAD_LOCAL) +// This is a bit of a sledgehammer, because really it's just libc++abi that has no +// support for thread_local, leading to linker errors such as +// "undefined reference to `__cxa_thread_atexit'". It is fixed in the +// most recent releases of libc++abi though... +# define BOOST_NO_CXX11_THREAD_LOCAL +#endif + +#if defined(__linux__) && (_LIBCPP_VERSION < 6000) && !defined(BOOST_NO_CXX11_THREAD_LOCAL) +// After libc++-dev is installed on Trusty, clang++-libc++ almost works, +// except uses of `thread_local` fail with undefined reference to +// `__cxa_thread_atexit`. +// +// clang's libc++abi provides an implementation by deferring to the glibc +// implementation, which may or may not be available (it is not on Trusty). +// clang 4's libc++abi will provide an implementation if one is not in glibc +// though, so thread local support should work with clang 4 and above as long +// as libc++abi is linked in. +# define BOOST_NO_CXX11_THREAD_LOCAL +#endif + +#if defined(__has_include) +#if !__has_include() +# define BOOST_NO_CXX14_HDR_SHARED_MUTEX +#elif __cplusplus <= 201103 +# define BOOST_NO_CXX14_HDR_SHARED_MUTEX +#endif +#elif __cplusplus < 201402 +# define BOOST_NO_CXX14_HDR_SHARED_MUTEX +#endif + +#if !defined(BOOST_NO_CXX14_HDR_SHARED_MUTEX) && (_LIBCPP_VERSION < 5000) +# define BOOST_NO_CXX14_HDR_SHARED_MUTEX +#endif + +#if _LIBCPP_VERSION >= 15000 +// +// Unary function is now deprecated in C++11 and later: +// +#if __cplusplus >= 201103L +#define BOOST_NO_CXX98_FUNCTION_BASE +#endif +#endif + +// --- end --- diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/stdlib/libstdcpp3.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/stdlib/libstdcpp3.hpp new file mode 100644 index 0000000..ad70936 --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/stdlib/libstdcpp3.hpp @@ -0,0 +1,482 @@ +// (C) Copyright John Maddock 2001. +// (C) Copyright Jens Maurer 2001. +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for most recent version. + +// config for libstdc++ v3 +// not much to go in here: + +#define BOOST_GNU_STDLIB 1 + +#ifdef __GLIBCXX__ +#define BOOST_STDLIB "GNU libstdc++ version " BOOST_STRINGIZE(__GLIBCXX__) +#else +#define BOOST_STDLIB "GNU libstdc++ version " BOOST_STRINGIZE(__GLIBCPP__) +#endif + +#if !defined(_GLIBCPP_USE_WCHAR_T) && !defined(_GLIBCXX_USE_WCHAR_T) +# define BOOST_NO_CWCHAR +# define BOOST_NO_CWCTYPE +# define BOOST_NO_STD_WSTRING +# define BOOST_NO_STD_WSTREAMBUF +#endif + +#if defined(__osf__) && !defined(_REENTRANT) \ + && ( defined(_GLIBCXX_HAVE_GTHR_DEFAULT) || defined(_GLIBCPP_HAVE_GTHR_DEFAULT) ) +// GCC 3 on Tru64 forces the definition of _REENTRANT when any std lib header +// file is included, therefore for consistency we define it here as well. +# define _REENTRANT +#endif + +#ifdef __GLIBCXX__ // gcc 3.4 and greater: +# if defined(_GLIBCXX_HAVE_GTHR_DEFAULT) \ + || defined(_GLIBCXX__PTHREADS) \ + || defined(_GLIBCXX_HAS_GTHREADS) \ + || defined(_WIN32) \ + || defined(_AIX) \ + || defined(__HAIKU__) + // + // If the std lib has thread support turned on, then turn it on in Boost + // as well. We do this because some gcc-3.4 std lib headers define _REENTANT + // while others do not... + // +# define BOOST_HAS_THREADS +# else +# define BOOST_DISABLE_THREADS +# endif +#elif defined(__GLIBCPP__) \ + && !defined(_GLIBCPP_HAVE_GTHR_DEFAULT) \ + && !defined(_GLIBCPP__PTHREADS) + // disable thread support if the std lib was built single threaded: +# define BOOST_DISABLE_THREADS +#endif + +#if (defined(linux) || defined(__linux) || defined(__linux__)) && defined(__arm__) && defined(_GLIBCPP_HAVE_GTHR_DEFAULT) +// linux on arm apparently doesn't define _REENTRANT +// so just turn on threading support whenever the std lib is thread safe: +# define BOOST_HAS_THREADS +#endif + +#if !defined(_GLIBCPP_USE_LONG_LONG) \ + && !defined(_GLIBCXX_USE_LONG_LONG)\ + && defined(BOOST_HAS_LONG_LONG) +// May have been set by compiler/*.hpp, but "long long" without library +// support is useless. +# undef BOOST_HAS_LONG_LONG +#endif + +// Apple doesn't seem to reliably defined a *unix* macro +#if !defined(CYGWIN) && ( defined(__unix__) \ + || defined(__unix) \ + || defined(unix) \ + || defined(__APPLE__) \ + || defined(__APPLE) \ + || defined(APPLE)) +# include +#endif + +#ifndef __VXWORKS__ // VxWorks uses Dinkum, not GNU STL with GCC +#if defined(__GLIBCXX__) || (defined(__GLIBCPP__) && __GLIBCPP__>=20020514) // GCC >= 3.1.0 +# define BOOST_STD_EXTENSION_NAMESPACE __gnu_cxx +# define BOOST_HAS_SLIST +# define BOOST_HAS_HASH +# define BOOST_SLIST_HEADER +# if !defined(__GNUC__) || __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 3) +# define BOOST_HASH_SET_HEADER +# define BOOST_HASH_MAP_HEADER +# else +# define BOOST_HASH_SET_HEADER +# define BOOST_HASH_MAP_HEADER +# endif +#endif +#endif + +#if defined(__has_include) +#if defined(BOOST_HAS_HASH) +#if !__has_include(BOOST_HASH_SET_HEADER) || (__GNUC__ >= 10) +#undef BOOST_HAS_HASH +#undef BOOST_HAS_SET_HEADER +#undef BOOST_HAS_MAP_HEADER +#endif +#if !__has_include(BOOST_SLIST_HEADER) +#undef BOOST_HAS_SLIST +#undef BOOST_HAS_SLIST_HEADER +#endif +#endif +#endif + +// +// Decide whether we have C++11 support turned on: +// +#if defined(__GXX_EXPERIMENTAL_CXX0X__) || (__cplusplus >= 201103) +# define BOOST_LIBSTDCXX11 +#endif + +// +// Decide which version of libstdc++ we have, normally +// libstdc++ C++0x support is detected via __GNUC__, __GNUC_MINOR__, and possibly +// __GNUC_PATCHLEVEL__ at the suggestion of Jonathan Wakely, one of the libstdc++ +// developers. He also commented: +// +// "I'm not sure how useful __GLIBCXX__ is for your purposes, for instance in +// GCC 4.2.4 it is set to 20080519 but in GCC 4.3.0 it is set to 20080305. +// Although 4.3.0 was released earlier than 4.2.4, it has better C++0x support +// than any release in the 4.2 series." +// +// Another resource for understanding libstdc++ features is: +// http://gcc.gnu.org/onlinedocs/libstdc++/manual/status.html#manual.intro.status.standard.200x +// +// However, using the GCC version number fails when the compiler is clang since this +// only ever claims to emulate GCC-4.2, see https://svn.boost.org/trac/boost/ticket/7473 +// for a long discussion on this issue. What we can do though is use clang's __has_include +// to detect the presence of a C++11 header that was introduced with a specific GCC release. +// We still have to be careful though as many such headers were buggy and/or incomplete when +// first introduced, so we only check for headers that were fully featured from day 1, and then +// use that to infer the underlying GCC version: +// +#ifdef __clang__ + +#ifdef _GLIBCXX_RELEASE +# define BOOST_LIBSTDCXX_VERSION (_GLIBCXX_RELEASE * 10000 + 100) +#else +// +// We figure out which gcc version issued this std lib +// by checking which headers are available: +// +#if __has_include() +# define BOOST_LIBSTDCXX_VERSION 120100 +#elif __has_include() +# define BOOST_LIBSTDCXX_VERSION 110100 +#elif __has_include() +# define BOOST_LIBSTDCXX_VERSION 100100 +#elif __has_include() +# define BOOST_LIBSTDCXX_VERSION 90100 +#elif __has_include() +# define BOOST_LIBSTDCXX_VERSION 80100 +#elif __has_include() +# define BOOST_LIBSTDCXX_VERSION 70100 +#elif __has_include() +# define BOOST_LIBSTDCXX_VERSION 60100 +#elif __has_include() +# define BOOST_LIBSTDCXX_VERSION 50100 +#elif __has_include() +# define BOOST_LIBSTDCXX_VERSION 40900 +#elif __has_include() +# define BOOST_LIBSTDCXX_VERSION 40800 +#elif __has_include() +# define BOOST_LIBSTDCXX_VERSION 40700 +#elif __has_include() +# define BOOST_LIBSTDCXX_VERSION 40600 +#elif __has_include() +# define BOOST_LIBSTDCXX_VERSION 40500 +#elif __has_include() +# define BOOST_LIBSTDCXX_VERSION 40400 +#elif __has_include() +# define BOOST_LIBSTDCXX_VERSION 40300 +#endif +#endif +// +// If BOOST_HAS_FLOAT128 is set, now that we know the std lib is libstdc++3, check to see if the std lib is +// configured to support this type. If not disable it: +// +#if defined(BOOST_HAS_FLOAT128) && !defined(_GLIBCXX_USE_FLOAT128) +# undef BOOST_HAS_FLOAT128 +#endif + +#if (BOOST_LIBSTDCXX_VERSION >= 100000) && defined(BOOST_HAS_HASH) +// +// hash_set/hash_map deprecated and have terminal bugs: +// +#undef BOOST_HAS_HASH +#undef BOOST_HAS_SET_HEADER +#undef BOOST_HAS_MAP_HEADER +#endif + + +#if (BOOST_LIBSTDCXX_VERSION >= 100000) && defined(BOOST_HAS_HASH) +// +// hash_set/hash_map deprecated and have terminal bugs: +// +#undef BOOST_HAS_HASH +#undef BOOST_HAS_SET_HEADER +#undef BOOST_HAS_MAP_HEADER +#endif + + +#if (BOOST_LIBSTDCXX_VERSION < 50100) +// libstdc++ does not define this function as it's deprecated in C++11, but clang still looks for it, +// defining it here is a terrible cludge, but should get things working: +extern "C" char *gets (char *__s); +#endif +// +// clang is unable to parse some GCC headers, add those workarounds here: +// +#if BOOST_LIBSTDCXX_VERSION < 50000 +# define BOOST_NO_CXX11_HDR_REGEX +#endif +// +// GCC 4.7.x has no __cxa_thread_atexit which +// thread_local objects require for cleanup: +// +#if BOOST_LIBSTDCXX_VERSION < 40800 +# define BOOST_NO_CXX11_THREAD_LOCAL +#endif +// +// Early clang versions can handle , not exactly sure which versions +// but certainly up to clang-3.8 and gcc-4.6: +// +#if (__clang_major__ < 5) +# if BOOST_LIBSTDCXX_VERSION < 40800 +# define BOOST_NO_CXX11_HDR_FUTURE +# define BOOST_NO_CXX11_HDR_MUTEX +# define BOOST_NO_CXX11_HDR_CONDITION_VARIABLE +# define BOOST_NO_CXX11_HDR_CHRONO +# endif +#endif + +// +// GCC 4.8 and 9 add working versions of and respectively. +// However, we have no test for these as the headers were present but broken +// in early GCC versions. +// +#endif + +#if defined(__SUNPRO_CC) && (__SUNPRO_CC >= 0x5130) && (__cplusplus >= 201103L) +// +// Oracle Solaris compiler uses it's own verison of libstdc++ but doesn't +// set __GNUC__ +// +#if __SUNPRO_CC >= 0x5140 +#define BOOST_LIBSTDCXX_VERSION 50100 +#else +#define BOOST_LIBSTDCXX_VERSION 40800 +#endif +#endif + +#if !defined(BOOST_LIBSTDCXX_VERSION) +# define BOOST_LIBSTDCXX_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) +#endif + +// std::auto_ptr isn't provided with _GLIBCXX_DEPRECATED=0 (GCC 4.5 and earlier) +// or _GLIBCXX_USE_DEPRECATED=0 (GCC 4.6 and later). +#if defined(BOOST_LIBSTDCXX11) +# if BOOST_LIBSTDCXX_VERSION < 40600 +# if !_GLIBCXX_DEPRECATED +# define BOOST_NO_AUTO_PTR +# endif +# elif !defined(_GLIBCXX_USE_DEPRECATED) || !_GLIBCXX_USE_DEPRECATED +# define BOOST_NO_AUTO_PTR +# define BOOST_NO_CXX98_BINDERS +# endif +#endif + +// C++0x headers in GCC 4.3.0 and later +// +#if (BOOST_LIBSTDCXX_VERSION < 40300) || !defined(BOOST_LIBSTDCXX11) +# define BOOST_NO_CXX11_HDR_ARRAY +# define BOOST_NO_CXX11_HDR_TUPLE +# define BOOST_NO_CXX11_HDR_UNORDERED_MAP +# define BOOST_NO_CXX11_HDR_UNORDERED_SET +# define BOOST_NO_CXX11_HDR_FUNCTIONAL +#endif + +// C++0x headers in GCC 4.4.0 and later +// +#if (BOOST_LIBSTDCXX_VERSION < 40400) || !defined(BOOST_LIBSTDCXX11) +# define BOOST_NO_CXX11_HDR_CONDITION_VARIABLE +# define BOOST_NO_CXX11_HDR_FORWARD_LIST +# define BOOST_NO_CXX11_HDR_INITIALIZER_LIST +# define BOOST_NO_CXX11_HDR_MUTEX +# define BOOST_NO_CXX11_HDR_RATIO +# define BOOST_NO_CXX11_HDR_SYSTEM_ERROR +# define BOOST_NO_CXX11_SMART_PTR +# define BOOST_NO_CXX11_HDR_EXCEPTION +#else +# define BOOST_HAS_TR1_COMPLEX_INVERSE_TRIG +# define BOOST_HAS_TR1_COMPLEX_OVERLOADS +#endif + +// C++0x features in GCC 4.5.0 and later +// +#if (BOOST_LIBSTDCXX_VERSION < 40500) || !defined(BOOST_LIBSTDCXX11) +# define BOOST_NO_CXX11_NUMERIC_LIMITS +# define BOOST_NO_CXX11_HDR_FUTURE +# define BOOST_NO_CXX11_HDR_RANDOM +#endif + +// C++0x features in GCC 4.6.0 and later +// +#if (BOOST_LIBSTDCXX_VERSION < 40600) || !defined(BOOST_LIBSTDCXX11) +# define BOOST_NO_CXX11_HDR_TYPEINDEX +# define BOOST_NO_CXX11_ADDRESSOF +# define BOOST_NO_CXX17_ITERATOR_TRAITS +#endif + +// C++0x features in GCC 4.7.0 and later +// +#if (BOOST_LIBSTDCXX_VERSION < 40700) || !defined(BOOST_LIBSTDCXX11) +// Note that although existed prior to 4.7, "steady_clock" is spelled "monotonic_clock" +// so 4.7.0 is the first truly conforming one. +# define BOOST_NO_CXX11_HDR_CHRONO +# define BOOST_NO_CXX11_ALLOCATOR +# define BOOST_NO_CXX11_POINTER_TRAITS +#endif +// C++0x features in GCC 4.8.0 and later +// +#if (BOOST_LIBSTDCXX_VERSION < 40800) || !defined(BOOST_LIBSTDCXX11) +// Note that although existed prior to gcc 4.8 it was largely unimplemented for many types: +# define BOOST_NO_CXX11_HDR_ATOMIC +# define BOOST_NO_CXX11_HDR_THREAD +#endif +// C++0x features in GCC 4.9.0 and later +// +#if (BOOST_LIBSTDCXX_VERSION < 40900) || !defined(BOOST_LIBSTDCXX11) +// Although is present and compilable against, the actual implementation is not functional +// even for the simplest patterns such as "\d" or "[0-9]". This is the case at least in gcc up to 4.8, inclusively. +# define BOOST_NO_CXX11_HDR_REGEX +#endif +#if (BOOST_LIBSTDCXX_VERSION < 40900) || (__cplusplus <= 201103) +# define BOOST_NO_CXX14_STD_EXCHANGE +#endif + +// +// C++0x features in GCC 5.1 and later +// +#if (BOOST_LIBSTDCXX_VERSION < 50100) || !defined(BOOST_LIBSTDCXX11) +# define BOOST_NO_CXX11_HDR_TYPE_TRAITS +# define BOOST_NO_CXX11_HDR_CODECVT +# define BOOST_NO_CXX11_ATOMIC_SMART_PTR +# define BOOST_NO_CXX11_STD_ALIGN +#endif + +// +// C++17 features in GCC 7.1 and later +// +#if (BOOST_LIBSTDCXX_VERSION < 70100) || (__cplusplus <= 201402L) +# define BOOST_NO_CXX17_STD_INVOKE +# define BOOST_NO_CXX17_STD_APPLY +# define BOOST_NO_CXX17_HDR_OPTIONAL +# define BOOST_NO_CXX17_HDR_STRING_VIEW +# define BOOST_NO_CXX17_HDR_VARIANT +#endif + +#if defined(__has_include) +#if !__has_include() +# define BOOST_NO_CXX14_HDR_SHARED_MUTEX +#elif __cplusplus <= 201103 +# define BOOST_NO_CXX14_HDR_SHARED_MUTEX +#endif +// +// has a dependency to Intel's thread building blocks: +// unless these are installed seperately, including leads +// to inscrutable errors inside libstdc++'s own headers. +// +#if (BOOST_LIBSTDCXX_VERSION < 100100) +#if !__has_include() +#define BOOST_NO_CXX17_HDR_EXECUTION +#endif +#endif +#elif __cplusplus < 201402 || (BOOST_LIBSTDCXX_VERSION < 40900) || !defined(BOOST_LIBSTDCXX11) +# define BOOST_NO_CXX14_HDR_SHARED_MUTEX +#endif + +#if BOOST_LIBSTDCXX_VERSION < 100100 +// +// The header may be present but is incomplete: +// +# define BOOST_NO_CXX17_HDR_CHARCONV +#endif + +#if BOOST_LIBSTDCXX_VERSION < 110000 +// +// Header may be present but lacks std::bit_cast: +// +#define BOOST_NO_CXX20_HDR_BIT +#endif + +#if BOOST_LIBSTDCXX_VERSION >= 120000 +// +// Unary function is now deprecated in C++11 and later: +// +#if __cplusplus >= 201103L +#define BOOST_NO_CXX98_FUNCTION_BASE +#endif +#endif + +#ifndef __cpp_impl_coroutine +# define BOOST_NO_CXX20_HDR_COROUTINE +#endif + +// +// These next defines are mostly for older clang versions with a newer libstdc++ : +// +#if !defined(__cpp_lib_concepts) +#if !defined(BOOST_NO_CXX20_HDR_COMPARE) +# define BOOST_NO_CXX20_HDR_COMPARE +#endif +#if !defined(BOOST_NO_CXX20_HDR_CONCEPTS) +# define BOOST_NO_CXX20_HDR_CONCEPTS +#endif +#if !defined(BOOST_NO_CXX20_HDR_SPAN) +# define BOOST_NO_CXX20_HDR_SPAN +#endif +#if !defined(BOOST_NO_CXX20_HDR_RANGES) +# define BOOST_NO_CXX20_HDR_RANGES +#endif +#endif + +#if defined(__clang__) +#if (__clang_major__ < 11) && !defined(BOOST_NO_CXX20_HDR_RANGES) +# define BOOST_NO_CXX20_HDR_RANGES +#endif +#if (__clang_major__ < 10) && (BOOST_LIBSTDCXX_VERSION >= 110000) && !defined(BOOST_NO_CXX11_HDR_CHRONO) +// Old clang can't parse : +# define BOOST_NO_CXX11_HDR_CHRONO +# define BOOST_NO_CXX11_HDR_CONDITION_VARIABLE +#endif +#endif + +#if defined(__clang__) && (BOOST_LIBSTDCXX_VERSION < 40300) && !defined(BOOST_NO_CXX11_NULLPTR) +# define BOOST_NO_CXX11_NULLPTR +#endif +#if defined(__clang__) && (BOOST_LIBSTDCXX_VERSION < 40300) && defined(BOOST_HAS_INT128) && defined(__APPLE_CC__) +#undef BOOST_HAS_INT128 +#endif + +// +// Headers not present on Solaris with the Oracle compiler: +#if defined(__SUNPRO_CC) && (__SUNPRO_CC < 0x5140) +#define BOOST_NO_CXX11_HDR_FUTURE +#define BOOST_NO_CXX11_HDR_FORWARD_LIST +#define BOOST_NO_CXX11_HDR_ATOMIC +// shared_ptr is present, but is not convertible to bool +// which causes all kinds of problems especially in Boost.Thread +// but probably elsewhere as well. +#define BOOST_NO_CXX11_SMART_PTR +#endif + +#if (!defined(_GLIBCXX_HAS_GTHREADS) || !defined(_GLIBCXX_USE_C99_STDINT_TR1)) + // Headers not always available: +# ifndef BOOST_NO_CXX11_HDR_CONDITION_VARIABLE +# define BOOST_NO_CXX11_HDR_CONDITION_VARIABLE +# endif +# ifndef BOOST_NO_CXX11_HDR_MUTEX +# define BOOST_NO_CXX11_HDR_MUTEX +# endif +# ifndef BOOST_NO_CXX11_HDR_THREAD +# define BOOST_NO_CXX11_HDR_THREAD +# endif +# ifndef BOOST_NO_CXX14_HDR_SHARED_MUTEX +# define BOOST_NO_CXX14_HDR_SHARED_MUTEX +# endif +#endif + +#if (!defined(_GTHREAD_USE_MUTEX_TIMEDLOCK) || (_GTHREAD_USE_MUTEX_TIMEDLOCK == 0)) && !defined(BOOST_NO_CXX11_HDR_MUTEX) && (__GNUC__ < 6) +// Timed mutexes are not always available: +# define BOOST_NO_CXX11_HDR_MUTEX +#endif + +// --- end --- diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/stdlib/modena.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/stdlib/modena.hpp new file mode 100644 index 0000000..31a26c8 --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/stdlib/modena.hpp @@ -0,0 +1,79 @@ +// (C) Copyright Jens Maurer 2001. +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for most recent version. + +// Modena C++ standard library (comes with KAI C++) + +#if !defined(MSIPL_COMPILE_H) +# include +# if !defined(__MSIPL_COMPILE_H) +# error "This is not the Modena C++ library!" +# endif +#endif + +#ifndef MSIPL_NL_TYPES +#define BOOST_NO_STD_MESSAGES +#endif + +#ifndef MSIPL_WCHART +#define BOOST_NO_STD_WSTRING +#endif + +// C++0x headers not yet implemented +// +# define BOOST_NO_CXX11_HDR_ARRAY +# define BOOST_NO_CXX11_HDR_CHRONO +# define BOOST_NO_CXX11_HDR_CODECVT +# define BOOST_NO_CXX11_HDR_CONDITION_VARIABLE +# define BOOST_NO_CXX11_HDR_FORWARD_LIST +# define BOOST_NO_CXX11_HDR_FUTURE +# define BOOST_NO_CXX11_HDR_INITIALIZER_LIST +# define BOOST_NO_CXX11_HDR_MUTEX +# define BOOST_NO_CXX11_HDR_RANDOM +# define BOOST_NO_CXX11_HDR_RATIO +# define BOOST_NO_CXX11_HDR_REGEX +# define BOOST_NO_CXX11_HDR_SYSTEM_ERROR +# define BOOST_NO_CXX11_HDR_THREAD +# define BOOST_NO_CXX11_HDR_TUPLE +# define BOOST_NO_CXX11_HDR_TYPE_TRAITS +# define BOOST_NO_CXX11_HDR_TYPEINDEX +# define BOOST_NO_CXX11_HDR_UNORDERED_MAP +# define BOOST_NO_CXX11_HDR_UNORDERED_SET +# define BOOST_NO_CXX11_NUMERIC_LIMITS +# define BOOST_NO_CXX11_ALLOCATOR +# define BOOST_NO_CXX11_POINTER_TRAITS +# define BOOST_NO_CXX11_ATOMIC_SMART_PTR +# define BOOST_NO_CXX11_SMART_PTR +# define BOOST_NO_CXX11_HDR_FUNCTIONAL +# define BOOST_NO_CXX11_HDR_ATOMIC +# define BOOST_NO_CXX11_STD_ALIGN +# define BOOST_NO_CXX11_ADDRESSOF +# define BOOST_NO_CXX11_HDR_EXCEPTION + +#if defined(__has_include) +#if !__has_include() +# define BOOST_NO_CXX14_HDR_SHARED_MUTEX +#elif __cplusplus < 201402 +# define BOOST_NO_CXX14_HDR_SHARED_MUTEX +#endif +#else +# define BOOST_NO_CXX14_HDR_SHARED_MUTEX +#endif + +// C++14 features +# define BOOST_NO_CXX14_STD_EXCHANGE + +// C++17 features +# define BOOST_NO_CXX17_STD_APPLY +# define BOOST_NO_CXX17_STD_INVOKE +# define BOOST_NO_CXX17_ITERATOR_TRAITS + +#define BOOST_STDLIB "Modena C++ standard library" + + + + + diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/stdlib/msl.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/stdlib/msl.hpp new file mode 100644 index 0000000..f2f8259 --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/stdlib/msl.hpp @@ -0,0 +1,98 @@ +// (C) Copyright John Maddock 2001. +// (C) Copyright Darin Adler 2001. +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for most recent version. + +// Metrowerks standard library: + +#ifndef __MSL_CPP__ +# include +# ifndef __MSL_CPP__ +# error This is not the MSL standard library! +# endif +#endif + +#if __MSL_CPP__ >= 0x6000 // Pro 6 +# define BOOST_HAS_HASH +# define BOOST_STD_EXTENSION_NAMESPACE Metrowerks +#endif +#define BOOST_HAS_SLIST + +#if __MSL_CPP__ < 0x6209 +# define BOOST_NO_STD_MESSAGES +#endif + +// check C lib version for +#include + +#if defined(__MSL__) && (__MSL__ >= 0x5000) +# define BOOST_HAS_STDINT_H +# if !defined(__PALMOS_TRAPS__) +# define BOOST_HAS_UNISTD_H +# endif + // boilerplate code: +# include +#endif + +#if defined(_MWMT) || _MSL_THREADSAFE +# define BOOST_HAS_THREADS +#endif + +#ifdef _MSL_NO_EXPLICIT_FUNC_TEMPLATE_ARG +# define BOOST_NO_STD_USE_FACET +# define BOOST_HAS_TWO_ARG_USE_FACET +#endif + +// C++0x headers not yet implemented +// +# define BOOST_NO_CXX11_HDR_ARRAY +# define BOOST_NO_CXX11_HDR_CHRONO +# define BOOST_NO_CXX11_HDR_CODECVT +# define BOOST_NO_CXX11_HDR_CONDITION_VARIABLE +# define BOOST_NO_CXX11_HDR_FORWARD_LIST +# define BOOST_NO_CXX11_HDR_FUTURE +# define BOOST_NO_CXX11_HDR_INITIALIZER_LIST +# define BOOST_NO_CXX11_HDR_MUTEX +# define BOOST_NO_CXX11_HDR_RANDOM +# define BOOST_NO_CXX11_HDR_RATIO +# define BOOST_NO_CXX11_HDR_REGEX +# define BOOST_NO_CXX11_HDR_SYSTEM_ERROR +# define BOOST_NO_CXX11_HDR_THREAD +# define BOOST_NO_CXX11_HDR_TUPLE +# define BOOST_NO_CXX11_HDR_TYPE_TRAITS +# define BOOST_NO_CXX11_HDR_TYPEINDEX +# define BOOST_NO_CXX11_HDR_UNORDERED_MAP +# define BOOST_NO_CXX11_HDR_UNORDERED_SET +# define BOOST_NO_CXX11_NUMERIC_LIMITS +# define BOOST_NO_CXX11_ALLOCATOR +# define BOOST_NO_CXX11_POINTER_TRAITS +# define BOOST_NO_CXX11_ATOMIC_SMART_PTR +# define BOOST_NO_CXX11_SMART_PTR +# define BOOST_NO_CXX11_HDR_FUNCTIONAL +# define BOOST_NO_CXX11_HDR_ATOMIC +# define BOOST_NO_CXX11_STD_ALIGN +# define BOOST_NO_CXX11_ADDRESSOF +# define BOOST_NO_CXX11_HDR_EXCEPTION + +#if defined(__has_include) +#if !__has_include() +# define BOOST_NO_CXX14_HDR_SHARED_MUTEX +#elif __cplusplus < 201402 +# define BOOST_NO_CXX14_HDR_SHARED_MUTEX +#endif +#else +# define BOOST_NO_CXX14_HDR_SHARED_MUTEX +#endif + +// C++14 features +# define BOOST_NO_CXX14_STD_EXCHANGE + +// C++17 features +# define BOOST_NO_CXX17_STD_APPLY +# define BOOST_NO_CXX17_STD_INVOKE +# define BOOST_NO_CXX17_ITERATOR_TRAITS + +#define BOOST_STDLIB "Metrowerks Standard Library version " BOOST_STRINGIZE(__MSL_CPP__) diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/stdlib/roguewave.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/stdlib/roguewave.hpp new file mode 100644 index 0000000..03a6576 --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/stdlib/roguewave.hpp @@ -0,0 +1,208 @@ +// (C) Copyright John Maddock 2001 - 2003. +// (C) Copyright Jens Maurer 2001. +// (C) Copyright David Abrahams 2003. +// (C) Copyright Boris Gubenko 2007. +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for most recent version. + +// Rogue Wave std lib: + +#define BOOST_RW_STDLIB 1 + +#if !defined(__STD_RWCOMPILER_H__) && !defined(_RWSTD_VER) +# include +# if !defined(__STD_RWCOMPILER_H__) && !defined(_RWSTD_VER) +# error This is not the Rogue Wave standard library +# endif +#endif +// +// figure out a consistent version number: +// +#ifndef _RWSTD_VER +# define BOOST_RWSTD_VER 0x010000 +#elif _RWSTD_VER < 0x010000 +# define BOOST_RWSTD_VER (_RWSTD_VER << 8) +#else +# define BOOST_RWSTD_VER _RWSTD_VER +#endif + +#ifndef _RWSTD_VER +# define BOOST_STDLIB "Rogue Wave standard library version (Unknown version)" +#elif _RWSTD_VER < 0x04010200 + # define BOOST_STDLIB "Rogue Wave standard library version " BOOST_STRINGIZE(_RWSTD_VER) +#else +# ifdef _RWSTD_VER_STR +# define BOOST_STDLIB "Apache STDCXX standard library version " _RWSTD_VER_STR +# else +# define BOOST_STDLIB "Apache STDCXX standard library version " BOOST_STRINGIZE(_RWSTD_VER) +# endif +#endif + +// +// Prior to version 2.2.0 the primary template for std::numeric_limits +// does not have compile time constants, even though specializations of that +// template do: +// +#if BOOST_RWSTD_VER < 0x020200 +# define BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS +#endif + +// Sun CC 5.5 patch 113817-07 adds long long specialization, but does not change the +// library version number (http://sunsolve6.sun.com/search/document.do?assetkey=1-21-113817): +#if BOOST_RWSTD_VER <= 0x020101 && (!defined(__SUNPRO_CC) || (__SUNPRO_CC < 0x550)) +# define BOOST_NO_LONG_LONG_NUMERIC_LIMITS +# endif + +// +// Borland version of numeric_limits lacks __int64 specialisation: +// +#ifdef BOOST_BORLANDC +# define BOOST_NO_MS_INT64_NUMERIC_LIMITS +#endif + +// +// No std::iterator if it can't figure out default template args: +// +#if defined(_RWSTD_NO_SIMPLE_DEFAULT_TEMPLATES) || defined(RWSTD_NO_SIMPLE_DEFAULT_TEMPLATES) || (BOOST_RWSTD_VER < 0x020000) +# define BOOST_NO_STD_ITERATOR +#endif + +// +// No iterator traits without partial specialization: +// +#if defined(_RWSTD_NO_CLASS_PARTIAL_SPEC) || defined(RWSTD_NO_CLASS_PARTIAL_SPEC) +# define BOOST_NO_STD_ITERATOR_TRAITS +#endif + +// +// Prior to version 2.0, std::auto_ptr was buggy, and there were no +// new-style iostreams, and no conformant std::allocator: +// +#if (BOOST_RWSTD_VER < 0x020000) +# define BOOST_NO_AUTO_PTR +# define BOOST_NO_STRINGSTREAM +# define BOOST_NO_STD_ALLOCATOR +# define BOOST_NO_STD_LOCALE +#endif + +// +// No template iterator constructors without member template support: +// +#if defined(RWSTD_NO_MEMBER_TEMPLATES) || defined(_RWSTD_NO_MEMBER_TEMPLATES) +# define BOOST_NO_TEMPLATED_ITERATOR_CONSTRUCTORS +#endif + +// +// RW defines _RWSTD_ALLOCATOR if the allocator is conformant and in use +// (the or _HPACC_ part is a hack - the library seems to define _RWSTD_ALLOCATOR +// on HP aCC systems even though the allocator is in fact broken): +// +#if !defined(_RWSTD_ALLOCATOR) || (defined(__HP_aCC) && __HP_aCC <= 33100) +# define BOOST_NO_STD_ALLOCATOR +#endif + +// +// If we have a std::locale, we still may not have std::use_facet: +// +#if defined(_RWSTD_NO_TEMPLATE_ON_RETURN_TYPE) && !defined(BOOST_NO_STD_LOCALE) +# define BOOST_NO_STD_USE_FACET +# define BOOST_HAS_TWO_ARG_USE_FACET +#endif + +// +// There's no std::distance prior to version 2, or without +// partial specialization support: +// +#if (BOOST_RWSTD_VER < 0x020000) || defined(_RWSTD_NO_CLASS_PARTIAL_SPEC) + #define BOOST_NO_STD_DISTANCE +#endif + +// +// Some versions of the rogue wave library don't have assignable +// OutputIterators: +// +#if BOOST_RWSTD_VER < 0x020100 +# define BOOST_NO_STD_OUTPUT_ITERATOR_ASSIGN +#endif + +// +// Disable BOOST_HAS_LONG_LONG when the library has no support for it. +// +#if !defined(_RWSTD_LONG_LONG) && defined(BOOST_HAS_LONG_LONG) +# undef BOOST_HAS_LONG_LONG +#endif + +// +// check that on HP-UX, the proper RW library is used +// +#if defined(__HP_aCC) && !defined(_HP_NAMESPACE_STD) +# error "Boost requires Standard RW library. Please compile and link with -AA" +#endif + +// +// Define macros specific to RW V2.2 on HP-UX +// +#if defined(__HP_aCC) && (BOOST_RWSTD_VER == 0x02020100) +# ifndef __HP_TC1_MAKE_PAIR +# define __HP_TC1_MAKE_PAIR +# endif +# ifndef _HP_INSTANTIATE_STD2_VL +# define _HP_INSTANTIATE_STD2_VL +# endif +#endif + +#if _RWSTD_VER < 0x05000000 +# define BOOST_NO_CXX11_HDR_ARRAY +#endif +// type_traits header is incomplete: +# define BOOST_NO_CXX11_HDR_TYPE_TRAITS +// +// C++0x headers not yet implemented +// +# define BOOST_NO_CXX11_HDR_CHRONO +# define BOOST_NO_CXX11_HDR_CODECVT +# define BOOST_NO_CXX11_HDR_CONDITION_VARIABLE +# define BOOST_NO_CXX11_HDR_FORWARD_LIST +# define BOOST_NO_CXX11_HDR_FUTURE +# define BOOST_NO_CXX11_HDR_INITIALIZER_LIST +# define BOOST_NO_CXX11_HDR_MUTEX +# define BOOST_NO_CXX11_HDR_RANDOM +# define BOOST_NO_CXX11_HDR_RATIO +# define BOOST_NO_CXX11_HDR_REGEX +# define BOOST_NO_CXX11_HDR_SYSTEM_ERROR +# define BOOST_NO_CXX11_HDR_THREAD +# define BOOST_NO_CXX11_HDR_TUPLE +# define BOOST_NO_CXX11_HDR_TYPEINDEX +# define BOOST_NO_CXX11_HDR_UNORDERED_MAP +# define BOOST_NO_CXX11_HDR_UNORDERED_SET +# define BOOST_NO_CXX11_NUMERIC_LIMITS +# define BOOST_NO_CXX11_ALLOCATOR +# define BOOST_NO_CXX11_POINTER_TRAITS +# define BOOST_NO_CXX11_ATOMIC_SMART_PTR +# define BOOST_NO_CXX11_SMART_PTR +# define BOOST_NO_CXX11_HDR_FUNCTIONAL +# define BOOST_NO_CXX11_HDR_ATOMIC +# define BOOST_NO_CXX11_STD_ALIGN +# define BOOST_NO_CXX11_ADDRESSOF +# define BOOST_NO_CXX11_HDR_EXCEPTION + +#if defined(__has_include) +#if !__has_include() +# define BOOST_NO_CXX14_HDR_SHARED_MUTEX +#elif __cplusplus < 201402 +# define BOOST_NO_CXX14_HDR_SHARED_MUTEX +#endif +#else +# define BOOST_NO_CXX14_HDR_SHARED_MUTEX +#endif + +// C++14 features +# define BOOST_NO_CXX14_STD_EXCHANGE + +// C++17 features +# define BOOST_NO_CXX17_STD_APPLY +# define BOOST_NO_CXX17_STD_INVOKE +# define BOOST_NO_CXX17_ITERATOR_TRAITS diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/stdlib/sgi.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/stdlib/sgi.hpp new file mode 100644 index 0000000..c49957c --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/stdlib/sgi.hpp @@ -0,0 +1,168 @@ +// (C) Copyright John Maddock 2001 - 2003. +// (C) Copyright Darin Adler 2001. +// (C) Copyright Jens Maurer 2001 - 2003. +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for most recent version. + +// generic SGI STL: + +#if !defined(__STL_CONFIG_H) +# include +# if !defined(__STL_CONFIG_H) +# error "This is not the SGI STL!" +# endif +#endif + +// +// No std::iterator traits without partial specialisation: +// +#if !defined(__STL_CLASS_PARTIAL_SPECIALIZATION) +# define BOOST_NO_STD_ITERATOR_TRAITS +#endif + +// +// No std::stringstream with gcc < 3 +// +#if defined(__GNUC__) && (__GNUC__ < 3) && \ + ((__GNUC_MINOR__ < 95) || (__GNUC_MINOR__ == 96)) && \ + !defined(__STL_USE_NEW_IOSTREAMS) || \ + defined(__APPLE_CC__) + // Note that we only set this for GNU C++ prior to 2.95 since the + // latest patches for that release do contain a minimal + // If you are running a 2.95 release prior to 2.95.3 then this will need + // setting, but there is no way to detect that automatically (other + // than by running the configure script). + // Also, the unofficial GNU C++ 2.96 included in RedHat 7.1 doesn't + // have . +# define BOOST_NO_STRINGSTREAM +#endif + +// Apple doesn't seem to reliably defined a *unix* macro +#if !defined(CYGWIN) && ( defined(__unix__) \ + || defined(__unix) \ + || defined(unix) \ + || defined(__APPLE__) \ + || defined(__APPLE) \ + || defined(APPLE)) +# include +#endif + + +// +// Assume no std::locale without own iostreams (this may be an +// incorrect assumption in some cases): +// +#if !defined(__SGI_STL_OWN_IOSTREAMS) && !defined(__STL_USE_NEW_IOSTREAMS) +# define BOOST_NO_STD_LOCALE +#endif + +// +// Original native SGI streams have non-standard std::messages facet: +// +#if defined(__sgi) && (_COMPILER_VERSION <= 650) && !defined(__SGI_STL_OWN_IOSTREAMS) +# define BOOST_NO_STD_LOCALE +#endif + +// +// SGI's new iostreams have missing "const" in messages<>::open +// +#if defined(__sgi) && (_COMPILER_VERSION <= 740) && defined(__STL_USE_NEW_IOSTREAMS) +# define BOOST_NO_STD_MESSAGES +#endif + +// +// No template iterator constructors, or std::allocator +// without member templates: +// +#if !defined(__STL_MEMBER_TEMPLATES) +# define BOOST_NO_TEMPLATED_ITERATOR_CONSTRUCTORS +# define BOOST_NO_STD_ALLOCATOR +#endif + +// +// We always have SGI style hash_set, hash_map, and slist: +// +#define BOOST_HAS_HASH +#define BOOST_HAS_SLIST + +// +// If this is GNU libstdc++2, then no and no std::wstring: +// +#if (defined(__GNUC__) && (__GNUC__ < 3)) +# include +# if defined(__BASTRING__) +# define BOOST_NO_LIMITS +// Note: will provide compile-time constants +# undef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS +# define BOOST_NO_STD_WSTRING +# endif +#endif + +// +// There is no standard iterator unless we have namespace support: +// +#if !defined(__STL_USE_NAMESPACES) +# define BOOST_NO_STD_ITERATOR +#endif + +// +// Intrinsic type_traits support. +// The SGI STL has it's own __type_traits class, which +// has intrinsic compiler support with SGI's compilers. +// Whatever map SGI style type traits to boost equivalents: +// +#define BOOST_HAS_SGI_TYPE_TRAITS + +// C++0x headers not yet implemented +// +# define BOOST_NO_CXX11_HDR_ARRAY +# define BOOST_NO_CXX11_HDR_CHRONO +# define BOOST_NO_CXX11_HDR_CODECVT +# define BOOST_NO_CXX11_HDR_CONDITION_VARIABLE +# define BOOST_NO_CXX11_HDR_FORWARD_LIST +# define BOOST_NO_CXX11_HDR_FUTURE +# define BOOST_NO_CXX11_HDR_INITIALIZER_LIST +# define BOOST_NO_CXX11_HDR_MUTEX +# define BOOST_NO_CXX11_HDR_RANDOM +# define BOOST_NO_CXX11_HDR_RATIO +# define BOOST_NO_CXX11_HDR_REGEX +# define BOOST_NO_CXX11_HDR_SYSTEM_ERROR +# define BOOST_NO_CXX11_HDR_THREAD +# define BOOST_NO_CXX11_HDR_TUPLE +# define BOOST_NO_CXX11_HDR_TYPE_TRAITS +# define BOOST_NO_CXX11_HDR_TYPEINDEX +# define BOOST_NO_CXX11_HDR_UNORDERED_MAP +# define BOOST_NO_CXX11_HDR_UNORDERED_SET +# define BOOST_NO_CXX11_NUMERIC_LIMITS +# define BOOST_NO_CXX11_ALLOCATOR +# define BOOST_NO_CXX11_POINTER_TRAITS +# define BOOST_NO_CXX11_ATOMIC_SMART_PTR +# define BOOST_NO_CXX11_SMART_PTR +# define BOOST_NO_CXX11_HDR_FUNCTIONAL +# define BOOST_NO_CXX11_HDR_ATOMIC +# define BOOST_NO_CXX11_STD_ALIGN +# define BOOST_NO_CXX11_ADDRESSOF +# define BOOST_NO_CXX11_HDR_EXCEPTION + +#if defined(__has_include) +#if !__has_include() +# define BOOST_NO_CXX14_HDR_SHARED_MUTEX +#elif __cplusplus < 201402 +# define BOOST_NO_CXX14_HDR_SHARED_MUTEX +#endif +#else +# define BOOST_NO_CXX14_HDR_SHARED_MUTEX +#endif + +// C++14 features +# define BOOST_NO_CXX14_STD_EXCHANGE + +// C++17 features +# define BOOST_NO_CXX17_STD_APPLY +# define BOOST_NO_CXX17_STD_INVOKE +# define BOOST_NO_CXX17_ITERATOR_TRAITS + +#define BOOST_STDLIB "SGI standard library" diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/stdlib/stlport.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/stdlib/stlport.hpp new file mode 100644 index 0000000..38bc763 --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/stdlib/stlport.hpp @@ -0,0 +1,258 @@ +// (C) Copyright John Maddock 2001 - 2002. +// (C) Copyright Darin Adler 2001. +// (C) Copyright Jens Maurer 2001. +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for most recent version. + +// STLPort standard library config: + +#if !defined(__SGI_STL_PORT) && !defined(_STLPORT_VERSION) +# include +# if !defined(__SGI_STL_PORT) && !defined(_STLPORT_VERSION) +# error "This is not STLPort!" +# endif +#endif + +// Apple doesn't seem to reliably defined a *unix* macro +#if !defined(CYGWIN) && ( defined(__unix__) \ + || defined(__unix) \ + || defined(unix) \ + || defined(__APPLE__) \ + || defined(__APPLE) \ + || defined(APPLE)) +# include +#endif + +// +// __STL_STATIC_CONST_INIT_BUG implies BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS +// for versions prior to 4.1(beta) +// +#if (defined(__STL_STATIC_CONST_INIT_BUG) || defined(_STLP_STATIC_CONST_INIT_BUG)) && (__SGI_STL_PORT <= 0x400) +# define BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS +#endif + +// +// If STLport thinks that there is no partial specialisation, then there is no +// std::iterator traits: +// +#if !(defined(_STLP_CLASS_PARTIAL_SPECIALIZATION) || defined(__STL_CLASS_PARTIAL_SPECIALIZATION)) +# define BOOST_NO_STD_ITERATOR_TRAITS +#endif + +// +// No new style iostreams on GCC without STLport's iostreams enabled: +// +#if (defined(__GNUC__) && (__GNUC__ < 3)) && !(defined(__SGI_STL_OWN_IOSTREAMS) || defined(_STLP_OWN_IOSTREAMS)) +# define BOOST_NO_STRINGSTREAM +#endif + +// +// No new iostreams implies no std::locale, and no std::stringstream: +// +#if defined(__STL_NO_IOSTREAMS) || defined(__STL_NO_NEW_IOSTREAMS) || defined(_STLP_NO_IOSTREAMS) || defined(_STLP_NO_NEW_IOSTREAMS) +# define BOOST_NO_STD_LOCALE +# define BOOST_NO_STRINGSTREAM +#endif + +// +// If the streams are not native, and we have a "using ::x" compiler bug +// then the io stream facets are not available in namespace std:: +// +#ifdef _STLPORT_VERSION +# if !(_STLPORT_VERSION >= 0x500) && !defined(_STLP_OWN_IOSTREAMS) && defined(_STLP_USE_NAMESPACES) && defined(BOOST_NO_USING_TEMPLATE) && !defined(BOOST_BORLANDC) +# define BOOST_NO_STD_LOCALE +# endif +#else +# if !defined(__SGI_STL_OWN_IOSTREAMS) && defined(__STL_USE_NAMESPACES) && defined(BOOST_NO_USING_TEMPLATE) && !defined(BOOST_BORLANDC) +# define BOOST_NO_STD_LOCALE +# endif +#endif + +#if defined(_STLPORT_VERSION) && (_STLPORT_VERSION >= 0x520) +# define BOOST_HAS_TR1_UNORDERED_SET +# define BOOST_HAS_TR1_UNORDERED_MAP +#endif +// +// Without member template support enabled, their are no template +// iterate constructors, and no std::allocator: +// +#if !(defined(__STL_MEMBER_TEMPLATES) || defined(_STLP_MEMBER_TEMPLATES)) +# define BOOST_NO_TEMPLATED_ITERATOR_CONSTRUCTORS +# define BOOST_NO_STD_ALLOCATOR +#endif +// +// however we always have at least a partial allocator: +// +#define BOOST_HAS_PARTIAL_STD_ALLOCATOR + +#if !defined(_STLP_MEMBER_TEMPLATE_CLASSES) || defined(_STLP_DONT_SUPPORT_REBIND_MEMBER_TEMPLATE) +# define BOOST_NO_STD_ALLOCATOR +#endif + +#if defined(_STLP_NO_MEMBER_TEMPLATE_KEYWORD) && defined(BOOST_MSVC) && (BOOST_MSVC <= 1300) +# define BOOST_NO_STD_ALLOCATOR +#endif + +// +// If STLport thinks there is no wchar_t at all, then we have to disable +// the support for the relevant specilazations of std:: templates. +// +#if !defined(_STLP_HAS_WCHAR_T) && !defined(_STLP_WCHAR_T_IS_USHORT) +# ifndef BOOST_NO_STD_WSTRING +# define BOOST_NO_STD_WSTRING +# endif +# ifndef BOOST_NO_STD_WSTREAMBUF +# define BOOST_NO_STD_WSTREAMBUF +# endif +#endif + +// +// We always have SGI style hash_set, hash_map, and slist: +// +#ifndef _STLP_NO_EXTENSIONS +#define BOOST_HAS_HASH +#define BOOST_HAS_SLIST +#endif + +// +// STLport does a good job of importing names into namespace std::, +// but doesn't always get them all, define BOOST_NO_STDC_NAMESPACE, since our +// workaround does not conflict with STLports: +// +// +// Harold Howe says: +// Borland switched to STLport in BCB6. Defining BOOST_NO_STDC_NAMESPACE with +// BCB6 does cause problems. If we detect C++ Builder, then don't define +// BOOST_NO_STDC_NAMESPACE +// +#if !defined(BOOST_BORLANDC) && !defined(__DMC__) +// +// If STLport is using it's own namespace, and the real names are in +// the global namespace, then we duplicate STLport's using declarations +// (by defining BOOST_NO_STDC_NAMESPACE), we do this because STLport doesn't +// necessarily import all the names we need into namespace std:: +// +# if (defined(__STL_IMPORT_VENDOR_CSTD) \ + || defined(__STL_USE_OWN_NAMESPACE) \ + || defined(_STLP_IMPORT_VENDOR_CSTD) \ + || defined(_STLP_USE_OWN_NAMESPACE)) \ + && (defined(__STL_VENDOR_GLOBAL_CSTD) || defined (_STLP_VENDOR_GLOBAL_CSTD)) +# define BOOST_NO_STDC_NAMESPACE +# define BOOST_NO_EXCEPTION_STD_NAMESPACE +# endif +#elif defined(BOOST_BORLANDC) && BOOST_BORLANDC < 0x560 +// STLport doesn't import std::abs correctly: +#include +namespace std { using ::abs; } +// and strcmp/strcpy don't get imported either ('cos they are macros) +#include +#ifdef strcpy +# undef strcpy +#endif +#ifdef strcmp +# undef strcmp +#endif +#ifdef _STLP_VENDOR_CSTD +namespace std{ using _STLP_VENDOR_CSTD::strcmp; using _STLP_VENDOR_CSTD::strcpy; } +#endif +#endif + +// +// std::use_facet may be non-standard, uses a class instead: +// +#if defined(__STL_NO_EXPLICIT_FUNCTION_TMPL_ARGS) || defined(_STLP_NO_EXPLICIT_FUNCTION_TMPL_ARGS) +# define BOOST_NO_STD_USE_FACET +# define BOOST_HAS_STLP_USE_FACET +#endif + +// +// If STLport thinks there are no wide functions, etc. is not working; but +// only if BOOST_NO_STDC_NAMESPACE is not defined (if it is then we do the import +// into std:: ourselves). +// +#if defined(_STLP_NO_NATIVE_WIDE_FUNCTIONS) && !defined(BOOST_NO_STDC_NAMESPACE) +# define BOOST_NO_CWCHAR +# define BOOST_NO_CWCTYPE +#endif + +// +// If STLport for some reason was configured so that it thinks that wchar_t +// is not an intrinsic type, then we have to disable the support for it as +// well (we would be missing required specializations otherwise). +// +#if !defined( _STLP_HAS_WCHAR_T) || defined(_STLP_WCHAR_T_IS_USHORT) +# undef BOOST_NO_INTRINSIC_WCHAR_T +# define BOOST_NO_INTRINSIC_WCHAR_T +#endif + +// +// Borland ships a version of STLport with C++ Builder 6 that lacks +// hashtables and the like: +// +#if defined(BOOST_BORLANDC) && (BOOST_BORLANDC == 0x560) +# undef BOOST_HAS_HASH +#endif + +// +// gcc-2.95.3/STLPort does not like the using declarations we use to get ADL with std::min/max +// +#if defined(__GNUC__) && (__GNUC__ < 3) +# include // for std::min and std::max +# define BOOST_USING_STD_MIN() ((void)0) +# define BOOST_USING_STD_MAX() ((void)0) +namespace boost { using std::min; using std::max; } +#endif + +// C++0x headers not yet implemented +// +# define BOOST_NO_CXX11_HDR_ARRAY +# define BOOST_NO_CXX11_HDR_CHRONO +# define BOOST_NO_CXX11_HDR_CODECVT +# define BOOST_NO_CXX11_HDR_CONDITION_VARIABLE +# define BOOST_NO_CXX11_HDR_FORWARD_LIST +# define BOOST_NO_CXX11_HDR_FUTURE +# define BOOST_NO_CXX11_HDR_INITIALIZER_LIST +# define BOOST_NO_CXX11_HDR_MUTEX +# define BOOST_NO_CXX11_HDR_RANDOM +# define BOOST_NO_CXX11_HDR_RATIO +# define BOOST_NO_CXX11_HDR_REGEX +# define BOOST_NO_CXX11_HDR_SYSTEM_ERROR +# define BOOST_NO_CXX11_HDR_THREAD +# define BOOST_NO_CXX11_HDR_TUPLE +# define BOOST_NO_CXX11_HDR_TYPE_TRAITS +# define BOOST_NO_CXX11_HDR_TYPEINDEX +# define BOOST_NO_CXX11_HDR_UNORDERED_MAP +# define BOOST_NO_CXX11_HDR_UNORDERED_SET +# define BOOST_NO_CXX11_NUMERIC_LIMITS +# define BOOST_NO_CXX11_ALLOCATOR +# define BOOST_NO_CXX11_POINTER_TRAITS +# define BOOST_NO_CXX11_ATOMIC_SMART_PTR +# define BOOST_NO_CXX11_SMART_PTR +# define BOOST_NO_CXX11_HDR_FUNCTIONAL +# define BOOST_NO_CXX11_HDR_ATOMIC +# define BOOST_NO_CXX11_STD_ALIGN +# define BOOST_NO_CXX11_ADDRESSOF +# define BOOST_NO_CXX11_HDR_EXCEPTION + +#if defined(__has_include) +#if !__has_include() +# define BOOST_NO_CXX14_HDR_SHARED_MUTEX +#elif __cplusplus < 201402 +# define BOOST_NO_CXX14_HDR_SHARED_MUTEX +#endif +#else +# define BOOST_NO_CXX14_HDR_SHARED_MUTEX +#endif + +// C++14 features +# define BOOST_NO_CXX14_STD_EXCHANGE + +// C++17 features +# define BOOST_NO_CXX17_STD_APPLY +# define BOOST_NO_CXX17_STD_INVOKE +# define BOOST_NO_CXX17_ITERATOR_TRAITS + +#define BOOST_STDLIB "STLPort standard library version " BOOST_STRINGIZE(__SGI_STL_PORT) diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/stdlib/vacpp.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/stdlib/vacpp.hpp new file mode 100644 index 0000000..b14dd65 --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/stdlib/vacpp.hpp @@ -0,0 +1,74 @@ +// (C) Copyright John Maddock 2001 - 2002. +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for most recent version. + +#if __IBMCPP__ <= 501 +# define BOOST_NO_STD_ALLOCATOR +#endif + +#define BOOST_HAS_MACRO_USE_FACET +#define BOOST_NO_STD_MESSAGES + +// Apple doesn't seem to reliably defined a *unix* macro +#if !defined(CYGWIN) && ( defined(__unix__) \ + || defined(__unix) \ + || defined(unix) \ + || defined(__APPLE__) \ + || defined(__APPLE) \ + || defined(APPLE)) +# include +#endif + +// C++0x headers not yet implemented +// +# define BOOST_NO_CXX11_HDR_ARRAY +# define BOOST_NO_CXX11_HDR_CHRONO +# define BOOST_NO_CXX11_HDR_CODECVT +# define BOOST_NO_CXX11_HDR_CONDITION_VARIABLE +# define BOOST_NO_CXX11_HDR_FORWARD_LIST +# define BOOST_NO_CXX11_HDR_FUTURE +# define BOOST_NO_CXX11_HDR_INITIALIZER_LIST +# define BOOST_NO_CXX11_HDR_MUTEX +# define BOOST_NO_CXX11_HDR_RANDOM +# define BOOST_NO_CXX11_HDR_RATIO +# define BOOST_NO_CXX11_HDR_REGEX +# define BOOST_NO_CXX11_HDR_SYSTEM_ERROR +# define BOOST_NO_CXX11_HDR_THREAD +# define BOOST_NO_CXX11_HDR_TUPLE +# define BOOST_NO_CXX11_HDR_TYPE_TRAITS +# define BOOST_NO_CXX11_HDR_TYPEINDEX +# define BOOST_NO_CXX11_HDR_UNORDERED_MAP +# define BOOST_NO_CXX11_HDR_UNORDERED_SET +# define BOOST_NO_CXX11_NUMERIC_LIMITS +# define BOOST_NO_CXX11_ALLOCATOR +# define BOOST_NO_CXX11_POINTER_TRAITS +# define BOOST_NO_CXX11_ATOMIC_SMART_PTR +# define BOOST_NO_CXX11_SMART_PTR +# define BOOST_NO_CXX11_HDR_FUNCTIONAL +# define BOOST_NO_CXX11_HDR_ATOMIC +# define BOOST_NO_CXX11_STD_ALIGN +# define BOOST_NO_CXX11_ADDRESSOF +# define BOOST_NO_CXX11_HDR_EXCEPTION + +#if defined(__has_include) +#if !__has_include() +# define BOOST_NO_CXX14_HDR_SHARED_MUTEX +#elif __cplusplus < 201402 +# define BOOST_NO_CXX14_HDR_SHARED_MUTEX +#endif +#else +# define BOOST_NO_CXX14_HDR_SHARED_MUTEX +#endif + +// C++14 features +# define BOOST_NO_CXX14_STD_EXCHANGE + +// C++17 features +# define BOOST_NO_CXX17_STD_APPLY +# define BOOST_NO_CXX17_STD_INVOKE +# define BOOST_NO_CXX17_ITERATOR_TRAITS + +#define BOOST_STDLIB "Visual Age default standard library" diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/stdlib/xlcpp_zos.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/stdlib/xlcpp_zos.hpp new file mode 100644 index 0000000..a5e02fd --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/stdlib/xlcpp_zos.hpp @@ -0,0 +1,61 @@ +// Copyright (c) 2017 Dynatrace +// +// Distributed under the Boost Software License, Version 1.0. +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt + +// See http://www.boost.org for most recent version. + +// Standard library setup for IBM z/OS XL C/C++ compiler. + +// Oldest library version currently supported is 2.1 (V2R1) +#if __TARGET_LIB__ < 0x42010000 +# error "Library version not supported or configured - please reconfigure" +#endif + +#if __TARGET_LIB__ > 0x42010000 +# if defined(BOOST_ASSERT_CONFIG) +# error "Unknown library version - please run the configure tests and report the results" +# endif +#endif + +#define BOOST_STDLIB "IBM z/OS XL C/C++ standard library" + +#define BOOST_HAS_MACRO_USE_FACET + +#define BOOST_NO_CXX11_HDR_TYPE_TRAITS +#define BOOST_NO_CXX11_HDR_INITIALIZER_LIST + +#define BOOST_NO_CXX11_ADDRESSOF +#define BOOST_NO_CXX11_SMART_PTR +#define BOOST_NO_CXX11_ATOMIC_SMART_PTR +#define BOOST_NO_CXX11_NUMERIC_LIMITS +#define BOOST_NO_CXX11_ALLOCATOR +#define BOOST_NO_CXX11_POINTER_TRAITS +#define BOOST_NO_CXX11_HDR_FUNCTIONAL +#define BOOST_NO_CXX11_HDR_UNORDERED_SET +#define BOOST_NO_CXX11_HDR_UNORDERED_MAP +#define BOOST_NO_CXX11_HDR_TYPEINDEX +#define BOOST_NO_CXX11_HDR_TUPLE +#define BOOST_NO_CXX11_HDR_THREAD +#define BOOST_NO_CXX11_HDR_SYSTEM_ERROR +#define BOOST_NO_CXX11_HDR_REGEX +#define BOOST_NO_CXX11_HDR_RATIO +#define BOOST_NO_CXX11_HDR_RANDOM +#define BOOST_NO_CXX11_HDR_MUTEX +#define BOOST_NO_CXX11_HDR_FUTURE +#define BOOST_NO_CXX11_HDR_FORWARD_LIST +#define BOOST_NO_CXX11_HDR_CONDITION_VARIABLE +#define BOOST_NO_CXX11_HDR_CODECVT +#define BOOST_NO_CXX11_HDR_CHRONO +#define BOOST_NO_CXX11_HDR_ATOMIC +#define BOOST_NO_CXX11_HDR_ARRAY +#define BOOST_NO_CXX11_HDR_EXCEPTION +#define BOOST_NO_CXX11_STD_ALIGN + +#define BOOST_NO_CXX14_STD_EXCHANGE +#define BOOST_NO_CXX14_HDR_SHARED_MUTEX + +#define BOOST_NO_CXX17_STD_INVOKE +#define BOOST_NO_CXX17_STD_APPLY +#define BOOST_NO_CXX17_ITERATOR_TRAITS diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/user.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/user.hpp new file mode 100644 index 0000000..8160fca --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/user.hpp @@ -0,0 +1,133 @@ +// boost/config/user.hpp ---------------------------------------------------// + +// (C) Copyright John Maddock 2001. +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// Do not check in modified versions of this file, +// This file may be customized by the end user, but not by boost. + +// +// Use this file to define a site and compiler specific +// configuration policy: +// + +// define this to locate a compiler config file: +// #define BOOST_COMPILER_CONFIG + +// define this to locate a stdlib config file: +// #define BOOST_STDLIB_CONFIG + +// define this to locate a platform config file: +// #define BOOST_PLATFORM_CONFIG + +// define this to disable compiler config, +// use if your compiler config has nothing to set: +// #define BOOST_NO_COMPILER_CONFIG + +// define this to disable stdlib config, +// use if your stdlib config has nothing to set: +// #define BOOST_NO_STDLIB_CONFIG + +// define this to disable platform config, +// use if your platform config has nothing to set: +// #define BOOST_NO_PLATFORM_CONFIG + +// define this to disable all config options, +// excluding the user config. Use if your +// setup is fully ISO compliant, and has no +// useful extensions, or for autoconf generated +// setups: +// #define BOOST_NO_CONFIG + +// define this to make the config "optimistic" +// about unknown compiler versions. Normally +// unknown compiler versions are assumed to have +// all the defects of the last known version, however +// setting this flag, causes the config to assume +// that unknown compiler versions are fully conformant +// with the standard: +// #define BOOST_STRICT_CONFIG + +// define this to cause the config to halt compilation +// with an #error if it encounters anything unknown -- +// either an unknown compiler version or an unknown +// compiler/platform/library: +// #define BOOST_ASSERT_CONFIG + + +// define if you want to disable threading support, even +// when available: +// #define BOOST_DISABLE_THREADS + +// define when you want to disable Win32 specific features +// even when available: +// #define BOOST_DISABLE_WIN32 + +// BOOST_DISABLE_ABI_HEADERS: Stops boost headers from including any +// prefix/suffix headers that normally control things like struct +// packing and alignment. +// #define BOOST_DISABLE_ABI_HEADERS + +// BOOST_ABI_PREFIX: A prefix header to include in place of whatever +// boost.config would normally select, any replacement should set up +// struct packing and alignment options as required. +// #define BOOST_ABI_PREFIX my-header-name + +// BOOST_ABI_SUFFIX: A suffix header to include in place of whatever +// boost.config would normally select, any replacement should undo +// the effects of the prefix header. +// #define BOOST_ABI_SUFFIX my-header-name + +// BOOST_ALL_DYN_LINK: Forces all libraries that have separate source, +// to be linked as dll's rather than static libraries on Microsoft Windows +// (this macro is used to turn on __declspec(dllimport) modifiers, so that +// the compiler knows which symbols to look for in a dll rather than in a +// static library). Note that there may be some libraries that can only +// be linked in one way (statically or dynamically), in these cases this +// macro has no effect. +// #define BOOST_ALL_DYN_LINK + +// BOOST_WHATEVER_DYN_LINK: Forces library "whatever" to be linked as a dll +// rather than a static library on Microsoft Windows: replace the WHATEVER +// part of the macro name with the name of the library that you want to +// dynamically link to, for example use BOOST_DATE_TIME_DYN_LINK or +// BOOST_REGEX_DYN_LINK etc (this macro is used to turn on __declspec(dllimport) +// modifiers, so that the compiler knows which symbols to look for in a dll +// rather than in a static library). +// Note that there may be some libraries that can only +// be linked in one way (statically or dynamically), +// in these cases this macro is unsupported. +// #define BOOST_WHATEVER_DYN_LINK + +// BOOST_ALL_NO_LIB: Tells the config system not to automatically select +// which libraries to link against. +// Normally if a compiler supports #pragma lib, then the correct library +// build variant will be automatically selected and linked against, +// simply by the act of including one of that library's headers. +// This macro turns that feature off. +// #define BOOST_ALL_NO_LIB + +// BOOST_WHATEVER_NO_LIB: Tells the config system not to automatically +// select which library to link against for library "whatever", +// replace WHATEVER in the macro name with the name of the library; +// for example BOOST_DATE_TIME_NO_LIB or BOOST_REGEX_NO_LIB. +// Normally if a compiler supports #pragma lib, then the correct library +// build variant will be automatically selected and linked against, simply +// by the act of including one of that library's headers. This macro turns +// that feature off. +// #define BOOST_WHATEVER_NO_LIB + +// BOOST_LIB_BUILDID: Set to the same value as the value passed to Boost.Build's +// --buildid command line option. For example if you built using: +// +// bjam address-model=64 --buildid=amd64 +// +// then compile your code with: +// +// -DBOOST_LIB_BUILDID = amd64 +// +// to ensure the correct libraries are selected at link time. +// #define BOOST_LIB_BUILDID amd64 + diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/warning_disable.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/warning_disable.hpp new file mode 100644 index 0000000..fea8e82 --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/warning_disable.hpp @@ -0,0 +1,47 @@ +// Copyright John Maddock 2008 +// Use, modification, and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// This file exists to turn off some overly-pedantic warning emitted +// by certain compilers. You should include this header only in: +// +// * A test case, before any other headers, or, +// * A library source file before any other headers. +// +// IT SHOULD NOT BE INCLUDED BY ANY BOOST HEADER. +// +// YOU SHOULD NOT INCLUDE IT IF YOU CAN REASONABLY FIX THE WARNING. +// +// The only warnings disabled here are those that are: +// +// * Quite unreasonably pedantic. +// * Generally only emitted by a single compiler. +// * Can't easily be fixed: for example if the vendors own std lib +// code emits these warnings! +// +// Note that THIS HEADER MUST NOT INCLUDE ANY OTHER HEADERS: +// not even std library ones! Doing so may turn the warning +// off too late to be of any use. For example the VC++ C4996 +// warning can be emitted from if that header is included +// before or by this one :-( +// + +#ifndef BOOST_CONFIG_WARNING_DISABLE_HPP +#define BOOST_CONFIG_WARNING_DISABLE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1400) + // Error 'function': was declared deprecated + // http://msdn2.microsoft.com/en-us/library/ttcz0bys(VS.80).aspx + // This error is emitted when you use some perfectly conforming + // std lib functions in a perfectly correct way, and also by + // some of Microsoft's own std lib code ! +# pragma warning(disable:4996) +#endif +#if defined(__INTEL_COMPILER) || defined(__ICL) + // As above: gives warning when a "deprecated" + // std library function is encountered. +# pragma warning(disable:1786) +#endif + +#endif // BOOST_CONFIG_WARNING_DISABLE_HPP diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/workaround.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/workaround.hpp new file mode 100644 index 0000000..688f963 --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/config/workaround.hpp @@ -0,0 +1,305 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef BOOST_CONFIG_WORKAROUND_HPP +#define BOOST_CONFIG_WORKAROUND_HPP + +// Compiler/library version workaround macro +// +// Usage: +// +// #if BOOST_WORKAROUND(BOOST_MSVC, < 1300) +// // workaround for eVC4 and VC6 +// ... // workaround code here +// #endif +// +// When BOOST_STRICT_CONFIG is defined, expands to 0. Otherwise, the +// first argument must be undefined or expand to a numeric +// value. The above expands to: +// +// (BOOST_MSVC) != 0 && (BOOST_MSVC) < 1300 +// +// When used for workarounds that apply to the latest known version +// and all earlier versions of a compiler, the following convention +// should be observed: +// +// #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1301)) +// +// The version number in this case corresponds to the last version in +// which the workaround was known to have been required. When +// BOOST_DETECT_OUTDATED_WORKAROUNDS is not the defined, the macro +// BOOST_TESTED_AT(x) expands to "!= 0", which effectively activates +// the workaround for any version of the compiler. When +// BOOST_DETECT_OUTDATED_WORKAROUNDS is defined, a compiler warning or +// error will be issued if the compiler version exceeds the argument +// to BOOST_TESTED_AT(). This can be used to locate workarounds which +// may be obsoleted by newer versions. + +#ifndef BOOST_STRICT_CONFIG + +#include + +#ifndef __BORLANDC__ +#define __BORLANDC___WORKAROUND_GUARD 1 +#else +#define __BORLANDC___WORKAROUND_GUARD 0 +#endif +#ifndef __CODEGEARC__ +#define __CODEGEARC___WORKAROUND_GUARD 1 +#else +#define __CODEGEARC___WORKAROUND_GUARD 0 +#endif +#ifndef BOOST_BORLANDC +#define BOOST_BORLANDC_WORKAROUND_GUARD 1 +#else +#define BOOST_BORLANDC_WORKAROUND_GUARD 0 +#endif +#ifndef BOOST_CODEGEARC +#define BOOST_CODEGEARC_WORKAROUND_GUARD 1 +#else +#define BOOST_CODEGEARC_WORKAROUND_GUARD 0 +#endif +#ifndef BOOST_EMBTC +#define BOOST_EMBTC_WORKAROUND_GUARD 1 +#else +#define BOOST_EMBTC_WORKAROUND_GUARD 0 +#endif +#ifndef _MSC_VER +#define _MSC_VER_WORKAROUND_GUARD 1 +#else +#define _MSC_VER_WORKAROUND_GUARD 0 +#endif +#ifndef _MSC_FULL_VER +#define _MSC_FULL_VER_WORKAROUND_GUARD 1 +#else +#define _MSC_FULL_VER_WORKAROUND_GUARD 0 +#endif +#ifndef BOOST_MSVC +#define BOOST_MSVC_WORKAROUND_GUARD 1 +#else +#define BOOST_MSVC_WORKAROUND_GUARD 0 +#endif +#ifndef BOOST_MSVC_FULL_VER +#define BOOST_MSVC_FULL_VER_WORKAROUND_GUARD 1 +#else +#define BOOST_MSVC_FULL_VER_WORKAROUND_GUARD 0 +#endif +#ifndef __GNUC__ +#define __GNUC___WORKAROUND_GUARD 1 +#else +#define __GNUC___WORKAROUND_GUARD 0 +#endif +#ifndef __GNUC_MINOR__ +#define __GNUC_MINOR___WORKAROUND_GUARD 1 +#else +#define __GNUC_MINOR___WORKAROUND_GUARD 0 +#endif +#ifndef __GNUC_PATCHLEVEL__ +#define __GNUC_PATCHLEVEL___WORKAROUND_GUARD 1 +#else +#define __GNUC_PATCHLEVEL___WORKAROUND_GUARD 0 +#endif +#ifndef BOOST_GCC +#define BOOST_GCC_WORKAROUND_GUARD 1 +#define BOOST_GCC_VERSION_WORKAROUND_GUARD 1 +#else +#define BOOST_GCC_WORKAROUND_GUARD 0 +#define BOOST_GCC_VERSION_WORKAROUND_GUARD 0 +#endif +#ifndef BOOST_XLCPP_ZOS +#define BOOST_XLCPP_ZOS_WORKAROUND_GUARD 1 +#else +#define BOOST_XLCPP_ZOS_WORKAROUND_GUARD 0 +#endif +#ifndef __IBMCPP__ +#define __IBMCPP___WORKAROUND_GUARD 1 +#else +#define __IBMCPP___WORKAROUND_GUARD 0 +#endif +#ifndef __SUNPRO_CC +#define __SUNPRO_CC_WORKAROUND_GUARD 1 +#else +#define __SUNPRO_CC_WORKAROUND_GUARD 0 +#endif +#ifndef __DECCXX_VER +#define __DECCXX_VER_WORKAROUND_GUARD 1 +#else +#define __DECCXX_VER_WORKAROUND_GUARD 0 +#endif +#ifndef __MWERKS__ +#define __MWERKS___WORKAROUND_GUARD 1 +#else +#define __MWERKS___WORKAROUND_GUARD 0 +#endif +#ifndef __EDG__ +#define __EDG___WORKAROUND_GUARD 1 +#else +#define __EDG___WORKAROUND_GUARD 0 +#endif +#ifndef __EDG_VERSION__ +#define __EDG_VERSION___WORKAROUND_GUARD 1 +#else +#define __EDG_VERSION___WORKAROUND_GUARD 0 +#endif +#ifndef __HP_aCC +#define __HP_aCC_WORKAROUND_GUARD 1 +#else +#define __HP_aCC_WORKAROUND_GUARD 0 +#endif +#ifndef __hpxstd98 +#define __hpxstd98_WORKAROUND_GUARD 1 +#else +#define __hpxstd98_WORKAROUND_GUARD 0 +#endif +#ifndef _CRAYC +#define _CRAYC_WORKAROUND_GUARD 1 +#else +#define _CRAYC_WORKAROUND_GUARD 0 +#endif +#ifndef __DMC__ +#define __DMC___WORKAROUND_GUARD 1 +#else +#define __DMC___WORKAROUND_GUARD 0 +#endif +#ifndef MPW_CPLUS +#define MPW_CPLUS_WORKAROUND_GUARD 1 +#else +#define MPW_CPLUS_WORKAROUND_GUARD 0 +#endif +#ifndef __COMO__ +#define __COMO___WORKAROUND_GUARD 1 +#else +#define __COMO___WORKAROUND_GUARD 0 +#endif +#ifndef __COMO_VERSION__ +#define __COMO_VERSION___WORKAROUND_GUARD 1 +#else +#define __COMO_VERSION___WORKAROUND_GUARD 0 +#endif +#ifndef __INTEL_COMPILER +#define __INTEL_COMPILER_WORKAROUND_GUARD 1 +#else +#define __INTEL_COMPILER_WORKAROUND_GUARD 0 +#endif +#ifndef __ICL +#define __ICL_WORKAROUND_GUARD 1 +#else +#define __ICL_WORKAROUND_GUARD 0 +#endif +#ifndef _COMPILER_VERSION +#define _COMPILER_VERSION_WORKAROUND_GUARD 1 +#else +#define _COMPILER_VERSION_WORKAROUND_GUARD 0 +#endif +#ifndef __clang_major__ +#define __clang_major___WORKAROUND_GUARD 1 +#else +#define __clang_major___WORKAROUND_GUARD 0 +#endif + +#ifndef _RWSTD_VER +#define _RWSTD_VER_WORKAROUND_GUARD 1 +#else +#define _RWSTD_VER_WORKAROUND_GUARD 0 +#endif +#ifndef BOOST_RWSTD_VER +#define BOOST_RWSTD_VER_WORKAROUND_GUARD 1 +#else +#define BOOST_RWSTD_VER_WORKAROUND_GUARD 0 +#endif +#ifndef __GLIBCPP__ +#define __GLIBCPP___WORKAROUND_GUARD 1 +#else +#define __GLIBCPP___WORKAROUND_GUARD 0 +#endif +#ifndef _GLIBCXX_USE_C99_FP_MACROS_DYNAMIC +#define _GLIBCXX_USE_C99_FP_MACROS_DYNAMIC_WORKAROUND_GUARD 1 +#else +#define _GLIBCXX_USE_C99_FP_MACROS_DYNAMIC_WORKAROUND_GUARD 0 +#endif +#ifndef __SGI_STL_PORT +#define __SGI_STL_PORT_WORKAROUND_GUARD 1 +#else +#define __SGI_STL_PORT_WORKAROUND_GUARD 0 +#endif +#ifndef _STLPORT_VERSION +#define _STLPORT_VERSION_WORKAROUND_GUARD 1 +#else +#define _STLPORT_VERSION_WORKAROUND_GUARD 0 +#endif +#ifndef __LIBCOMO_VERSION__ +#define __LIBCOMO_VERSION___WORKAROUND_GUARD 1 +#else +#define __LIBCOMO_VERSION___WORKAROUND_GUARD 0 +#endif +#ifndef _CPPLIB_VER +#define _CPPLIB_VER_WORKAROUND_GUARD 1 +#else +#define _CPPLIB_VER_WORKAROUND_GUARD 0 +#endif + +#ifndef BOOST_INTEL_CXX_VERSION +#define BOOST_INTEL_CXX_VERSION_WORKAROUND_GUARD 1 +#else +#define BOOST_INTEL_CXX_VERSION_WORKAROUND_GUARD 0 +#endif +#ifndef BOOST_INTEL_WIN +#define BOOST_INTEL_WIN_WORKAROUND_GUARD 1 +#else +#define BOOST_INTEL_WIN_WORKAROUND_GUARD 0 +#endif +#ifndef BOOST_DINKUMWARE_STDLIB +#define BOOST_DINKUMWARE_STDLIB_WORKAROUND_GUARD 1 +#else +#define BOOST_DINKUMWARE_STDLIB_WORKAROUND_GUARD 0 +#endif +#ifndef BOOST_INTEL +#define BOOST_INTEL_WORKAROUND_GUARD 1 +#else +#define BOOST_INTEL_WORKAROUND_GUARD 0 +#endif +#ifndef BOOST_CLANG_VERSION +#define BOOST_CLANG_VERSION_WORKAROUND_GUARD 1 +#else +#define BOOST_CLANG_VERSION_WORKAROUND_GUARD 0 +#endif + +// Always define to zero, if it's used it'll be defined my MPL: +#define BOOST_MPL_CFG_GCC_WORKAROUND_GUARD 0 + +#define BOOST_WORKAROUND(symbol, test) \ + ((symbol ## _WORKAROUND_GUARD + 0 == 0) && \ + (symbol != 0) && (1 % (( (symbol test) ) + 1))) +// ^ ^ ^ ^ +// The extra level of parenthesis nesting above, along with the +// BOOST_OPEN_PAREN indirection below, is required to satisfy the +// broken preprocessor in MWCW 8.3 and earlier. +// +// The basic mechanism works as follows: +// (symbol test) + 1 => if (symbol test) then 2 else 1 +// 1 % ((symbol test) + 1) => if (symbol test) then 1 else 0 +// +// The complication with % is for cooperation with BOOST_TESTED_AT(). +// When "test" is BOOST_TESTED_AT(x) and +// BOOST_DETECT_OUTDATED_WORKAROUNDS is #defined, +// +// symbol test => if (symbol <= x) then 1 else -1 +// (symbol test) + 1 => if (symbol <= x) then 2 else 0 +// 1 % ((symbol test) + 1) => if (symbol <= x) then 1 else divide-by-zero +// + +#ifdef BOOST_DETECT_OUTDATED_WORKAROUNDS +# define BOOST_OPEN_PAREN ( +# define BOOST_TESTED_AT(value) > value) ?(-1): BOOST_OPEN_PAREN 1 +#else +# define BOOST_TESTED_AT(value) != ((value)-(value)) +#endif + +#else + +#define BOOST_WORKAROUND(symbol, test) 0 + +#endif + +#endif // BOOST_CONFIG_WORKAROUND_HPP diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/detail/boolean_op.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/detail/boolean_op.hpp new file mode 100644 index 0000000..0c674a2 --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/detail/boolean_op.hpp @@ -0,0 +1,442 @@ +/* + Copyright 2008 Intel Corporation + + Use, modification and distribution are subject to the Boost Software License, + Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at + http://www.boost.org/LICENSE_1_0.txt). +*/ +#ifndef BOOST_POLYGON_BOOLEAN_OP_HPP +#define BOOST_POLYGON_BOOLEAN_OP_HPP +namespace boost { namespace polygon{ +namespace boolean_op { + + //BooleanOp is the generic boolean operation scanline algorithm that provides + //all the simple boolean set operations on manhattan data. By templatizing + //the intersection count of the input and algorithm internals it is extensible + //to multi-layer scans, properties and other advanced scanline operations above + //and beyond simple booleans. + //T must cast to int + template + class BooleanOp { + public: + typedef std::map ScanData; + typedef std::pair ElementType; + protected: + ScanData scanData_; + typename ScanData::iterator nextItr_; + T nullT_; + public: + inline BooleanOp () : scanData_(), nextItr_(), nullT_() { nextItr_ = scanData_.end(); nullT_ = 0; } + inline BooleanOp (T nullT) : scanData_(), nextItr_(), nullT_(nullT) { nextItr_ = scanData_.end(); } + inline BooleanOp (const BooleanOp& that) : scanData_(that.scanData_), nextItr_(), + nullT_(that.nullT_) { nextItr_ = scanData_.begin(); } + inline BooleanOp& operator=(const BooleanOp& that); + + //moves scanline forward + inline void advanceScan() { nextItr_ = scanData_.begin(); } + + //proceses the given interval and T data + //appends output edges to cT + template + inline void processInterval(cT& outputContainer, interval_data ivl, T deltaCount); + + private: + inline typename ScanData::iterator lookup_(Unit pos){ + if(nextItr_ != scanData_.end() && nextItr_->first >= pos) { + return nextItr_; + } + return nextItr_ = scanData_.lower_bound(pos); + } + inline typename ScanData::iterator insert_(Unit pos, T count){ + return nextItr_ = scanData_.insert(nextItr_, ElementType(pos, count)); + } + template + inline void evaluateInterval_(cT& outputContainer, interval_data ivl, T beforeCount, T afterCount); + }; + + class BinaryAnd { + public: + inline BinaryAnd() {} + inline bool operator()(int a, int b) { return (a > 0) & (b > 0); } + }; + class BinaryOr { + public: + inline BinaryOr() {} + inline bool operator()(int a, int b) { return (a > 0) | (b > 0); } + }; + class BinaryNot { + public: + inline BinaryNot() {} + inline bool operator()(int a, int b) { return (a > 0) & !(b > 0); } + }; + class BinaryXor { + public: + inline BinaryXor() {} + inline bool operator()(int a, int b) { return (a > 0) ^ (b > 0); } + }; + + //BinaryCount is an array of two deltaCounts coming from two different layers + //of scan event data. It is the merged count of the two suitable for consumption + //as the template argument of the BooleanOp algorithm because BinaryCount casts to int. + //T is a binary functor object that evaluates the array of counts and returns a logical + //result of some operation on those values. + //BinaryCount supports many of the operators that work with int, particularly the + //binary operators, but cannot support less than or increment. + template + class BinaryCount { + public: + inline BinaryCount() +#ifndef BOOST_POLYGON_MSVC + : counts_() +#endif + { counts_[0] = counts_[1] = 0; } + // constructs from two integers + inline BinaryCount(int countL, int countR) +#ifndef BOOST_POLYGON_MSVC + : counts_() +#endif + { counts_[0] = countL, counts_[1] = countR; } + inline BinaryCount& operator=(int count) { counts_[0] = count, counts_[1] = count; return *this; } + inline BinaryCount& operator=(const BinaryCount& that); + inline BinaryCount(const BinaryCount& that) +#ifndef BOOST_POLYGON_MSVC + : counts_() +#endif + { *this = that; } + inline bool operator==(const BinaryCount& that) const; + inline bool operator!=(const BinaryCount& that) const { return !((*this) == that);} + inline BinaryCount& operator+=(const BinaryCount& that); + inline BinaryCount& operator-=(const BinaryCount& that); + inline BinaryCount operator+(const BinaryCount& that) const; + inline BinaryCount operator-(const BinaryCount& that) const; + inline BinaryCount operator-() const; + inline int& operator[](bool index) { return counts_[index]; } + + //cast to int operator evaluates data using T binary functor + inline operator int() const { return T()(counts_[0], counts_[1]); } + private: + int counts_[2]; + }; + + class UnaryCount { + public: + inline UnaryCount() : count_(0) {} + // constructs from two integers + inline explicit UnaryCount(int count) : count_(count) {} + inline UnaryCount& operator=(int count) { count_ = count; return *this; } + inline UnaryCount& operator=(const UnaryCount& that) { count_ = that.count_; return *this; } + inline UnaryCount(const UnaryCount& that) : count_(that.count_) {} + inline bool operator==(const UnaryCount& that) const { return count_ == that.count_; } + inline bool operator!=(const UnaryCount& that) const { return !((*this) == that);} + inline UnaryCount& operator+=(const UnaryCount& that) { count_ += that.count_; return *this; } + inline UnaryCount& operator-=(const UnaryCount& that) { count_ -= that.count_; return *this; } + inline UnaryCount operator+(const UnaryCount& that) const { UnaryCount tmp(*this); tmp += that; return tmp; } + inline UnaryCount operator-(const UnaryCount& that) const { UnaryCount tmp(*this); tmp -= that; return tmp; } + inline UnaryCount operator-() const { UnaryCount tmp; return tmp - *this; } + + //cast to int operator evaluates data using T binary functor + inline operator int() const { return count_ % 2; } + private: + int count_; + }; + + template + inline BooleanOp& BooleanOp::operator=(const BooleanOp& that) { + scanData_ = that.scanData_; + nextItr_ = scanData_.begin(); + nullT_ = that.nullT_; + return *this; + } + + //appends output edges to cT + template + template + inline void BooleanOp::processInterval(cT& outputContainer, interval_data ivl, T deltaCount) { + typename ScanData::iterator lowItr = lookup_(ivl.low()); + typename ScanData::iterator highItr = lookup_(ivl.high()); + //add interval to scan data if it is past the end + if(lowItr == scanData_.end()) { + lowItr = insert_(ivl.low(), deltaCount); + highItr = insert_(ivl.high(), nullT_); + evaluateInterval_(outputContainer, ivl, nullT_, deltaCount); + return; + } + //ensure that highItr points to the end of the ivl + if(highItr == scanData_.end() || (*highItr).first > ivl.high()) { + T value = nullT_; + if(highItr != scanData_.begin()) { + --highItr; + value = highItr->second; + } + nextItr_ = highItr; + highItr = insert_(ivl.high(), value); + } + //split the low interval if needed + if(lowItr->first > ivl.low()) { + if(lowItr != scanData_.begin()) { + --lowItr; + nextItr_ = lowItr; + lowItr = insert_(ivl.low(), lowItr->second); + } else { + nextItr_ = lowItr; + lowItr = insert_(ivl.low(), nullT_); + } + } + //process scan data intersecting interval + for(typename ScanData::iterator itr = lowItr; itr != highItr; ){ + T beforeCount = itr->second; + T afterCount = itr->second += deltaCount; + Unit low = itr->first; + ++itr; + Unit high = itr->first; + evaluateInterval_(outputContainer, interval_data(low, high), beforeCount, afterCount); + } + //merge the bottom interval with the one below if they have the same count + if(lowItr != scanData_.begin()){ + typename ScanData::iterator belowLowItr = lowItr; + --belowLowItr; + if(belowLowItr->second == lowItr->second) { + scanData_.erase(lowItr); + } + } + //merge the top interval with the one above if they have the same count + if(highItr != scanData_.begin()) { + typename ScanData::iterator beforeHighItr = highItr; + --beforeHighItr; + if(beforeHighItr->second == highItr->second) { + scanData_.erase(highItr); + highItr = beforeHighItr; + ++highItr; + } + } + nextItr_ = highItr; + } + + template + template + inline void BooleanOp::evaluateInterval_(cT& outputContainer, interval_data ivl, + T beforeCount, T afterCount) { + bool before = (int)beforeCount > 0; + bool after = (int)afterCount > 0; + int value = (!before & after) - (before & !after); + if(value) { + outputContainer.insert(outputContainer.end(), std::pair, int>(ivl, value)); + } + } + + template + inline BinaryCount& BinaryCount::operator=(const BinaryCount& that) { + counts_[0] = that.counts_[0]; + counts_[1] = that.counts_[1]; + return *this; + } + template + inline bool BinaryCount::operator==(const BinaryCount& that) const { + return counts_[0] == that.counts_[0] && + counts_[1] == that.counts_[1]; + } + template + inline BinaryCount& BinaryCount::operator+=(const BinaryCount& that) { + counts_[0] += that.counts_[0]; + counts_[1] += that.counts_[1]; + return *this; + } + template + inline BinaryCount& BinaryCount::operator-=(const BinaryCount& that) { + counts_[0] += that.counts_[0]; + counts_[1] += that.counts_[1]; + return *this; + } + template + inline BinaryCount BinaryCount::operator+(const BinaryCount& that) const { + BinaryCount retVal(*this); + retVal += that; + return retVal; + } + template + inline BinaryCount BinaryCount::operator-(const BinaryCount& that) const { + BinaryCount retVal(*this); + retVal -= that; + return retVal; + } + template + inline BinaryCount BinaryCount::operator-() const { + return BinaryCount() - *this; + } + + + template + inline void applyBooleanBinaryOp(std::vector > >& output, + //const std::vector > >& input1, + //const std::vector > >& input2, + iterator_type_1 itr1, iterator_type_1 itr1_end, + iterator_type_2 itr2, iterator_type_2 itr2_end, + T defaultCount) { + BooleanOp boolean(defaultCount); + //typename std::vector > >::const_iterator itr1 = input1.begin(); + //typename std::vector > >::const_iterator itr2 = input2.begin(); + std::vector, int> > container; + //output.reserve((std::max)(input1.size(), input2.size())); + + //consider eliminating dependecy on limits with bool flag for initial state + Unit UnitMax = (std::numeric_limits::max)(); + Unit prevCoord = UnitMax; + Unit prevPosition = UnitMax; + T count(defaultCount); + //define the starting point + if(itr1 != itr1_end) { + prevCoord = (*itr1).first; + prevPosition = (*itr1).second.first; + count[0] += (*itr1).second.second; + } + if(itr2 != itr2_end) { + if((*itr2).first < prevCoord || + ((*itr2).first == prevCoord && (*itr2).second.first < prevPosition)) { + prevCoord = (*itr2).first; + prevPosition = (*itr2).second.first; + count = defaultCount; + count[1] += (*itr2).second.second; + ++itr2; + } else if((*itr2).first == prevCoord && (*itr2).second.first == prevPosition) { + count[1] += (*itr2).second.second; + ++itr2; + if(itr1 != itr1_end) ++itr1; + } else { + if(itr1 != itr1_end) ++itr1; + } + } else { + if(itr1 != itr1_end) ++itr1; + } + + while(itr1 != itr1_end || itr2 != itr2_end) { + Unit curCoord = UnitMax; + Unit curPosition = UnitMax; + T curCount(defaultCount); + if(itr1 != itr1_end) { + curCoord = (*itr1).first; + curPosition = (*itr1).second.first; + curCount[0] += (*itr1).second.second; + } + if(itr2 != itr2_end) { + if((*itr2).first < curCoord || + ((*itr2).first == curCoord && (*itr2).second.first < curPosition)) { + curCoord = (*itr2).first; + curPosition = (*itr2).second.first; + curCount = defaultCount; + curCount[1] += (*itr2).second.second; + ++itr2; + } else if((*itr2).first == curCoord && (*itr2).second.first == curPosition) { + curCount[1] += (*itr2).second.second; + ++itr2; + if(itr1 != itr1_end) ++itr1; + } else { + if(itr1 != itr1_end) ++itr1; + } + } else { + ++itr1; + } + + if(prevCoord != curCoord) { + boolean.advanceScan(); + prevCoord = curCoord; + prevPosition = curPosition; + count = curCount; + continue; + } + if(curPosition != prevPosition && count != defaultCount) { + interval_data ivl(prevPosition, curPosition); + container.clear(); + boolean.processInterval(container, ivl, count); + for(std::size_t i = 0; i < container.size(); ++i) { + std::pair, int>& element = container[i]; + if(!output.empty() && output.back().first == prevCoord && + output.back().second.first == element.first.low() && + output.back().second.second == element.second * -1) { + output.pop_back(); + } else { + output.push_back(std::pair >(prevCoord, std::pair(element.first.low(), + element.second))); + } + output.push_back(std::pair >(prevCoord, std::pair(element.first.high(), + element.second * -1))); + } + } + prevPosition = curPosition; + count += curCount; + } + } + + template + inline void applyBooleanBinaryOp(std::vector > >& inputOutput, + const std::vector > >& input2, + T defaultCount) { + std::vector > > output; + applyBooleanBinaryOp(output, inputOutput, input2, defaultCount); + if(output.size() < inputOutput.size() / 2) { + inputOutput = std::vector > >(); + } else { + inputOutput.clear(); + } + inputOutput.insert(inputOutput.end(), output.begin(), output.end()); + } + + template + struct default_arg_workaround { + template + static inline void applyBooleanOr(std::vector > >& input) { + BooleanOp booleanOr; + std::vector, int> > container; + std::vector > > output; + output.reserve(input.size()); + //consider eliminating dependecy on limits with bool flag for initial state + Unit UnitMax = (std::numeric_limits::max)(); + Unit prevPos = UnitMax; + Unit prevY = UnitMax; + int count = 0; + for(typename std::vector > >::iterator itr = input.begin(); + itr != input.end(); ++itr) { + Unit pos = (*itr).first; + Unit y = (*itr).second.first; + if(pos != prevPos) { + booleanOr.advanceScan(); + prevPos = pos; + prevY = y; + count = (*itr).second.second; + continue; + } + if(y != prevY && count != 0) { + interval_data ivl(prevY, y); + container.clear(); + booleanOr.processInterval(container, ivl, count_type(count)); + for(std::size_t i = 0; i < container.size(); ++i) { + std::pair, int>& element = container[i]; + if(!output.empty() && output.back().first == prevPos && + output.back().second.first == element.first.low() && + output.back().second.second == element.second * -1) { + output.pop_back(); + } else { + output.push_back(std::pair >(prevPos, std::pair(element.first.low(), + element.second))); + } + output.push_back(std::pair >(prevPos, std::pair(element.first.high(), + element.second * -1))); + } + } + prevY = y; + count += (*itr).second.second; + } + if(output.size() < input.size() / 2) { + input = std::vector > >(); + } else { + input.clear(); + } + input.insert(input.end(), output.begin(), output.end()); + } + }; + +} + +} + +} +#endif diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/detail/boolean_op_45.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/detail/boolean_op_45.hpp new file mode 100644 index 0000000..0d65501 --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/detail/boolean_op_45.hpp @@ -0,0 +1,1398 @@ +/* + Copyright 2008 Intel Corporation + + Use, modification and distribution are subject to the Boost Software License, + Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at + http://www.boost.org/LICENSE_1_0.txt). +*/ +#ifndef BOOST_POLYGON_BOOLEAN_OP_45_HPP +#define BOOST_POLYGON_BOOLEAN_OP_45_HPP +namespace boost { namespace polygon{ + + template + struct boolean_op_45 { + typedef point_data Point; + typedef typename coordinate_traits::manhattan_area_type LongUnit; + + class Count2 { + public: + inline Count2() +#ifndef BOOST_POLYGON_MSVC + : counts() +#endif + { counts[0] = counts[1] = 0; } + //inline Count2(int count) { counts[0] = counts[1] = count; } + inline Count2(int count1, int count2) +#ifndef BOOST_POLYGON_MSVC + : counts() +#endif + { counts[0] = count1; counts[1] = count2; } + inline Count2(const Count2& count) +#ifndef BOOST_POLYGON_MSVC + : counts() +#endif + { counts[0] = count.counts[0]; counts[1] = count.counts[1]; } + inline bool operator==(const Count2& count) const { return counts[0] == count.counts[0] && counts[1] == count.counts[1]; } + inline bool operator!=(const Count2& count) const { return !((*this) == count); } + inline Count2& operator=(int count) { counts[0] = counts[1] = count; return *this; } + inline Count2& operator=(const Count2& count) { counts[0] = count.counts[0]; counts[1] = count.counts[1]; return *this; } + inline int& operator[](bool index) { return counts[index]; } + inline int operator[](bool index) const {return counts[index]; } + inline Count2& operator+=(const Count2& count){ + counts[0] += count[0]; + counts[1] += count[1]; + return *this; + } + inline Count2& operator-=(const Count2& count){ + counts[0] -= count[0]; + counts[1] -= count[1]; + return *this; + } + inline Count2 operator+(const Count2& count) const { + return Count2(*this)+=count; + } + inline Count2 operator-(const Count2& count) const { + return Count2(*this)-=count; + } + inline Count2 invert() const { + return Count2(-counts[0], -counts[1]); + } + private: + int counts[2]; + }; + + class Count1 { + public: + inline Count1() : count_(0) { } + inline Count1(int count) : count_(count) { } + inline Count1(const Count1& count) : count_(count.count_) { } + inline bool operator==(const Count1& count) const { return count_ == count.count_; } + inline bool operator!=(const Count1& count) const { return !((*this) == count); } + inline Count1& operator=(int count) { count_ = count; return *this; } + inline Count1& operator=(const Count1& count) { count_ = count.count_; return *this; } + inline Count1& operator+=(const Count1& count){ + count_ += count.count_; + return *this; + } + inline Count1& operator-=(const Count1& count){ + count_ -= count.count_; + return *this; + } + inline Count1 operator+(const Count1& count) const { + return Count1(*this)+=count; + } + inline Count1 operator-(const Count1& count) const { + return Count1(*this)-=count; + } + inline Count1 invert() const { + return Count1(-count_); + } + int count_; + }; + + // inline std::ostream& operator<< (std::ostream& o, const Count2& c) { + // o << c[0] << " " << c[1]; + // return o; + // } + + template + class Scan45ElementT { + public: + Unit x; + Unit y; + int rise; //-1, 0, +1 + mutable CountType count; + inline Scan45ElementT() : x(), y(), rise(), count() {} + inline Scan45ElementT(Unit xIn, Unit yIn, int riseIn, CountType countIn = CountType()) : + x(xIn), y(yIn), rise(riseIn), count(countIn) {} + inline Scan45ElementT(const Scan45ElementT& that) : + x(that.x), y(that.y), rise(that.rise), count(that.count) {} + inline Scan45ElementT& operator=(const Scan45ElementT& that) { + x = that.x; y = that.y; rise = that.rise; count = that.count; + return *this; + } + inline Unit evalAtX(Unit xIn) const { + return y + rise * (xIn - x); + } + + inline bool cross(Point& crossPoint, const Scan45ElementT& edge, Unit currentX) const { + Unit y1 = evalAtX(currentX); + Unit y2 = edge.evalAtX(currentX); + int rise1 = rise; + int rise2 = edge.rise; + if(rise > edge.rise){ + if(y1 > y2) return false; + } else if(rise < edge.rise){ + if(y2 > y1) return false; + std::swap(y1, y2); + std::swap(rise1, rise2); + } else { return false; } + if(rise1 == 1) { + if(rise2 == 0) { + crossPoint = Point(currentX + y2 - y1, y2); + } else { + //rise2 == -1 + Unit delta = (y2 - y1)/2; + crossPoint = Point(currentX + delta, y1 + delta); + } + } else { + //rise1 == 0 and rise2 == -1 + crossPoint = Point(currentX + y2 - y1, y1); + } + return true; + } + }; + + typedef Scan45ElementT Scan45Element; + + // inline std::ostream& operator<< (std::ostream& o, const Scan45Element& c) { + // o << c.x << " " << c.y << " " << c.rise << " " << c.count; + // return o; + // } + + class lessScan45ElementRise { + public: + typedef Scan45Element first_argument_type; + typedef Scan45Element second_argument_type; + typedef bool result_type; + inline lessScan45ElementRise() {} //default constructor is only constructor + inline bool operator () (Scan45Element elm1, Scan45Element elm2) const { + return elm1.rise < elm2.rise; + } + }; + + template + class lessScan45Element { + private: + Unit *x_; //x value at which to apply comparison + int *justBefore_; + public: + inline lessScan45Element() : x_(0), justBefore_(0) {} + inline lessScan45Element(Unit *x, int *justBefore) : x_(x), justBefore_(justBefore) {} + inline lessScan45Element(const lessScan45Element& that) : x_(that.x_), justBefore_(that.justBefore_) {} + inline lessScan45Element& operator=(const lessScan45Element& that) { x_ = that.x_; justBefore_ = that.justBefore_; return *this; } + inline bool operator () (const Scan45ElementT& elm1, + const Scan45ElementT& elm2) const { + Unit y1 = elm1.evalAtX(*x_); + Unit y2 = elm2.evalAtX(*x_); + if(y1 < y2) return true; + if(y1 == y2) { + //if justBefore is true we invert the result of the comparison of slopes + if(*justBefore_) { + return elm1.rise > elm2.rise; + } else { + return elm1.rise < elm2.rise; + } + } + return false; + } + }; + + template + class Scan45CountT { + public: + inline Scan45CountT() : counts() {} //counts[0] = counts[1] = counts[2] = counts[3] = 0; } + inline Scan45CountT(CountType count) : counts() { counts[0] = counts[1] = counts[2] = counts[3] = count; } + inline Scan45CountT(const CountType& count1, const CountType& count2, const CountType& count3, + const CountType& count4) : counts() { + counts[0] = count1; + counts[1] = count2; + counts[2] = count3; + counts[3] = count4; + } + inline Scan45CountT(const Scan45CountT& count) : counts() { + (*this) = count; + } + inline bool operator==(const Scan45CountT& count) const { + for(unsigned int i = 0; i < 4; ++i) { + if(counts[i] != count.counts[i]) return false; + } + return true; + } + inline bool operator!=(const Scan45CountT& count) const { return !((*this) == count); } + inline Scan45CountT& operator=(CountType count) { + counts[0] = counts[1] = counts[2] = counts[3] = count; return *this; } + inline Scan45CountT& operator=(const Scan45CountT& count) { + for(unsigned int i = 0; i < 4; ++i) { + counts[i] = count.counts[i]; + } + return *this; + } + inline CountType& operator[](int index) { return counts[index]; } + inline CountType operator[](int index) const {return counts[index]; } + inline Scan45CountT& operator+=(const Scan45CountT& count){ + for(unsigned int i = 0; i < 4; ++i) { + counts[i] += count.counts[i]; + } + return *this; + } + inline Scan45CountT& operator-=(const Scan45CountT& count){ + for(unsigned int i = 0; i < 4; ++i) { + counts[i] -= count.counts[i]; + } + return *this; + } + inline Scan45CountT operator+(const Scan45CountT& count) const { + return Scan45CountT(*this)+=count; + } + inline Scan45CountT operator-(const Scan45CountT& count) const { + return Scan45CountT(*this)-=count; + } + inline Scan45CountT invert() const { + return Scan45CountT(CountType())-=(*this); + } + inline Scan45CountT& operator+=(const Scan45ElementT& element){ + counts[element.rise+1] += element.count; return *this; + } + private: + CountType counts[4]; + }; + + typedef Scan45CountT Scan45Count; + + // inline std::ostream& operator<< (std::ostream& o, const Scan45Count& c) { + // o << c[0] << ", " << c[1] << ", "; + // o << c[2] << ", " << c[3]; + // return o; + // } + + + // inline std::ostream& operator<< (std::ostream& o, const Scan45Vertex& c) { + // o << c.first << ": " << c.second; + // return o; + // } + + + //vetex45 is sortable + template + class Vertex45T { + public: + Point pt; + int rise; // 1, 0 or -1 + ct count; //dxdydTheta + inline Vertex45T() : pt(), rise(), count() {} + inline Vertex45T(const Point& point, int riseIn, ct countIn) : pt(point), rise(riseIn), count(countIn) {} + inline Vertex45T(const Vertex45T& vertex) : pt(vertex.pt), rise(vertex.rise), count(vertex.count) {} + inline Vertex45T& operator=(const Vertex45T& vertex){ + pt = vertex.pt; rise = vertex.rise; count = vertex.count; return *this; } + inline bool operator==(const Vertex45T& vertex) const { + return pt == vertex.pt && rise == vertex.rise && count == vertex.count; } + inline bool operator!=(const Vertex45T& vertex) const { return !((*this) == vertex); } + inline bool operator<(const Vertex45T& vertex) const { + if(pt.x() < vertex.pt.x()) return true; + if(pt.x() == vertex.pt.x()) { + if(pt.y() < vertex.pt.y()) return true; + if(pt.y() == vertex.pt.y()) { return rise < vertex.rise; } + } + return false; + } + inline bool operator>(const Vertex45T& vertex) const { return vertex < (*this); } + inline bool operator<=(const Vertex45T& vertex) const { return !((*this) > vertex); } + inline bool operator>=(const Vertex45T& vertex) const { return !((*this) < vertex); } + inline Unit evalAtX(Unit xIn) const { return pt.y() + rise * (xIn - pt.x()); } + }; + + typedef Vertex45T Vertex45; + + // inline std::ostream& operator<< (std::ostream& o, const Vertex45& c) { + // o << c.pt << " " << c.rise << " " << c.count; + // return o; + // } + + //when scanning Vertex45 for polygon formation we need a scanline comparator functor + class lessVertex45 { + private: + Unit *x_; //x value at which to apply comparison + int *justBefore_; + public: + inline lessVertex45() : x_(0), justBefore_() {} + + inline lessVertex45(Unit *x, int *justBefore) : x_(x), justBefore_(justBefore) {} + + inline lessVertex45(const lessVertex45& that) : x_(that.x_), justBefore_(that.justBefore_) {} + + inline lessVertex45& operator=(const lessVertex45& that) { x_ = that.x_; justBefore_ = that.justBefore_; return *this; } + + template + inline bool operator () (const Vertex45T& elm1, const Vertex45T& elm2) const { + Unit y1 = elm1.evalAtX(*x_); + Unit y2 = elm2.evalAtX(*x_); + if(y1 < y2) return true; + if(y1 == y2) { + //if justBefore is true we invert the result of the comparison of slopes + if(*justBefore_) { + return elm1.rise > elm2.rise; + } else { + return elm1.rise < elm2.rise; + } + } + return false; + } + }; + + // 0 right to left + // 1 upper right to lower left + // 2 high to low + // 3 upper left to lower right + // 4 left to right + // 5 lower left to upper right + // 6 low to high + // 7 lower right to upper left + static inline int classifyEdge45(const Point& prevPt, const Point& nextPt) { + if(prevPt.x() == nextPt.x()) { + //2 or 6 + return predicated_value(prevPt.y() < nextPt.y(), 6, 2); + } + if(prevPt.y() == nextPt.y()) { + //0 or 4 + return predicated_value(prevPt.x() < nextPt.x(), 4, 0); + } + if(prevPt.x() < nextPt.x()) { + //3 or 5 + return predicated_value(prevPt.y() < nextPt.y(), 5, 3); + } + //prevPt.x() > nextPt.y() + //1 or 7 + return predicated_value(prevPt.y() < nextPt.y(), 7, 1); + } + + template + static int applyLogic(CountType count1, CountType count2){ + bool l1 = applyLogic(count1); + bool l2 = applyLogic(count2); + if(l1 && !l2) + return -1; //was true before and became false like a trailing edge + if(!l1 && l2) + return 1; //was false before and became true like a leading edge + return 0; //no change in logic between the two counts + } + template + static bool applyLogic(Count2 count) { +#ifdef BOOST_POLYGON_MSVC +#pragma warning (push) +#pragma warning (disable: 4127) +#endif + if(op == 0) { //apply or + return count[0] > 0 || count[1] > 0; + } else if(op == 1) { //apply and + return count[0] > 0 && count[1] > 0; + } else if(op == 2) { //apply not + return count[0] > 0 && !(count[1] > 0); + } else if(op == 3) { //apply xor + return (count[0] > 0) ^ (count[1] > 0); + } else + return false; +#ifdef BOOST_POLYGON_MSVC +#pragma warning (pop) +#endif + } + + template + struct boolean_op_45_output_functor { + template + void operator()(cT& output, const Count2& count1, const Count2& count2, + const Point& pt, int rise, direction_1d end) { + int edgeType = applyLogic(count1, count2); + if(edgeType) { + int multiplier = end == LOW ? -1 : 1; + //std::cout << "cross logic: " << edgeType << "\n"; + output.insert(output.end(), Vertex45(pt, rise, edgeType * multiplier)); + //std::cout << "write out: " << crossPoint << " " << Point(eraseItrs[i]->x, eraseItrs[i]->y) << "\n"; + } + } + }; + + template + static bool applyLogic(Count1 count) { +#ifdef BOOST_POLYGON_MSVC +#pragma warning (push) +#pragma warning (disable: 4127) +#endif + if(op == 0) { //apply or + return count.count_ > 0; + } else if(op == 1) { //apply and + return count.count_ > 1; + } else if(op == 3) { //apply xor + return (count.count_ % 2) != 0; + } else + return false; +#ifdef BOOST_POLYGON_MSVC +#pragma warning (pop) +#endif + } + + template + struct unary_op_45_output_functor { + template + void operator()(cT& output, const Count1& count1, const Count1& count2, + const Point& pt, int rise, direction_1d end) { + int edgeType = applyLogic(count1, count2); + if(edgeType) { + int multiplier = end == LOW ? -1 : 1; + //std::cout << "cross logic: " << edgeType << "\n"; + output.insert(output.end(), Vertex45(pt, rise, edgeType * multiplier)); + //std::cout << "write out: " << crossPoint << " " << Point(eraseItrs[i]->x, eraseItrs[i]->y) << "\n"; + } + } + }; + + class lessScan45Vertex { + public: + inline lessScan45Vertex() {} //default constructor is only constructor + template + inline bool operator () (const Scan45Vertex& v1, const Scan45Vertex& v2) const { + return (v1.first.x() < v2.first.x()) || (v1.first.x() == v2.first.x() && v1.first.y() < v2.first.y()); + } + }; + template + static inline void sortScan45Vector(S45V& vec) { + polygon_sort(vec.begin(), vec.end(), lessScan45Vertex()); + } + + template + class Scan45 { + public: + typedef Scan45CountT Scan45Count; + typedef std::pair Scan45Vertex; + + //index is the index into the vertex + static inline Scan45Element getElement(const Scan45Vertex& vertex, int index) { + return Scan45Element(vertex.first.x(), vertex.first.y(), index - 1, vertex.second[index]); + } + + class lessScan45Point { + public: + typedef Point first_argument_type; + typedef Point second_argument_type; + typedef bool result_type; + inline lessScan45Point() {} //default constructor is only constructor + inline bool operator () (const Point& v1, const Point& v2) const { + return (v1.x() < v2.x()) || (v1.x() == v2.x() && v1.y() < v2.y()); + } + }; + + typedef std::vector Scan45Vector; + + //definitions + typedef std::set, lessScan45Element > Scan45Data; + typedef typename Scan45Data::iterator iterator; + typedef typename Scan45Data::const_iterator const_iterator; + typedef std::set CrossQueue; + + //data + Scan45Data scanData_; + CrossQueue crossQueue_; + Scan45Vector crossVector_; + Unit x_; + int justBefore_; + public: + inline Scan45() : scanData_(), crossQueue_(), crossVector_(), + x_((std::numeric_limits::min)()), justBefore_(false) { + lessScan45Element lessElm(&x_, &justBefore_); + scanData_ = std::set, lessScan45Element >(lessElm); + } + inline Scan45(const Scan45& that) : scanData_(), crossQueue_(), crossVector_(), + x_((std::numeric_limits::min)()), justBefore_(false) { + (*this) = that; } + inline Scan45& operator=(const Scan45& that) { + x_ = that.x_; + justBefore_ = that.justBefore_; + crossQueue_ = that.crossQueue_; + crossVector_ = that.crossVector_; + lessScan45Element lessElm(&x_, &justBefore_); + scanData_ = std::set, lessScan45Element >(lessElm); + for(const_iterator itr = that.scanData_.begin(); itr != that.scanData_.end(); ++itr){ + scanData_.insert(scanData_.end(), *itr); + } + return *this; + } + + //cT is an output container of Vertex45 + //iT is an iterator over Scan45Vertex elements + template + void scan(cT& output, iT inputBegin, iT inputEnd) { + //std::cout << "1\n"; + while(inputBegin != inputEnd) { + //std::cout << "2\n"; + //std::cout << "x_ = " << x_ << "\n"; + //std::cout << "scan line size: " << scanData_.size() << "\n"; + //for(iterator iter = scanData_.begin(); + // iter != scanData_.end(); ++iter) { + // std::cout << "scan element\n"; + // std::cout << *iter << " " << iter->evalAtX(x_) << "\n"; + // } + // std::cout << "cross queue size: " << crossQueue_.size() << "\n"; + // std::cout << "cross vector size: " << crossVector_.size() << "\n"; + //for(CrossQueue::iterator cqitr = crossQueue_.begin(); cqitr != crossQueue_.end(); ++cqitr) { + // std::cout << *cqitr << " "; + //} std::cout << "\n"; + Unit nextX = (*inputBegin).first.x(); + if(!crossVector_.empty() && crossVector_[0].first.x() < nextX) nextX = crossVector_[0].first.x(); + if(nextX != x_) { + //std::cout << "3\n"; + //we need to move to the next scanline stop + //we need to process end events then cross events + //process end events + if(!crossQueue_.empty() && + (*crossQueue_.begin()).x() < nextX) { + //std::cout << "4\n"; + nextX = (std::min)(nextX, (*crossQueue_.begin()).x()); + } + //std::cout << "6\n"; + justBefore_ = true; + x_ = nextX; + advance_(output); + justBefore_ = false; + if(!crossVector_.empty() && + nextX == (*inputBegin).first.x()) { + inputBegin = mergeCross_(inputBegin, inputEnd); + } + processEvent_(output, crossVector_.begin(), crossVector_.end()); + crossVector_.clear(); + } else { + //std::cout << "7\n"; + //our scanline has progressed to the event that is next in the queue + inputBegin = processEvent_(output, inputBegin, inputEnd); + } + } + //std::cout << "done scanning\n"; + } + + private: + //functions + + template + inline void advance_(cT& output) { + //process all cross points on the cross queue at the current x_ + //std::cout << "advance_\n"; + std::vector eraseVec; + while(!crossQueue_.empty() && + (*crossQueue_.begin()).x() == x_){ + //std::cout << "loop\n"; + //pop point off the cross queue + Point crossPoint = *(crossQueue_.begin()); + //std::cout << crossPoint << "\n"; + //for(iterator iter = scanData_.begin(); + // iter != scanData_.end(); ++iter) { + // std::cout << "scan element\n"; + // std::cout << *iter << " " << iter->evalAtX(x_) << "\n"; + //} + crossQueue_.erase(crossQueue_.begin()); + Scan45Vertex vertex(crossPoint, Scan45Count()); + iterator lowIter = lookUp_(vertex.first.y()); + //std::cout << "searching at: " << vertex.first.y() << "\n"; + //if(lowIter == scanData_.end()) std::cout << "could not find\n"; + //else std::cout << "found: " << *lowIter << "\n"; + if(lowIter == scanData_.end() || + lowIter->evalAtX(x_) != vertex.first.y()) { + // std::cout << "skipping\n"; + //there weren't any edges at this potential cross point + continue; + } + CountType countBelow; + iterator searchDownItr = lowIter; + while(searchDownItr != scanData_.begin() + && searchDownItr->evalAtX(x_) == vertex.first.y()) { + //get count from below + --searchDownItr; + countBelow = searchDownItr->count; + } + //std::cout << "Below Count: " << countBelow << "\n"; + Scan45Count count(countBelow); + std::size_t numEdges = 0; + iterator eraseItrs[3]; + while(lowIter != scanData_.end() && + lowIter->evalAtX(x_) == vertex.first.y()) { + for(int index = lowIter->rise +1; index >= 0; --index) + count[index] = lowIter->count; + //std::cout << count << "\n"; + eraseItrs[numEdges] = lowIter; + ++numEdges; + ++lowIter; + } + if(numEdges == 1) { + //look for the next crossing point and continue + //std::cout << "found only one edge\n"; + findCross_(eraseItrs[0]); + continue; + } + //before we erase the elements we need to decide if they should be written out + CountType currentCount = countBelow; + for(std::size_t i = 0; i < numEdges; ++i) { + output_functor f; + f(output, currentCount, eraseItrs[i]->count, crossPoint, eraseItrs[i]->rise, LOW); + currentCount = eraseItrs[i]->count; + } + //schedule erase of the elements + for(std::size_t i = 0; i < numEdges; ++i) { + eraseVec.push_back(eraseItrs[i]); + } + + //take the derivative wrt theta of the count at the crossing point + vertex.second[2] = count[2] - countBelow; + vertex.second[1] = count[1] - count[2]; + vertex.second[0] = count[0] - count[1]; + //add the point, deriviative pair into the cross vector + //std::cout << "LOOK HERE!\n"; + //std::cout << count << "\n"; + //std::cout << vertex << "\n"; + crossVector_.push_back(vertex); + } + //erase crossing elements + std::vector searchVec; + for(std::size_t i = 0; i < eraseVec.size(); ++i) { + if(eraseVec[i] != scanData_.begin()) { + iterator searchItr = eraseVec[i]; + --searchItr; + if(searchVec.empty() || + searchVec.back() != searchItr) + searchVec.push_back(searchItr); + } + scanData_.erase(eraseVec[i]); + } + for(std::size_t i = 0; i < searchVec.size(); ++i) { + findCross_(searchVec[i]); + } + } + + template + inline iT mergeCross_(iT inputBegin, iT inputEnd) { + Scan45Vector vec; + swap(vec, crossVector_); + iT mergeEnd = inputBegin; + std::size_t mergeCount = 0; + while(mergeEnd != inputEnd && + (*mergeEnd).first.x() == x_) { + ++mergeCount; + ++mergeEnd; + } + crossVector_.reserve((std::max)(vec.capacity(), vec.size() + mergeCount)); + for(std::size_t i = 0; i < vec.size(); ++i){ + while(inputBegin != mergeEnd && + (*inputBegin).first.y() < vec[i].first.y()) { + crossVector_.push_back(*inputBegin); + ++inputBegin; + } + crossVector_.push_back(vec[i]); + } + while(inputBegin != mergeEnd){ + crossVector_.push_back(*inputBegin); + ++inputBegin; + } + return inputBegin; + } + + template + inline iT processEvent_(cT& output, iT inputBegin, iT inputEnd) { + //std::cout << "processEvent_\n"; + CountType verticalCount = CountType(); + Point prevPoint; + iterator prevIter = scanData_.end(); + while(inputBegin != inputEnd && + (*inputBegin).first.x() == x_) { + //std::cout << (*inputBegin) << "\n"; + //std::cout << "loop\n"; + Scan45Vertex vertex = *inputBegin; + //std::cout << vertex.first << "\n"; + //if vertical count propigating up fake a null event at the next element + if(verticalCount != CountType() && (prevIter != scanData_.end() && + prevIter->evalAtX(x_) < vertex.first.y())) { + //std::cout << "faking null event\n"; + vertex = Scan45Vertex(Point(x_, prevIter->evalAtX(x_)), Scan45Count()); + } else { + ++inputBegin; + //std::cout << "after increment\n"; + //accumulate overlapping changes in Scan45Count + while(inputBegin != inputEnd && + (*inputBegin).first.x() == x_ && + (*inputBegin).first.y() == vertex.first.y()) { + //std::cout << "accumulate\n"; + vertex.second += (*inputBegin).second; + ++inputBegin; + } + } + //std::cout << vertex.second << "\n"; + //integrate vertex + CountType currentCount = verticalCount;// + vertex.second[0]; + for(unsigned int i = 0; i < 3; ++i) { + vertex.second[i] = currentCount += vertex.second[i]; + } + //std::cout << vertex.second << "\n"; + //vertex represents the change in state at this point + + //get counts at current vertex + CountType countBelow; + iterator lowIter = lookUp_(vertex.first.y()); + if(lowIter != scanData_.begin()) { + //get count from below + --lowIter; + countBelow = lowIter->count; + ++lowIter; + } + //std::cout << "Count Below: " << countBelow[0] << " " << countBelow[1] << "\n"; + //std::cout << "vertical count: " << verticalCount[0] << " " << verticalCount[1] << "\n"; + Scan45Count countAt(countBelow - verticalCount); + //check if the vertical edge should be written out + if(verticalCount != CountType()) { + output_functor f; + f(output, countBelow - verticalCount, countBelow, prevPoint, 2, HIGH); + f(output, countBelow - verticalCount, countBelow, vertex.first, 2, LOW); + } + currentCount = countBelow - verticalCount; + while(lowIter != scanData_.end() && + lowIter->evalAtX(x_) == vertex.first.y()) { + for(unsigned int i = lowIter->rise + 1; i < 3; ++i) { + countAt[i] = lowIter->count; + } + Point lp(lowIter->x, lowIter->y); + if(lp != vertex.first) { + output_functor f; + f(output, currentCount, lowIter->count, vertex.first, lowIter->rise, LOW); + } + currentCount = lowIter->count; + iterator nextIter = lowIter; + ++nextIter; + //std::cout << "erase\n"; + scanData_.erase(lowIter); + if(nextIter != scanData_.end()) + findCross_(nextIter); + lowIter = nextIter; + } + verticalCount += vertex.second[3]; + prevPoint = vertex.first; + //std::cout << "new vertical count: " << verticalCount[0] << " " << verticalCount[1] << "\n"; + prevIter = lowIter; + //count represents the current state at this point + //std::cout << vertex.second << "\n"; + //std::cout << countAt << "\n"; + //std::cout << "ADD\n"; + vertex.second += countAt; + //std::cout << vertex.second << "\n"; + + //add elements to the scanline + for(int i = 0; i < 3; ++i) { + if(vertex.second[i] != countBelow) { + //std::cout << "insert: " << vertex.first.x() << " " << vertex.first.y() << " " << i-1 << + // " " << vertex.second[i][0] << " " << vertex.second[i][1] << "\n"; + iterator insertIter = scanData_.insert(scanData_.end(), + Scan45ElementT(vertex.first.x(), + vertex.first.y(), + i - 1, vertex.second[i])); + findCross_(insertIter); + output_functor f; + f(output, countBelow, vertex.second[i], vertex.first, i - 1, HIGH); + } + countBelow = vertex.second[i]; + } + } + //std::cout << "end processEvent\n"; + return inputBegin; + } + + //iter1 is horizontal + inline void scheduleCross0_(iterator iter1, iterator iter2) { + //std::cout << "0, "; + Unit y1 = iter1->evalAtX(x_); + Unit y2 = iter2->evalAtX(x_); + LongUnit delta = local_abs(LongUnit(y1) - LongUnit(y2)); + if(delta + static_cast(x_) <= (std::numeric_limits::max)()) + crossQueue_.insert(crossQueue_.end(), Point(x_ + static_cast(delta), y1)); + //std::cout << Point(x_ + delta, y1); + } + + //neither iter is horizontal + inline void scheduleCross1_(iterator iter1, iterator iter2) { + //std::cout << "1, "; + Unit y1 = iter1->evalAtX(x_); + Unit y2 = iter2->evalAtX(x_); + //std::cout << y1 << " " << y2 << ": "; + //note that half the delta cannot exceed the positive inter range + LongUnit delta = y1; + delta -= y2; + Unit UnitMax = (std::numeric_limits::max)(); + if((delta & 1) == 1) { + //delta is odd, division by 2 will result in integer trunctaion + if(delta == 1) { + //the cross point is not on the integer grid and cannot be represented + //we must throw an exception + std::string msg = "GTL 45 Boolean error, precision insufficient to represent edge intersection coordinate value."; + throw(msg); + } else { + //note that result of this subtraction is always positive because itr1 is above itr2 in scanline + LongUnit halfDelta2 = (LongUnit)((((LongUnit)y1) - y2)/2); + //note that halfDelta2 has been truncated + if(halfDelta2 + x_ <= UnitMax && halfDelta2 + y2 <= UnitMax) { + crossQueue_.insert(crossQueue_.end(), Point(x_+static_cast(halfDelta2), y2+static_cast(halfDelta2))); + crossQueue_.insert(crossQueue_.end(), Point(x_+static_cast(halfDelta2), y2+static_cast(halfDelta2)+1)); + } + } + } else { + LongUnit halfDelta = (LongUnit)((((LongUnit)y1) - y2)/2); + if(halfDelta + x_ <= UnitMax && halfDelta + y2 <= UnitMax) + crossQueue_.insert(crossQueue_.end(), Point(x_+static_cast(halfDelta), y2+static_cast(halfDelta))); + //std::cout << Point(x_+halfDelta, y2+halfDelta); + } + } + + inline void findCross_(iterator iter) { + //std::cout << "find cross "; + iterator iteratorBelow = iter; + iterator iteratorAbove = iter; + if(iter != scanData_.begin() && iter->rise < 1) { + --iteratorBelow; + if(iter->rise == 0){ + if(iteratorBelow->rise == 1) { + scheduleCross0_(iter, iteratorBelow); + } + } else { + //iter->rise == -1 + if(iteratorBelow->rise == 1) { + scheduleCross1_(iter, iteratorBelow); + } else if(iteratorBelow->rise == 0) { + scheduleCross0_(iteratorBelow, iter); + } + } + } + ++iteratorAbove; + if(iteratorAbove != scanData_.end() && iter->rise > -1) { + if(iter->rise == 0) { + if(iteratorAbove->rise == -1) { + scheduleCross0_(iter, iteratorAbove); + } + } else { + //iter->rise == 1 + if(iteratorAbove->rise == -1) { + scheduleCross1_(iteratorAbove, iter); + } else if(iteratorAbove->rise == 0) { + scheduleCross0_(iteratorAbove, iter); + } + } + } + //std::cout << "\n"; + } + + inline iterator lookUp_(Unit y){ + //if just before then we need to look from 1 not -1 + return scanData_.lower_bound(Scan45ElementT(x_, y, -1+2*justBefore_)); + } + }; + + //template + //static inline void print45Data(const std::set, + // lessScan45Element >& data) { + // typename std::set, lessScan45Element >::const_iterator iter; + // for(iter = data.begin(); iter != data.end(); ++iter) { + // std::cout << iter->x << " " << iter->y << " " << iter->rise << "\n"; + // } + //} + + template + static inline bool testScan45Data(streamtype& stdcout) { + Unit x = 0; + int justBefore = false; + lessScan45Element lessElm(&x, &justBefore); + std::set, lessScan45Element > testData(lessElm); + //Unit size = testData.size(); + typedef std::set, lessScan45Element > Scan45Data; + typename Scan45Data::iterator itr10 = testData.insert(testData.end(), Scan45Element(0, 10, 1)); + typename Scan45Data::iterator itr20 = testData.insert(testData.end(), Scan45Element(0, 20, 1)); + typename Scan45Data::iterator itr30 = testData.insert(testData.end(), Scan45Element(0, 30, -1)); + typename Scan45Data::iterator itr40 = testData.insert(testData.end(), Scan45Element(0, 40, -1)); + typename Scan45Data::iterator itrA = testData.lower_bound(Scan45Element(0, 29, -1)); + typename Scan45Data::iterator itr1 = testData.lower_bound(Scan45Element(0, 10, -1)); + x = 4; + //now at 14 24 26 36 + typename Scan45Data::iterator itrB = testData.lower_bound(Scan45Element(4, 29, -1)); + typename Scan45Data::iterator itr2 = testData.lower_bound(Scan45Element(4, 14, -1)); + if(itr1 != itr2) stdcout << "test1 failed\n"; + if(itrA == itrB) stdcout << "test2 failed\n"; + //remove crossing elements + testData.erase(itr20); + testData.erase(itr30); + x = 5; + itr20 = testData.insert(testData.end(), Scan45Element(0, 20, 1)); + itr30 = testData.insert(testData.end(), Scan45Element(0, 30, -1)); + //now at 15 25 25 35 + typename Scan45Data::iterator itr = testData.begin(); + if(itr != itr10) stdcout << "test3 failed\n"; + ++itr; + if(itr != itr30) stdcout << "test4 failed\n"; + ++itr; + if(itr != itr20) stdcout << "test5 failed\n"; + ++itr; + if(itr != itr40) stdcout << "test6 failed\n"; + stdcout << "done testing Scan45Data\n"; + return true; + } + + template + static inline bool testScan45Rect(stream_type& stdcout) { + stdcout << "testing Scan45Rect\n"; + Scan45 > scan45; + std::vector result; + typedef std::pair Scan45Vertex; + std::vector vertices; + //is a Rectnagle(0, 0, 10, 10); + Count2 count(1, 0); + Count2 ncount(-1, 0); + vertices.push_back(Scan45Vertex(Point(0,0), Scan45Count(Count2(0, 0), count, Count2(0, 0), count))); + vertices.push_back(Scan45Vertex(Point(0,10), Scan45Count(Count2(0, 0), ncount, Count2(0, 0), ncount))); + vertices.push_back(Scan45Vertex(Point(10,0), Scan45Count(Count2(0, 0), ncount, Count2(0, 0), ncount))); + vertices.push_back(Scan45Vertex(Point(10,10), Scan45Count(Count2(0, 0), count, Count2(0, 0), count))); + stdcout << "scanning\n"; + scan45.scan(result, vertices.begin(), vertices.end()); + stdcout << "done scanning\n"; + // result size == 8 + // result == 0 0 0 1 + // result == 0 0 2 1 + // result == 0 10 2 -1 + // result == 0 10 0 -1 + // result == 10 0 0 -1 + // result == 10 0 2 -1 + // result == 10 10 2 1 + // result == 10 10 0 1 + std::vector reference; + reference.push_back(Vertex45(Point(0, 0), 0, 1)); + reference.push_back(Vertex45(Point(0, 0), 2, 1)); + reference.push_back(Vertex45(Point(0, 10), 2, -1)); + reference.push_back(Vertex45(Point(0, 10), 0, -1)); + reference.push_back(Vertex45(Point(10, 0), 0, -1)); + reference.push_back(Vertex45(Point(10, 0), 2, -1)); + reference.push_back(Vertex45(Point(10, 10), 2, 1)); + reference.push_back(Vertex45(Point(10, 10), 0, 1)); + if(result != reference) { + stdcout << "result size == " << result.size() << "\n"; + for(std::size_t i = 0; i < result.size(); ++i) { + //std::cout << "result == " << result[i]<< "\n"; + } + stdcout << "reference size == " << reference.size() << "\n"; + for(std::size_t i = 0; i < reference.size(); ++i) { + //std::cout << "reference == " << reference[i]<< "\n"; + } + return false; + } + stdcout << "done testing Scan45Rect\n"; + return true; + } + + template + static inline bool testScan45P1(stream_type& stdcout) { + stdcout << "testing Scan45P1\n"; + Scan45 > scan45; + std::vector result; + typedef std::pair Scan45Vertex; + std::vector vertices; + //is a Rectnagle(0, 0, 10, 10); + Count2 count(1, 0); + Count2 ncount(-1, 0); + vertices.push_back(Scan45Vertex(Point(0,0), Scan45Count(Count2(0, 0), Count2(0, 0), count, count))); + vertices.push_back(Scan45Vertex(Point(0,10), Scan45Count(Count2(0, 0), Count2(0, 0), ncount, ncount))); + vertices.push_back(Scan45Vertex(Point(10,10), Scan45Count(Count2(0, 0), Count2(0, 0), ncount, ncount))); + vertices.push_back(Scan45Vertex(Point(10,20), Scan45Count(Count2(0, 0), Count2(0, 0), count, count))); + stdcout << "scanning\n"; + scan45.scan(result, vertices.begin(), vertices.end()); + stdcout << "done scanning\n"; + // result size == 8 + // result == 0 0 1 1 + // result == 0 0 2 1 + // result == 0 10 2 -1 + // result == 0 10 1 -1 + // result == 10 10 1 -1 + // result == 10 10 2 -1 + // result == 10 20 2 1 + // result == 10 20 1 1 + std::vector reference; + reference.push_back(Vertex45(Point(0, 0), 1, 1)); + reference.push_back(Vertex45(Point(0, 0), 2, 1)); + reference.push_back(Vertex45(Point(0, 10), 2, -1)); + reference.push_back(Vertex45(Point(0, 10), 1, -1)); + reference.push_back(Vertex45(Point(10, 10), 1, -1)); + reference.push_back(Vertex45(Point(10, 10), 2, -1)); + reference.push_back(Vertex45(Point(10, 20), 2, 1)); + reference.push_back(Vertex45(Point(10, 20), 1, 1)); + if(result != reference) { + stdcout << "result size == " << result.size() << "\n"; + for(std::size_t i = 0; i < result.size(); ++i) { + //std::cout << "result == " << result[i]<< "\n"; + } + stdcout << "reference size == " << reference.size() << "\n"; + for(std::size_t i = 0; i < reference.size(); ++i) { + //std::cout << "reference == " << reference[i]<< "\n"; + } + return false; + } + stdcout << "done testing Scan45P1\n"; + return true; + } + + template + static inline bool testScan45P2(stream_type& stdcout) { + stdcout << "testing Scan45P2\n"; + Scan45 > scan45; + std::vector result; + typedef std::pair Scan45Vertex; + std::vector vertices; + //is a Rectnagle(0, 0, 10, 10); + Count2 count(1, 0); + Count2 ncount(-1, 0); + vertices.push_back(Scan45Vertex(Point(0,0), Scan45Count(Count2(0, 0), count, ncount, Count2(0, 0)))); + vertices.push_back(Scan45Vertex(Point(10,0), Scan45Count(Count2(0, 0), ncount, count, Count2(0, 0)))); + vertices.push_back(Scan45Vertex(Point(10,10), Scan45Count(Count2(0, 0), ncount, count, Count2(0, 0)))); + vertices.push_back(Scan45Vertex(Point(20,10), Scan45Count(Count2(0, 0), count, ncount, Count2(0, 0)))); + stdcout << "scanning\n"; + scan45.scan(result, vertices.begin(), vertices.end()); + stdcout << "done scanning\n"; + // result size == 8 + // result == 0 0 0 1 + // result == 0 0 1 -1 + // result == 10 0 0 -1 + // result == 10 0 1 1 + // result == 10 10 1 1 + // result == 10 10 0 -1 + // result == 20 10 1 -1 + // result == 20 10 0 1 + std::vector reference; + reference.push_back(Vertex45(Point(0, 0), 0, 1)); + reference.push_back(Vertex45(Point(0, 0), 1, -1)); + reference.push_back(Vertex45(Point(10, 0), 0, -1)); + reference.push_back(Vertex45(Point(10, 0), 1, 1)); + reference.push_back(Vertex45(Point(10, 10), 1, 1)); + reference.push_back(Vertex45(Point(10, 10), 0, -1)); + reference.push_back(Vertex45(Point(20, 10), 1, -1)); + reference.push_back(Vertex45(Point(20, 10), 0, 1)); + if(result != reference) { + stdcout << "result size == " << result.size() << "\n"; + for(std::size_t i = 0; i < result.size(); ++i) { + //stdcout << "result == " << result[i]<< "\n"; + } + stdcout << "reference size == " << reference.size() << "\n"; + for(std::size_t i = 0; i < reference.size(); ++i) { + //stdcout << "reference == " << reference[i]<< "\n"; + } + return false; + } + stdcout << "done testing Scan45P2\n"; + return true; + } + + template + static inline bool testScan45And(streamtype& stdcout) { + stdcout << "testing Scan45And\n"; + Scan45 > scan45; + std::vector result; + typedef std::pair Scan45Vertex; + std::vector vertices; + //is a Rectnagle(0, 0, 10, 10); + Count2 count(1, 0); + Count2 ncount(-1, 0); + vertices.push_back(Scan45Vertex(Point(0,0), Scan45Count(Count2(0, 0), count, Count2(0, 0), count))); + vertices.push_back(Scan45Vertex(Point(0,10), Scan45Count(Count2(0, 0), ncount, Count2(0, 0), ncount))); + vertices.push_back(Scan45Vertex(Point(10,0), Scan45Count(Count2(0, 0), ncount, Count2(0, 0), ncount))); + vertices.push_back(Scan45Vertex(Point(10,10), Scan45Count(Count2(0, 0), count, Count2(0, 0), count))); + count = Count2(0, 1); + ncount = count.invert(); + vertices.push_back(Scan45Vertex(Point(2,2), Scan45Count(Count2(0, 0), count, Count2(0, 0), count))); + vertices.push_back(Scan45Vertex(Point(2,12), Scan45Count(Count2(0, 0), ncount, Count2(0, 0), ncount))); + vertices.push_back(Scan45Vertex(Point(12,2), Scan45Count(Count2(0, 0), ncount, Count2(0, 0), ncount))); + vertices.push_back(Scan45Vertex(Point(12,12), Scan45Count(Count2(0, 0), count, Count2(0, 0), count))); + sortScan45Vector(vertices); + stdcout << "scanning\n"; + scan45.scan(result, vertices.begin(), vertices.end()); + stdcout << "done scanning\n"; + //result size == 8 + //result == 2 2 0 1 + //result == 2 2 2 1 + //result == 2 10 2 -1 + //result == 2 10 0 -1 + //result == 10 2 0 -1 + //result == 10 2 2 -1 + //result == 10 10 2 1 + //result == 10 10 0 1 + std::vector reference; + reference.push_back(Vertex45(Point(2, 2), 0, 1)); + reference.push_back(Vertex45(Point(2, 2), 2, 1)); + reference.push_back(Vertex45(Point(2, 10), 2, -1)); + reference.push_back(Vertex45(Point(2, 10), 0, -1)); + reference.push_back(Vertex45(Point(10, 2), 0, -1)); + reference.push_back(Vertex45(Point(10, 2), 2, -1)); + reference.push_back(Vertex45(Point(10, 10), 2, 1)); + reference.push_back(Vertex45(Point(10, 10), 0, 1)); + if(result != reference) { + stdcout << "result size == " << result.size() << "\n"; + for(std::size_t i = 0; i < result.size(); ++i) { + //stdcout << "result == " << result[i]<< "\n"; + } + stdcout << "reference size == " << reference.size() << "\n"; + for(std::size_t i = 0; i < reference.size(); ++i) { + //stdcout << "reference == " << reference[i]<< "\n"; + } + return false; + } + stdcout << "done testing Scan45And\n"; + return true; + } + + template + static inline bool testScan45Star1(stream_type& stdcout) { + stdcout << "testing Scan45Star1\n"; + Scan45 > scan45; + std::vector result; + typedef std::pair Scan45Vertex; + std::vector vertices; + //is a Rectnagle(0, 0, 10, 10); + Count2 count(1, 0); + Count2 ncount(-1, 0); + vertices.push_back(Scan45Vertex(Point(0,8), Scan45Count(count, Count2(0, 0), ncount, Count2(0, 0)))); + vertices.push_back(Scan45Vertex(Point(8,0), Scan45Count(ncount, Count2(0, 0), Count2(0, 0), ncount))); + vertices.push_back(Scan45Vertex(Point(8,16), Scan45Count(Count2(0, 0), Count2(0, 0), count, count))); + count = Count2(0, 1); + ncount = count.invert(); + vertices.push_back(Scan45Vertex(Point(12,8), Scan45Count(count, Count2(0, 0), ncount, Count2(0, 0)))); + vertices.push_back(Scan45Vertex(Point(4,0), Scan45Count(Count2(0, 0), Count2(0, 0), count, count))); + vertices.push_back(Scan45Vertex(Point(4,16), Scan45Count(ncount, Count2(0, 0), Count2(0, 0), ncount))); + sortScan45Vector(vertices); + stdcout << "scanning\n"; + scan45.scan(result, vertices.begin(), vertices.end()); + stdcout << "done scanning\n"; + // result size == 24 + // result == 0 8 -1 1 + // result == 0 8 1 -1 + // result == 4 0 1 1 + // result == 4 0 2 1 + // result == 4 4 2 -1 + // result == 4 4 -1 -1 + // result == 4 12 1 1 + // result == 4 12 2 1 + // result == 4 16 2 -1 + // result == 4 16 -1 -1 + // result == 6 2 1 -1 + // result == 6 14 -1 1 + // result == 6 2 -1 1 + // result == 6 14 1 -1 + // result == 8 0 -1 -1 + // result == 8 0 2 -1 + // result == 8 4 2 1 + // result == 8 4 1 1 + // result == 8 12 -1 -1 + // result == 8 12 2 -1 + // result == 8 16 2 1 + // result == 8 16 1 1 + // result == 12 8 1 -1 + // result == 12 8 -1 1 + if(result.size() != 24) { + //stdcout << "result size == " << result.size() << "\n"; + //stdcout << "reference size == " << 24 << "\n"; + return false; + } + stdcout << "done testing Scan45Star1\n"; + return true; + } + + template + static inline bool testScan45Star2(stream_type& stdcout) { + stdcout << "testing Scan45Star2\n"; + Scan45 > scan45; + std::vector result; + typedef std::pair Scan45Vertex; + std::vector vertices; + //is a Rectnagle(0, 0, 10, 10); + Count2 count(1, 0); + Count2 ncount(-1, 0); + vertices.push_back(Scan45Vertex(Point(0,4), Scan45Count(Count2(0, 0), count, ncount, Count2(0, 0)))); + vertices.push_back(Scan45Vertex(Point(16,4), Scan45Count(count, ncount, Count2(0, 0), Count2(0, 0)))); + vertices.push_back(Scan45Vertex(Point(8,12), Scan45Count(ncount, Count2(0, 0), count, Count2(0, 0)))); + count = Count2(0, 1); + ncount = count.invert(); + vertices.push_back(Scan45Vertex(Point(0,8), Scan45Count(count, ncount, Count2(0, 0), Count2(0, 0)))); + vertices.push_back(Scan45Vertex(Point(16,8), Scan45Count(Count2(0, 0), count, ncount, Count2(0, 0)))); + vertices.push_back(Scan45Vertex(Point(8,0), Scan45Count(ncount, Count2(0, 0), count, Count2(0, 0)))); + sortScan45Vector(vertices); + stdcout << "scanning\n"; + scan45.scan(result, vertices.begin(), vertices.end()); + stdcout << "done scanning\n"; + // result size == 24 + // result == 0 4 0 1 + // result == 0 4 1 -1 + // result == 0 8 -1 1 + // result == 0 8 0 -1 + // result == 2 6 1 1 + // result == 2 6 -1 -1 + // result == 4 4 0 -1 + // result == 4 8 0 1 + // result == 4 4 -1 1 + // result == 4 8 1 -1 + // result == 8 0 -1 -1 + // result == 8 0 1 1 + // result == 8 12 1 1 + // result == 8 12 -1 -1 + // result == 12 4 1 -1 + // result == 12 8 -1 1 + // result == 12 4 0 1 + // result == 12 8 0 -1 + // result == 14 6 -1 -1 + // result == 14 6 1 1 + // result == 16 4 0 -1 + // result == 16 4 -1 1 + // result == 16 8 1 -1 + // result == 16 8 0 1 + if(result.size() != 24) { + //std::cout << "result size == " << result.size() << "\n"; + //std::cout << "reference size == " << 24 << "\n"; + return false; + } + stdcout << "done testing Scan45Star2\n"; + return true; + } + + template + static inline bool testScan45Star3(stream_type& stdcout) { + stdcout << "testing Scan45Star3\n"; + Scan45 > scan45; + std::vector result; + typedef std::pair Scan45Vertex; + std::vector vertices; + //is a Rectnagle(0, 0, 10, 10); + Count2 count(1, 0); + Count2 ncount(-1, 0); + vertices.push_back(Scan45Vertex(Point(0,8), Scan45Count(count, Count2(0, 0), ncount, Count2(0, 0)))); + vertices.push_back(Scan45Vertex(Point(8,0), Scan45Count(ncount, Count2(0, 0), Count2(0, 0), ncount))); + vertices.push_back(Scan45Vertex(Point(8,16), Scan45Count(Count2(0, 0), Count2(0, 0), count, count))); + + vertices.push_back(Scan45Vertex(Point(6,0), Scan45Count(Count2(0, 0), count, Count2(0, 0), count))); + vertices.push_back(Scan45Vertex(Point(6,14), Scan45Count(Count2(0, 0), ncount, Count2(0, 0), ncount))); + vertices.push_back(Scan45Vertex(Point(12,0), Scan45Count(Count2(0, 0), ncount, Count2(0, 0), ncount))); + vertices.push_back(Scan45Vertex(Point(12,14), Scan45Count(Count2(0, 0), count, Count2(0, 0), count))); + count = Count2(0, 1); + ncount = count.invert(); + vertices.push_back(Scan45Vertex(Point(12,8), Scan45Count(count, Count2(0, 0), ncount, Count2(0, 0)))); + vertices.push_back(Scan45Vertex(Point(4,0), Scan45Count(Count2(0, 0), Count2(0, 0), count, count))); + vertices.push_back(Scan45Vertex(Point(4,16), Scan45Count(ncount, Count2(0, 0), Count2(0, 0), ncount))); + sortScan45Vector(vertices); + stdcout << "scanning\n"; + scan45.scan(result, vertices.begin(), vertices.end()); + stdcout << "done scanning\n"; + // result size == 28 + // result == 0 8 -1 1 + // result == 0 8 1 -1 + // result == 4 0 1 1 + // result == 4 0 2 1 + // result == 4 4 2 -1 + // result == 4 4 -1 -1 + // result == 4 12 1 1 + // result == 4 12 2 1 + // result == 4 16 2 -1 + // result == 4 16 -1 -1 + // result == 6 2 1 -1 + // result == 6 14 -1 1 + // result == 6 0 0 1 + // result == 6 0 2 1 + // result == 6 2 2 -1 + // result == 6 14 1 -1 + // result == 8 0 0 -1 + // result == 8 0 0 1 + // result == 8 14 0 -1 + // result == 8 14 2 -1 + // result == 8 16 2 1 + // result == 8 16 1 1 + // result == 12 0 0 -1 + // result == 12 0 2 -1 + // result == 12 8 2 1 + // result == 12 8 2 -1 + // result == 12 14 2 1 + // result == 12 14 0 1 + if(result.size() != 28) { + //std::cout << "result size == " << result.size() << "\n"; + //std::cout << "reference size == " << 28 << "\n"; + return false; + } + + stdcout << "done testing Scan45Star3\n"; + return true; + } + + + template + static inline bool testScan45Star4(stream_type& stdcout) { + stdcout << "testing Scan45Star4\n"; + Scan45 > scan45; + std::vector result; + typedef std::pair Scan45Vertex; + std::vector vertices; + //is a Rectnagle(0, 0, 10, 10); + Count2 count(1, 0); + Count2 ncount(-1, 0); + vertices.push_back(Scan45Vertex(Point(0,4), Scan45Count(Count2(0, 0), count, ncount, Count2(0, 0)))); + vertices.push_back(Scan45Vertex(Point(16,4), Scan45Count(count, ncount, Count2(0, 0), Count2(0, 0)))); + vertices.push_back(Scan45Vertex(Point(8,12), Scan45Count(ncount, Count2(0, 0), count, Count2(0, 0)))); + + vertices.push_back(Scan45Vertex(Point(0,6), Scan45Count(Count2(0, 0), count, Count2(0, 0), count))); + vertices.push_back(Scan45Vertex(Point(0,12), Scan45Count(Count2(0, 0), ncount, Count2(0, 0), ncount))); + vertices.push_back(Scan45Vertex(Point(16,6), Scan45Count(Count2(0, 0), ncount, Count2(0, 0), ncount))); + vertices.push_back(Scan45Vertex(Point(16,12), Scan45Count(Count2(0, 0), count, Count2(0, 0), count))); + count = Count2(0, 1); + ncount = count.invert(); + vertices.push_back(Scan45Vertex(Point(0,8), Scan45Count(count, ncount, Count2(0, 0), Count2(0, 0)))); + vertices.push_back(Scan45Vertex(Point(16,8), Scan45Count(Count2(0, 0), count, ncount, Count2(0, 0)))); + vertices.push_back(Scan45Vertex(Point(8,0), Scan45Count(ncount, Count2(0, 0), count, Count2(0, 0)))); + sortScan45Vector(vertices); + stdcout << "scanning\n"; + scan45.scan(result, vertices.begin(), vertices.end()); + stdcout << "done scanning\n"; + // result size == 28 + // result == 0 4 0 1 + // result == 0 4 1 -1 + // result == 0 6 0 1 + // result == 0 6 2 1 + // result == 0 8 2 -1 + // result == 0 8 2 1 + // result == 0 12 2 -1 + // result == 0 12 0 -1 + // result == 2 6 1 1 + // result == 2 6 0 -1 + // result == 4 4 0 -1 + // result == 4 4 -1 1 + // result == 8 12 0 1 + // result == 8 0 -1 -1 + // result == 8 0 1 1 + // result == 8 12 0 -1 + // result == 12 4 1 -1 + // result == 12 4 0 1 + // result == 14 6 -1 -1 + // result == 14 6 0 1 + // result == 16 4 0 -1 + // result == 16 4 -1 1 + // result == 16 6 0 -1 + // result == 16 6 2 -1 + // result == 16 8 2 1 + // result == 16 8 2 -1 + // result == 16 12 2 1 + // result == 16 12 0 1 + if(result.size() != 28) { + //stdcout << "result size == " << result.size() << "\n"; + //stdcout << "reference size == " << 28 << "\n"; + return false; + } + + stdcout << "done testing Scan45Star4\n"; + return true; + } + + template + static inline bool testScan45(stream_type& stdcout) { + if(!testScan45Rect(stdcout)) return false; + if(!testScan45P1(stdcout)) return false; + if(!testScan45P2(stdcout)) return false; + if(!testScan45And(stdcout)) return false; + if(!testScan45Star1(stdcout)) return false; + if(!testScan45Star2(stdcout)) return false; + if(!testScan45Star3(stdcout)) return false; + if(!testScan45Star4(stdcout)) return false; + return true; + } + + }; + +} + +} +#endif diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/detail/iterator_compact_to_points.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/detail/iterator_compact_to_points.hpp new file mode 100644 index 0000000..e0f61d3 --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/detail/iterator_compact_to_points.hpp @@ -0,0 +1,74 @@ +/* + Copyright 2008 Intel Corporation + + Use, modification and distribution are subject to the Boost Software License, + Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at + http://www.boost.org/LICENSE_1_0.txt). +*/ +#ifndef BOOST_POLYGON_ITERATOR_COMPACT_TO_POINTS_HPP +#define BOOST_POLYGON_ITERATOR_COMPACT_TO_POINTS_HPP +namespace boost { namespace polygon{ +template +class iterator_compact_to_points { +private: + iterator_type iter_; + iterator_type iter_end_; + point_type pt_; + typename point_traits::coordinate_type firstX_; + orientation_2d orient_; +public: + typedef std::forward_iterator_tag iterator_category; + typedef point_type value_type; + typedef std::ptrdiff_t difference_type; + typedef const point_type* pointer; //immutable + typedef const point_type& reference; //immutable + + inline iterator_compact_to_points() : iter_(), iter_end_(), pt_(), firstX_(), orient_() {} + inline iterator_compact_to_points(iterator_type iter, iterator_type iter_end) : + iter_(iter), iter_end_(iter_end), pt_(), firstX_(), orient_(HORIZONTAL) { + if(iter_ != iter_end_) { + firstX_ = *iter_; + x(pt_, firstX_); + ++iter_; + if(iter_ != iter_end_) { + y(pt_, *iter_); + } + } + } + //use bitwise copy and assign provided by the compiler + inline iterator_compact_to_points& operator++() { + iterator_type prev_iter = iter_; + ++iter_; + if(iter_ == iter_end_) { + if(x(pt_) != firstX_) { + iter_ = prev_iter; + x(pt_, firstX_); + } + } else { + set(pt_, orient_, *iter_); + orient_.turn_90(); + } + return *this; + } + inline const iterator_compact_to_points operator++(int) { + iterator_compact_to_points tmp(*this); + ++(*this); + return tmp; + } + inline bool operator==(const iterator_compact_to_points& that) const { + if (iter_ == iter_end_) { + return iter_ == that.iter_; + } + return (iter_ == that.iter_) && (x(pt_) == x(that.pt_)); + } + inline bool operator!=(const iterator_compact_to_points& that) const { + if (iter_ == iter_end_) { + return iter_ != that.iter_; + } + return (iter_ != that.iter_) || (x(pt_) != x(that.pt_)); + } + inline reference operator*() const { return pt_; } +}; +} +} +#endif diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/detail/iterator_geometry_to_set.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/detail/iterator_geometry_to_set.hpp new file mode 100644 index 0000000..6ad371b --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/detail/iterator_geometry_to_set.hpp @@ -0,0 +1,314 @@ +/* + Copyright 2008 Intel Corporation + + Use, modification and distribution are subject to the Boost Software License, + Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at + http://www.boost.org/LICENSE_1_0.txt). +*/ +#ifndef BOOST_POLYGON_ITERATOR_GEOMETRY_TO_SET_HPP +#define BOOST_POLYGON_ITERATOR_GEOMETRY_TO_SET_HPP +namespace boost { namespace polygon{ +template +class iterator_geometry_to_set {}; + +template +class iterator_geometry_to_set { +public: + typedef typename rectangle_traits::coordinate_type coordinate_type; + typedef std::forward_iterator_tag iterator_category; + typedef std::pair > value_type; + typedef std::ptrdiff_t difference_type; + typedef const value_type* pointer; //immutable + typedef const value_type& reference; //immutable +private: + rectangle_data rectangle_; + mutable value_type vertex_; + unsigned int corner_; + orientation_2d orient_; + bool is_hole_; +public: + iterator_geometry_to_set() : rectangle_(), vertex_(), corner_(4), orient_(), is_hole_() {} + iterator_geometry_to_set(const rectangle_type& rectangle, direction_1d dir, + orientation_2d orient = HORIZONTAL, bool is_hole = false, bool = false, direction_1d = CLOCKWISE) : + rectangle_(), vertex_(), corner_(0), orient_(orient), is_hole_(is_hole) { + assign(rectangle_, rectangle); + if(dir == HIGH) corner_ = 4; + } + inline iterator_geometry_to_set& operator++() { + ++corner_; + return *this; + } + inline const iterator_geometry_to_set operator++(int) { + iterator_geometry_to_set tmp(*this); + ++(*this); + return tmp; + } + inline bool operator==(const iterator_geometry_to_set& that) const { + return corner_ == that.corner_; + } + inline bool operator!=(const iterator_geometry_to_set& that) const { + return !(*this == that); + } + inline reference operator*() const { + if(corner_ == 0) { + vertex_.first = get(get(rectangle_, orient_.get_perpendicular()), LOW); + vertex_.second.first = get(get(rectangle_, orient_), LOW); + vertex_.second.second = 1; + if(is_hole_) vertex_.second.second *= -1; + } else if(corner_ == 1) { + vertex_.second.first = get(get(rectangle_, orient_), HIGH); + vertex_.second.second = -1; + if(is_hole_) vertex_.second.second *= -1; + } else if(corner_ == 2) { + vertex_.first = get(get(rectangle_, orient_.get_perpendicular()), HIGH); + vertex_.second.first = get(get(rectangle_, orient_), LOW); + } else { + vertex_.second.first = get(get(rectangle_, orient_), HIGH); + vertex_.second.second = 1; + if(is_hole_) vertex_.second.second *= -1; + } + return vertex_; + } +}; + +template +class iterator_geometry_to_set { +public: + typedef typename polygon_traits::coordinate_type coordinate_type; + typedef std::forward_iterator_tag iterator_category; + typedef std::pair > value_type; + typedef std::ptrdiff_t difference_type; + typedef const value_type* pointer; //immutable + typedef const value_type& reference; //immutable + typedef typename polygon_traits::iterator_type coord_iterator_type; +private: + value_type vertex_; + typename polygon_traits::iterator_type itrb, itre; + bool last_vertex_; + bool is_hole_; + int multiplier_; + point_data first_pt, second_pt, pts[3]; + bool use_wrap; + orientation_2d orient_; + int polygon_index; +public: + iterator_geometry_to_set() : vertex_(), itrb(), itre(), last_vertex_(), is_hole_(), multiplier_(), first_pt(), second_pt(), pts(), use_wrap(), orient_(), polygon_index(-1) {} + iterator_geometry_to_set(const polygon_type& polygon, direction_1d dir, orientation_2d orient = HORIZONTAL, bool is_hole = false, bool winding_override = false, direction_1d w = CLOCKWISE) : + vertex_(), itrb(), itre(), last_vertex_(), + is_hole_(is_hole), multiplier_(), first_pt(), second_pt(), pts(), use_wrap(), + orient_(orient), polygon_index(0) { + itrb = begin_points(polygon); + itre = end_points(polygon); + use_wrap = false; + if(itrb == itre || dir == HIGH || ::boost::polygon::size(polygon) < 4) { + polygon_index = -1; + } else { + direction_1d wdir = w; + if(!winding_override) + wdir = winding(polygon); + multiplier_ = wdir == LOW ? -1 : 1; + if(is_hole_) multiplier_ *= -1; + first_pt = pts[0] = *itrb; + ++itrb; + second_pt = pts[1] = *itrb; + ++itrb; + pts[2] = *itrb; + evaluate_(); + } + } + iterator_geometry_to_set(const iterator_geometry_to_set& that) : + vertex_(), itrb(), itre(), last_vertex_(), is_hole_(), multiplier_(), first_pt(), + second_pt(), pts(), use_wrap(), orient_(), polygon_index(-1) { + vertex_ = that.vertex_; + itrb = that.itrb; + itre = that.itre; + last_vertex_ = that.last_vertex_; + is_hole_ = that.is_hole_; + multiplier_ = that.multiplier_; + first_pt = that.first_pt; + second_pt = that.second_pt; + pts[0] = that.pts[0]; + pts[1] = that.pts[1]; + pts[2] = that.pts[2]; + use_wrap = that.use_wrap; + orient_ = that.orient_; + polygon_index = that.polygon_index; + } + inline iterator_geometry_to_set& operator++() { + ++polygon_index; + if(itrb == itre) { + if(first_pt == pts[1]) polygon_index = -1; + else { + pts[0] = pts[1]; + pts[1] = pts[2]; + if(first_pt == pts[2]) { + pts[2] = second_pt; + } else { + pts[2] = first_pt; + } + } + } else { + ++itrb; + pts[0] = pts[1]; + pts[1] = pts[2]; + if(itrb == itre) { + if(first_pt == pts[2]) { + pts[2] = second_pt; + } else { + pts[2] = first_pt; + } + } else { + pts[2] = *itrb; + } + } + evaluate_(); + return *this; + } + inline const iterator_geometry_to_set operator++(int) { + iterator_geometry_to_set tmp(*this); + ++(*this); + return tmp; + } + inline bool operator==(const iterator_geometry_to_set& that) const { + return polygon_index == that.polygon_index; + } + inline bool operator!=(const iterator_geometry_to_set& that) const { + return !(*this == that); + } + inline reference operator*() const { + return vertex_; + } + + inline void evaluate_() { + vertex_.first = pts[1].get(orient_.get_perpendicular()); + vertex_.second.first =pts[1].get(orient_); + if(pts[1] == pts[2]) { + vertex_.second.second = 0; + } else if(pts[0].get(HORIZONTAL) != pts[1].get(HORIZONTAL)) { + vertex_.second.second = -1; + } else if(pts[0].get(VERTICAL) != pts[1].get(VERTICAL)) { + vertex_.second.second = 1; + } else { + vertex_.second.second = 0; + } + vertex_.second.second *= multiplier_; + } +}; + +template +class iterator_geometry_to_set { +public: + typedef typename polygon_90_traits::coordinate_type coordinate_type; + typedef std::forward_iterator_tag iterator_category; + typedef std::pair > value_type; + typedef std::ptrdiff_t difference_type; + typedef const value_type* pointer; //immutable + typedef const value_type& reference; //immutable +private: + iterator_geometry_to_set itrb, itre; + iterator_geometry_to_set::hole_type> itrhib, itrhie; + typename polygon_with_holes_traits::iterator_holes_type itrhb, itrhe; + orientation_2d orient_; + bool is_hole_; + bool started_holes; +public: + iterator_geometry_to_set() : itrb(), itre(), itrhib(), itrhie(), itrhb(), itrhe(), orient_(), is_hole_(), started_holes() {} + iterator_geometry_to_set(const polygon_with_holes_type& polygon, direction_1d dir, + orientation_2d orient = HORIZONTAL, bool is_hole = false, bool = false, direction_1d = CLOCKWISE) : + itrb(), itre(), itrhib(), itrhie(), itrhb(), itrhe(), orient_(orient), is_hole_(is_hole), started_holes() { + itre = iterator_geometry_to_set(polygon, HIGH, orient, is_hole_); + itrhe = end_holes(polygon); + if(dir == HIGH) { + itrb = itre; + itrhb = itrhe; + started_holes = true; + } else { + itrb = iterator_geometry_to_set(polygon, LOW, orient, is_hole_); + itrhb = begin_holes(polygon); + started_holes = false; + } + } + iterator_geometry_to_set(const iterator_geometry_to_set& that) : + itrb(), itre(), itrhib(), itrhie(), itrhb(), itrhe(), orient_(), is_hole_(), started_holes() { + itrb = that.itrb; + itre = that.itre; + if(that.itrhib != that.itrhie) { + itrhib = that.itrhib; + itrhie = that.itrhie; + } + itrhb = that.itrhb; + itrhe = that.itrhe; + orient_ = that.orient_; + is_hole_ = that.is_hole_; + started_holes = that.started_holes; + } + inline iterator_geometry_to_set& operator++() { + //this code can be folded with flow control factoring + if(itrb == itre) { + if(itrhib == itrhie) { + if(itrhb != itrhe) { + itrhib = iterator_geometry_to_set::hole_type>(*itrhb, LOW, orient_, !is_hole_); + itrhie = iterator_geometry_to_set::hole_type>(*itrhb, HIGH, orient_, !is_hole_); + ++itrhb; + } else { + //in this case we have no holes so we just need the iterhib == itrhie, which + //is always true if they were default initialized in the initial case or + //both point to end of the previous hole processed + //no need to explicitly reset them, and it causes an stl debug assertion to use + //the default constructed iterator this way + //itrhib = itrhie = iterator_geometry_to_set::hole_type>(); + } + } else { + ++itrhib; + if(itrhib == itrhie) { + if(itrhb != itrhe) { + itrhib = iterator_geometry_to_set::hole_type>(*itrhb, LOW, orient_, !is_hole_); + itrhie = iterator_geometry_to_set::hole_type>(*itrhb, HIGH, orient_, !is_hole_); + ++itrhb; + } else { + //this is the same case as above + //itrhib = itrhie = iterator_geometry_to_set::hole_type>(); + } + } + } + } else { + ++itrb; + if(itrb == itre) { + if(itrhb != itrhe) { + itrhib = iterator_geometry_to_set::hole_type>(*itrhb, LOW, orient_, !is_hole_); + itrhie = iterator_geometry_to_set::hole_type>(*itrhb, HIGH, orient_, !is_hole_); + ++itrhb; + } + } + } + return *this; + } + inline const iterator_geometry_to_set operator++(int) { + iterator_geometry_to_set tmp(*this); + ++(*this); + return tmp; + } + inline bool operator==(const iterator_geometry_to_set& that) const { + return itrb == that.itrb && itrhb == that.itrhb && itrhib == that.itrhib; + } + inline bool operator!=(const iterator_geometry_to_set& that) const { + return !(*this == that); + } + inline reference operator*() const { + if(itrb != itre) return *itrb; + return *itrhib; + } +}; + + +} +} +#endif diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/detail/iterator_points_to_compact.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/detail/iterator_points_to_compact.hpp new file mode 100644 index 0000000..25ddb15 --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/detail/iterator_points_to_compact.hpp @@ -0,0 +1,60 @@ +/* + Copyright 2008 Intel Corporation + + Use, modification and distribution are subject to the Boost Software License, + Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at + http://www.boost.org/LICENSE_1_0.txt). +*/ +#ifndef BOOST_POLYGON_ITERATOR_POINTS_TO_COMPACT_HPP +#define BOOST_POLYGON_ITERATOR_POINTS_TO_COMPACT_HPP +namespace boost { namespace polygon{ +template +class iterator_points_to_compact { +private: + iT iter_, iterEnd_; + orientation_2d orient_; + mutable typename point_traits::coordinate_type coord_; +public: + typedef typename point_traits::coordinate_type coordinate_type; + typedef std::forward_iterator_tag iterator_category; + typedef coordinate_type value_type; + typedef std::ptrdiff_t difference_type; + typedef const coordinate_type* pointer; //immutable + typedef const coordinate_type& reference; //immutable + + inline iterator_points_to_compact() : iter_(), iterEnd_(), orient_(), coord_() {} + inline iterator_points_to_compact(iT iter, iT iterEnd) : + iter_(iter), iterEnd_(iterEnd), orient_(HORIZONTAL), coord_() {} + inline iterator_points_to_compact(const iterator_points_to_compact& that) : + iter_(that.iter_), iterEnd_(that.iterEnd_), orient_(that.orient_), coord_(that.coord_) {} + //use bitwise copy and assign provided by the compiler + inline iterator_points_to_compact& operator++() { + //iT tmp = iter_; + ++iter_; + //iT tmp2 = iter_; + orient_.turn_90(); + //while(tmp2 != iterEnd_ && get(*tmp2, orient_) == get(*tmp, orient_)) { + // iter_ = tmp2; + // ++tmp2; + //} + return *this; + } + inline const iterator_points_to_compact operator++(int) { + iT tmp(*this); + ++(*this); + return tmp; + } + inline bool operator==(const iterator_points_to_compact& that) const { + return (iter_ == that.iter_); + } + inline bool operator!=(const iterator_points_to_compact& that) const { + return (iter_ != that.iter_); + } + inline reference operator*() const { coord_ = get(*iter_, orient_); + return coord_; + } +}; +} +} +#endif + diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/detail/max_cover.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/detail/max_cover.hpp new file mode 100644 index 0000000..f01eac8 --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/detail/max_cover.hpp @@ -0,0 +1,281 @@ +/* + Copyright 2008 Intel Corporation + + Use, modification and distribution are subject to the Boost Software License, + Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at + http://www.boost.org/LICENSE_1_0.txt). +*/ +#ifndef BOOST_POLYGON_MAX_COVER_HPP +#define BOOST_POLYGON_MAX_COVER_HPP +namespace boost { namespace polygon{ + + template + struct MaxCover { + typedef interval_data Interval; + typedef rectangle_data Rectangle; + + class Node { + private: + std::vector children_; + std::set tracedPaths_; + public: + Rectangle rect; + Node() : children_(), tracedPaths_(), rect() {} + Node(const Rectangle rectIn) : children_(), tracedPaths_(), rect(rectIn) {} + typedef typename std::vector::iterator iterator; + inline iterator begin() { return children_.begin(); } + inline iterator end() { return children_.end(); } + inline void add(Node* child) { children_.push_back(child); } + inline bool tracedPath(const Interval& ivl) const { + return tracedPaths_.find(ivl) != tracedPaths_.end(); + } + inline void addPath(const Interval& ivl) { + tracedPaths_.insert(tracedPaths_.end(), ivl); + } + }; + + typedef std::pair, Node* > EdgeAssociation; + + class lessEdgeAssociation { + public: + typedef const EdgeAssociation& first_argument_type; + typedef const EdgeAssociation& second_argument_type; + typedef bool result_type; + inline lessEdgeAssociation() {} + inline bool operator () (const EdgeAssociation& elem1, const EdgeAssociation& elem2) const { + if(elem1.first.first < elem2.first.first) return true; + if(elem1.first.first > elem2.first.first) return false; + return elem1.first.second < elem2.first.second; + } + }; + + template + static inline void getMaxCover(cT& outputContainer, Node* node, orientation_2d orient) { + Interval rectIvl = node->rect.get(orient); + if(node->tracedPath(rectIvl)) { + return; + } + node->addPath(rectIvl); + if(node->begin() == node->end()) { + //std::cout << "WRITE OUT 3: " << node->rect << std::endl; + outputContainer.push_back(copy_construct(node->rect)); + return; + } + bool writeOut = true; + for(typename Node::iterator itr = node->begin(); itr != node->end(); ++itr) { + getMaxCover(outputContainer, *itr, orient, node->rect); //get rectangles down path + Interval nodeIvl = (*itr)->rect.get(orient); + if(contains(nodeIvl, rectIvl, true)) writeOut = false; + } + if(writeOut) { + //std::cout << "WRITE OUT 2: " << node->rect << std::endl; + outputContainer.push_back(copy_construct(node->rect)); + } + } + + struct stack_element { + inline stack_element() : + node(), rect(), itr() {} + inline stack_element(Node* n, + const Rectangle& r, + typename Node::iterator i) : + node(n), rect(r), itr(i) {} + Node* node; + Rectangle rect; + typename Node::iterator itr; + }; + + template + static inline void getMaxCover(cT& outputContainer, Node* node, orientation_2d orient, + Rectangle rect) { + //std::cout << "New Root\n"; + std::vector stack; + typename Node::iterator itr = node->begin(); + do { + //std::cout << "LOOP\n"; + //std::cout << node->rect << std::endl; + Interval rectIvl = rect.get(orient); + Interval nodeIvl = node->rect.get(orient); + bool iresult = intersect(rectIvl, nodeIvl, false); + bool tresult = !node->tracedPath(rectIvl); + //std::cout << (itr != node->end()) << " " << iresult << " " << tresult << std::endl; + Rectangle nextRect1 = Rectangle(rectIvl, rectIvl); + Unit low = rect.get(orient.get_perpendicular()).low(); + Unit high = node->rect.get(orient.get_perpendicular()).high(); + nextRect1.set(orient.get_perpendicular(), Interval(low, high)); + if(iresult && tresult) { + node->addPath(rectIvl); + bool writeOut = true; + //check further visibility beyond this node + for(typename Node::iterator itr2 = node->begin(); itr2 != node->end(); ++itr2) { + Interval nodeIvl3 = (*itr2)->rect.get(orient); + //if a child of this node can contain the interval then we can extend through + if(contains(nodeIvl3, rectIvl, true)) writeOut = false; + //std::cout << "child " << (*itr2)->rect << std::endl; + } + Rectangle nextRect2 = Rectangle(rectIvl, rectIvl); + Unit low2 = rect.get(orient.get_perpendicular()).low(); + Unit high2 = node->rect.get(orient.get_perpendicular()).high(); + nextRect2.set(orient.get_perpendicular(), Interval(low2, high2)); + if(writeOut) { + //std::cout << "write out " << nextRect << std::endl; + outputContainer.push_back(copy_construct(nextRect2)); + } else { + //std::cout << "suppress " << nextRect << std::endl; + } + } + if(itr != node->end() && iresult && tresult) { + //std::cout << "recurse into child\n"; + stack.push_back(stack_element(node, rect, itr)); + rect = nextRect1; + node = *itr; + itr = node->begin(); + } else { + if(!stack.empty()) { + //std::cout << "recurse out of child\n"; + node = stack.back().node; + rect = stack.back().rect; + itr = stack.back().itr; + stack.pop_back(); + } else { + //std::cout << "empty stack\n"; + //if there were no children of the root node +// Rectangle nextRect = Rectangle(rectIvl, rectIvl); +// Unit low = rect.get(orient.get_perpendicular()).low(); +// Unit high = node->rect.get(orient.get_perpendicular()).high(); +// nextRect.set(orient.get_perpendicular(), Interval(low, high)); +// outputContainer.push_back(copy_construct(nextRect)); + } + //std::cout << "increment " << (itr != node->end()) << std::endl; + if(itr != node->end()) { + ++itr; + if(itr != node->end()) { + //std::cout << "recurse into next child.\n"; + stack.push_back(stack_element(node, rect, itr)); + Interval rectIvl2 = rect.get(orient); + Interval nodeIvl2 = node->rect.get(orient); + /*bool iresult =*/ intersect(rectIvl2, nodeIvl2, false); + Rectangle nextRect2 = Rectangle(rectIvl2, rectIvl2); + Unit low2 = rect.get(orient.get_perpendicular()).low(); + Unit high2 = node->rect.get(orient.get_perpendicular()).high(); + nextRect2.set(orient.get_perpendicular(), Interval(low2, high2)); + rect = nextRect2; + //std::cout << "rect for next child" << rect << std::endl; + node = *itr; + itr = node->begin(); + } + } + } + } while(!stack.empty() || itr != node->end()); + } + + /* Function recursive version of getMaxCover + Because the code is so much simpler than the loop algorithm I retain it for clarity + + template + static inline void getMaxCover(cT& outputContainer, Node* node, orientation_2d orient, + const Rectangle& rect) { + Interval rectIvl = rect.get(orient); + Interval nodeIvl = node->rect.get(orient); + if(!intersect(rectIvl, nodeIvl, false)) { + return; + } + if(node->tracedPath(rectIvl)) { + return; + } + node->addPath(rectIvl); + Rectangle nextRect(rectIvl, rectIvl); + Unit low = rect.get(orient.get_perpendicular()).low(); + Unit high = node->rect.get(orient.get_perpendicular()).high(); + nextRect.set(orient.get_perpendicular(), Interval(low, high)); + bool writeOut = true; + rectIvl = nextRect.get(orient); + for(typename Node::iterator itr = node->begin(); itr != node->end(); ++itr) { + nodeIvl = (*itr)->rect.get(orient); + if(contains(nodeIvl, rectIvl, true)) writeOut = false; + } + if(writeOut) { + outputContainer.push_back(copy_construct(nextRect)); + } + for(typename Node::iterator itr = node->begin(); itr != node->end(); ++itr) { + getMaxCover(outputContainer, *itr, orient, nextRect); + } + } + */ + + //iterator range is assummed to be in topological order meaning all node's trailing + //edges are in sorted order + template + static inline void computeDag(iT beginNode, iT endNode, orientation_2d orient, + std::size_t size) { + std::vector leadingEdges; + leadingEdges.reserve(size); + for(iT iter = beginNode; iter != endNode; ++iter) { + Node* nodep = &(*iter); + Unit leading = nodep->rect.get(orient.get_perpendicular()).low(); + Interval rectIvl = nodep->rect.get(orient); + leadingEdges.push_back(EdgeAssociation(std::pair(leading, rectIvl), nodep)); + } + polygon_sort(leadingEdges.begin(), leadingEdges.end(), lessEdgeAssociation()); + typename std::vector::iterator leadingBegin = leadingEdges.begin(); + iT trailingBegin = beginNode; + while(leadingBegin != leadingEdges.end()) { + EdgeAssociation& leadingSegment = (*leadingBegin); + Unit trailing = (*trailingBegin).rect.get(orient.get_perpendicular()).high(); + Interval ivl = (*trailingBegin).rect.get(orient); + std::pair trailingSegment(trailing, ivl); + if(leadingSegment.first.first < trailingSegment.first) { + ++leadingBegin; + continue; + } + if(leadingSegment.first.first > trailingSegment.first) { + ++trailingBegin; + continue; + } + if(leadingSegment.first.second.high() <= trailingSegment.second.low()) { + ++leadingBegin; + continue; + } + if(trailingSegment.second.high() <= leadingSegment.first.second.low()) { + ++trailingBegin; + continue; + } + //leading segment intersects trailing segment + (*trailingBegin).add((*leadingBegin).second); + if(leadingSegment.first.second.high() > trailingSegment.second.high()) { + ++trailingBegin; + continue; + } + if(trailingSegment.second.high() > leadingSegment.first.second.high()) { + ++leadingBegin; + continue; + } + ++leadingBegin; + ++trailingBegin; + } + } + + template + static inline void getMaxCover(cT& outputContainer, + const std::vector& rects, orientation_2d orient) { + if(rects.empty()) return; + std::vector nodes; + { + if(rects.size() == 1) { + outputContainer.push_back(copy_construct(rects[0])); + return; + } + nodes.reserve(rects.size()); + for(std::size_t i = 0; i < rects.size(); ++i) { nodes.push_back(Node(rects[i])); } + } + computeDag(nodes.begin(), nodes.end(), orient, nodes.size()); + for(std::size_t i = 0; i < nodes.size(); ++i) { + getMaxCover(outputContainer, &(nodes[i]), orient); + } + } + + }; +} +} + +#endif diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/detail/minkowski.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/detail/minkowski.hpp new file mode 100644 index 0000000..ce34947 --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/detail/minkowski.hpp @@ -0,0 +1,131 @@ +/* + Copyright 2008 Intel Corporation + + Use, modification and distribution are subject to the Boost Software License, + Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at + http://www.boost.org/LICENSE_1_0.txt). +*/ +namespace boost { namespace polygon { namespace detail { + +template +struct minkowski_offset { + typedef point_data point; + typedef polygon_set_data polygon_set; + typedef polygon_with_holes_data polygon; + typedef std::pair edge; + + static void convolve_two_segments(std::vector& figure, const edge& a, const edge& b) { + figure.clear(); + figure.push_back(point(a.first)); + figure.push_back(point(a.first)); + figure.push_back(point(a.second)); + figure.push_back(point(a.second)); + convolve(figure[0], b.second); + convolve(figure[1], b.first); + convolve(figure[2], b.first); + convolve(figure[3], b.second); + } + + template + static void convolve_two_point_sequences(polygon_set& result, itrT1 ab, itrT1 ae, itrT2 bb, itrT2 be) { + if(ab == ae || bb == be) + return; + point first_a = *ab; + point prev_a = *ab; + std::vector vec; + polygon poly; + ++ab; + for( ; ab != ae; ++ab) { + point first_b = *bb; + point prev_b = *bb; + itrT2 tmpb = bb; + ++tmpb; + for( ; tmpb != be; ++tmpb) { + convolve_two_segments(vec, std::make_pair(prev_b, *tmpb), std::make_pair(prev_a, *ab)); + set_points(poly, vec.begin(), vec.end()); + result.insert(poly); + prev_b = *tmpb; + } + prev_a = *ab; + } + } + + template + static void convolve_point_sequence_with_polygons(polygon_set& result, itrT b, itrT e, const std::vector& polygons) { + for(std::size_t i = 0; i < polygons.size(); ++i) { + convolve_two_point_sequences(result, b, e, begin_points(polygons[i]), end_points(polygons[i])); + for(typename polygon_with_holes_traits::iterator_holes_type itrh = begin_holes(polygons[i]); + itrh != end_holes(polygons[i]); ++itrh) { + convolve_two_point_sequences(result, b, e, begin_points(*itrh), end_points(*itrh)); + } + } + } + + static void convolve_two_polygon_sets(polygon_set& result, const polygon_set& a, const polygon_set& b) { + result.clear(); + std::vector a_polygons; + std::vector b_polygons; + a.get(a_polygons); + b.get(b_polygons); + for(std::size_t ai = 0; ai < a_polygons.size(); ++ai) { + convolve_point_sequence_with_polygons(result, begin_points(a_polygons[ai]), + end_points(a_polygons[ai]), b_polygons); + for(typename polygon_with_holes_traits::iterator_holes_type itrh = begin_holes(a_polygons[ai]); + itrh != end_holes(a_polygons[ai]); ++itrh) { + convolve_point_sequence_with_polygons(result, begin_points(*itrh), + end_points(*itrh), b_polygons); + } + for(std::size_t bi = 0; bi < b_polygons.size(); ++bi) { + polygon tmp_poly = a_polygons[ai]; + result.insert(convolve(tmp_poly, *(begin_points(b_polygons[bi])))); + tmp_poly = b_polygons[bi]; + result.insert(convolve(tmp_poly, *(begin_points(a_polygons[ai])))); + } + } + } +}; + +} + template + inline polygon_set_data& + polygon_set_data::resize(coordinate_type resizing, bool corner_fill_arc, unsigned int num_circle_segments) { + using namespace ::boost::polygon::operators; + if(!corner_fill_arc) { + if(resizing < 0) + return shrink(-resizing); + if(resizing > 0) + return bloat(resizing); + return *this; + } + if(resizing == 0) return *this; + if(empty()) return *this; + if(num_circle_segments < 3) num_circle_segments = 4; + rectangle_data rect; + extents(rect); + if(resizing < 0) { + ::boost::polygon::bloat(rect, 10); + (*this) = rect - (*this); //invert + } + //make_arc(std::vector >& return_points, + //point_data< double> start, point_data< double> end, + //point_data< double> center, double r, unsigned int num_circle_segments) + std::vector > circle; + point_data center(0.0, 0.0), start(0.0, (double)resizing); + make_arc(circle, start, start, center, std::abs((double)resizing), + num_circle_segments); + polygon_data poly; + set_points(poly, circle.begin(), circle.end()); + polygon_set_data offset_set; + offset_set += poly; + polygon_set_data result; + detail::minkowski_offset::convolve_two_polygon_sets + (result, *this, offset_set); + if(resizing < 0) { + result = result & rect;//eliminate overhang + result = result ^ rect;//invert + } + *this = result; + return *this; + } + +}} diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/detail/polygon_45_formation.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/detail/polygon_45_formation.hpp new file mode 100644 index 0000000..7034986 --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/detail/polygon_45_formation.hpp @@ -0,0 +1,2238 @@ +/* + Copyright 2008 Intel Corporation + + Use, modification and distribution are subject to the Boost Software License, + Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at + http://www.boost.org/LICENSE_1_0.txt). +*/ +#ifndef BOOST_POLYGON_POLYGON_45_FORMATION_HPP +#define BOOST_POLYGON_POLYGON_45_FORMATION_HPP +namespace boost { namespace polygon{ + + template + struct PolyLineByConcept {}; + + template + class PolyLine45PolygonData; + template + class PolyLine45HoleData; + + //polygon45formation algorithm + template + struct polygon_45_formation : public boolean_op_45 { + typedef point_data Point; + typedef polygon_45_data Polygon45; + typedef polygon_45_with_holes_data Polygon45WithHoles; + typedef typename boolean_op_45::Vertex45 Vertex45; + typedef typename boolean_op_45::lessVertex45 lessVertex45; + typedef typename boolean_op_45::Count2 Count2; + typedef typename boolean_op_45::Scan45Count Scan45Count; + typedef std::pair Scan45Vertex; + typedef typename boolean_op_45::template + Scan45::template boolean_op_45_output_functor<0> > Scan45; + + class PolyLine45 { + public: + typedef typename std::list::const_iterator iterator; + + // default constructor of point does not initialize x and y + inline PolyLine45() : points() {} //do nothing default constructor + + // initialize a polygon from x,y values, it is assumed that the first is an x + // and that the input is a well behaved polygon + template + inline PolyLine45& set(iT inputBegin, iT inputEnd) { + points.clear(); //just in case there was some old data there + while(inputBegin != inputEnd) { + points.insert(points.end(), *inputBegin); + ++inputBegin; + } + return *this; + } + + // copy constructor (since we have dynamic memory) + inline PolyLine45(const PolyLine45& that) : points(that.points) {} + + // assignment operator (since we have dynamic memory do a deep copy) + inline PolyLine45& operator=(const PolyLine45& that) { + points = that.points; + return *this; + } + + // get begin iterator, returns a pointer to a const Unit + inline iterator begin() const { return points.begin(); } + + // get end iterator, returns a pointer to a const Unit + inline iterator end() const { return points.end(); } + + inline std::size_t size() const { return points.size(); } + + //public data member + std::list points; + }; + + class ActiveTail45 { + private: + //data + PolyLine45* tailp_; + ActiveTail45 *otherTailp_; + std::list holesList_; + bool head_; + public: + + /** + * @brief iterator over coordinates of the figure + */ + typedef typename PolyLine45::iterator iterator; + + /** + * @brief iterator over holes contained within the figure + */ + typedef typename std::list::const_iterator iteratorHoles; + + //default constructor + inline ActiveTail45() : tailp_(0), otherTailp_(0), holesList_(), head_(0) {} + + //constructor + inline ActiveTail45(const Vertex45& vertex, ActiveTail45* otherTailp = 0) : + tailp_(0), otherTailp_(0), holesList_(), head_(0) { + tailp_ = new PolyLine45; + tailp_->points.push_back(vertex.pt); + bool headArray[4] = {false, true, true, true}; + bool inverted = vertex.count == -1; + head_ = headArray[vertex.rise+1] ^ inverted; + otherTailp_ = otherTailp; + } + + inline ActiveTail45(Point point, ActiveTail45* otherTailp, bool head = true) : + tailp_(0), otherTailp_(0), holesList_(), head_(0) { + tailp_ = new PolyLine45; + tailp_->points.push_back(point); + head_ = head; + otherTailp_ = otherTailp; + + } + inline ActiveTail45(ActiveTail45* otherTailp) : + tailp_(0), otherTailp_(0), holesList_(), head_(0) { + tailp_ = otherTailp->tailp_; + otherTailp_ = otherTailp; + } + + //copy constructor + inline ActiveTail45(const ActiveTail45& that) : + tailp_(0), otherTailp_(0), holesList_(), head_(0) { (*this) = that; } + + //destructor + inline ~ActiveTail45() { + destroyContents(); + } + + //assignment operator + inline ActiveTail45& operator=(const ActiveTail45& that) { + tailp_ = new PolyLine45(*(that.tailp_)); + head_ = that.head_; + otherTailp_ = that.otherTailp_; + holesList_ = that.holesList_; + return *this; + } + + //equivalence operator + inline bool operator==(const ActiveTail45& b) const { + return tailp_ == b.tailp_ && head_ == b.head_; + } + + /** + * @brief get the pointer to the polyline that this is an active tail of + */ + inline PolyLine45* getTail() const { return tailp_; } + + /** + * @brief get the pointer to the polyline at the other end of the chain + */ + inline PolyLine45* getOtherTail() const { return otherTailp_->tailp_; } + + /** + * @brief get the pointer to the activetail at the other end of the chain + */ + inline ActiveTail45* getOtherActiveTail() const { return otherTailp_; } + + /** + * @brief test if another active tail is the other end of the chain + */ + inline bool isOtherTail(const ActiveTail45& b) const { return &b == otherTailp_; } + + /** + * @brief update this end of chain pointer to new polyline + */ + inline ActiveTail45& updateTail(PolyLine45* newTail) { tailp_ = newTail; return *this; } + + inline bool join(ActiveTail45* tail) { + if(tail == otherTailp_) { + //std::cout << "joining to other tail!\n"; + return false; + } + if(tail->head_ == head_) { + //std::cout << "joining head to head!\n"; + return false; + } + if(!tailp_) { + //std::cout << "joining empty tail!\n"; + return false; + } + if(!(otherTailp_->head_)) { + otherTailp_->copyHoles(*tail); + otherTailp_->copyHoles(*this); + } else { + tail->otherTailp_->copyHoles(*this); + tail->otherTailp_->copyHoles(*tail); + } + PolyLine45* tail1 = tailp_; + PolyLine45* tail2 = tail->tailp_; + if(head_) std::swap(tail1, tail2); + tail1->points.splice(tail1->points.end(), tail2->points); + delete tail2; + otherTailp_->tailp_ = tail1; + tail->otherTailp_->tailp_ = tail1; + otherTailp_->otherTailp_ = tail->otherTailp_; + tail->otherTailp_->otherTailp_ = otherTailp_; + tailp_ = 0; + tail->tailp_ = 0; + tail->otherTailp_ = 0; + otherTailp_ = 0; + return true; + } + + /** + * @brief associate a hole to this active tail by the specified policy + */ + inline ActiveTail45* addHole(ActiveTail45* hole) { + holesList_.push_back(hole); + copyHoles(*hole); + copyHoles(*(hole->otherTailp_)); + return this; + } + + /** + * @brief get the list of holes + */ + inline const std::list& getHoles() const { return holesList_; } + + /** + * @brief copy holes from that to this + */ + inline void copyHoles(ActiveTail45& that) { holesList_.splice(holesList_.end(), that.holesList_); } + + /** + * @brief find out if solid to right + */ + inline bool solidToRight() const { return !head_; } + inline bool solidToLeft() const { return head_; } + + /** + * @brief get vertex + */ + inline Point getPoint() const { + if(head_) return tailp_->points.front(); + return tailp_->points.back(); + } + + /** + * @brief add a coordinate to the polygon at this active tail end, properly handle degenerate edges by removing redundant coordinate + */ + inline void pushPoint(Point point) { + if(head_) { + //if(tailp_->points.size() < 2) { + // tailp_->points.push_front(point); + // return; + //} + typename std::list::iterator iter = tailp_->points.begin(); + if(iter == tailp_->points.end()) { + tailp_->points.push_front(point); + return; + } + Unit firstY = (*iter).y(); + Unit firstX = (*iter).x(); + ++iter; + if(iter == tailp_->points.end()) { + tailp_->points.push_front(point); + return; + } + if((iter->y() == point.y() && firstY == point.y()) || + (iter->x() == point.x() && firstX == point.x())){ + --iter; + *iter = point; + } else { + tailp_->points.push_front(point); + } + return; + } + //if(tailp_->points.size() < 2) { + // tailp_->points.push_back(point); + // return; + //} + typename std::list::reverse_iterator iter = tailp_->points.rbegin(); + if(iter == tailp_->points.rend()) { + tailp_->points.push_back(point); + return; + } + Unit firstY = (*iter).y(); + Unit firstX = (*iter).x(); + ++iter; + if(iter == tailp_->points.rend()) { + tailp_->points.push_back(point); + return; + } + if((iter->y() == point.y() && firstY == point.y()) || + (iter->x() == point.x() && firstX == point.x())){ + --iter; + *iter = point; + } else { + tailp_->points.push_back(point); + } + } + + /** + * @brief joins the two chains that the two active tail tails are ends of + * checks for closure of figure and writes out polygons appropriately + * returns a handle to a hole if one is closed + */ + + template + static inline ActiveTail45* joinChains(Point point, ActiveTail45* at1, ActiveTail45* at2, bool solid, + cT& output) { + if(at1->otherTailp_ == at2) { + //if(at2->otherTailp_ != at1) std::cout << "half closed error\n"; + //we are closing a figure + at1->pushPoint(point); + at2->pushPoint(point); + if(solid) { + //we are closing a solid figure, write to output + //std::cout << "test1\n"; + at1->copyHoles(*(at1->otherTailp_)); + //std::cout << "test2\n"; + //Polygon45WithHolesImpl poly(polyData); + //std::cout << poly << "\n"; + //std::cout << "test3\n"; + typedef typename cT::value_type pType; + output.push_back(pType()); + typedef typename geometry_concept::type cType; + typename PolyLineByConcept::type polyData(at1); + assign(output.back(), polyData); + //std::cout << "test4\n"; + //std::cout << "delete " << at1->otherTailp_ << "\n"; + //at1->print(); + //at1->otherTailp_->print(); + delete at1->otherTailp_; + //at1->print(); + //at1->otherTailp_->print(); + //std::cout << "test5\n"; + //std::cout << "delete " << at1 << "\n"; + delete at1; + //std::cout << "test6\n"; + return 0; + } else { + //we are closing a hole, return the tail end active tail of the figure + return at1; + } + } + //we are not closing a figure + at1->pushPoint(point); + at1->join(at2); + delete at1; + delete at2; + return 0; + } + + inline void destroyContents() { + if(otherTailp_) { + //std::cout << "delete p " << tailp_ << "\n"; + if(tailp_) delete tailp_; + tailp_ = 0; + otherTailp_->otherTailp_ = 0; + otherTailp_->tailp_ = 0; + otherTailp_ = 0; + } + for(typename std::list::iterator itr = holesList_.begin(); itr != holesList_.end(); ++itr) { + //std::cout << "delete p " << (*itr) << "\n"; + if(*itr) { + if((*itr)->otherTailp_) { + delete (*itr)->otherTailp_; + (*itr)->otherTailp_ = 0; + } + delete (*itr); + } + (*itr) = 0; + } + holesList_.clear(); + } + +// inline void print() { +// std::cout << this << " " << tailp_ << " " << otherTailp_ << " " << holesList_.size() << " " << head_ << "\n"; +// } + + static inline std::pair createActiveTail45sAsPair(Point point, bool solid, + ActiveTail45* phole, bool fractureHoles) { + ActiveTail45* at1 = 0; + ActiveTail45* at2 = 0; + if(phole && fractureHoles) { + //std::cout << "adding hole\n"; + at1 = phole; + //assert solid == false, we should be creating a corner with solid below and to the left if there was a hole + at2 = at1->getOtherActiveTail(); + at2->pushPoint(point); + at1->pushPoint(point); + } else { + at1 = new ActiveTail45(point, at2, solid); + at2 = new ActiveTail45(at1); + at1->otherTailp_ = at2; + at2->head_ = !solid; + if(phole) + at2->addHole(phole); //assert fractureHoles == false + } + return std::pair(at1, at2); + } + + }; + + template + class Vertex45CountT { + public: + typedef ct count_type; + inline Vertex45CountT() +#ifndef BOOST_POLYGON_MSVC + : counts() +#endif + { counts[0] = counts[1] = counts[2] = counts[3] = 0; } + //inline Vertex45CountT(ct count) { counts[0] = counts[1] = counts[2] = counts[3] = count; } + inline Vertex45CountT(const ct& count1, const ct& count2, const ct& count3, + const ct& count4) +#ifndef BOOST_POLYGON_MSVC + : counts() +#endif + { + counts[0] = count1; + counts[1] = count2; + counts[2] = count3; + counts[3] = count4; + } + inline Vertex45CountT(const Vertex45& vertex) +#ifndef BOOST_POLYGON_MSVC + : counts() +#endif + { + counts[0] = counts[1] = counts[2] = counts[3] = 0; + (*this) += vertex; + } + inline Vertex45CountT(const Vertex45CountT& count) +#ifndef BOOST_POLYGON_MSVC + : counts() +#endif + { + (*this) = count; + } + inline bool operator==(const Vertex45CountT& count) const { + for(unsigned int i = 0; i < 4; ++i) { + if(counts[i] != count.counts[i]) return false; + } + return true; + } + inline bool operator!=(const Vertex45CountT& count) const { return !((*this) == count); } + inline Vertex45CountT& operator=(ct count) { + counts[0] = counts[1] = counts[2] = counts[3] = count; return *this; } + inline Vertex45CountT& operator=(const Vertex45CountT& count) { + for(unsigned int i = 0; i < 4; ++i) { + counts[i] = count.counts[i]; + } + return *this; + } + inline ct& operator[](int index) { return counts[index]; } + inline ct operator[](int index) const {return counts[index]; } + inline Vertex45CountT& operator+=(const Vertex45CountT& count){ + for(unsigned int i = 0; i < 4; ++i) { + counts[i] += count.counts[i]; + } + return *this; + } + inline Vertex45CountT& operator-=(const Vertex45CountT& count){ + for(unsigned int i = 0; i < 4; ++i) { + counts[i] -= count.counts[i]; + } + return *this; + } + inline Vertex45CountT operator+(const Vertex45CountT& count) const { + return Vertex45CountT(*this)+=count; + } + inline Vertex45CountT operator-(const Vertex45CountT& count) const { + return Vertex45CountT(*this)-=count; + } + inline Vertex45CountT invert() const { + return Vertex45CountT()-=(*this); + } + inline Vertex45CountT& operator+=(const Vertex45& element){ + counts[element.rise+1] += element.count; return *this; + } + inline bool is_45() const { + return counts[0] != 0 || counts[2] != 0; + } + private: + ct counts[4]; + }; + + typedef Vertex45CountT Vertex45Count; + +// inline std::ostream& operator<< (std::ostream& o, const Vertex45Count& c) { +// o << c[0] << ", " << c[1] << ", "; +// o << c[2] << ", " << c[3]; +// return o; +// } + + template + class Vertex45CompactT { + public: + Point pt; + ct count; + typedef typename boolean_op_45::template Vertex45T Vertex45T; + inline Vertex45CompactT() : pt(), count() {} + inline Vertex45CompactT(const Point& point, int riseIn, int countIn) : pt(point), count() { + count[riseIn+1] = countIn; + } + template + inline Vertex45CompactT(const typename boolean_op_45::template Vertex45T& vertex) : pt(vertex.pt), count() { + count[vertex.rise+1] = vertex.count; + } + inline Vertex45CompactT(const Vertex45CompactT& vertex) : pt(vertex.pt), count(vertex.count) {} + inline Vertex45CompactT& operator=(const Vertex45CompactT& vertex){ + pt = vertex.pt; count = vertex.count; return *this; } + inline bool operator==(const Vertex45CompactT& vertex) const { + return pt == vertex.pt && count == vertex.count; } + inline bool operator!=(const Vertex45CompactT& vertex) const { return !((*this) == vertex); } + inline bool operator<(const Vertex45CompactT& vertex) const { + if(pt.x() < vertex.pt.x()) return true; + if(pt.x() == vertex.pt.x()) { + return pt.y() < vertex.pt.y(); + } + return false; + } + inline bool operator>(const Vertex45CompactT& vertex) const { return vertex < (*this); } + inline bool operator<=(const Vertex45CompactT& vertex) const { return !((*this) > vertex); } + inline bool operator>=(const Vertex45CompactT& vertex) const { return !((*this) < vertex); } + inline bool haveVertex45(int index) const { return count[index]; } + inline Vertex45T operator[](int index) const { + return Vertex45T(pt, index-1, count[index]); } + }; + + typedef Vertex45CompactT Vertex45Compact; + +// inline std::ostream& operator<< (std::ostream& o, const Vertex45Compact& c) { +// o << c.pt << ", " << c.count; +// return o; +// } + + class Polygon45Formation { + private: + //definitions + typedef std::map Polygon45FormationData; + typedef typename Polygon45FormationData::iterator iterator; + typedef typename Polygon45FormationData::const_iterator const_iterator; + + //data + Polygon45FormationData scanData_; + Unit x_; + int justBefore_; + int fractureHoles_; + public: + inline Polygon45Formation() : scanData_(), x_((std::numeric_limits::min)()), justBefore_(false), fractureHoles_(0) { + lessVertex45 lessElm(&x_, &justBefore_); + scanData_ = Polygon45FormationData(lessElm); + } + inline Polygon45Formation(bool fractureHoles) : scanData_(), x_((std::numeric_limits::min)()), justBefore_(false), fractureHoles_(fractureHoles) { + lessVertex45 lessElm(&x_, &justBefore_); + scanData_ = Polygon45FormationData(lessElm); + } + inline Polygon45Formation(const Polygon45Formation& that) : + scanData_(), x_((std::numeric_limits::min)()), justBefore_(false), fractureHoles_(0) { (*this) = that; } + inline Polygon45Formation& operator=(const Polygon45Formation& that) { + x_ = that.x_; + justBefore_ = that.justBefore_; + fractureHoles_ = that.fractureHoles_; + lessVertex45 lessElm(&x_, &justBefore_); + scanData_ = Polygon45FormationData(lessElm); + for(const_iterator itr = that.scanData_.begin(); itr != that.scanData_.end(); ++itr){ + scanData_.insert(scanData_.end(), *itr); + } + return *this; + } + + //cT is an output container of Polygon45 or Polygon45WithHoles + //iT is an iterator over Vertex45 elements + //inputBegin - inputEnd is a range of sorted iT that represents + //one or more scanline stops worth of data + template + void scan(cT& output, iT inputBegin, iT inputEnd) { + //std::cout << "1\n"; + while(inputBegin != inputEnd) { + //std::cout << "2\n"; + x_ = (*inputBegin).pt.x(); + //std::cout << "SCAN FORMATION " << x_ << "\n"; + //std::cout << "x_ = " << x_ << "\n"; + //std::cout << "scan line size: " << scanData_.size() << "\n"; + inputBegin = processEvent_(output, inputBegin, inputEnd); + } + } + + private: + //functions + template + inline std::pair processPoint_(cT& output, cT2& elements, Point point, + Vertex45Count& counts, ActiveTail45** tails, Vertex45Count& incoming) { + //std::cout << point << "\n"; + //std::cout << counts[0] << " "; + //std::cout << counts[1] << " "; + //std::cout << counts[2] << " "; + //std::cout << counts[3] << "\n"; + //std::cout << incoming[0] << " "; + //std::cout << incoming[1] << " "; + //std::cout << incoming[2] << " "; + //std::cout << incoming[3] << "\n"; + //join any closing solid corners + ActiveTail45* returnValue = 0; + int returnCount = 0; + for(int i = 0; i < 3; ++i) { + //std::cout << i << "\n"; + if(counts[i] == -1) { + //std::cout << "fixed i\n"; + for(int j = i + 1; j < 4; ++j) { + //std::cout << j << "\n"; + if(counts[j]) { + if(counts[j] == 1) { + //std::cout << "case1: " << i << " " << j << "\n"; + //if a figure is closed it will be written out by this function to output + ActiveTail45::joinChains(point, tails[i], tails[j], true, output); + counts[i] = 0; + counts[j] = 0; + tails[i] = 0; + tails[j] = 0; + } + break; + } + } + } + } + //find any pairs of incoming edges that need to create pair for leading solid + //std::cout << "checking case2\n"; + for(int i = 0; i < 3; ++i) { + //std::cout << i << "\n"; + if(incoming[i] == 1) { + //std::cout << "fixed i\n"; + for(int j = i + 1; j < 4; ++j) { + //std::cout << j << "\n"; + if(incoming[j]) { + if(incoming[j] == -1) { + //std::cout << "case2: " << i << " " << j << "\n"; + //std::cout << "creating active tail pair\n"; + std::pair tailPair = + ActiveTail45::createActiveTail45sAsPair(point, true, 0, fractureHoles_ != 0); + //tailPair.first->print(); + //tailPair.second->print(); + if(j == 3) { + //vertical active tail becomes return value + returnValue = tailPair.first; + returnCount = 1; + } else { + Vertex45 vertex(point, i -1, incoming[i]); + //std::cout << "new element " << j-1 << " " << -1 << "\n"; + elements.push_back(std::pair(Vertex45(point, j -1, -1), tailPair.first)); + } + //std::cout << "new element " << i-1 << " " << 1 << "\n"; + elements.push_back(std::pair(Vertex45(point, i -1, 1), tailPair.second)); + incoming[i] = 0; + incoming[j] = 0; + } + break; + } + } + } + } + + //find any active tail that needs to pass through to an incoming edge + //we expect to find no more than two pass through + + //find pass through with solid on top + //std::cout << "checking case 3\n"; + for(int i = 0; i < 4; ++i) { + //std::cout << i << "\n"; + if(counts[i] != 0) { + if(counts[i] == 1) { + //std::cout << "fixed i\n"; + for(int j = 3; j >= 0; --j) { + if(incoming[j] != 0) { + if(incoming[j] == 1) { + //std::cout << "case3: " << i << " " << j << "\n"; + //tails[i]->print(); + //pass through solid on top + tails[i]->pushPoint(point); + //std::cout << "after push\n"; + if(j == 3) { + returnValue = tails[i]; + returnCount = -1; + } else { + elements.push_back(std::pair(Vertex45(point, j -1, incoming[j]), tails[i])); + } + tails[i] = 0; + counts[i] = 0; + incoming[j] = 0; + } + break; + } + } + } + break; + } + } + //std::cout << "checking case 4\n"; + //find pass through with solid on bottom + for(int i = 3; i >= 0; --i) { + if(counts[i] != 0) { + if(counts[i] == -1) { + for(int j = 0; j < 4; ++j) { + if(incoming[j] != 0) { + if(incoming[j] == -1) { + //std::cout << "case4: " << i << " " << j << "\n"; + //pass through solid on bottom + tails[i]->pushPoint(point); + if(j == 3) { + returnValue = tails[i]; + returnCount = 1; + } else { + //std::cout << "new element " << j-1 << " " << incoming[j] << "\n"; + elements.push_back(std::pair(Vertex45(point, j -1, incoming[j]), tails[i])); + } + tails[i] = 0; + counts[i] = 0; + incoming[j] = 0; + } + break; + } + } + } + break; + } + } + + //find the end of a hole or the beginning of a hole + + //find end of a hole + for(int i = 0; i < 3; ++i) { + if(counts[i] != 0) { + for(int j = i+1; j < 4; ++j) { + if(counts[j] != 0) { + //std::cout << "case5: " << i << " " << j << "\n"; + //we are ending a hole and may potentially close a figure and have to handle the hole + returnValue = ActiveTail45::joinChains(point, tails[i], tails[j], false, output); + tails[i] = 0; + tails[j] = 0; + counts[i] = 0; + counts[j] = 0; + break; + } + } + break; + } + } + //find beginning of a hole + for(int i = 0; i < 3; ++i) { + if(incoming[i] != 0) { + for(int j = i+1; j < 4; ++j) { + if(incoming[j] != 0) { + //std::cout << "case6: " << i << " " << j << "\n"; + //we are beginning a empty space + ActiveTail45* holep = 0; + if(counts[3] == 0) holep = tails[3]; + std::pair tailPair = + ActiveTail45::createActiveTail45sAsPair(point, false, holep, fractureHoles_ != 0); + if(j == 3) { + returnValue = tailPair.first; + returnCount = -1; + } else { + //std::cout << "new element " << j-1 << " " << incoming[j] << "\n"; + elements.push_back(std::pair(Vertex45(point, j -1, incoming[j]), tailPair.first)); + } + //std::cout << "new element " << i-1 << " " << incoming[i] << "\n"; + elements.push_back(std::pair(Vertex45(point, i -1, incoming[i]), tailPair.second)); + incoming[i] = 0; + incoming[j] = 0; + break; + } + } + break; + } + } + //assert that tails, counts and incoming are all null + return std::pair(returnCount, returnValue); + } + + template + inline iT processEvent_(cT& output, iT inputBegin, iT inputEnd) { + //std::cout << "processEvent_\n"; + justBefore_ = true; + //collect up all elements from the tree that are at the y + //values of events in the input queue + //create vector of new elements to add into tree + ActiveTail45* verticalTail = 0; + int verticalCount = 0; + iT currentIter = inputBegin; + std::vector elementIters; + std::vector > elements; + while(currentIter != inputEnd && currentIter->pt.x() == x_) { + //std::cout << "loop\n"; + Unit currentY = (*currentIter).pt.y(); + iterator iter = lookUp_(currentY); + //int counts[4] = {0, 0, 0, 0}; + Vertex45Count counts; + ActiveTail45* tails[4] = {0, 0, 0, verticalTail}; + //std::cout << "finding elements in tree\n"; + while(iter != scanData_.end() && + iter->first.evalAtX(x_) == currentY) { + //std::cout << "loop2\n"; + elementIters.push_back(iter); + int index = iter->first.rise + 1; + //std::cout << index << " " << iter->first.count << "\n"; + counts[index] = iter->first.count; + tails[index] = iter->second; + ++iter; + } + //int incoming[4] = {0, 0, 0, 0}; + Vertex45Count incoming; + //std::cout << "aggregating\n"; + do { + //std::cout << "loop3\n"; + Vertex45Compact currentVertex(*currentIter); + incoming += currentVertex.count; + ++currentIter; + } while(currentIter != inputEnd && currentIter->pt.y() == currentY && + currentIter->pt.x() == x_); + //now counts and tails have the data from the left and + //incoming has the data from the right at this point + //cancel out any end points + //std::cout << counts[0] << " "; + //std::cout << counts[1] << " "; + //std::cout << counts[2] << " "; + //std::cout << counts[3] << "\n"; + //std::cout << incoming[0] << " "; + //std::cout << incoming[1] << " "; + //std::cout << incoming[2] << " "; + //std::cout << incoming[3] << "\n"; + if(verticalTail) { + counts[3] = -verticalCount; + } + incoming[3] *= -1; + for(unsigned int i = 0; i < 4; ++i) incoming[i] += counts[i]; + //std::cout << "calling processPoint_\n"; + std::pair result = processPoint_(output, elements, Point(x_, currentY), counts, tails, incoming); + verticalCount = result.first; + verticalTail = result.second; + //if(verticalTail) std::cout << "have vertical tail\n"; + //std::cout << "verticalCount: " << verticalCount << "\n"; + if(verticalTail && !verticalCount) { + //we got a hole out of the point we just processed + //iter is still at the next y element above the current y value in the tree + //std::cout << "checking whether ot handle hole\n"; + if(currentIter == inputEnd || + currentIter->pt.x() != x_ || + currentIter->pt.y() >= iter->first.evalAtX(x_)) { + //std::cout << "handle hole here\n"; + if(fractureHoles_) { + //std::cout << "fracture hole here\n"; + //we need to handle the hole now and not at the next input vertex + ActiveTail45* at = iter->second; + Point point(x_, iter->first.evalAtX(x_)); + verticalTail->getOtherActiveTail()->pushPoint(point); + iter->second = verticalTail->getOtherActiveTail(); + at->pushPoint(point); + verticalTail->join(at); + delete at; + delete verticalTail; + verticalTail = 0; + } else { + //std::cout << "push hole onto list\n"; + iter->second->addHole(verticalTail); + verticalTail = 0; + } + } + } + } + //std::cout << "erasing\n"; + //erase all elements from the tree + for(typename std::vector::iterator iter = elementIters.begin(); + iter != elementIters.end(); ++iter) { + //std::cout << "erasing loop\n"; + scanData_.erase(*iter); + } + //switch comparison tie breaking policy + justBefore_ = false; + //add new elements into tree + //std::cout << "inserting\n"; + for(typename std::vector >::iterator iter = elements.begin(); + iter != elements.end(); ++iter) { + //std::cout << "inserting loop\n"; + scanData_.insert(scanData_.end(), *iter); + } + //std::cout << "end processEvent\n"; + return currentIter; + } + + inline iterator lookUp_(Unit y){ + //if just before then we need to look from 1 not -1 + return scanData_.lower_bound(Vertex45(Point(x_, y), -1+2*justBefore_, 0)); + } + + }; + + template + static inline bool testPolygon45FormationRect(stream_type& stdcout) { + stdcout << "testing polygon formation\n"; + Polygon45Formation pf(true); + std::vector polys; + std::vector data; + data.push_back(Vertex45(Point(0, 0), 0, 1)); + data.push_back(Vertex45(Point(0, 0), 2, 1)); + data.push_back(Vertex45(Point(0, 10), 2, -1)); + data.push_back(Vertex45(Point(0, 10), 0, -1)); + data.push_back(Vertex45(Point(10, 0), 0, -1)); + data.push_back(Vertex45(Point(10, 0), 2, -1)); + data.push_back(Vertex45(Point(10, 10), 2, 1)); + data.push_back(Vertex45(Point(10, 10), 0, 1)); + polygon_sort(data.begin(), data.end()); + pf.scan(polys, data.begin(), data.end()); + stdcout << "result size: " << polys.size() << "\n"; + for(std::size_t i = 0; i < polys.size(); ++i) { + stdcout << polys[i] << "\n"; + } + stdcout << "done testing polygon formation\n"; + return true; + } + + template + static inline bool testPolygon45FormationP1(stream_type& stdcout) { + stdcout << "testing polygon formation\n"; + Polygon45Formation pf(true); + std::vector polys; + std::vector data; + data.push_back(Vertex45(Point(0, 0), 1, 1)); + data.push_back(Vertex45(Point(0, 0), 2, 1)); + data.push_back(Vertex45(Point(0, 10), 2, -1)); + data.push_back(Vertex45(Point(0, 10), 1, -1)); + data.push_back(Vertex45(Point(10, 10), 1, -1)); + data.push_back(Vertex45(Point(10, 10), 2, -1)); + data.push_back(Vertex45(Point(10, 20), 2, 1)); + data.push_back(Vertex45(Point(10, 20), 1, 1)); + polygon_sort(data.begin(), data.end()); + pf.scan(polys, data.begin(), data.end()); + stdcout << "result size: " << polys.size() << "\n"; + for(std::size_t i = 0; i < polys.size(); ++i) { + stdcout << polys[i] << "\n"; + } + stdcout << "done testing polygon formation\n"; + return true; + } + //polygon45set class + + template + static inline bool testPolygon45FormationP2(stream_type& stdcout) { + stdcout << "testing polygon formation\n"; + Polygon45Formation pf(true); + std::vector polys; + std::vector data; + data.push_back(Vertex45(Point(0, 0), 0, 1)); + data.push_back(Vertex45(Point(0, 0), 1, -1)); + data.push_back(Vertex45(Point(10, 0), 0, -1)); + data.push_back(Vertex45(Point(10, 0), 1, 1)); + data.push_back(Vertex45(Point(10, 10), 1, 1)); + data.push_back(Vertex45(Point(10, 10), 0, -1)); + data.push_back(Vertex45(Point(20, 10), 1, -1)); + data.push_back(Vertex45(Point(20, 10), 0, 1)); + polygon_sort(data.begin(), data.end()); + pf.scan(polys, data.begin(), data.end()); + stdcout << "result size: " << polys.size() << "\n"; + for(std::size_t i = 0; i < polys.size(); ++i) { + stdcout << polys[i] << "\n"; + } + stdcout << "done testing polygon formation\n"; + return true; + } + //polygon45set class + + template + static inline bool testPolygon45FormationStar1(stream_type& stdcout) { + stdcout << "testing polygon formation\n"; + Polygon45Formation pf(true); + std::vector polys; + std::vector data; + // result == 0 8 -1 1 + data.push_back(Vertex45(Point(0, 8), -1, 1)); + // result == 0 8 1 -1 + data.push_back(Vertex45(Point(0, 8), 1, -1)); + // result == 4 0 1 1 + data.push_back(Vertex45(Point(4, 0), 1, 1)); + // result == 4 0 2 1 + data.push_back(Vertex45(Point(4, 0), 2, 1)); + // result == 4 4 2 -1 + data.push_back(Vertex45(Point(4, 4), 2, -1)); + // result == 4 4 -1 -1 + data.push_back(Vertex45(Point(4, 4), -1, -1)); + // result == 4 12 1 1 + data.push_back(Vertex45(Point(4, 12), 1, 1)); + // result == 4 12 2 1 + data.push_back(Vertex45(Point(4, 12), 2, 1)); + // result == 4 16 2 -1 + data.push_back(Vertex45(Point(4, 16), 2, 1)); + // result == 4 16 -1 -1 + data.push_back(Vertex45(Point(4, 16), -1, -1)); + // result == 6 2 1 -1 + data.push_back(Vertex45(Point(6, 2), 1, -1)); + // result == 6 14 -1 1 + data.push_back(Vertex45(Point(6, 14), -1, 1)); + // result == 6 2 -1 1 + data.push_back(Vertex45(Point(6, 2), -1, 1)); + // result == 6 14 1 -1 + data.push_back(Vertex45(Point(6, 14), 1, -1)); + // result == 8 0 -1 -1 + data.push_back(Vertex45(Point(8, 0), -1, -1)); + // result == 8 0 2 -1 + data.push_back(Vertex45(Point(8, 0), 2, -1)); + // result == 8 4 2 1 + data.push_back(Vertex45(Point(8, 4), 2, 1)); + // result == 8 4 1 1 + data.push_back(Vertex45(Point(8, 4), 1, 1)); + // result == 8 12 -1 -1 + data.push_back(Vertex45(Point(8, 12), -1, -1)); + // result == 8 12 2 -1 + data.push_back(Vertex45(Point(8, 12), 2, -1)); + // result == 8 16 2 1 + data.push_back(Vertex45(Point(8, 16), 2, 1)); + // result == 8 16 1 1 + data.push_back(Vertex45(Point(8, 16), 1, 1)); + // result == 12 8 1 -1 + data.push_back(Vertex45(Point(12, 8), 1, -1)); + // result == 12 8 -1 1 + data.push_back(Vertex45(Point(12, 8), -1, 1)); + polygon_sort(data.begin(), data.end()); + pf.scan(polys, data.begin(), data.end()); + stdcout << "result size: " << polys.size() << "\n"; + for(std::size_t i = 0; i < polys.size(); ++i) { + stdcout << polys[i] << "\n"; + } + stdcout << "done testing polygon formation\n"; + return true; + } + + template + static inline bool testPolygon45FormationStar2(stream_type& stdcout) { + stdcout << "testing polygon formation\n"; + Polygon45Formation pf(true); + std::vector polys; + Scan45 scan45; + std::vector result; + std::vector vertices; + //is a Rectnagle(0, 0, 10, 10); + Count2 count(1, 0); + Count2 ncount(-1, 0); + vertices.push_back(Scan45Vertex(Point(0,4), Scan45Count(Count2(0, 0), count, ncount, Count2(0, 0)))); + vertices.push_back(Scan45Vertex(Point(16,4), Scan45Count(count, ncount, Count2(0, 0), Count2(0, 0)))); + vertices.push_back(Scan45Vertex(Point(8,12), Scan45Count(ncount, Count2(0, 0), count, Count2(0, 0)))); + count = Count2(0, 1); + ncount = count.invert(); + vertices.push_back(Scan45Vertex(Point(0,8), Scan45Count(count, ncount, Count2(0, 0), Count2(0, 0)))); + vertices.push_back(Scan45Vertex(Point(16,8), Scan45Count(Count2(0, 0), count, ncount, Count2(0, 0)))); + vertices.push_back(Scan45Vertex(Point(8,0), Scan45Count(ncount, Count2(0, 0), count, Count2(0, 0)))); + sortScan45Vector(vertices); + stdcout << "scanning\n"; + scan45.scan(result, vertices.begin(), vertices.end()); + + polygon_sort(result.begin(), result.end()); + pf.scan(polys, result.begin(), result.end()); + stdcout << "result size: " << polys.size() << "\n"; + for(std::size_t i = 0; i < polys.size(); ++i) { + stdcout << polys[i] << "\n"; + } + stdcout << "done testing polygon formation\n"; + return true; + } + + template + static inline bool testPolygon45FormationStarHole1(stream_type& stdcout) { + stdcout << "testing polygon formation\n"; + Polygon45Formation pf(true); + std::vector polys; + std::vector data; + // result == 0 8 -1 1 + data.push_back(Vertex45(Point(0, 8), -1, 1)); + // result == 0 8 1 -1 + data.push_back(Vertex45(Point(0, 8), 1, -1)); + // result == 4 0 1 1 + data.push_back(Vertex45(Point(4, 0), 1, 1)); + // result == 4 0 2 1 + data.push_back(Vertex45(Point(4, 0), 2, 1)); + // result == 4 4 2 -1 + data.push_back(Vertex45(Point(4, 4), 2, -1)); + // result == 4 4 -1 -1 + data.push_back(Vertex45(Point(4, 4), -1, -1)); + // result == 4 12 1 1 + data.push_back(Vertex45(Point(4, 12), 1, 1)); + // result == 4 12 2 1 + data.push_back(Vertex45(Point(4, 12), 2, 1)); + // result == 4 16 2 -1 + data.push_back(Vertex45(Point(4, 16), 2, 1)); + // result == 4 16 -1 -1 + data.push_back(Vertex45(Point(4, 16), -1, -1)); + // result == 6 2 1 -1 + data.push_back(Vertex45(Point(6, 2), 1, -1)); + // result == 6 14 -1 1 + data.push_back(Vertex45(Point(6, 14), -1, 1)); + // result == 6 2 -1 1 + data.push_back(Vertex45(Point(6, 2), -1, 1)); + // result == 6 14 1 -1 + data.push_back(Vertex45(Point(6, 14), 1, -1)); + // result == 8 0 -1 -1 + data.push_back(Vertex45(Point(8, 0), -1, -1)); + // result == 8 0 2 -1 + data.push_back(Vertex45(Point(8, 0), 2, -1)); + // result == 8 4 2 1 + data.push_back(Vertex45(Point(8, 4), 2, 1)); + // result == 8 4 1 1 + data.push_back(Vertex45(Point(8, 4), 1, 1)); + // result == 8 12 -1 -1 + data.push_back(Vertex45(Point(8, 12), -1, -1)); + // result == 8 12 2 -1 + data.push_back(Vertex45(Point(8, 12), 2, -1)); + // result == 8 16 2 1 + data.push_back(Vertex45(Point(8, 16), 2, 1)); + // result == 8 16 1 1 + data.push_back(Vertex45(Point(8, 16), 1, 1)); + // result == 12 8 1 -1 + data.push_back(Vertex45(Point(12, 8), 1, -1)); + // result == 12 8 -1 1 + data.push_back(Vertex45(Point(12, 8), -1, 1)); + + data.push_back(Vertex45(Point(6, 4), 1, -1)); + data.push_back(Vertex45(Point(6, 4), 2, -1)); + data.push_back(Vertex45(Point(6, 8), -1, 1)); + data.push_back(Vertex45(Point(6, 8), 2, 1)); + data.push_back(Vertex45(Point(8, 6), -1, -1)); + data.push_back(Vertex45(Point(8, 6), 1, 1)); + + polygon_sort(data.begin(), data.end()); + pf.scan(polys, data.begin(), data.end()); + stdcout << "result size: " << polys.size() << "\n"; + for(std::size_t i = 0; i < polys.size(); ++i) { + stdcout << polys[i] << "\n"; + } + stdcout << "done testing polygon formation\n"; + return true; + } + + template + static inline bool testPolygon45FormationStarHole2(stream_type& stdcout) { + stdcout << "testing polygon formation\n"; + Polygon45Formation pf(false); + std::vector polys; + std::vector data; + // result == 0 8 -1 1 + data.push_back(Vertex45(Point(0, 8), -1, 1)); + // result == 0 8 1 -1 + data.push_back(Vertex45(Point(0, 8), 1, -1)); + // result == 4 0 1 1 + data.push_back(Vertex45(Point(4, 0), 1, 1)); + // result == 4 0 2 1 + data.push_back(Vertex45(Point(4, 0), 2, 1)); + // result == 4 4 2 -1 + data.push_back(Vertex45(Point(4, 4), 2, -1)); + // result == 4 4 -1 -1 + data.push_back(Vertex45(Point(4, 4), -1, -1)); + // result == 4 12 1 1 + data.push_back(Vertex45(Point(4, 12), 1, 1)); + // result == 4 12 2 1 + data.push_back(Vertex45(Point(4, 12), 2, 1)); + // result == 4 16 2 -1 + data.push_back(Vertex45(Point(4, 16), 2, 1)); + // result == 4 16 -1 -1 + data.push_back(Vertex45(Point(4, 16), -1, -1)); + // result == 6 2 1 -1 + data.push_back(Vertex45(Point(6, 2), 1, -1)); + // result == 6 14 -1 1 + data.push_back(Vertex45(Point(6, 14), -1, 1)); + // result == 6 2 -1 1 + data.push_back(Vertex45(Point(6, 2), -1, 1)); + // result == 6 14 1 -1 + data.push_back(Vertex45(Point(6, 14), 1, -1)); + // result == 8 0 -1 -1 + data.push_back(Vertex45(Point(8, 0), -1, -1)); + // result == 8 0 2 -1 + data.push_back(Vertex45(Point(8, 0), 2, -1)); + // result == 8 4 2 1 + data.push_back(Vertex45(Point(8, 4), 2, 1)); + // result == 8 4 1 1 + data.push_back(Vertex45(Point(8, 4), 1, 1)); + // result == 8 12 -1 -1 + data.push_back(Vertex45(Point(8, 12), -1, -1)); + // result == 8 12 2 -1 + data.push_back(Vertex45(Point(8, 12), 2, -1)); + // result == 8 16 2 1 + data.push_back(Vertex45(Point(8, 16), 2, 1)); + // result == 8 16 1 1 + data.push_back(Vertex45(Point(8, 16), 1, 1)); + // result == 12 8 1 -1 + data.push_back(Vertex45(Point(12, 8), 1, -1)); + // result == 12 8 -1 1 + data.push_back(Vertex45(Point(12, 8), -1, 1)); + + data.push_back(Vertex45(Point(6, 4), 1, -1)); + data.push_back(Vertex45(Point(6, 4), 2, -1)); + data.push_back(Vertex45(Point(6, 12), -1, 1)); + data.push_back(Vertex45(Point(6, 12), 2, 1)); + data.push_back(Vertex45(Point(10, 8), -1, -1)); + data.push_back(Vertex45(Point(10, 8), 1, 1)); + + polygon_sort(data.begin(), data.end()); + pf.scan(polys, data.begin(), data.end()); + stdcout << "result size: " << polys.size() << "\n"; + for(std::size_t i = 0; i < polys.size(); ++i) { + stdcout << polys[i] << "\n"; + } + stdcout << "done testing polygon formation\n"; + return true; + } + + template + static inline bool testPolygon45Formation(stream_type& stdcout) { + stdcout << "testing polygon formation\n"; + Polygon45Formation pf(false); + std::vector polys; + std::vector data; + + data.push_back(Vertex45(Point(0, 0), 0, 1)); + data.push_back(Vertex45(Point(0, 0), 2, 1)); + data.push_back(Vertex45(Point(0, 100), 2, -1)); + data.push_back(Vertex45(Point(0, 100), 0, -1)); + data.push_back(Vertex45(Point(100, 0), 0, -1)); + data.push_back(Vertex45(Point(100, 0), 2, -1)); + data.push_back(Vertex45(Point(100, 100), 2, 1)); + data.push_back(Vertex45(Point(100, 100), 0, 1)); + + data.push_back(Vertex45(Point(2, 2), 0, -1)); + data.push_back(Vertex45(Point(2, 2), 2, -1)); + data.push_back(Vertex45(Point(2, 10), 2, 1)); + data.push_back(Vertex45(Point(2, 10), 0, 1)); + data.push_back(Vertex45(Point(10, 2), 0, 1)); + data.push_back(Vertex45(Point(10, 2), 2, 1)); + data.push_back(Vertex45(Point(10, 10), 2, -1)); + data.push_back(Vertex45(Point(10, 10), 0, -1)); + + data.push_back(Vertex45(Point(2, 12), 0, -1)); + data.push_back(Vertex45(Point(2, 12), 2, -1)); + data.push_back(Vertex45(Point(2, 22), 2, 1)); + data.push_back(Vertex45(Point(2, 22), 0, 1)); + data.push_back(Vertex45(Point(10, 12), 0, 1)); + data.push_back(Vertex45(Point(10, 12), 2, 1)); + data.push_back(Vertex45(Point(10, 22), 2, -1)); + data.push_back(Vertex45(Point(10, 22), 0, -1)); + + polygon_sort(data.begin(), data.end()); + pf.scan(polys, data.begin(), data.end()); + stdcout << "result size: " << polys.size() << "\n"; + for(std::size_t i = 0; i < polys.size(); ++i) { + stdcout << polys[i] << "\n"; + } + stdcout << "done testing polygon formation\n"; + return true; + } + + + class Polygon45Tiling { + private: + //definitions + typedef std::map Polygon45FormationData; + typedef typename Polygon45FormationData::iterator iterator; + typedef typename Polygon45FormationData::const_iterator const_iterator; + + //data + Polygon45FormationData scanData_; + Unit x_; + int justBefore_; + public: + inline Polygon45Tiling() : scanData_(), x_((std::numeric_limits::min)()), justBefore_(false) { + lessVertex45 lessElm(&x_, &justBefore_); + scanData_ = Polygon45FormationData(lessElm); + } + inline Polygon45Tiling(const Polygon45Tiling& that) : + scanData_(), x_((std::numeric_limits::min)()), justBefore_(false) { (*this) = that; } + inline Polygon45Tiling& operator=(const Polygon45Tiling& that) { + x_ = that.x_; + justBefore_ = that.justBefore_; + lessVertex45 lessElm(&x_, &justBefore_); + scanData_ = Polygon45FormationData(lessElm); + for(const_iterator itr = that.scanData_.begin(); itr != that.scanData_.end(); ++itr){ + scanData_.insert(scanData_.end(), *itr); + } + return *this; + } + + //cT is an output container of Polygon45 or Polygon45WithHoles + //iT is an iterator over Vertex45 elements + //inputBegin - inputEnd is a range of sorted iT that represents + //one or more scanline stops worth of data + template + void scan(cT& output, iT inputBegin, iT inputEnd) { + //std::cout << "1\n"; + while(inputBegin != inputEnd) { + //std::cout << "2\n"; + x_ = (*inputBegin).pt.x(); + //std::cout << "SCAN FORMATION " << x_ << "\n"; + //std::cout << "x_ = " << x_ << "\n"; + //std::cout << "scan line size: " << scanData_.size() << "\n"; + inputBegin = processEvent_(output, inputBegin, inputEnd); + } + } + + private: + //functions + + inline void getVerticalPair_(std::pair& verticalPair, + iterator previter) { + ActiveTail45* iterTail = (*previter).second; + Point prevPoint(x_, previter->first.evalAtX(x_)); + iterTail->pushPoint(prevPoint); + std::pair tailPair = + ActiveTail45::createActiveTail45sAsPair(prevPoint, true, 0, false); + verticalPair.first = iterTail; + verticalPair.second = tailPair.first; + (*previter).second = tailPair.second; + } + + template + inline std::pair processPoint_(cT& output, cT2& elements, + std::pair& verticalPair, + iterator previter, Point point, + Vertex45Count& counts, ActiveTail45** tails, Vertex45Count& incoming) { + //std::cout << point << "\n"; + //std::cout << counts[0] << " "; + //std::cout << counts[1] << " "; + //std::cout << counts[2] << " "; + //std::cout << counts[3] << "\n"; + //std::cout << incoming[0] << " "; + //std::cout << incoming[1] << " "; + //std::cout << incoming[2] << " "; + //std::cout << incoming[3] << "\n"; + //join any closing solid corners + ActiveTail45* returnValue = 0; + std::pair verticalPairOut; + verticalPairOut.first = 0; + verticalPairOut.second = 0; + int returnCount = 0; + for(int i = 0; i < 3; ++i) { + //std::cout << i << "\n"; + if(counts[i] == -1) { + //std::cout << "fixed i\n"; + for(int j = i + 1; j < 4; ++j) { + //std::cout << j << "\n"; + if(counts[j]) { + if(counts[j] == 1) { + //std::cout << "case1: " << i << " " << j << "\n"; + //if a figure is closed it will be written out by this function to output + ActiveTail45::joinChains(point, tails[i], tails[j], true, output); + counts[i] = 0; + counts[j] = 0; + tails[i] = 0; + tails[j] = 0; + } + break; + } + } + } + } + //find any pairs of incoming edges that need to create pair for leading solid + //std::cout << "checking case2\n"; + for(int i = 0; i < 3; ++i) { + //std::cout << i << "\n"; + if(incoming[i] == 1) { + //std::cout << "fixed i\n"; + for(int j = i + 1; j < 4; ++j) { + //std::cout << j << "\n"; + if(incoming[j]) { + if(incoming[j] == -1) { + //std::cout << "case2: " << i << " " << j << "\n"; + //std::cout << "creating active tail pair\n"; + std::pair tailPair = + ActiveTail45::createActiveTail45sAsPair(point, true, 0, false); + //tailPair.first->print(); + //tailPair.second->print(); + if(j == 3) { + //vertical active tail becomes return value + returnValue = tailPair.first; + returnCount = 1; + } else { + Vertex45 vertex(point, i -1, incoming[i]); + //std::cout << "new element " << j-1 << " " << -1 << "\n"; + elements.push_back(std::pair(Vertex45(point, j -1, -1), tailPair.first)); + } + //std::cout << "new element " << i-1 << " " << 1 << "\n"; + elements.push_back(std::pair(Vertex45(point, i -1, 1), tailPair.second)); + incoming[i] = 0; + incoming[j] = 0; + } + break; + } + } + } + } + + //find any active tail that needs to pass through to an incoming edge + //we expect to find no more than two pass through + + //find pass through with solid on top + //std::cout << "checking case 3\n"; + for(int i = 0; i < 4; ++i) { + //std::cout << i << "\n"; + if(counts[i] != 0) { + if(counts[i] == 1) { + //std::cout << "fixed i\n"; + for(int j = 3; j >= 0; --j) { + if(incoming[j] != 0) { + if(incoming[j] == 1) { + //std::cout << "case3: " << i << " " << j << "\n"; + //tails[i]->print(); + //pass through solid on top + if(i != 3) + tails[i]->pushPoint(point); + //std::cout << "after push\n"; + if(j == 3) { + returnValue = tails[i]; + returnCount = -1; + } else { + verticalPairOut.first = tails[i]; + std::pair tailPair = + ActiveTail45::createActiveTail45sAsPair(point, true, 0, false); + verticalPairOut.second = tailPair.first; + elements.push_back(std::pair(Vertex45(point, j -1, incoming[j]), + tailPair.second)); + } + tails[i] = 0; + counts[i] = 0; + incoming[j] = 0; + } + break; + } + } + } + break; + } + } + //std::cout << "checking case 4\n"; + //find pass through with solid on bottom + for(int i = 3; i >= 0; --i) { + if(counts[i] != 0) { + if(counts[i] == -1) { + for(int j = 0; j < 4; ++j) { + if(incoming[j] != 0) { + if(incoming[j] == -1) { + //std::cout << "case4: " << i << " " << j << "\n"; + //pass through solid on bottom + if(i == 3) { + //std::cout << "new element " << j-1 << " " << incoming[j] << "\n"; + if(j == 3) { + returnValue = tails[i]; + returnCount = 1; + } else { + tails[i]->pushPoint(point); + elements.push_back(std::pair(Vertex45(point, j -1, incoming[j]), tails[i])); + } + } else if(j == 3) { + if(verticalPair.first == 0) { + getVerticalPair_(verticalPair, previter); + } + ActiveTail45::joinChains(point, tails[i], verticalPair.first, true, output); + returnValue = verticalPair.second; + returnCount = 1; + } else { + if(verticalPair.first == 0) { + getVerticalPair_(verticalPair, previter); + } + ActiveTail45::joinChains(point, tails[i], verticalPair.first, true, output); + verticalPair.second->pushPoint(point); + elements.push_back(std::pair(Vertex45(point, j -1, incoming[j]), + verticalPair.second)); + } + tails[i] = 0; + counts[i] = 0; + incoming[j] = 0; + } + break; + } + } + } + break; + } + } + + //find the end of a hole or the beginning of a hole + + //find end of a hole + for(int i = 0; i < 3; ++i) { + if(counts[i] != 0) { + for(int j = i+1; j < 4; ++j) { + if(counts[j] != 0) { + //std::cout << "case5: " << i << " " << j << "\n"; + //we are ending a hole and may potentially close a figure and have to handle the hole + tails[i]->pushPoint(point); + verticalPairOut.first = tails[i]; + if(j == 3) { + verticalPairOut.second = tails[j]; + } else { + if(verticalPair.first == 0) { + getVerticalPair_(verticalPair, previter); + } + ActiveTail45::joinChains(point, tails[j], verticalPair.first, true, output); + verticalPairOut.second = verticalPair.second; + } + tails[i] = 0; + tails[j] = 0; + counts[i] = 0; + counts[j] = 0; + break; + } + } + break; + } + } + //find beginning of a hole + for(int i = 0; i < 3; ++i) { + if(incoming[i] != 0) { + for(int j = i+1; j < 4; ++j) { + if(incoming[j] != 0) { + //std::cout << "case6: " << i << " " << j << "\n"; + //we are beginning a empty space + if(verticalPair.first == 0) { + getVerticalPair_(verticalPair, previter); + } + verticalPair.second->pushPoint(point); + if(j == 3) { + returnValue = verticalPair.first; + returnCount = -1; + } else { + std::pair tailPair = + ActiveTail45::createActiveTail45sAsPair(point, true, 0, false); + //std::cout << "new element " << j-1 << " " << incoming[j] << "\n"; + elements.push_back(std::pair(Vertex45(point, j -1, incoming[j]), tailPair.second)); + verticalPairOut.second = tailPair.first; + verticalPairOut.first = verticalPair.first; + } + //std::cout << "new element " << i-1 << " " << incoming[i] << "\n"; + elements.push_back(std::pair(Vertex45(point, i -1, incoming[i]), verticalPair.second)); + incoming[i] = 0; + incoming[j] = 0; + break; + } + } + break; + } + } + verticalPair = verticalPairOut; + //assert that verticalPair is either both null, or neither null + //assert that returnValue is null if verticalPair is not null + //assert that tails, counts and incoming are all null + return std::pair(returnCount, returnValue); + } + + template + inline iT processEvent_(cT& output, iT inputBegin, iT inputEnd) { + //std::cout << "processEvent_\n"; + justBefore_ = true; + //collect up all elements from the tree that are at the y + //values of events in the input queue + //create vector of new elements to add into tree + ActiveTail45* verticalTail = 0; + std::pair verticalPair; + verticalPair.first = 0; + verticalPair.second = 0; + int verticalCount = 0; + iT currentIter = inputBegin; + std::vector elementIters; + std::vector > elements; + while(currentIter != inputEnd && currentIter->pt.x() == x_) { + //std::cout << "loop\n"; + Unit currentY = (*currentIter).pt.y(); + iterator iter = lookUp_(currentY); + //int counts[4] = {0, 0, 0, 0}; + Vertex45Count counts; + ActiveTail45* tails[4] = {0, 0, 0, verticalTail}; + //std::cout << "finding elements in tree\n"; + iterator previter = iter; + if(previter != scanData_.end() && + previter->first.evalAtX(x_) >= currentY && + previter != scanData_.begin()) + --previter; + while(iter != scanData_.end() && + iter->first.evalAtX(x_) == currentY) { + //std::cout << "loop2\n"; + elementIters.push_back(iter); + int index = iter->first.rise + 1; + //std::cout << index << " " << iter->first.count << "\n"; + counts[index] = iter->first.count; + tails[index] = iter->second; + ++iter; + } + //int incoming[4] = {0, 0, 0, 0}; + Vertex45Count incoming; + //std::cout << "aggregating\n"; + do { + //std::cout << "loop3\n"; + Vertex45Compact currentVertex(*currentIter); + incoming += currentVertex.count; + ++currentIter; + } while(currentIter != inputEnd && currentIter->pt.y() == currentY && + currentIter->pt.x() == x_); + //now counts and tails have the data from the left and + //incoming has the data from the right at this point + //cancel out any end points + //std::cout << counts[0] << " "; + //std::cout << counts[1] << " "; + //std::cout << counts[2] << " "; + //std::cout << counts[3] << "\n"; + //std::cout << incoming[0] << " "; + //std::cout << incoming[1] << " "; + //std::cout << incoming[2] << " "; + //std::cout << incoming[3] << "\n"; + if(verticalTail) { + counts[3] = -verticalCount; + } + incoming[3] *= -1; + for(unsigned int i = 0; i < 4; ++i) incoming[i] += counts[i]; + //std::cout << "calling processPoint_\n"; + std::pair result = processPoint_(output, elements, verticalPair, previter, + Point(x_, currentY), counts, tails, incoming); + verticalCount = result.first; + verticalTail = result.second; + if(verticalPair.first != 0 && iter != scanData_.end() && + (currentIter == inputEnd || currentIter->pt.x() != x_ || + currentIter->pt.y() > (*iter).first.evalAtX(x_))) { + //splice vertical pair into edge above + ActiveTail45* tailabove = (*iter).second; + Point point(x_, (*iter).first.evalAtX(x_)); + verticalPair.second->pushPoint(point); + ActiveTail45::joinChains(point, tailabove, verticalPair.first, true, output); + (*iter).second = verticalPair.second; + verticalPair.first = 0; + verticalPair.second = 0; + } + } + //std::cout << "erasing\n"; + //erase all elements from the tree + for(typename std::vector::iterator iter = elementIters.begin(); + iter != elementIters.end(); ++iter) { + //std::cout << "erasing loop\n"; + scanData_.erase(*iter); + } + //switch comparison tie breaking policy + justBefore_ = false; + //add new elements into tree + //std::cout << "inserting\n"; + for(typename std::vector >::iterator iter = elements.begin(); + iter != elements.end(); ++iter) { + //std::cout << "inserting loop\n"; + scanData_.insert(scanData_.end(), *iter); + } + //std::cout << "end processEvent\n"; + return currentIter; + } + + inline iterator lookUp_(Unit y){ + //if just before then we need to look from 1 not -1 + return scanData_.lower_bound(Vertex45(Point(x_, y), -1+2*justBefore_, 0)); + } + + }; + + template + static inline bool testPolygon45TilingRect(stream_type& stdcout) { + stdcout << "testing polygon tiling\n"; + Polygon45Tiling pf; + std::vector polys; + std::vector data; + data.push_back(Vertex45(Point(0, 0), 0, 1)); + data.push_back(Vertex45(Point(0, 0), 2, 1)); + data.push_back(Vertex45(Point(0, 10), 2, -1)); + data.push_back(Vertex45(Point(0, 10), 0, -1)); + data.push_back(Vertex45(Point(10, 0), 0, -1)); + data.push_back(Vertex45(Point(10, 0), 2, -1)); + data.push_back(Vertex45(Point(10, 10), 2, 1)); + data.push_back(Vertex45(Point(10, 10), 0, 1)); + polygon_sort(data.begin(), data.end()); + pf.scan(polys, data.begin(), data.end()); + stdcout << "result size: " << polys.size() << "\n"; + for(std::size_t i = 0; i < polys.size(); ++i) { + stdcout << polys[i] << "\n"; + } + stdcout << "done testing polygon tiling\n"; + return true; + } + + template + static inline bool testPolygon45TilingP1(stream_type& stdcout) { + stdcout << "testing polygon tiling\n"; + Polygon45Tiling pf; + std::vector polys; + std::vector data; + data.push_back(Vertex45(Point(0, 0), 1, 1)); + data.push_back(Vertex45(Point(0, 0), 2, 1)); + data.push_back(Vertex45(Point(0, 10), 2, -1)); + data.push_back(Vertex45(Point(0, 10), 1, -1)); + data.push_back(Vertex45(Point(10, 10), 1, -1)); + data.push_back(Vertex45(Point(10, 10), 2, -1)); + data.push_back(Vertex45(Point(10, 20), 2, 1)); + data.push_back(Vertex45(Point(10, 20), 1, 1)); + polygon_sort(data.begin(), data.end()); + pf.scan(polys, data.begin(), data.end()); + stdcout << "result size: " << polys.size() << "\n"; + for(std::size_t i = 0; i < polys.size(); ++i) { + stdcout << polys[i] << "\n"; + } + stdcout << "done testing polygon tiling\n"; + return true; + } + + template + static inline bool testPolygon45TilingP2(stream_type& stdcout) { + stdcout << "testing polygon tiling\n"; + Polygon45Tiling pf; + std::vector polys; + std::vector data; + data.push_back(Vertex45(Point(0, 0), 0, 1)); + data.push_back(Vertex45(Point(0, 0), 1, -1)); + data.push_back(Vertex45(Point(10, 0), 0, -1)); + data.push_back(Vertex45(Point(10, 0), 1, 1)); + data.push_back(Vertex45(Point(10, 10), 1, 1)); + data.push_back(Vertex45(Point(10, 10), 0, -1)); + data.push_back(Vertex45(Point(20, 10), 1, -1)); + data.push_back(Vertex45(Point(20, 10), 0, 1)); + polygon_sort(data.begin(), data.end()); + pf.scan(polys, data.begin(), data.end()); + stdcout << "result size: " << polys.size() << "\n"; + for(std::size_t i = 0; i < polys.size(); ++i) { + stdcout << polys[i] << "\n"; + } + stdcout << "done testing polygon tiling\n"; + return true; + } + + template + static inline bool testPolygon45TilingP3(stream_type& stdcout) { + stdcout << "testing polygon tiling\n"; + Polygon45Tiling pf; + std::vector polys; + std::vector data; + data.push_back(Vertex45(Point(0, 0), 0, 1)); + data.push_back(Vertex45(Point(0, 0), 2, 1)); + data.push_back(Vertex45(Point(0, 10), 2, -1)); + data.push_back(Vertex45(Point(0, 10), 0, -1)); + data.push_back(Vertex45(Point(20, 0), 0, -1)); + data.push_back(Vertex45(Point(20, 0), 2, -1)); + data.push_back(Vertex45(Point(10, 10), 1, -1)); + data.push_back(Vertex45(Point(10, 10), 0, 1)); + data.push_back(Vertex45(Point(20, 20), 1, 1)); + data.push_back(Vertex45(Point(20, 20), 2, 1)); + polygon_sort(data.begin(), data.end()); + pf.scan(polys, data.begin(), data.end()); + stdcout << "result size: " << polys.size() << "\n"; + for(std::size_t i = 0; i < polys.size(); ++i) { + stdcout << polys[i] << "\n"; + } + stdcout << "done testing polygon tiling\n"; + return true; + } + + template + static inline bool testPolygon45TilingP4(stream_type& stdcout) { + stdcout << "testing polygon tiling p4\n"; + Polygon45Tiling pf; + std::vector polys; + std::vector data; + data.push_back(Vertex45(Point(0, 0), 0, 1)); + data.push_back(Vertex45(Point(0, 0), 2, 1)); + data.push_back(Vertex45(Point(0, 10), 2, -1)); + data.push_back(Vertex45(Point(0, 10), 0, -1)); + data.push_back(Vertex45(Point(10, 0), -1, 1)); + data.push_back(Vertex45(Point(10, 0), 0, -1)); + data.push_back(Vertex45(Point(20, 10), 2, 1)); + data.push_back(Vertex45(Point(20, 10), 0, 1)); + data.push_back(Vertex45(Point(20, -10), -1, -1)); + data.push_back(Vertex45(Point(20, -10), 2, -1)); + polygon_sort(data.begin(), data.end()); + pf.scan(polys, data.begin(), data.end()); + stdcout << "result size: " << polys.size() << "\n"; + for(std::size_t i = 0; i < polys.size(); ++i) { + stdcout << polys[i] << "\n"; + } + stdcout << "done testing polygon tiling\n"; + return true; + } + + template + static inline bool testPolygon45TilingP5(stream_type& stdcout) { + stdcout << "testing polygon tiling P5\n"; + Polygon45Tiling pf; + std::vector polys; + std::vector data; + data.push_back(Vertex45(Point(0, 0), 0, 1)); + data.push_back(Vertex45(Point(0, 0), 2, 1)); + data.push_back(Vertex45(Point(0, 10), 2, -1)); + data.push_back(Vertex45(Point(0, 10), 0, -1)); + data.push_back(Vertex45(Point(10, 0), 0, -1)); + data.push_back(Vertex45(Point(10, 0), 2, -1)); + data.push_back(Vertex45(Point(10, 10), 2, 1)); + data.push_back(Vertex45(Point(10, 10), 0, 1)); + + data.push_back(Vertex45(Point(1, 1), 0, -1)); + data.push_back(Vertex45(Point(1, 1), 1, 1)); + data.push_back(Vertex45(Point(2, 1), 0, 1)); + data.push_back(Vertex45(Point(2, 1), 1, -1)); + data.push_back(Vertex45(Point(2, 2), 1, -1)); + data.push_back(Vertex45(Point(2, 2), 0, 1)); + data.push_back(Vertex45(Point(3, 2), 1, 1)); + data.push_back(Vertex45(Point(3, 2), 0, -1)); + polygon_sort(data.begin(), data.end()); + pf.scan(polys, data.begin(), data.end()); + stdcout << "result size: " << polys.size() << "\n"; + for(std::size_t i = 0; i < polys.size(); ++i) { + stdcout << polys[i] << "\n"; + } + stdcout << "done testing polygon tiling\n"; + return true; + } + + template + static inline bool testPolygon45TilingP6(stream_type& stdcout) { + stdcout << "testing polygon tiling P6\n"; + Polygon45Tiling pf; + std::vector polys; + std::vector data; + data.push_back(Vertex45(Point(0, 0), 0, 1)); + data.push_back(Vertex45(Point(0, 0), 2, 1)); + data.push_back(Vertex45(Point(0, 10), 2, -1)); + data.push_back(Vertex45(Point(0, 10), 0, -1)); + data.push_back(Vertex45(Point(10, 0), 0, -1)); + data.push_back(Vertex45(Point(10, 0), 2, -1)); + data.push_back(Vertex45(Point(10, 10), 2, 1)); + data.push_back(Vertex45(Point(10, 10), 0, 1)); + + data.push_back(Vertex45(Point(1, 1), 0, -1)); + data.push_back(Vertex45(Point(1, 1), 2, -1)); + data.push_back(Vertex45(Point(1, 2), 2, 1)); + data.push_back(Vertex45(Point(1, 2), 0, 1)); + data.push_back(Vertex45(Point(2, 1), 0, 1)); + data.push_back(Vertex45(Point(2, 1), 2, 1)); + data.push_back(Vertex45(Point(2, 2), 2, -1)); + data.push_back(Vertex45(Point(2, 2), 0, -1)); + + polygon_sort(data.begin(), data.end()); + pf.scan(polys, data.begin(), data.end()); + stdcout << "result size: " << polys.size() << "\n"; + for(std::size_t i = 0; i < polys.size(); ++i) { + stdcout << polys[i] << "\n"; + } + stdcout << "done testing polygon tiling\n"; + return true; + } + + template + static inline bool testPolygon45TilingStar1(stream_type& stdcout) { + stdcout << "testing polygon tiling star1\n"; + Polygon45Tiling pf; + std::vector polys; + std::vector data; + // result == 0 8 -1 1 + data.push_back(Vertex45(Point(0, 8), -1, 1)); + // result == 0 8 1 -1 + data.push_back(Vertex45(Point(0, 8), 1, -1)); + // result == 4 0 1 1 + data.push_back(Vertex45(Point(4, 0), 1, 1)); + // result == 4 0 2 1 + data.push_back(Vertex45(Point(4, 0), 2, 1)); + // result == 4 4 2 -1 + data.push_back(Vertex45(Point(4, 4), 2, -1)); + // result == 4 4 -1 -1 + data.push_back(Vertex45(Point(4, 4), -1, -1)); + // result == 4 12 1 1 + data.push_back(Vertex45(Point(4, 12), 1, 1)); + // result == 4 12 2 1 + data.push_back(Vertex45(Point(4, 12), 2, 1)); + // result == 4 16 2 -1 + data.push_back(Vertex45(Point(4, 16), 2, 1)); + // result == 4 16 -1 -1 + data.push_back(Vertex45(Point(4, 16), -1, -1)); + // result == 6 2 1 -1 + data.push_back(Vertex45(Point(6, 2), 1, -1)); + // result == 6 14 -1 1 + data.push_back(Vertex45(Point(6, 14), -1, 1)); + // result == 6 2 -1 1 + data.push_back(Vertex45(Point(6, 2), -1, 1)); + // result == 6 14 1 -1 + data.push_back(Vertex45(Point(6, 14), 1, -1)); + // result == 8 0 -1 -1 + data.push_back(Vertex45(Point(8, 0), -1, -1)); + // result == 8 0 2 -1 + data.push_back(Vertex45(Point(8, 0), 2, -1)); + // result == 8 4 2 1 + data.push_back(Vertex45(Point(8, 4), 2, 1)); + // result == 8 4 1 1 + data.push_back(Vertex45(Point(8, 4), 1, 1)); + // result == 8 12 -1 -1 + data.push_back(Vertex45(Point(8, 12), -1, -1)); + // result == 8 12 2 -1 + data.push_back(Vertex45(Point(8, 12), 2, -1)); + // result == 8 16 2 1 + data.push_back(Vertex45(Point(8, 16), 2, 1)); + // result == 8 16 1 1 + data.push_back(Vertex45(Point(8, 16), 1, 1)); + // result == 12 8 1 -1 + data.push_back(Vertex45(Point(12, 8), 1, -1)); + // result == 12 8 -1 1 + data.push_back(Vertex45(Point(12, 8), -1, 1)); + polygon_sort(data.begin(), data.end()); + pf.scan(polys, data.begin(), data.end()); + stdcout << "result size: " << polys.size() << "\n"; + for(std::size_t i = 0; i < polys.size(); ++i) { + stdcout << polys[i] << "\n"; + } + stdcout << "done testing polygon tiling\n"; + return true; + } + + template + static inline bool testPolygon45TilingStar2(stream_type& stdcout) { + stdcout << "testing polygon tiling\n"; + Polygon45Tiling pf; + std::vector polys; + + Scan45 scan45; + std::vector result; + std::vector vertices; + //is a Rectnagle(0, 0, 10, 10); + Count2 count(1, 0); + Count2 ncount(-1, 0); + vertices.push_back(Scan45Vertex(Point(0,4), Scan45Count(Count2(0, 0), count, ncount, Count2(0, 0)))); + vertices.push_back(Scan45Vertex(Point(16,4), Scan45Count(count, ncount, Count2(0, 0), Count2(0, 0)))); + vertices.push_back(Scan45Vertex(Point(8,12), Scan45Count(ncount, Count2(0, 0), count, Count2(0, 0)))); + count = Count2(0, 1); + ncount = count.invert(); + vertices.push_back(Scan45Vertex(Point(0,8), Scan45Count(count, ncount, Count2(0, 0), Count2(0, 0)))); + vertices.push_back(Scan45Vertex(Point(16,8), Scan45Count(Count2(0, 0), count, ncount, Count2(0, 0)))); + vertices.push_back(Scan45Vertex(Point(8,0), Scan45Count(ncount, Count2(0, 0), count, Count2(0, 0)))); + sortScan45Vector(vertices); + stdcout << "scanning\n"; + scan45.scan(result, vertices.begin(), vertices.end()); + + polygon_sort(result.begin(), result.end()); + pf.scan(polys, result.begin(), result.end()); + stdcout << "result size: " << polys.size() << "\n"; + for(std::size_t i = 0; i < polys.size(); ++i) { + stdcout << polys[i] << "\n"; + } + stdcout << "done testing polygon tiling\n"; + return true; + } + + template + static inline bool testPolygon45TilingStarHole1(stream_type& stdcout) { + stdcout << "testing polygon tiling star hole 1\n"; + Polygon45Tiling pf; + std::vector polys; + std::vector data; + // result == 0 8 -1 1 + data.push_back(Vertex45(Point(0, 8), -1, 1)); + // result == 0 8 1 -1 + data.push_back(Vertex45(Point(0, 8), 1, -1)); + // result == 4 0 1 1 + data.push_back(Vertex45(Point(4, 0), 1, 1)); + // result == 4 0 2 1 + data.push_back(Vertex45(Point(4, 0), 2, 1)); + // result == 4 4 2 -1 + data.push_back(Vertex45(Point(4, 4), 2, -1)); + // result == 4 4 -1 -1 + data.push_back(Vertex45(Point(4, 4), -1, -1)); + // result == 4 12 1 1 + data.push_back(Vertex45(Point(4, 12), 1, 1)); + // result == 4 12 2 1 + data.push_back(Vertex45(Point(4, 12), 2, 1)); + // result == 4 16 2 -1 + data.push_back(Vertex45(Point(4, 16), 2, 1)); + // result == 4 16 -1 -1 + data.push_back(Vertex45(Point(4, 16), -1, -1)); + // result == 6 2 1 -1 + data.push_back(Vertex45(Point(6, 2), 1, -1)); + // result == 6 14 -1 1 + data.push_back(Vertex45(Point(6, 14), -1, 1)); + // result == 6 2 -1 1 + data.push_back(Vertex45(Point(6, 2), -1, 1)); + // result == 6 14 1 -1 + data.push_back(Vertex45(Point(6, 14), 1, -1)); + // result == 8 0 -1 -1 + data.push_back(Vertex45(Point(8, 0), -1, -1)); + // result == 8 0 2 -1 + data.push_back(Vertex45(Point(8, 0), 2, -1)); + // result == 8 4 2 1 + data.push_back(Vertex45(Point(8, 4), 2, 1)); + // result == 8 4 1 1 + data.push_back(Vertex45(Point(8, 4), 1, 1)); + // result == 8 12 -1 -1 + data.push_back(Vertex45(Point(8, 12), -1, -1)); + // result == 8 12 2 -1 + data.push_back(Vertex45(Point(8, 12), 2, -1)); + // result == 8 16 2 1 + data.push_back(Vertex45(Point(8, 16), 2, 1)); + // result == 8 16 1 1 + data.push_back(Vertex45(Point(8, 16), 1, 1)); + // result == 12 8 1 -1 + data.push_back(Vertex45(Point(12, 8), 1, -1)); + // result == 12 8 -1 1 + data.push_back(Vertex45(Point(12, 8), -1, 1)); + + data.push_back(Vertex45(Point(6, 4), 1, -1)); + data.push_back(Vertex45(Point(6, 4), 2, -1)); + data.push_back(Vertex45(Point(6, 8), -1, 1)); + data.push_back(Vertex45(Point(6, 8), 2, 1)); + data.push_back(Vertex45(Point(8, 6), -1, -1)); + data.push_back(Vertex45(Point(8, 6), 1, 1)); + + polygon_sort(data.begin(), data.end()); + pf.scan(polys, data.begin(), data.end()); + stdcout << "result size: " << polys.size() << "\n"; + for(std::size_t i = 0; i < polys.size(); ++i) { + stdcout << polys[i] << "\n"; + } + stdcout << "done testing polygon tiling\n"; + return true; + } + + template + static inline bool testPolygon45TilingStarHole2(stream_type& stdcout) { + stdcout << "testing polygon tiling star hole 2\n"; + Polygon45Tiling pf; + std::vector polys; + std::vector data; + // result == 0 8 -1 1 + data.push_back(Vertex45(Point(0, 8), -1, 1)); + // result == 0 8 1 -1 + data.push_back(Vertex45(Point(0, 8), 1, -1)); + // result == 4 0 1 1 + data.push_back(Vertex45(Point(4, 0), 1, 1)); + // result == 4 0 2 1 + data.push_back(Vertex45(Point(4, 0), 2, 1)); + // result == 4 4 2 -1 + data.push_back(Vertex45(Point(4, 4), 2, -1)); + // result == 4 4 -1 -1 + data.push_back(Vertex45(Point(4, 4), -1, -1)); + // result == 4 12 1 1 + data.push_back(Vertex45(Point(4, 12), 1, 1)); + // result == 4 12 2 1 + data.push_back(Vertex45(Point(4, 12), 2, 1)); + // result == 4 16 2 -1 + data.push_back(Vertex45(Point(4, 16), 2, 1)); + // result == 4 16 -1 -1 + data.push_back(Vertex45(Point(4, 16), -1, -1)); + // result == 6 2 1 -1 + data.push_back(Vertex45(Point(6, 2), 1, -1)); + // result == 6 14 -1 1 + data.push_back(Vertex45(Point(6, 14), -1, 1)); + // result == 6 2 -1 1 + data.push_back(Vertex45(Point(6, 2), -1, 1)); + // result == 6 14 1 -1 + data.push_back(Vertex45(Point(6, 14), 1, -1)); + // result == 8 0 -1 -1 + data.push_back(Vertex45(Point(8, 0), -1, -1)); + // result == 8 0 2 -1 + data.push_back(Vertex45(Point(8, 0), 2, -1)); + // result == 8 4 2 1 + data.push_back(Vertex45(Point(8, 4), 2, 1)); + // result == 8 4 1 1 + data.push_back(Vertex45(Point(8, 4), 1, 1)); + // result == 8 12 -1 -1 + data.push_back(Vertex45(Point(8, 12), -1, -1)); + // result == 8 12 2 -1 + data.push_back(Vertex45(Point(8, 12), 2, -1)); + // result == 8 16 2 1 + data.push_back(Vertex45(Point(8, 16), 2, 1)); + // result == 8 16 1 1 + data.push_back(Vertex45(Point(8, 16), 1, 1)); + // result == 12 8 1 -1 + data.push_back(Vertex45(Point(12, 8), 1, -1)); + // result == 12 8 -1 1 + data.push_back(Vertex45(Point(12, 8), -1, 1)); + + data.push_back(Vertex45(Point(6, 4), 1, -1)); + data.push_back(Vertex45(Point(6, 4), 2, -1)); + data.push_back(Vertex45(Point(6, 12), -1, 1)); + data.push_back(Vertex45(Point(6, 12), 2, 1)); + data.push_back(Vertex45(Point(10, 8), -1, -1)); + data.push_back(Vertex45(Point(10, 8), 1, 1)); + + polygon_sort(data.begin(), data.end()); + pf.scan(polys, data.begin(), data.end()); + stdcout << "result size: " << polys.size() << "\n"; + for(std::size_t i = 0; i < polys.size(); ++i) { + stdcout << polys[i] << "\n"; + } + stdcout << "done testing polygon tiling\n"; + return true; + } + + template + static inline bool testPolygon45Tiling(stream_type& stdcout) { + stdcout << "testing polygon tiling\n"; + Polygon45Tiling pf; + std::vector polys; + std::vector data; + + data.push_back(Vertex45(Point(0, 0), 0, 1)); + data.push_back(Vertex45(Point(0, 0), 2, 1)); + data.push_back(Vertex45(Point(0, 100), 2, -1)); + data.push_back(Vertex45(Point(0, 100), 0, -1)); + data.push_back(Vertex45(Point(100, 0), 0, -1)); + data.push_back(Vertex45(Point(100, 0), 2, -1)); + data.push_back(Vertex45(Point(100, 100), 2, 1)); + data.push_back(Vertex45(Point(100, 100), 0, 1)); + + data.push_back(Vertex45(Point(2, 2), 0, -1)); + data.push_back(Vertex45(Point(2, 2), 2, -1)); + data.push_back(Vertex45(Point(2, 10), 2, 1)); + data.push_back(Vertex45(Point(2, 10), 0, 1)); + data.push_back(Vertex45(Point(10, 2), 0, 1)); + data.push_back(Vertex45(Point(10, 2), 2, 1)); + data.push_back(Vertex45(Point(10, 10), 2, -1)); + data.push_back(Vertex45(Point(10, 10), 0, -1)); + + data.push_back(Vertex45(Point(2, 12), 0, -1)); + data.push_back(Vertex45(Point(2, 12), 2, -1)); + data.push_back(Vertex45(Point(2, 22), 2, 1)); + data.push_back(Vertex45(Point(2, 22), 0, 1)); + data.push_back(Vertex45(Point(10, 12), 0, 1)); + data.push_back(Vertex45(Point(10, 12), 2, 1)); + data.push_back(Vertex45(Point(10, 22), 2, -1)); + data.push_back(Vertex45(Point(10, 22), 0, -1)); + + polygon_sort(data.begin(), data.end()); + pf.scan(polys, data.begin(), data.end()); + stdcout << "result size: " << polys.size() << "\n"; + for(std::size_t i = 0; i < polys.size(); ++i) { + stdcout << polys[i] << "\n"; + } + stdcout << "done testing polygon tiling\n"; + return true; + } + }; + + template + class PolyLine45HoleData { + public: + typedef typename polygon_45_formation::ActiveTail45 ActiveTail45; + typedef typename ActiveTail45::iterator iterator; + + typedef polygon_45_concept geometry_type; + typedef Unit coordinate_type; + typedef point_data Point; + typedef Point point_type; + // typedef iterator_points_to_compact compact_iterator_type; + typedef iterator iterator_type; + typedef typename coordinate_traits::area_type area_type; + + inline PolyLine45HoleData() : p_(0) {} + inline PolyLine45HoleData(ActiveTail45* p) : p_(p) {} + //use default copy and assign + inline iterator begin() const { return p_->getTail()->begin(); } + inline iterator end() const { return p_->getTail()->end(); } + inline std::size_t size() const { return 0; } + private: + ActiveTail45* p_; + }; + + template + class PolyLine45PolygonData { + public: + typedef typename polygon_45_formation::ActiveTail45 ActiveTail45; + typedef typename ActiveTail45::iterator iterator; + typedef PolyLine45HoleData holeType; + + typedef polygon_45_with_holes_concept geometry_type; + typedef Unit coordinate_type; + typedef point_data Point; + typedef Point point_type; + // typedef iterator_points_to_compact compact_iterator_type; + typedef iterator iterator_type; + typedef holeType hole_type; + typedef typename coordinate_traits::area_type area_type; + class iteratorHoles { + private: + typename ActiveTail45::iteratorHoles itr_; + public: + typedef PolyLine45HoleData holeType; + typedef holeType value_type; + typedef std::forward_iterator_tag iterator_category; + typedef std::ptrdiff_t difference_type; + typedef const value_type* pointer; //immutable + typedef const value_type& reference; //immutable + inline iteratorHoles() : itr_() {} + inline iteratorHoles(typename ActiveTail45::iteratorHoles itr) : itr_(itr) {} + inline iteratorHoles(const iteratorHoles& that) : itr_(that.itr_) {} + inline iteratorHoles& operator=(const iteratorHoles& that) { + itr_ = that.itr_; + return *this; + } + inline bool operator==(const iteratorHoles& that) { return itr_ == that.itr_; } + inline bool operator!=(const iteratorHoles& that) { return itr_ != that.itr_; } + inline iteratorHoles& operator++() { + ++itr_; + return *this; + } + inline const iteratorHoles operator++(int) { + iteratorHoles tmp = *this; + ++(*this); + return tmp; + } + inline holeType operator*() { + return *itr_; + } + }; + typedef iteratorHoles iterator_holes_type; + + + inline PolyLine45PolygonData() : p_(0) {} + inline PolyLine45PolygonData(ActiveTail45* p) : p_(p) {} + //use default copy and assign + inline iterator begin() const { return p_->getTail()->begin(); } + inline iterator end() const { return p_->getTail()->end(); } + inline iteratorHoles begin_holes() const { return iteratorHoles(p_->getHoles().begin()); } + inline iteratorHoles end_holes() const { return iteratorHoles(p_->getHoles().end()); } + inline ActiveTail45* yield() { return p_; } + //stub out these four required functions that will not be used but are needed for the interface + inline std::size_t size_holes() const { return 0; } + inline std::size_t size() const { return 0; } + private: + ActiveTail45* p_; + }; + + template + struct PolyLineByConcept { typedef PolyLine45PolygonData type; }; + template + struct PolyLineByConcept { typedef PolyLine45PolygonData type; }; + template + struct PolyLineByConcept { typedef PolyLine45HoleData type; }; + template + struct PolyLineByConcept { typedef PolyLine45HoleData type; }; + + template + struct geometry_concept > { typedef polygon_45_with_holes_concept type; }; + template + struct geometry_concept > { typedef polygon_45_concept type; }; + +} +} +#endif diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/detail/polygon_45_set_view.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/detail/polygon_45_set_view.hpp new file mode 100644 index 0000000..a0dc046 --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/detail/polygon_45_set_view.hpp @@ -0,0 +1,380 @@ +/* + Copyright 2008 Intel Corporation + + Use, modification and distribution are subject to the Boost Software License, + Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at + http://www.boost.org/LICENSE_1_0.txt). +*/ +#ifndef BOOST_POLYGON_POLYGON_45_SET_VIEW_HPP +#define BOOST_POLYGON_POLYGON_45_SET_VIEW_HPP +namespace boost { namespace polygon{ + + template + class polygon_45_set_view; + + template + struct polygon_45_set_traits > { + typedef typename polygon_45_set_view::coordinate_type coordinate_type; + typedef typename polygon_45_set_view::iterator_type iterator_type; + typedef typename polygon_45_set_view::operator_arg_type operator_arg_type; + + static inline iterator_type begin(const polygon_45_set_view& polygon_45_set); + static inline iterator_type end(const polygon_45_set_view& polygon_45_set); + + template + static inline void set(polygon_45_set_view& polygon_45_set, + input_iterator_type input_begin, input_iterator_type input_end); + + static inline bool clean(const polygon_45_set_view& polygon_45_set); + + }; + + template + struct compute_45_set_value { + static + void value(value_type& output_, const ltype& lvalue_, const rtype& rvalue_) { + output_.set(polygon_45_set_traits::begin(lvalue_), + polygon_45_set_traits::end(lvalue_)); + value_type rinput_; + rinput_.set(polygon_45_set_traits::begin(rvalue_), + polygon_45_set_traits::end(rvalue_)); +#ifdef BOOST_POLYGON_MSVC +#pragma warning (push) +#pragma warning (disable: 4127) +#endif + if(op_type == 0) + output_ |= rinput_; + else if(op_type == 1) + output_ &= rinput_; + else if(op_type == 2) + output_ ^= rinput_; + else + output_ -= rinput_; +#ifdef BOOST_POLYGON_MSVC +#pragma warning (pop) +#endif + } + }; + + template + struct compute_45_set_value, op_type> { + static + void value(value_type& output_, const ltype& lvalue_, const polygon_45_set_data& rvalue_) { + output_.set(polygon_45_set_traits::begin(lvalue_), + polygon_45_set_traits::end(lvalue_)); +#ifdef BOOST_POLYGON_MSVC +#pragma warning (push) +#pragma warning (disable: 4127) +#endif + if(op_type == 0) + output_ |= rvalue_; + else if(op_type == 1) + output_ &= rvalue_; + else if(op_type == 2) + output_ ^= rvalue_; + else + output_ -= rvalue_; +#ifdef BOOST_POLYGON_MSVC +#pragma warning (pop) +#endif + } + }; + + template + class polygon_45_set_view { + public: + typedef typename polygon_45_set_traits::coordinate_type coordinate_type; + typedef polygon_45_set_data value_type; + typedef typename value_type::iterator_type iterator_type; + typedef polygon_45_set_view operator_arg_type; + private: + const ltype& lvalue_; + const rtype& rvalue_; + mutable value_type output_; + mutable bool evaluated_; + + polygon_45_set_view& operator=(const polygon_45_set_view&); + public: + polygon_45_set_view(const ltype& lvalue, + const rtype& rvalue ) : + lvalue_(lvalue), rvalue_(rvalue), output_(), evaluated_(false) {} + + // get iterator to begin vertex data + public: + const value_type& value() const { + if(!evaluated_) { + evaluated_ = true; + compute_45_set_value::value(output_, lvalue_, rvalue_); + } + return output_; + } + public: + iterator_type begin() const { return value().begin(); } + iterator_type end() const { return value().end(); } + + bool dirty() const { return value().dirty(); } //result of a boolean is clean + bool sorted() const { return value().sorted(); } //result of a boolean is sorted + + // template + // void set(input_iterator_type input_begin, input_iterator_type input_end, + // orientation_2d orient) const { + // orient_ = orient; + // output_.clear(); + // output_.insert(output_.end(), input_begin, input_end); + // polygon_sort(output_.begin(), output_.end()); + // } + }; + + template + typename polygon_45_set_traits >::iterator_type + polygon_45_set_traits >:: + begin(const polygon_45_set_view& polygon_45_set) { + return polygon_45_set.begin(); + } + template + typename polygon_45_set_traits >::iterator_type + polygon_45_set_traits >:: + end(const polygon_45_set_view& polygon_45_set) { + return polygon_45_set.end(); + } + template + bool polygon_45_set_traits >:: + clean(const polygon_45_set_view& polygon_45_set) { + return polygon_45_set.value().clean(); } + + template + geometry_type_1& self_assignment_boolean_op_45(geometry_type_1& lvalue_, const geometry_type_2& rvalue_) { + typedef geometry_type_1 ltype; + typedef geometry_type_2 rtype; + typedef typename polygon_45_set_traits::coordinate_type coordinate_type; + typedef polygon_45_set_data value_type; + value_type output_; + value_type rinput_; + output_.set(polygon_45_set_traits::begin(lvalue_), + polygon_45_set_traits::end(lvalue_)); + rinput_.set(polygon_45_set_traits::begin(rvalue_), + polygon_45_set_traits::end(rvalue_)); +#ifdef BOOST_POLYGON_MSVC +#pragma warning (push) +#pragma warning (disable: 4127) +#endif + if(op_type == 0) + output_ |= rinput_; + else if(op_type == 1) + output_ &= rinput_; + else if(op_type == 2) + output_ ^= rinput_; + else + output_ -= rinput_; +#ifdef BOOST_POLYGON_MSVC +#pragma warning (pop) +#endif + polygon_45_set_mutable_traits::set(lvalue_, output_.begin(), output_.end()); + return lvalue_; + } + + template + struct fracture_holes_option_by_type { + static const bool value = true; + }; + template <> + struct fracture_holes_option_by_type { + static const bool value = false; + }; + template <> + struct fracture_holes_option_by_type { + static const bool value = false; + }; + + template + struct geometry_concept > { typedef polygon_45_set_concept type; }; + + namespace operators { + struct y_ps45_b : gtl_yes {}; + + template + typename enable_if< typename gtl_and_4< y_ps45_b, + typename is_polygon_45_or_90_set_type::type, + typename is_polygon_45_or_90_set_type::type, + typename is_either_polygon_45_set_type::type>::type, + polygon_45_set_view >::type + operator|(const geometry_type_1& lvalue, const geometry_type_2& rvalue) { + return polygon_45_set_view + (lvalue, rvalue); + } + + struct y_ps45_p : gtl_yes {}; + + template + typename enable_if< typename gtl_and_4< y_ps45_p, + typename gtl_if::type>::type, + typename gtl_if::type>::type, + typename gtl_if::type>::type>::type, + polygon_45_set_view >::type + operator+(const geometry_type_1& lvalue, const geometry_type_2& rvalue) { + return polygon_45_set_view + (lvalue, rvalue); + } + + struct y_ps45_s : gtl_yes {}; + + template + typename enable_if< typename gtl_and_4< y_ps45_s, typename is_polygon_45_or_90_set_type::type, + typename is_polygon_45_or_90_set_type::type, + typename is_either_polygon_45_set_type::type>::type, + polygon_45_set_view >::type + operator*(const geometry_type_1& lvalue, const geometry_type_2& rvalue) { + return polygon_45_set_view + (lvalue, rvalue); + } + + struct y_ps45_a : gtl_yes {}; + + template + typename enable_if< typename gtl_and_4< y_ps45_a, typename is_polygon_45_or_90_set_type::type, + typename is_polygon_45_or_90_set_type::type, + typename is_either_polygon_45_set_type::type>::type, + polygon_45_set_view >::type + operator&(const geometry_type_1& lvalue, const geometry_type_2& rvalue) { + return polygon_45_set_view + (lvalue, rvalue); + } + + struct y_ps45_x : gtl_yes {}; + + template + typename enable_if< typename gtl_and_4< y_ps45_x, typename is_polygon_45_or_90_set_type::type, + typename is_polygon_45_or_90_set_type::type, + typename is_either_polygon_45_set_type::type>::type, + polygon_45_set_view >::type + operator^(const geometry_type_1& lvalue, const geometry_type_2& rvalue) { + return polygon_45_set_view + (lvalue, rvalue); + } + + struct y_ps45_m : gtl_yes {}; + + template + typename enable_if< typename gtl_and_4< y_ps45_m, + typename gtl_if::type>::type, + typename gtl_if::type>::type, + typename gtl_if::type>::type>::type, + polygon_45_set_view >::type + operator-(const geometry_type_1& lvalue, const geometry_type_2& rvalue) { + return polygon_45_set_view + (lvalue, rvalue); + } + + struct y_ps45_pe : gtl_yes {}; + + template + typename enable_if< typename gtl_and_4::type, gtl_yes, + typename is_polygon_45_or_90_set_type::type>::type, + geometry_type_1>::type & + operator+=(geometry_type_1& lvalue, const geometry_type_2& rvalue) { + return self_assignment_boolean_op_45(lvalue, rvalue); + } + + struct y_ps45_be : gtl_yes {}; + + template + typename enable_if< typename gtl_and_3::type, + typename is_polygon_45_or_90_set_type::type>::type, + geometry_type_1>::type & + operator|=(geometry_type_1& lvalue, const geometry_type_2& rvalue) { + return self_assignment_boolean_op_45(lvalue, rvalue); + } + + struct y_ps45_se : gtl_yes {}; + + template + typename enable_if< typename gtl_and_3< y_ps45_se, + typename is_mutable_polygon_45_set_type::type, + typename is_polygon_45_or_90_set_type::type>::type, + geometry_type_1>::type & + operator*=(geometry_type_1& lvalue, const geometry_type_2& rvalue) { + return self_assignment_boolean_op_45(lvalue, rvalue); + } + + struct y_ps45_ae : gtl_yes {}; + + template + typename enable_if< typename gtl_and_3::type, + typename is_polygon_45_or_90_set_type::type>::type, + geometry_type_1>::type & + operator&=(geometry_type_1& lvalue, const geometry_type_2& rvalue) { + return self_assignment_boolean_op_45(lvalue, rvalue); + } + + struct y_ps45_xe : gtl_yes {}; + + template + typename enable_if< + typename gtl_and_3::type, + typename is_polygon_45_or_90_set_type::type>::type, + geometry_type_1>::type & + operator^=(geometry_type_1& lvalue, const geometry_type_2& rvalue) { + return self_assignment_boolean_op_45(lvalue, rvalue); + } + + struct y_ps45_me : gtl_yes {}; + + template + typename enable_if< typename gtl_and_3::type, + typename is_polygon_45_or_90_set_type::type>::type, + geometry_type_1>::type & + operator-=(geometry_type_1& lvalue, const geometry_type_2& rvalue) { + return self_assignment_boolean_op_45(lvalue, rvalue); + } + + struct y_ps45_rpe : gtl_yes {}; + + template + typename enable_if< typename gtl_and_3< y_ps45_rpe, typename is_mutable_polygon_45_set_type::type, + typename gtl_same_type::type, + coordinate_concept>::type>::type, + geometry_type_1>::type & + operator+=(geometry_type_1& lvalue, coordinate_type_1 rvalue) { + return resize(lvalue, rvalue); + } + + struct y_ps45_rme : gtl_yes {}; + + template + typename enable_if< typename gtl_and_3::type>::type, + typename gtl_same_type::type, + coordinate_concept>::type>::type, + geometry_type_1>::type & + operator-=(geometry_type_1& lvalue, coordinate_type_1 rvalue) { + return resize(lvalue, -rvalue); + } + + struct y_ps45_rp : gtl_yes {}; + + template + typename enable_if< typename gtl_and_3::type>::type, + typename gtl_same_type::type, + coordinate_concept>::type> + ::type, geometry_type_1>::type + operator+(const geometry_type_1& lvalue, coordinate_type_1 rvalue) { + geometry_type_1 retval(lvalue); + retval += rvalue; + return retval; + } + + struct y_ps45_rm : gtl_yes {}; + + template + typename enable_if< typename gtl_and_3::type>::type, + typename gtl_same_type::type, + coordinate_concept>::type> + ::type, geometry_type_1>::type + operator-(const geometry_type_1& lvalue, coordinate_type_1 rvalue) { + geometry_type_1 retval(lvalue); + retval -= rvalue; + return retval; + } + } +} +} +#endif diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/detail/polygon_45_touch.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/detail/polygon_45_touch.hpp new file mode 100644 index 0000000..90717e1 --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/detail/polygon_45_touch.hpp @@ -0,0 +1,238 @@ +/* + Copyright 2008 Intel Corporation + + Use, modification and distribution are subject to the Boost Software License, + Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at + http://www.boost.org/LICENSE_1_0.txt). +*/ +#ifndef BOOST_POLYGON_POLYGON_45_TOUCH_HPP +#define BOOST_POLYGON_POLYGON_45_TOUCH_HPP +namespace boost { namespace polygon{ + + template + struct polygon_45_touch { + + typedef point_data Point; + typedef typename coordinate_traits::manhattan_area_type LongUnit; + + template + static inline void merge_property_maps(property_map& mp, const property_map& mp2, bool subtract = false) { + property_map newmp; + newmp.reserve(mp.size() + mp2.size()); + std::size_t i = 0; + std::size_t j = 0; + while(i != mp.size() && j != mp2.size()) { + if(mp[i].first < mp2[j].first) { + newmp.push_back(mp[i]); + ++i; + } else if(mp[i].first > mp2[j].first) { + newmp.push_back(mp2[j]); + if(subtract) newmp.back().second *= -1; + ++j; + } else { + int count = mp[i].second; + if(subtract) count -= mp2[j].second; + else count += mp2[j].second; + if(count) { + newmp.push_back(mp[i]); + newmp.back().second = count; + } + ++i; + ++j; + } + } + while(i != mp.size()) { + newmp.push_back(mp[i]); + ++i; + } + while(j != mp2.size()) { + newmp.push_back(mp2[j]); + if(subtract) newmp.back().second *= -1; + ++j; + } + mp.swap(newmp); + } + + class CountTouch { + public: + inline CountTouch() : counts() {} + //inline CountTouch(int count) { counts[0] = counts[1] = count; } + //inline CountTouch(int count1, int count2) { counts[0] = count1; counts[1] = count2; } + inline CountTouch(const CountTouch& count) : counts(count.counts) {} + inline bool operator==(const CountTouch& count) const { return counts == count.counts; } + inline bool operator!=(const CountTouch& count) const { return !((*this) == count); } + //inline CountTouch& operator=(int count) { counts[0] = counts[1] = count; return *this; } + inline CountTouch& operator=(const CountTouch& count) { counts = count.counts; return *this; } + inline int& operator[](int index) { + std::vector >::iterator itr = + std::lower_bound(counts.begin(), counts.end(), + std::make_pair(index, int(0))); + if(itr != counts.end() && itr->first == index) { + return itr->second; + } + itr = counts.insert(itr, std::make_pair(index, int(0))); + return itr->second; + } +// inline int operator[](int index) const { +// std::vector >::const_iterator itr = counts.begin(); +// for( ; itr != counts.end() && itr->first <= index; ++itr) { +// if(itr->first == index) { +// return itr->second; +// } +// } +// return 0; +// } + inline CountTouch& operator+=(const CountTouch& count){ + merge_property_maps(counts, count.counts, false); + return *this; + } + inline CountTouch& operator-=(const CountTouch& count){ + merge_property_maps(counts, count.counts, true); + return *this; + } + inline CountTouch operator+(const CountTouch& count) const { + return CountTouch(*this)+=count; + } + inline CountTouch operator-(const CountTouch& count) const { + return CountTouch(*this)-=count; + } + inline CountTouch invert() const { + CountTouch retval; + retval -= *this; + return retval; + } + std::vector > counts; + }; + + typedef std::pair > >, std::map > > map_graph_o; + typedef std::pair > >, std::vector > > vector_graph_o; + + template + static void process_previous_x(cT& output) { + std::map >& y_prop_map = output.first.second; + for(typename std::map >::iterator itr = y_prop_map.begin(); + itr != y_prop_map.end(); ++itr) { + for(std::set::iterator inner_itr = itr->second.begin(); + inner_itr != itr->second.end(); ++inner_itr) { + std::set& output_edges = (*(output.second))[*inner_itr]; + std::set::iterator inner_inner_itr = inner_itr; + ++inner_inner_itr; + for( ; inner_inner_itr != itr->second.end(); ++inner_inner_itr) { + output_edges.insert(output_edges.end(), *inner_inner_itr); + std::set& output_edges_2 = (*(output.second))[*inner_inner_itr]; + output_edges_2.insert(output_edges_2.end(), *inner_itr); + } + } + } + y_prop_map.clear(); + } + + struct touch_45_output_functor { + template + void operator()(cT& output, const CountTouch& count1, const CountTouch& count2, + const Point& pt, int , direction_1d ) { + Unit& x = output.first.first; + std::map >& y_prop_map = output.first.second; + if(pt.x() != x) process_previous_x(output); + x = pt.x(); + std::set& output_set = y_prop_map[pt.y()]; + for(std::vector >::const_iterator itr1 = count1.counts.begin(); + itr1 != count1.counts.end(); ++itr1) { + if(itr1->second > 0) { + output_set.insert(output_set.end(), itr1->first); + } + } + for(std::vector >::const_iterator itr2 = count2.counts.begin(); + itr2 != count2.counts.end(); ++itr2) { + if(itr2->second > 0) { + output_set.insert(output_set.end(), itr2->first); + } + } + } + }; + typedef typename std::pair::template Scan45CountT > Vertex45Compact; + typedef std::vector TouchSetData; + + struct lessVertex45Compact { + bool operator()(const Vertex45Compact& l, const Vertex45Compact& r) { + return l.first < r.first; + } + }; + +// template +// static void print_tsd(TSD& tsd) { +// for(std::size_t i = 0; i < tsd.size(); ++i) { +// std::cout << tsd[i].first << ": "; +// for(unsigned int r = 0; r < 4; ++r) { +// std::cout << r << " { "; +// for(std::vector >::iterator itr = tsd[i].second[r].counts.begin(); +// itr != tsd[i].second[r].counts.end(); ++itr) { +// std::cout << itr->first << "," << itr->second << " "; +// } std::cout << "} "; +// } +// } std::cout << std::endl; +// } + +// template +// static void print_scanline(T& t) { +// for(typename T::iterator itr = t.begin(); itr != t.end(); ++itr) { +// std::cout << itr->x << "," << itr->y << " " << itr->rise << " "; +// for(std::vector >::iterator itr2 = itr->count.counts.begin(); +// itr2 != itr->count.counts.end(); ++itr2) { +// std::cout << itr2->first << ":" << itr2->second << " "; +// } std::cout << std::endl; +// } +// } + + template + static void performTouch(graph_type& graph, TouchSetData& tsd) { + + polygon_sort(tsd.begin(), tsd.end(), lessVertex45Compact()); + typedef std::vector::template Scan45CountT > > TSD; + TSD tsd_; + tsd_.reserve(tsd.size()); + for(typename TouchSetData::iterator itr = tsd.begin(); itr != tsd.end(); ) { + typename TouchSetData::iterator itr2 = itr; + ++itr2; + for(; itr2 != tsd.end() && itr2->first == itr->first; ++itr2) { + (itr->second) += (itr2->second); //accumulate + } + tsd_.push_back(std::make_pair(itr->first, itr->second)); + itr = itr2; + } + std::pair > >, graph_type*> output + (std::make_pair(std::make_pair((std::numeric_limits::max)(), std::map >()), &graph)); + typename boolean_op_45::template Scan45 scanline; + for(typename TSD::iterator itr = tsd_.begin(); itr != tsd_.end(); ) { + typename TSD::iterator itr2 = itr; + ++itr2; + while(itr2 != tsd_.end() && itr2->first.x() == itr->first.x()) { + ++itr2; + } + scanline.scan(output, itr, itr2); + itr = itr2; + } + process_previous_x(output); + } + + template + static void populateTouchSetData(TouchSetData& tsd, iT begin, iT end, int nodeCount) { + for( ; begin != end; ++begin) { + Vertex45Compact vertex; + vertex.first = typename Vertex45Compact::first_type(begin->pt.x() * 2, begin->pt.y() * 2); + tsd.push_back(vertex); + for(unsigned int i = 0; i < 4; ++i) { + if(begin->count[i]) { + tsd.back().second[i][nodeCount] += begin->count[i]; + } + } + } + } + + }; + + +} +} +#endif diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/detail/polygon_90_set_view.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/detail/polygon_90_set_view.hpp new file mode 100644 index 0000000..7e93b03 --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/detail/polygon_90_set_view.hpp @@ -0,0 +1,490 @@ +/* + Copyright 2008 Intel Corporation + + Use, modification and distribution are subject to the Boost Software License, + Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at + http://www.boost.org/LICENSE_1_0.txt). +*/ +#ifndef BOOST_POLYGON_POLYGON_90_SET_VIEW_HPP +#define BOOST_POLYGON_POLYGON_90_SET_VIEW_HPP +namespace boost { namespace polygon{ + struct operator_provides_storage {}; + struct operator_requires_copy {}; + + template + inline void insert_into_view_arg(value_type& dest, const arg_type& arg, orientation_2d orient); + + template + class polygon_90_set_view; + + template + struct polygon_90_set_traits > { + typedef typename polygon_90_set_view::coordinate_type coordinate_type; + typedef typename polygon_90_set_view::iterator_type iterator_type; + typedef typename polygon_90_set_view::operator_arg_type operator_arg_type; + + static inline iterator_type begin(const polygon_90_set_view& polygon_set); + static inline iterator_type end(const polygon_90_set_view& polygon_set); + + static inline orientation_2d orient(const polygon_90_set_view& polygon_set); + + static inline bool clean(const polygon_90_set_view& polygon_set); + + static inline bool sorted(const polygon_90_set_view& polygon_set); + }; + + template + struct compute_90_set_value { + static + void value(value_type& output_, const ltype& lvalue_, const rtype& rvalue_, orientation_2d orient_) { + value_type linput_(orient_); + value_type rinput_(orient_); + orientation_2d orient_l = polygon_90_set_traits::orient(lvalue_); + orientation_2d orient_r = polygon_90_set_traits::orient(rvalue_); + //std::cout << "compute_90_set_value-0 orientations (left, right, out):\t" << orient_l.to_int() + // << "," << orient_r.to_int() << "," << orient_.to_int() << std::endl; + insert_into_view_arg(linput_, lvalue_, orient_l); + insert_into_view_arg(rinput_, rvalue_, orient_r); + output_.applyBooleanBinaryOp(linput_.begin(), linput_.end(), + rinput_.begin(), rinput_.end(), boolean_op::BinaryCount()); + } + }; + + template + struct compute_90_set_value, polygon_90_set_data, op_type> { + static + void value(value_type& output_, const polygon_90_set_data& lvalue_, + const polygon_90_set_data& rvalue_, orientation_2d orient_) { + orientation_2d orient_l = lvalue_.orient(); + orientation_2d orient_r = rvalue_.orient(); + value_type linput_(orient_); + value_type rinput_(orient_); + //std::cout << "compute_90_set_value-1 orientations (left, right, out):\t" << orient_l.to_int() + // << "," << orient_r.to_int() << "," << orient_.to_int() << std::endl; + if((orient_ == orient_l) && (orient_== orient_r)){ // assume that most of the time this condition is met + lvalue_.sort(); + rvalue_.sort(); + output_.applyBooleanBinaryOp(lvalue_.begin(), lvalue_.end(), + rvalue_.begin(), rvalue_.end(), boolean_op::BinaryCount()); + }else if((orient_ != orient_l) && (orient_!= orient_r)){ // both the orientations are not equal to input + // easier way is to ignore the input orientation and use the input data's orientation, but not done so + insert_into_view_arg(linput_, lvalue_, orient_l); + insert_into_view_arg(rinput_, rvalue_, orient_r); + output_.applyBooleanBinaryOp(linput_.begin(), linput_.end(), + rinput_.begin(), rinput_.end(), boolean_op::BinaryCount()); + }else if(orient_ != orient_l){ // left hand side orientation is different + insert_into_view_arg(linput_, lvalue_, orient_l); + rvalue_.sort(); + output_.applyBooleanBinaryOp(linput_.begin(), linput_.end(), + rvalue_.begin(), rvalue_.end(), boolean_op::BinaryCount()); + } else if(orient_ != orient_r){ // right hand side orientation is different + insert_into_view_arg(rinput_, rvalue_, orient_r); + lvalue_.sort(); + output_.applyBooleanBinaryOp(lvalue_.begin(), lvalue_.end(), + rinput_.begin(), rinput_.end(), boolean_op::BinaryCount()); + } + } + }; + + template + struct compute_90_set_value, rtype, op_type> { + static + void value(value_type& output_, const polygon_90_set_data& lvalue_, + const rtype& rvalue_, orientation_2d orient_) { + value_type rinput_(orient_); + lvalue_.sort(); + orientation_2d orient_r = polygon_90_set_traits::orient(rvalue_); + //std::cout << "compute_90_set_value-2 orientations (right, out):\t" << orient_r.to_int() + // << "," << orient_.to_int() << std::endl; + insert_into_view_arg(rinput_, rvalue_, orient_r); + output_.applyBooleanBinaryOp(lvalue_.begin(), lvalue_.end(), + rinput_.begin(), rinput_.end(), boolean_op::BinaryCount()); + } + }; + + template + struct compute_90_set_value, op_type> { + static + void value(value_type& output_, const ltype& lvalue_, + const polygon_90_set_data& rvalue_, orientation_2d orient_) { + value_type linput_(orient_); + orientation_2d orient_l = polygon_90_set_traits::orient(lvalue_); + insert_into_view_arg(linput_, lvalue_, orient_l); + rvalue_.sort(); + //std::cout << "compute_90_set_value-3 orientations (left, out):\t" << orient_l.to_int() + // << "," << orient_.to_int() << std::endl; + + output_.applyBooleanBinaryOp(linput_.begin(), linput_.end(), + rvalue_.begin(), rvalue_.end(), boolean_op::BinaryCount()); + } + }; + + template + class polygon_90_set_view { + public: + typedef typename polygon_90_set_traits::coordinate_type coordinate_type; + typedef polygon_90_set_data value_type; + typedef typename value_type::iterator_type iterator_type; + typedef polygon_90_set_view operator_arg_type; + private: + const ltype& lvalue_; + const rtype& rvalue_; + orientation_2d orient_; + op_type op_; + mutable value_type output_; + mutable bool evaluated_; + polygon_90_set_view& operator=(const polygon_90_set_view&); + public: + polygon_90_set_view(const ltype& lvalue, + const rtype& rvalue, + orientation_2d orient, + op_type op) : + lvalue_(lvalue), rvalue_(rvalue), orient_(orient), op_(op), output_(orient), evaluated_(false) {} + + // get iterator to begin vertex data + private: + const value_type& value() const { + if(!evaluated_) { + evaluated_ = true; + compute_90_set_value::value(output_, lvalue_, rvalue_, orient_); + } + return output_; + } + public: + iterator_type begin() const { return value().begin(); } + iterator_type end() const { return value().end(); } + + orientation_2d orient() const { return orient_; } + bool dirty() const { return false; } //result of a boolean is clean + bool sorted() const { return true; } //result of a boolean is sorted + +// template +// void set(input_iterator_type input_begin, input_iterator_type input_end, +// orientation_2d orient) const { +// orient_ = orient; +// output_.clear(); +// output_.insert(output_.end(), input_begin, input_end); +// polygon_sort(output_.begin(), output_.end()); +// } + void sort() const {} //is always sorted + }; + + template + struct geometry_concept > { + typedef polygon_90_set_concept type; + }; + + template + typename polygon_90_set_traits >::iterator_type + polygon_90_set_traits >:: + begin(const polygon_90_set_view& polygon_set) { + return polygon_set.begin(); + } + template + typename polygon_90_set_traits >::iterator_type + polygon_90_set_traits >:: + end(const polygon_90_set_view& polygon_set) { + return polygon_set.end(); + } +// template +// template +// void polygon_90_set_traits >:: +// set(polygon_90_set_view& polygon_set, +// input_iterator_type input_begin, input_iterator_type input_end, +// orientation_2d orient) { +// polygon_set.set(input_begin, input_end, orient); +// } + template + orientation_2d polygon_90_set_traits >:: + orient(const polygon_90_set_view& polygon_set) { + return polygon_set.orient(); } + template + bool polygon_90_set_traits >:: + clean(const polygon_90_set_view& polygon_set) { + return !polygon_set.dirty(); } + template + bool polygon_90_set_traits >:: + sorted(const polygon_90_set_view& polygon_set) { + return polygon_set.sorted(); } + + template + inline void insert_into_view_arg(value_type& dest, const arg_type& arg, orientation_2d orient) { + typedef typename polygon_90_set_traits::iterator_type literator; + literator itr1, itr2; + itr1 = polygon_90_set_traits::begin(arg); + itr2 = polygon_90_set_traits::end(arg); + dest.insert(itr1, itr2, orient); + dest.sort(); + } + + template + template + inline polygon_90_set_data& polygon_90_set_data::operator=(const polygon_90_set_view& that) { + set(that.begin(), that.end(), that.orient()); + dirty_ = false; + unsorted_ = false; + return *this; + } + + template + template + inline polygon_90_set_data::polygon_90_set_data(const polygon_90_set_view& that) : + orient_(that.orient()), data_(that.begin(), that.end()), dirty_(false), unsorted_(false) {} + + template + struct self_assign_operator_lvalue { + typedef geometry_type_1& type; + }; + + template + struct by_value_binary_operator { + typedef type_1 type; + }; + + template + geometry_type_1& self_assignment_boolean_op(geometry_type_1& lvalue_, const geometry_type_2& rvalue_) { + typedef geometry_type_1 ltype; + typedef geometry_type_2 rtype; + typedef typename polygon_90_set_traits::coordinate_type coordinate_type; + typedef polygon_90_set_data value_type; + orientation_2d orient_ = polygon_90_set_traits::orient(lvalue_); + //BM: rvalue_ data set may have its own orientation for scanline + orientation_2d orient_r = polygon_90_set_traits::orient(rvalue_); + //std::cout << "self-assignment boolean-op (left, right, out):\t" << orient_.to_int() + // << "," << orient_r.to_int() << "," << orient_.to_int() << std::endl; + value_type linput_(orient_); + // BM: the rinput_ set's (that stores the rvalue_ dataset polygons) scanline orientation is *forced* + // to be same as linput + value_type rinput_(orient_); + //BM: The output dataset's scanline orient is set as equal to first input dataset's (lvalue_) orientation + value_type output_(orient_); + insert_into_view_arg(linput_, lvalue_, orient_); + // BM: The last argument orient_r is the user initialized scanline orientation for rvalue_ data set. + // But since rinput (see above) is initialized to scanline orientation consistent with the lvalue_ + // data set, this insertion operation will change the incoming rvalue_ dataset's scanline orientation + insert_into_view_arg(rinput_, rvalue_, orient_r); + // BM: boolean operation and output uses lvalue_ dataset's scanline orientation. + output_.applyBooleanBinaryOp(linput_.begin(), linput_.end(), + rinput_.begin(), rinput_.end(), boolean_op::BinaryCount()); + polygon_90_set_mutable_traits::set(lvalue_, output_.begin(), output_.end(), orient_); + return lvalue_; + } + + namespace operators { + struct y_ps90_b : gtl_yes {}; + + template + typename enable_if< typename gtl_and_3< y_ps90_b, + typename is_polygon_90_set_type::type, + typename is_polygon_90_set_type::type>::type, + polygon_90_set_view >::type + operator|(const geometry_type_1& lvalue, const geometry_type_2& rvalue) { + return polygon_90_set_view + (lvalue, rvalue, + polygon_90_set_traits::orient(lvalue), + boolean_op::BinaryOr()); + } + + struct y_ps90_p : gtl_yes {}; + + template + typename enable_if< + typename gtl_and_3< y_ps90_p, + typename gtl_if::type>::type, + typename gtl_if::type>::type>::type, + polygon_90_set_view >::type + operator+(const geometry_type_1& lvalue, const geometry_type_2& rvalue) { + return polygon_90_set_view + (lvalue, rvalue, + polygon_90_set_traits::orient(lvalue), + boolean_op::BinaryOr()); + } + + struct y_ps90_s : gtl_yes {}; + + template + typename enable_if< typename gtl_and_3< y_ps90_s, + typename is_polygon_90_set_type::type, + typename is_polygon_90_set_type::type>::type, + polygon_90_set_view >::type + operator*(const geometry_type_1& lvalue, const geometry_type_2& rvalue) { + return polygon_90_set_view + (lvalue, rvalue, + polygon_90_set_traits::orient(lvalue), + boolean_op::BinaryAnd()); + } + + struct y_ps90_a : gtl_yes {}; + + template + typename enable_if< typename gtl_and_3< y_ps90_a, + typename is_polygon_90_set_type::type, + typename is_polygon_90_set_type::type>::type, + polygon_90_set_view >::type + operator&(const geometry_type_1& lvalue, const geometry_type_2& rvalue) { + return polygon_90_set_view + (lvalue, rvalue, + polygon_90_set_traits::orient(lvalue), + boolean_op::BinaryAnd()); + } + + struct y_ps90_x : gtl_yes {}; + + template + typename enable_if< typename gtl_and_3< y_ps90_x, + typename is_polygon_90_set_type::type, + typename is_polygon_90_set_type::type>::type, + polygon_90_set_view >::type + operator^(const geometry_type_1& lvalue, const geometry_type_2& rvalue) { + return polygon_90_set_view + (lvalue, rvalue, + polygon_90_set_traits::orient(lvalue), + boolean_op::BinaryXor()); + } + + struct y_ps90_m : gtl_yes {}; + + template + typename enable_if< typename gtl_and_3< y_ps90_m, + typename gtl_if::type>::type, + typename gtl_if::type>::type>::type, + polygon_90_set_view >::type + operator-(const geometry_type_1& lvalue, const geometry_type_2& rvalue) { + return polygon_90_set_view + (lvalue, rvalue, + polygon_90_set_traits::orient(lvalue), + boolean_op::BinaryNot()); + } + + struct y_ps90_pe : gtl_yes {}; + + template + typename enable_if< typename gtl_and< y_ps90_pe, typename is_polygon_90_set_type::type>::type, + polygon_90_set_data >::type & + operator+=(polygon_90_set_data& lvalue, const geometry_type_2& rvalue) { + lvalue.insert(polygon_90_set_traits::begin(rvalue), polygon_90_set_traits::end(rvalue), + polygon_90_set_traits::orient(rvalue)); + return lvalue; + } + + struct y_ps90_be : gtl_yes {}; + // + template + typename enable_if< typename gtl_and< y_ps90_be, typename is_polygon_90_set_type::type>::type, + polygon_90_set_data >::type & + operator|=(polygon_90_set_data& lvalue, const geometry_type_2& rvalue) { + return lvalue += rvalue; + } + + struct y_ps90_pe2 : gtl_yes {}; + + //normal self assignment boolean operations + template + typename enable_if< typename gtl_and_3< y_ps90_pe2, typename is_mutable_polygon_90_set_type::type, + typename is_polygon_90_set_type::type>::type, + geometry_type_1>::type & + operator+=(geometry_type_1& lvalue, const geometry_type_2& rvalue) { + return self_assignment_boolean_op(lvalue, rvalue); + } + + struct y_ps90_be2 : gtl_yes {}; + + template + typename enable_if< typename gtl_and_3::type, + typename is_polygon_90_set_type::type>::type, + geometry_type_1>::type & + operator|=(geometry_type_1& lvalue, const geometry_type_2& rvalue) { + return self_assignment_boolean_op(lvalue, rvalue); + } + + struct y_ps90_se : gtl_yes {}; + + template + typename enable_if< typename gtl_and_3::type, + typename is_polygon_90_set_type::type>::type, + geometry_type_1>::type & + operator*=(geometry_type_1& lvalue, const geometry_type_2& rvalue) { + return self_assignment_boolean_op(lvalue, rvalue); + } + + struct y_ps90_ae : gtl_yes {}; + + template + typename enable_if< typename gtl_and_3::type, + typename is_polygon_90_set_type::type>::type, + geometry_type_1>::type & + operator&=(geometry_type_1& lvalue, const geometry_type_2& rvalue) { + return self_assignment_boolean_op(lvalue, rvalue); + } + + struct y_ps90_xe : gtl_yes {}; + + template + typename enable_if< typename gtl_and_3::type, + typename is_polygon_90_set_type::type>::type, + geometry_type_1>::type & + operator^=(geometry_type_1& lvalue, const geometry_type_2& rvalue) { + return self_assignment_boolean_op(lvalue, rvalue); + } + + struct y_ps90_me : gtl_yes {}; + + template + typename enable_if< typename gtl_and_3< y_ps90_me, typename is_mutable_polygon_90_set_type::type, + typename is_polygon_90_set_type::type>::type, + geometry_type_1>::type & + operator-=(geometry_type_1& lvalue, const geometry_type_2& rvalue) { + return self_assignment_boolean_op(lvalue, rvalue); + } + + struct y_ps90_rpe : gtl_yes {}; + + template + typename enable_if< typename gtl_and_3::type, + typename gtl_same_type::type, coordinate_concept>::type>::type, + geometry_type_1>::type & + operator+=(geometry_type_1& lvalue, coordinate_type_1 rvalue) { + return resize(lvalue, rvalue); + } + + struct y_ps90_rme : gtl_yes {}; + + template + typename enable_if< typename gtl_and_3::type, + typename gtl_same_type::type, coordinate_concept>::type>::type, + geometry_type_1>::type & + operator-=(geometry_type_1& lvalue, coordinate_type_1 rvalue) { + return resize(lvalue, -rvalue); + } + + struct y_ps90_rp : gtl_yes {}; + + template + typename enable_if< typename gtl_and_3::type>::type, + typename gtl_if::type, coordinate_concept>::type>::type>::type, + geometry_type_1>::type + operator+(const geometry_type_1& lvalue, coordinate_type_1 rvalue) { + geometry_type_1 retval(lvalue); + retval += rvalue; + return retval; + } + + struct y_ps90_rm : gtl_yes {}; + + template + typename enable_if< typename gtl_and_3::type>::type, + typename gtl_if::type, coordinate_concept>::type>::type>::type, + geometry_type_1>::type + operator-(const geometry_type_1& lvalue, coordinate_type_1 rvalue) { + geometry_type_1 retval(lvalue); + retval -= rvalue; + return retval; + } + } +} +} +#endif diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/detail/polygon_90_touch.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/detail/polygon_90_touch.hpp new file mode 100644 index 0000000..77a516b --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/detail/polygon_90_touch.hpp @@ -0,0 +1,418 @@ +/* + Copyright 2008 Intel Corporation + + Use, modification and distribution are subject to the Boost Software License, + Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at + http://www.boost.org/LICENSE_1_0.txt). +*/ +#ifndef BOOST_POLYGON_POLYGON_90_TOUCH_HPP +#define BOOST_POLYGON_POLYGON_90_TOUCH_HPP +namespace boost { namespace polygon{ + + template + struct touch_90_operation { + typedef interval_data Interval; + + class TouchScanEvent { + private: + typedef std::map > EventData; + EventData eventData_; + public: + + // The TouchScanEvent::iterator is a lazy algorithm that accumulates + // polygon ids in a set as it is incremented through the + // scan event data structure. + // The iterator provides a forward iterator semantic only. + class iterator { + private: + typename EventData::const_iterator itr_; + std::pair > ivlIds_; + bool incremented_; + public: + inline iterator() : itr_(), ivlIds_(), incremented_(false) {} + inline iterator(typename EventData::const_iterator itr, + Unit prevPos, Unit curPos, const std::set& ivlIds) : itr_(itr), ivlIds_(), incremented_(false) { + ivlIds_.second = ivlIds; + ivlIds_.first = Interval(prevPos, curPos); + } + inline iterator(const iterator& that) : itr_(), ivlIds_(), incremented_(false) { (*this) = that; } + inline iterator& operator=(const iterator& that) { + itr_ = that.itr_; + ivlIds_.first = that.ivlIds_.first; + ivlIds_.second = that.ivlIds_.second; + incremented_ = that.incremented_; + return *this; + } + inline bool operator==(const iterator& that) { return itr_ == that.itr_; } + inline bool operator!=(const iterator& that) { return itr_ != that.itr_; } + inline iterator& operator++() { + //std::cout << "increment\n"; + //std::cout << "state\n"; + //for(std::set::iterator itr = ivlIds_.second.begin(); itr != ivlIds_.second.end(); ++itr) { + // std::cout << (*itr) << " "; + //} std::cout << std::endl; + //std::cout << "update\n"; + for(std::set::const_iterator itr = (*itr_).second.begin(); + itr != (*itr_).second.end(); ++itr) { + //std::cout << (*itr) << " "; + std::set::iterator lb = ivlIds_.second.find(*itr); + if(lb != ivlIds_.second.end()) { + ivlIds_.second.erase(lb); + } else { + ivlIds_.second.insert(*itr); + } + } + //std::cout << std::endl; + //std::cout << "new state\n"; + //for(std::set::iterator itr = ivlIds_.second.begin(); itr != ivlIds_.second.end(); ++itr) { + // std::cout << (*itr) << " "; + //} std::cout << std::endl; + ++itr_; + //ivlIds_.first = Interval(ivlIds_.first.get(HIGH), itr_->first); + incremented_ = true; + return *this; + } + inline const iterator operator++(int){ + iterator tmpItr(*this); + ++(*this); + return tmpItr; + } + inline std::pair >& operator*() { + if(incremented_) ivlIds_.first = Interval(ivlIds_.first.get(HIGH), itr_->first); + incremented_ = false; + if(ivlIds_.second.empty())(++(*this)); + if(incremented_) ivlIds_.first = Interval(ivlIds_.first.get(HIGH), itr_->first); + incremented_ = false; + return ivlIds_; } + }; + + inline TouchScanEvent() : eventData_() {} + template + inline TouchScanEvent(iT begin, iT end) : eventData_() { + for( ; begin != end; ++begin){ + insert(*begin); + } + } + inline TouchScanEvent(const TouchScanEvent& that) : eventData_(that.eventData_) {} + inline TouchScanEvent& operator=(const TouchScanEvent& that){ + eventData_ = that.eventData_; + return *this; + } + + //Insert an interval polygon id into the EventData + inline void insert(const std::pair& intervalId){ + insert(intervalId.first.low(), intervalId.second); + insert(intervalId.first.high(), intervalId.second); + } + + //Insert an position and polygon id into EventData + inline void insert(Unit pos, int id) { + typename EventData::iterator lb = eventData_.lower_bound(pos); + if(lb != eventData_.end() && lb->first == pos) { + std::set& mr (lb->second); + std::set::iterator mri = mr.find(id); + if(mri == mr.end()) { + mr.insert(id); + } else { + mr.erase(id); + } + } else { + lb = eventData_.insert(lb, std::pair >(pos, std::set())); + (*lb).second.insert(id); + } + } + + //merge this scan event with that by inserting its data + inline void insert(const TouchScanEvent& that){ + typename EventData::const_iterator itr; + for(itr = that.eventData_.begin(); itr != that.eventData_.end(); ++itr) { + eventData_[(*itr).first].insert(itr->second.begin(), itr->second.end()); + } + } + + //Get the begin iterator over event data + inline iterator begin() const { + //std::cout << "begin\n"; + if(eventData_.empty()) return end(); + typename EventData::const_iterator itr = eventData_.begin(); + Unit pos = itr->first; + const std::set& idr = itr->second; + ++itr; + return iterator(itr, pos, itr->first, idr); + } + + //Get the end iterator over event data + inline iterator end() const { return iterator(eventData_.end(), 0, 0, std::set()); } + + inline void clear() { eventData_.clear(); } + + inline Interval extents() const { + if(eventData_.empty()) return Interval(); + return Interval((*(eventData_.begin())).first, (*(eventData_.rbegin())).first); + } + }; + + //declaration of a map of scan events by coordinate value used to store all the + //polygon data for a single layer input into the scanline algorithm + typedef std::pair, std::map > TouchSetData; + + class TouchOp { + public: + typedef std::map > ScanData; + typedef std::pair > ElementType; + protected: + ScanData scanData_; + typename ScanData::iterator nextItr_; + public: + inline TouchOp () : scanData_(), nextItr_() { nextItr_ = scanData_.end(); } + inline TouchOp (const TouchOp& that) : scanData_(that.scanData_), nextItr_() { nextItr_ = scanData_.begin(); } + inline TouchOp& operator=(const TouchOp& that); + + //moves scanline forward + inline void advanceScan() { nextItr_ = scanData_.begin(); } + + //proceses the given interval and std::set data + //the output data structre is a graph, the indicies in the vector correspond to graph nodes, + //the integers in the set are vector indicies and are the nodes with which that node shares an edge + template + inline void processInterval(graphT& outputContainer, Interval ivl, const std::set& ids, bool leadingEdge) { + //print(); + typename ScanData::iterator lowItr = lookup_(ivl.low()); + typename ScanData::iterator highItr = lookup_(ivl.high()); + //std::cout << "Interval: " << ivl << std::endl; + //for(std::set::const_iterator itr = ids.begin(); itr != ids.end(); ++itr) + // std::cout << (*itr) << " "; + //std::cout << std::endl; + //add interval to scan data if it is past the end + if(lowItr == scanData_.end()) { + //std::cout << "case0" << std::endl; + lowItr = insert_(ivl.low(), ids); + evaluateBorder_(outputContainer, ids, ids); + highItr = insert_(ivl.high(), std::set()); + return; + } + //ensure that highItr points to the end of the ivl + if(highItr == scanData_.end() || (*highItr).first > ivl.high()) { + //std::cout << "case1" << std::endl; + //std::cout << highItr->first << std::endl; + std::set value = std::set(); + if(highItr != scanData_.begin()) { + --highItr; + //std::cout << highItr->first << std::endl; + //std::cout << "high set size " << highItr->second.size() << std::endl; + value = highItr->second; + } + nextItr_ = highItr; + highItr = insert_(ivl.high(), value); + } else { + //evaluate border with next higher interval + //std::cout << "case1a" << std::endl; + if(leadingEdge)evaluateBorder_(outputContainer, highItr->second, ids); + } + //split the low interval if needed + if(lowItr->first > ivl.low()) { + //std::cout << "case2" << std::endl; + if(lowItr != scanData_.begin()) { + //std::cout << "case3" << std::endl; + --lowItr; + nextItr_ = lowItr; + //std::cout << lowItr->first << " " << lowItr->second.size() << std::endl; + lowItr = insert_(ivl.low(), lowItr->second); + } else { + //std::cout << "case4" << std::endl; + nextItr_ = lowItr; + lowItr = insert_(ivl.low(), std::set()); + } + } else { + //evaluate border with next higher interval + //std::cout << "case2a" << std::endl; + typename ScanData::iterator nextLowerItr = lowItr; + if(leadingEdge && nextLowerItr != scanData_.begin()){ + --nextLowerItr; + evaluateBorder_(outputContainer, nextLowerItr->second, ids); + } + } + //std::cout << "low: " << lowItr->first << " high: " << highItr->first << std::endl; + //print(); + //process scan data intersecting interval + for(typename ScanData::iterator itr = lowItr; itr != highItr; ){ + //std::cout << "case5" << std::endl; + //std::cout << itr->first << std::endl; + std::set& beforeIds = itr->second; + ++itr; + evaluateInterval_(outputContainer, beforeIds, ids, leadingEdge); + } + //print(); + //merge the bottom interval with the one below if they have the same count + if(lowItr != scanData_.begin()){ + //std::cout << "case6" << std::endl; + typename ScanData::iterator belowLowItr = lowItr; + --belowLowItr; + if(belowLowItr->second == lowItr->second) { + //std::cout << "case7" << std::endl; + scanData_.erase(lowItr); + } + } + //merge the top interval with the one above if they have the same count + if(highItr != scanData_.begin()) { + //std::cout << "case8" << std::endl; + typename ScanData::iterator beforeHighItr = highItr; + --beforeHighItr; + if(beforeHighItr->second == highItr->second) { + //std::cout << "case9" << std::endl; + scanData_.erase(highItr); + highItr = beforeHighItr; + ++highItr; + } + } + //print(); + nextItr_ = highItr; + } + +// inline void print() const { +// for(typename ScanData::const_iterator itr = scanData_.begin(); itr != scanData_.end(); ++itr) { +// std::cout << itr->first << ": "; +// for(std::set::const_iterator sitr = itr->second.begin(); +// sitr != itr->second.end(); ++sitr){ +// std::cout << *sitr << " "; +// } +// std::cout << std::endl; +// } +// } + + private: + inline typename ScanData::iterator lookup_(Unit pos){ + if(nextItr_ != scanData_.end() && nextItr_->first >= pos) { + return nextItr_; + } + return nextItr_ = scanData_.lower_bound(pos); + } + + inline typename ScanData::iterator insert_(Unit pos, const std::set& ids){ + //std::cout << "inserting " << ids.size() << " ids at: " << pos << std::endl; + return nextItr_ = scanData_.insert(nextItr_, std::pair >(pos, ids)); + } + + template + inline void evaluateInterval_(graphT& outputContainer, std::set& ids, + const std::set& changingIds, bool leadingEdge) { + for(std::set::const_iterator ciditr = changingIds.begin(); ciditr != changingIds.end(); ++ciditr){ + //std::cout << "evaluateInterval " << (*ciditr) << std::endl; + evaluateId_(outputContainer, ids, *ciditr, leadingEdge); + } + } + template + inline void evaluateBorder_(graphT& outputContainer, const std::set& ids, const std::set& changingIds) { + for(std::set::const_iterator ciditr = changingIds.begin(); ciditr != changingIds.end(); ++ciditr){ + //std::cout << "evaluateBorder " << (*ciditr) << std::endl; + evaluateBorderId_(outputContainer, ids, *ciditr); + } + } + template + inline void evaluateBorderId_(graphT& outputContainer, const std::set& ids, int changingId) { + for(std::set::const_iterator scanItr = ids.begin(); scanItr != ids.end(); ++scanItr) { + //std::cout << "create edge: " << changingId << " " << *scanItr << std::endl; + if(changingId != *scanItr){ + outputContainer[changingId].insert(*scanItr); + outputContainer[*scanItr].insert(changingId); + } + } + } + template + inline void evaluateId_(graphT& outputContainer, std::set& ids, int changingId, bool leadingEdge) { + //std::cout << "changingId: " << changingId << std::endl; + //for( std::set::iterator itr = ids.begin(); itr != ids.end(); ++itr){ + // std::cout << *itr << " "; + //}std::cout << std::endl; + std::set::iterator lb = ids.lower_bound(changingId); + if(lb == ids.end() || (*lb) != changingId) { + if(leadingEdge) { + //std::cout << "insert\n"; + //insert and add to output + for(std::set::iterator scanItr = ids.begin(); scanItr != ids.end(); ++scanItr) { + //std::cout << "create edge: " << changingId << " " << *scanItr << std::endl; + if(changingId != *scanItr){ + outputContainer[changingId].insert(*scanItr); + outputContainer[*scanItr].insert(changingId); + } + } + ids.insert(changingId); + } + } else { + if(!leadingEdge){ + //std::cout << "erase\n"; + ids.erase(lb); + } + } + } + }; + + template + static inline void processEvent(graphT& outputContainer, TouchOp& op, const TouchScanEvent& data, bool leadingEdge) { + for(typename TouchScanEvent::iterator itr = data.begin(); itr != data.end(); ++itr) { + //std::cout << "processInterval" << std::endl; + op.processInterval(outputContainer, (*itr).first, (*itr).second, leadingEdge); + } + } + + template + static inline void performTouch(graphT& outputContainer, const TouchSetData& data) { + typename std::map::const_iterator leftItr = data.first.begin(); + typename std::map::const_iterator rightItr = data.second.begin(); + typename std::map::const_iterator leftEnd = data.first.end(); + typename std::map::const_iterator rightEnd = data.second.end(); + TouchOp op; + while(leftItr != leftEnd || rightItr != rightEnd) { + //std::cout << "loop" << std::endl; + op.advanceScan(); + //rightItr cannont be at end if leftItr is not at end + if(leftItr != leftEnd && rightItr != rightEnd && + leftItr->first <= rightItr->first) { + //std::cout << "case1" << std::endl; + //std::cout << leftItr ->first << std::endl; + processEvent(outputContainer, op, leftItr->second, true); + ++leftItr; + } else { + //std::cout << "case2" << std::endl; + //std::cout << rightItr ->first << std::endl; + processEvent(outputContainer, op, rightItr->second, false); + ++rightItr; + } + } + } + + template + static inline void populateTouchSetData(TouchSetData& data, iT beginData, iT endData, int id) { + Unit prevPos = ((std::numeric_limits::max)()); + Unit prevY = prevPos; + int count = 0; + for(iT itr = beginData; itr != endData; ++itr) { + Unit pos = (*itr).first; + if(pos != prevPos) { + prevPos = pos; + prevY = (*itr).second.first; + count = (*itr).second.second; + continue; + } + Unit y = (*itr).second.first; + if(count != 0 && y != prevY) { + std::pair element(Interval(prevY, y), id); + if(count > 0) { + data.first[pos].insert(element); + } else { + data.second[pos].insert(element); + } + } + prevY = y; + count += (*itr).second.second; + } + } + + static inline void populateTouchSetData(TouchSetData& data, const std::vector > >& inputData, int id) { + populateTouchSetData(data, inputData.begin(), inputData.end(), id); + } + + }; +} +} +#endif diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/detail/polygon_arbitrary_formation.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/detail/polygon_arbitrary_formation.hpp new file mode 100644 index 0000000..5495897 --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/detail/polygon_arbitrary_formation.hpp @@ -0,0 +1,2907 @@ +/* + Copyright 2008 Intel Corporation + + Use, modification and distribution are subject to the Boost Software License, + Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at + http://www.boost.org/LICENSE_1_0.txt). +*/ +#ifndef BOOST_POLYGON_POLYGON_ARBITRARY_FORMATION_HPP +#define BOOST_POLYGON_POLYGON_ARBITRARY_FORMATION_HPP +namespace boost { namespace polygon{ + template + struct PolyLineArbitraryByConcept {}; + + template + class poly_line_arbitrary_polygon_data; + template + class poly_line_arbitrary_hole_data; + + template + struct scanline_base { + + typedef point_data Point; + typedef std::pair half_edge; + + class less_point { + public: + typedef Point first_argument_type; + typedef Point second_argument_type; + typedef bool result_type; + inline less_point() {} + inline bool operator () (const Point& pt1, const Point& pt2) const { + if(pt1.get(HORIZONTAL) < pt2.get(HORIZONTAL)) return true; + if(pt1.get(HORIZONTAL) == pt2.get(HORIZONTAL)) { + if(pt1.get(VERTICAL) < pt2.get(VERTICAL)) return true; + } + return false; + } + }; + + static inline bool between(Point pt, Point pt1, Point pt2) { + less_point lp; + if(lp(pt1, pt2)) + return lp(pt, pt2) && lp(pt1, pt); + return lp(pt, pt1) && lp(pt2, pt); + } + + template + static inline Unit compute_intercept(const area_type& dy2, + const area_type& dx1, + const area_type& dx2) { + //intercept = dy2 * dx1 / dx2 + //return (Unit)(((area_type)dy2 * (area_type)dx1) / (area_type)dx2); + area_type dx1_q = dx1 / dx2; + area_type dx1_r = dx1 % dx2; + return dx1_q * dy2 + (dy2 * dx1_r)/dx2; + } + + template + static inline bool equal_slope(area_type dx1, area_type dy1, area_type dx2, area_type dy2) { + typedef typename coordinate_traits::unsigned_area_type unsigned_product_type; + unsigned_product_type cross_1 = (unsigned_product_type)(dx2 < 0 ? -dx2 :dx2) * (unsigned_product_type)(dy1 < 0 ? -dy1 : dy1); + unsigned_product_type cross_2 = (unsigned_product_type)(dx1 < 0 ? -dx1 :dx1) * (unsigned_product_type)(dy2 < 0 ? -dy2 : dy2); + int dx1_sign = dx1 < 0 ? -1 : 1; + int dx2_sign = dx2 < 0 ? -1 : 1; + int dy1_sign = dy1 < 0 ? -1 : 1; + int dy2_sign = dy2 < 0 ? -1 : 1; + int cross_1_sign = dx2_sign * dy1_sign; + int cross_2_sign = dx1_sign * dy2_sign; + return cross_1 == cross_2 && (cross_1_sign == cross_2_sign || cross_1 == 0); + } + + template + static inline bool equal_slope_hp(const T& dx1, const T& dy1, const T& dx2, const T& dy2) { + return dx1 * dy2 == dx2 * dy1; + } + + static inline bool equal_slope(const Unit& x, const Unit& y, + const Point& pt1, const Point& pt2) { + const Point* pts[2] = {&pt1, &pt2}; + typedef typename coordinate_traits::manhattan_area_type at; + at dy2 = (at)pts[1]->get(VERTICAL) - (at)y; + at dy1 = (at)pts[0]->get(VERTICAL) - (at)y; + at dx2 = (at)pts[1]->get(HORIZONTAL) - (at)x; + at dx1 = (at)pts[0]->get(HORIZONTAL) - (at)x; + return equal_slope(dx1, dy1, dx2, dy2); + } + + template + static inline bool less_slope(area_type dx1, area_type dy1, area_type dx2, area_type dy2) { + //reflext x and y slopes to right hand side half plane + if(dx1 < 0) { + dy1 *= -1; + dx1 *= -1; + } else if(dx1 == 0) { + //if the first slope is vertical the first cannot be less + return false; + } + if(dx2 < 0) { + dy2 *= -1; + dx2 *= -1; + } else if(dx2 == 0) { + //if the second slope is vertical the first is always less unless it is also vertical, in which case they are equal + return dx1 != 0; + } + typedef typename coordinate_traits::unsigned_area_type unsigned_product_type; + unsigned_product_type cross_1 = (unsigned_product_type)(dx2 < 0 ? -dx2 :dx2) * (unsigned_product_type)(dy1 < 0 ? -dy1 : dy1); + unsigned_product_type cross_2 = (unsigned_product_type)(dx1 < 0 ? -dx1 :dx1) * (unsigned_product_type)(dy2 < 0 ? -dy2 : dy2); + int dx1_sign = dx1 < 0 ? -1 : 1; + int dx2_sign = dx2 < 0 ? -1 : 1; + int dy1_sign = dy1 < 0 ? -1 : 1; + int dy2_sign = dy2 < 0 ? -1 : 1; + int cross_1_sign = dx2_sign * dy1_sign; + int cross_2_sign = dx1_sign * dy2_sign; + if(cross_1_sign < cross_2_sign) return true; + if(cross_2_sign < cross_1_sign) return false; + if(cross_1_sign == -1) return cross_2 < cross_1; + return cross_1 < cross_2; + } + + static inline bool less_slope(const Unit& x, const Unit& y, + const Point& pt1, const Point& pt2) { + const Point* pts[2] = {&pt1, &pt2}; + //compute y value on edge from pt_ to pts[1] at the x value of pts[0] + typedef typename coordinate_traits::manhattan_area_type at; + at dy2 = (at)pts[1]->get(VERTICAL) - (at)y; + at dy1 = (at)pts[0]->get(VERTICAL) - (at)y; + at dx2 = (at)pts[1]->get(HORIZONTAL) - (at)x; + at dx1 = (at)pts[0]->get(HORIZONTAL) - (at)x; + return less_slope(dx1, dy1, dx2, dy2); + } + + //return -1 below, 0 on and 1 above line + static inline int on_above_or_below(Point pt, const half_edge& he) { + if(pt == he.first || pt == he.second) return 0; + if(equal_slope(pt.get(HORIZONTAL), pt.get(VERTICAL), he.first, he.second)) return 0; + bool less_result = less_slope(pt.get(HORIZONTAL), pt.get(VERTICAL), he.first, he.second); + int retval = less_result ? -1 : 1; + less_point lp; + if(lp(he.second, he.first)) retval *= -1; + if(!between(pt, he.first, he.second)) retval *= -1; + return retval; + } + + //returns true is the segment intersects the integer grid square with lower + //left corner at point + static inline bool intersects_grid(Point pt, const half_edge& he) { + if(pt == he.second) return true; + if(pt == he.first) return true; + rectangle_data rect1; + set_points(rect1, he.first, he.second); + if(contains(rect1, pt, true)) { + if(is_vertical(he) || is_horizontal(he)) return true; + } else { + return false; //can't intersect a grid not within bounding box + } + Unit x = pt.get(HORIZONTAL); + Unit y = pt.get(VERTICAL); + if(equal_slope(x, y, he.first, he.second) && + between(pt, he.first, he.second)) return true; + Point pt01(pt.get(HORIZONTAL), pt.get(VERTICAL) + 1); + Point pt10(pt.get(HORIZONTAL) + 1, pt.get(VERTICAL)); + Point pt11(pt.get(HORIZONTAL) + 1, pt.get(VERTICAL) + 1); +// if(pt01 == he.first) return true; +// if(pt10 == he.first) return true; +// if(pt11 == he.first) return true; +// if(pt01 == he.second) return true; +// if(pt10 == he.second) return true; +// if(pt11 == he.second) return true; + //check non-integer intersections + half_edge widget1(pt, pt11); + //intersects but not just at pt11 + if(intersects(widget1, he) && on_above_or_below(pt11, he)) return true; + half_edge widget2(pt01, pt10); + //intersects but not just at pt01 or 10 + if(intersects(widget2, he) && on_above_or_below(pt01, he) && on_above_or_below(pt10, he)) return true; + return false; + } + + static inline Unit evalAtXforYlazy(Unit xIn, Point pt, Point other_pt) { + long double + evalAtXforYret, evalAtXforYxIn, evalAtXforYx1, evalAtXforYy1, evalAtXforYdx1, evalAtXforYdx, + evalAtXforYdy, evalAtXforYx2, evalAtXforYy2, evalAtXforY0; + //y = (x - x1)dy/dx + y1 + //y = (xIn - pt.x)*(other_pt.y-pt.y)/(other_pt.x-pt.x) + pt.y + //assert pt.x != other_pt.x + if(pt.y() == other_pt.y()) + return pt.y(); + evalAtXforYxIn = xIn; + evalAtXforYx1 = pt.get(HORIZONTAL); + evalAtXforYy1 = pt.get(VERTICAL); + evalAtXforYdx1 = evalAtXforYxIn - evalAtXforYx1; + evalAtXforY0 = 0; + if(evalAtXforYdx1 == evalAtXforY0) return (Unit)evalAtXforYy1; + evalAtXforYx2 = other_pt.get(HORIZONTAL); + evalAtXforYy2 = other_pt.get(VERTICAL); + + evalAtXforYdx = evalAtXforYx2 - evalAtXforYx1; + evalAtXforYdy = evalAtXforYy2 - evalAtXforYy1; + evalAtXforYret = ((evalAtXforYdx1) * evalAtXforYdy / evalAtXforYdx + evalAtXforYy1); + return (Unit)evalAtXforYret; + } + + static inline typename high_precision_type::type evalAtXforY(Unit xIn, Point pt, Point other_pt) { + typename high_precision_type::type + evalAtXforYret, evalAtXforYxIn, evalAtXforYx1, evalAtXforYy1, evalAtXforYdx1, evalAtXforYdx, + evalAtXforYdy, evalAtXforYx2, evalAtXforYy2, evalAtXforY0; + //y = (x - x1)dy/dx + y1 + //y = (xIn - pt.x)*(other_pt.y-pt.y)/(other_pt.x-pt.x) + pt.y + //assert pt.x != other_pt.x + typedef typename high_precision_type::type high_precision; + if(pt.y() == other_pt.y()) + return (high_precision)pt.y(); + evalAtXforYxIn = (high_precision)xIn; + evalAtXforYx1 = pt.get(HORIZONTAL); + evalAtXforYy1 = pt.get(VERTICAL); + evalAtXforYdx1 = evalAtXforYxIn - evalAtXforYx1; + evalAtXforY0 = high_precision(0); + if(evalAtXforYdx1 == evalAtXforY0) return evalAtXforYret = evalAtXforYy1; + evalAtXforYx2 = (high_precision)other_pt.get(HORIZONTAL); + evalAtXforYy2 = (high_precision)other_pt.get(VERTICAL); + + evalAtXforYdx = evalAtXforYx2 - evalAtXforYx1; + evalAtXforYdy = evalAtXforYy2 - evalAtXforYy1; + evalAtXforYret = ((evalAtXforYdx1) * evalAtXforYdy / evalAtXforYdx + evalAtXforYy1); + return evalAtXforYret; + } + + struct evalAtXforYPack { + typename high_precision_type::type + evalAtXforYret, evalAtXforYxIn, evalAtXforYx1, evalAtXforYy1, evalAtXforYdx1, evalAtXforYdx, + evalAtXforYdy, evalAtXforYx2, evalAtXforYy2, evalAtXforY0; + inline const typename high_precision_type::type& evalAtXforY(Unit xIn, Point pt, Point other_pt) { + //y = (x - x1)dy/dx + y1 + //y = (xIn - pt.x)*(other_pt.y-pt.y)/(other_pt.x-pt.x) + pt.y + //assert pt.x != other_pt.x + typedef typename high_precision_type::type high_precision; + if(pt.y() == other_pt.y()) { + evalAtXforYret = (high_precision)pt.y(); + return evalAtXforYret; + } + evalAtXforYxIn = (high_precision)xIn; + evalAtXforYx1 = pt.get(HORIZONTAL); + evalAtXforYy1 = pt.get(VERTICAL); + evalAtXforYdx1 = evalAtXforYxIn - evalAtXforYx1; + evalAtXforY0 = high_precision(0); + if(evalAtXforYdx1 == evalAtXforY0) return evalAtXforYret = evalAtXforYy1; + evalAtXforYx2 = (high_precision)other_pt.get(HORIZONTAL); + evalAtXforYy2 = (high_precision)other_pt.get(VERTICAL); + + evalAtXforYdx = evalAtXforYx2 - evalAtXforYx1; + evalAtXforYdy = evalAtXforYy2 - evalAtXforYy1; + evalAtXforYret = ((evalAtXforYdx1) * evalAtXforYdy / evalAtXforYdx + evalAtXforYy1); + return evalAtXforYret; + } + }; + + static inline bool is_vertical(const half_edge& he) { + return he.first.get(HORIZONTAL) == he.second.get(HORIZONTAL); + } + + static inline bool is_horizontal(const half_edge& he) { + return he.first.get(VERTICAL) == he.second.get(VERTICAL); + } + + static inline bool is_45_degree(const half_edge& he) { + return euclidean_distance(he.first, he.second, HORIZONTAL) == euclidean_distance(he.first, he.second, VERTICAL); + } + + //scanline comparator functor + class less_half_edge { + private: + Unit *x_; //x value at which to apply comparison + int *justBefore_; + evalAtXforYPack * pack_; + public: + typedef half_edge first_argument_type; + typedef half_edge second_argument_type; + typedef bool result_type; + inline less_half_edge() : x_(0), justBefore_(0), pack_(0) {} + inline less_half_edge(Unit *x, int *justBefore, evalAtXforYPack * packIn) : x_(x), justBefore_(justBefore), pack_(packIn) {} + inline less_half_edge(const less_half_edge& that) : x_(that.x_), justBefore_(that.justBefore_), + pack_(that.pack_){} + inline less_half_edge& operator=(const less_half_edge& that) { + x_ = that.x_; + justBefore_ = that.justBefore_; + pack_ = that.pack_; + return *this; } + inline bool operator () (const half_edge& elm1, const half_edge& elm2) const { + if((std::max)(elm1.first.y(), elm1.second.y()) < (std::min)(elm2.first.y(), elm2.second.y())) + return true; + if((std::min)(elm1.first.y(), elm1.second.y()) > (std::max)(elm2.first.y(), elm2.second.y())) + return false; + + //check if either x of elem1 is equal to x_ + Unit localx = *x_; + Unit elm1y = 0; + bool elm1_at_x = false; + if(localx == elm1.first.get(HORIZONTAL)) { + elm1_at_x = true; + elm1y = elm1.first.get(VERTICAL); + } else if(localx == elm1.second.get(HORIZONTAL)) { + elm1_at_x = true; + elm1y = elm1.second.get(VERTICAL); + } + Unit elm2y = 0; + bool elm2_at_x = false; + if(localx == elm2.first.get(HORIZONTAL)) { + elm2_at_x = true; + elm2y = elm2.first.get(VERTICAL); + } else if(localx == elm2.second.get(HORIZONTAL)) { + elm2_at_x = true; + elm2y = elm2.second.get(VERTICAL); + } + bool retval = false; + if(!(elm1_at_x && elm2_at_x)) { + //at least one of the segments doesn't have an end point a the current x + //-1 below, 1 above + int pt1_oab = on_above_or_below(elm1.first, half_edge(elm2.first, elm2.second)); + int pt2_oab = on_above_or_below(elm1.second, half_edge(elm2.first, elm2.second)); + if(pt1_oab == pt2_oab) { + if(pt1_oab == -1) + retval = true; //pt1 is below elm2 so elm1 is below elm2 + } else { + //the segments can't cross so elm2 is on whatever side of elm1 that one of its ends is + int pt3_oab = on_above_or_below(elm2.first, half_edge(elm1.first, elm1.second)); + if(pt3_oab == 1) + retval = true; //elm1's point is above elm1 + } + } else { + if(elm1y < elm2y) { + retval = true; + } else if(elm1y == elm2y) { + if(elm1 == elm2) + return false; + retval = less_slope(elm1.second.get(HORIZONTAL) - elm1.first.get(HORIZONTAL), + elm1.second.get(VERTICAL) - elm1.first.get(VERTICAL), + elm2.second.get(HORIZONTAL) - elm2.first.get(HORIZONTAL), + elm2.second.get(VERTICAL) - elm2.first.get(VERTICAL)); + retval = ((*justBefore_) != 0) ^ retval; + } + } + return retval; + } + }; + + template + static inline void unsigned_add(unsigned_product_type& result, int& result_sign, unsigned_product_type a, int a_sign, unsigned_product_type b, int b_sign) { + int switcher = 0; + if(a_sign < 0) switcher += 1; + if(b_sign < 0) switcher += 2; + if(a < b) switcher += 4; + switch (switcher) { + case 0: //both positive + result = a + b; + result_sign = 1; + break; + case 1: //a is negative + result = a - b; + result_sign = -1; + break; + case 2: //b is negative + result = a - b; + result_sign = 1; + break; + case 3: //both negative + result = a + b; + result_sign = -1; + break; + case 4: //both positive + result = a + b; + result_sign = 1; + break; + case 5: //a is negative + result = b - a; + result_sign = 1; + break; + case 6: //b is negative + result = b - a; + result_sign = -1; + break; + case 7: //both negative + result = b + a; + result_sign = -1; + break; + }; + } + + struct compute_intersection_pack { + typedef typename high_precision_type::type high_precision; + high_precision y_high, dx1, dy1, dx2, dy2, x11, x21, y11, y21, x_num, y_num, x_den, y_den, x, y; + static inline bool compute_lazy_intersection(Point& intersection, const half_edge& he1, const half_edge& he2, + bool projected = false, bool round_closest = false) { + long double y_high, dx1, dy1, dx2, dy2, x11, x21, y11, y21, x_num, y_num, x_den, y_den, x, y; + typedef rectangle_data Rectangle; + Rectangle rect1, rect2; + set_points(rect1, he1.first, he1.second); + set_points(rect2, he2.first, he2.second); + if(!projected && !::boost::polygon::intersects(rect1, rect2, true)) return false; + if(is_vertical(he1)) { + if(is_vertical(he2)) return false; + y_high = evalAtXforYlazy(he1.first.get(HORIZONTAL), he2.first, he2.second); + Unit y_local = (Unit)y_high; + if(y_high < y_local) --y_local; + if(projected || contains(rect1.get(VERTICAL), y_local, true)) { + intersection = Point(he1.first.get(HORIZONTAL), y_local); + return true; + } else { + return false; + } + } else if(is_vertical(he2)) { + y_high = evalAtXforYlazy(he2.first.get(HORIZONTAL), he1.first, he1.second); + Unit y_local = (Unit)y_high; + if(y_high < y_local) --y_local; + if(projected || contains(rect2.get(VERTICAL), y_local, true)) { + intersection = Point(he2.first.get(HORIZONTAL), y_local); + return true; + } else { + return false; + } + } + //the bounding boxes of the two line segments intersect, so we check closer to find the intersection point + dy2 = (he2.second.get(VERTICAL)) - + (he2.first.get(VERTICAL)); + dy1 = (he1.second.get(VERTICAL)) - + (he1.first.get(VERTICAL)); + dx2 = (he2.second.get(HORIZONTAL)) - + (he2.first.get(HORIZONTAL)); + dx1 = (he1.second.get(HORIZONTAL)) - + (he1.first.get(HORIZONTAL)); + if(equal_slope_hp(dx1, dy1, dx2, dy2)) return false; + //the line segments have different slopes + //we can assume that the line segments are not vertical because such an intersection is handled elsewhere + x11 = (he1.first.get(HORIZONTAL)); + x21 = (he2.first.get(HORIZONTAL)); + y11 = (he1.first.get(VERTICAL)); + y21 = (he2.first.get(VERTICAL)); + //Unit exp_x = ((at)x11 * (at)dy1 * (at)dx2 - (at)x21 * (at)dy2 * (at)dx1 + (at)y21 * (at)dx1 * (at)dx2 - (at)y11 * (at)dx1 * (at)dx2) / ((at)dy1 * (at)dx2 - (at)dy2 * (at)dx1); + //Unit exp_y = ((at)y11 * (at)dx1 * (at)dy2 - (at)y21 * (at)dx2 * (at)dy1 + (at)x21 * (at)dy1 * (at)dy2 - (at)x11 * (at)dy1 * (at)dy2) / ((at)dx1 * (at)dy2 - (at)dx2 * (at)dy1); + x_num = (x11 * dy1 * dx2 - x21 * dy2 * dx1 + y21 * dx1 * dx2 - y11 * dx1 * dx2); + x_den = (dy1 * dx2 - dy2 * dx1); + y_num = (y11 * dx1 * dy2 - y21 * dx2 * dy1 + x21 * dy1 * dy2 - x11 * dy1 * dy2); + y_den = (dx1 * dy2 - dx2 * dy1); + x = x_num / x_den; + y = y_num / y_den; + //std::cout << "cross1 " << dy1 << " " << dx2 << " " << dy1 * dx2 << "\n"; + //std::cout << "cross2 " << dy2 << " " << dx1 << " " << dy2 * dx1 << "\n"; + //Unit exp_x = compute_x_intercept(x11, x21, y11, y21, dy1, dy2, dx1, dx2); + //Unit exp_y = compute_x_intercept(y11, y21, x11, x21, dx1, dx2, dy1, dy2); + if(round_closest) { + x = x + 0.5; + y = y + 0.5; + } + Unit x_unit = (Unit)(x); + Unit y_unit = (Unit)(y); + //truncate downward if it went up due to negative number + if(x < x_unit) --x_unit; + if(y < y_unit) --y_unit; + if(is_horizontal(he1)) + y_unit = he1.first.y(); + if(is_horizontal(he2)) + y_unit = he2.first.y(); + //if(x != exp_x || y != exp_y) + // std::cout << exp_x << " " << exp_y << " " << x << " " << y << "\n"; + //Unit y1 = evalAtXforY(exp_x, he1.first, he1.second); + //Unit y2 = evalAtXforY(exp_x, he2.first, he2.second); + //std::cout << exp_x << " " << exp_y << " " << y1 << " " << y2 << "\n"; + Point result(x_unit, y_unit); + if(!projected && !contains(rect1, result, true)) return false; + if(!projected && !contains(rect2, result, true)) return false; + if(projected) { + rectangle_data inf_rect(-(long double)(std::numeric_limits::max)(), + -(long double) (std::numeric_limits::max)(), + (long double)(std::numeric_limits::max)(), + (long double) (std::numeric_limits::max)() ); + if(contains(inf_rect, point_data(x, y), true)) { + intersection = result; + return true; + } else + return false; + } + intersection = result; + return true; + } + + inline bool compute_intersection(Point& intersection, const half_edge& he1, const half_edge& he2, + bool projected = false, bool round_closest = false) { + if(!projected && !intersects(he1, he2)) + return false; + bool lazy_success = compute_lazy_intersection(intersection, he1, he2, projected); + if(!projected) { + if(lazy_success) { + if(intersects_grid(intersection, he1) && + intersects_grid(intersection, he2)) + return true; + } + } else { + return lazy_success; + } + return compute_exact_intersection(intersection, he1, he2, projected, round_closest); + } + + inline bool compute_exact_intersection(Point& intersection, const half_edge& he1, const half_edge& he2, + bool projected = false, bool round_closest = false) { + if(!projected && !intersects(he1, he2)) + return false; + typedef rectangle_data Rectangle; + Rectangle rect1, rect2; + set_points(rect1, he1.first, he1.second); + set_points(rect2, he2.first, he2.second); + if(!::boost::polygon::intersects(rect1, rect2, true)) return false; + if(is_vertical(he1)) { + if(is_vertical(he2)) return false; + y_high = evalAtXforY(he1.first.get(HORIZONTAL), he2.first, he2.second); + Unit y = convert_high_precision_type(y_high); + if(y_high < (high_precision)y) --y; + if(contains(rect1.get(VERTICAL), y, true)) { + intersection = Point(he1.first.get(HORIZONTAL), y); + return true; + } else { + return false; + } + } else if(is_vertical(he2)) { + y_high = evalAtXforY(he2.first.get(HORIZONTAL), he1.first, he1.second); + Unit y = convert_high_precision_type(y_high); + if(y_high < (high_precision)y) --y; + if(contains(rect2.get(VERTICAL), y, true)) { + intersection = Point(he2.first.get(HORIZONTAL), y); + return true; + } else { + return false; + } + } + //the bounding boxes of the two line segments intersect, so we check closer to find the intersection point + dy2 = (high_precision)(he2.second.get(VERTICAL)) - + (high_precision)(he2.first.get(VERTICAL)); + dy1 = (high_precision)(he1.second.get(VERTICAL)) - + (high_precision)(he1.first.get(VERTICAL)); + dx2 = (high_precision)(he2.second.get(HORIZONTAL)) - + (high_precision)(he2.first.get(HORIZONTAL)); + dx1 = (high_precision)(he1.second.get(HORIZONTAL)) - + (high_precision)(he1.first.get(HORIZONTAL)); + if(equal_slope_hp(dx1, dy1, dx2, dy2)) return false; + //the line segments have different slopes + //we can assume that the line segments are not vertical because such an intersection is handled elsewhere + x11 = (high_precision)(he1.first.get(HORIZONTAL)); + x21 = (high_precision)(he2.first.get(HORIZONTAL)); + y11 = (high_precision)(he1.first.get(VERTICAL)); + y21 = (high_precision)(he2.first.get(VERTICAL)); + //Unit exp_x = ((at)x11 * (at)dy1 * (at)dx2 - (at)x21 * (at)dy2 * (at)dx1 + (at)y21 * (at)dx1 * (at)dx2 - (at)y11 * (at)dx1 * (at)dx2) / ((at)dy1 * (at)dx2 - (at)dy2 * (at)dx1); + //Unit exp_y = ((at)y11 * (at)dx1 * (at)dy2 - (at)y21 * (at)dx2 * (at)dy1 + (at)x21 * (at)dy1 * (at)dy2 - (at)x11 * (at)dy1 * (at)dy2) / ((at)dx1 * (at)dy2 - (at)dx2 * (at)dy1); + x_num = (x11 * dy1 * dx2 - x21 * dy2 * dx1 + y21 * dx1 * dx2 - y11 * dx1 * dx2); + x_den = (dy1 * dx2 - dy2 * dx1); + y_num = (y11 * dx1 * dy2 - y21 * dx2 * dy1 + x21 * dy1 * dy2 - x11 * dy1 * dy2); + y_den = (dx1 * dy2 - dx2 * dy1); + x = x_num / x_den; + y = y_num / y_den; + //std::cout << x << " " << y << "\n"; + //std::cout << "cross1 " << dy1 << " " << dx2 << " " << dy1 * dx2 << "\n"; + //std::cout << "cross2 " << dy2 << " " << dx1 << " " << dy2 * dx1 << "\n"; + //Unit exp_x = compute_x_intercept(x11, x21, y11, y21, dy1, dy2, dx1, dx2); + //Unit exp_y = compute_x_intercept(y11, y21, x11, x21, dx1, dx2, dy1, dy2); + if(round_closest) { + x = x + (high_precision)0.5; + y = y + (high_precision)0.5; + } + Unit x_unit = convert_high_precision_type(x); + Unit y_unit = convert_high_precision_type(y); + //truncate downward if it went up due to negative number + if(x < (high_precision)x_unit) --x_unit; + if(y < (high_precision)y_unit) --y_unit; + if(is_horizontal(he1)) + y_unit = he1.first.y(); + if(is_horizontal(he2)) + y_unit = he2.first.y(); + //if(x != exp_x || y != exp_y) + // std::cout << exp_x << " " << exp_y << " " << x << " " << y << "\n"; + //Unit y1 = evalAtXforY(exp_x, he1.first, he1.second); + //Unit y2 = evalAtXforY(exp_x, he2.first, he2.second); + //std::cout << exp_x << " " << exp_y << " " << y1 << " " << y2 << "\n"; + Point result(x_unit, y_unit); + if(!contains(rect1, result, true)) return false; + if(!contains(rect2, result, true)) return false; + if(projected) { + high_precision b1 = (high_precision) (std::numeric_limits::min)(); + high_precision b2 = (high_precision) (std::numeric_limits::max)(); + if(x > b2 || y > b2 || x < b1 || y < b1) + return false; + } + intersection = result; + return true; + } + }; + + static inline bool compute_intersection(Point& intersection, const half_edge& he1, const half_edge& he2) { + typedef typename high_precision_type::type high_precision; + typedef rectangle_data Rectangle; + Rectangle rect1, rect2; + set_points(rect1, he1.first, he1.second); + set_points(rect2, he2.first, he2.second); + if(!::boost::polygon::intersects(rect1, rect2, true)) return false; + if(is_vertical(he1)) { + if(is_vertical(he2)) return false; + high_precision y_high = evalAtXforY(he1.first.get(HORIZONTAL), he2.first, he2.second); + Unit y = convert_high_precision_type(y_high); + if(y_high < (high_precision)y) --y; + if(contains(rect1.get(VERTICAL), y, true)) { + intersection = Point(he1.first.get(HORIZONTAL), y); + return true; + } else { + return false; + } + } else if(is_vertical(he2)) { + high_precision y_high = evalAtXforY(he2.first.get(HORIZONTAL), he1.first, he1.second); + Unit y = convert_high_precision_type(y_high); + if(y_high < (high_precision)y) --y; + if(contains(rect2.get(VERTICAL), y, true)) { + intersection = Point(he2.first.get(HORIZONTAL), y); + return true; + } else { + return false; + } + } + //the bounding boxes of the two line segments intersect, so we check closer to find the intersection point + high_precision dy2 = (high_precision)(he2.second.get(VERTICAL)) - + (high_precision)(he2.first.get(VERTICAL)); + high_precision dy1 = (high_precision)(he1.second.get(VERTICAL)) - + (high_precision)(he1.first.get(VERTICAL)); + high_precision dx2 = (high_precision)(he2.second.get(HORIZONTAL)) - + (high_precision)(he2.first.get(HORIZONTAL)); + high_precision dx1 = (high_precision)(he1.second.get(HORIZONTAL)) - + (high_precision)(he1.first.get(HORIZONTAL)); + if(equal_slope_hp(dx1, dy1, dx2, dy2)) return false; + //the line segments have different slopes + //we can assume that the line segments are not vertical because such an intersection is handled elsewhere + high_precision x11 = (high_precision)(he1.first.get(HORIZONTAL)); + high_precision x21 = (high_precision)(he2.first.get(HORIZONTAL)); + high_precision y11 = (high_precision)(he1.first.get(VERTICAL)); + high_precision y21 = (high_precision)(he2.first.get(VERTICAL)); + //Unit exp_x = ((at)x11 * (at)dy1 * (at)dx2 - (at)x21 * (at)dy2 * (at)dx1 + (at)y21 * (at)dx1 * (at)dx2 - (at)y11 * (at)dx1 * (at)dx2) / ((at)dy1 * (at)dx2 - (at)dy2 * (at)dx1); + //Unit exp_y = ((at)y11 * (at)dx1 * (at)dy2 - (at)y21 * (at)dx2 * (at)dy1 + (at)x21 * (at)dy1 * (at)dy2 - (at)x11 * (at)dy1 * (at)dy2) / ((at)dx1 * (at)dy2 - (at)dx2 * (at)dy1); + high_precision x_num = (x11 * dy1 * dx2 - x21 * dy2 * dx1 + y21 * dx1 * dx2 - y11 * dx1 * dx2); + high_precision x_den = (dy1 * dx2 - dy2 * dx1); + high_precision y_num = (y11 * dx1 * dy2 - y21 * dx2 * dy1 + x21 * dy1 * dy2 - x11 * dy1 * dy2); + high_precision y_den = (dx1 * dy2 - dx2 * dy1); + high_precision x = x_num / x_den; + high_precision y = y_num / y_den; + //std::cout << "cross1 " << dy1 << " " << dx2 << " " << dy1 * dx2 << "\n"; + //std::cout << "cross2 " << dy2 << " " << dx1 << " " << dy2 * dx1 << "\n"; + //Unit exp_x = compute_x_intercept(x11, x21, y11, y21, dy1, dy2, dx1, dx2); + //Unit exp_y = compute_x_intercept(y11, y21, x11, x21, dx1, dx2, dy1, dy2); + Unit x_unit = convert_high_precision_type(x); + Unit y_unit = convert_high_precision_type(y); + //truncate downward if it went up due to negative number + if(x < (high_precision)x_unit) --x_unit; + if(y < (high_precision)y_unit) --y_unit; + if(is_horizontal(he1)) + y_unit = he1.first.y(); + if(is_horizontal(he2)) + y_unit = he2.first.y(); + //if(x != exp_x || y != exp_y) + // std::cout << exp_x << " " << exp_y << " " << x << " " << y << "\n"; + //Unit y1 = evalAtXforY(exp_x, he1.first, he1.second); + //Unit y2 = evalAtXforY(exp_x, he2.first, he2.second); + //std::cout << exp_x << " " << exp_y << " " << y1 << " " << y2 << "\n"; + Point result(x_unit, y_unit); + if(!contains(rect1, result, true)) return false; + if(!contains(rect2, result, true)) return false; + intersection = result; + return true; + } + + static inline bool intersects(const half_edge& he1, const half_edge& he2) { + typedef rectangle_data Rectangle; + Rectangle rect1, rect2; + set_points(rect1, he1.first, he1.second); + set_points(rect2, he2.first, he2.second); + if(::boost::polygon::intersects(rect1, rect2, false)) { + if(he1.first == he2.first) { + if(he1.second != he2.second && equal_slope(he1.first.get(HORIZONTAL), he1.first.get(VERTICAL), + he1.second, he2.second)) { + return true; + } else { + return false; + } + } + if(he1.first == he2.second) { + if(he1.second != he2.first && equal_slope(he1.first.get(HORIZONTAL), he1.first.get(VERTICAL), + he1.second, he2.first)) { + return true; + } else { + return false; + } + } + if(he1.second == he2.first) { + if(he1.first != he2.second && equal_slope(he1.second.get(HORIZONTAL), he1.second.get(VERTICAL), + he1.first, he2.second)) { + return true; + } else { + return false; + } + } + if(he1.second == he2.second) { + if(he1.first != he2.first && equal_slope(he1.second.get(HORIZONTAL), he1.second.get(VERTICAL), + he1.first, he2.first)) { + return true; + } else { + return false; + } + } + int oab1 = on_above_or_below(he1.first, he2); + if(oab1 == 0 && between(he1.first, he2.first, he2.second)) return true; + int oab2 = on_above_or_below(he1.second, he2); + if(oab2 == 0 && between(he1.second, he2.first, he2.second)) return true; + if(oab1 == oab2 && oab1 != 0) return false; //both points of he1 are on same side of he2 + int oab3 = on_above_or_below(he2.first, he1); + if(oab3 == 0 && between(he2.first, he1.first, he1.second)) return true; + int oab4 = on_above_or_below(he2.second, he1); + if(oab4 == 0 && between(he2.second, he1.first, he1.second)) return true; + if(oab3 == oab4) return false; //both points of he2 are on same side of he1 + return true; //they must cross + } + if(is_vertical(he1) && is_vertical(he2) && he1.first.get(HORIZONTAL) == he2.first.get(HORIZONTAL)) + return ::boost::polygon::intersects(rect1.get(VERTICAL), rect2.get(VERTICAL), false) && + rect1.get(VERTICAL) != rect2.get(VERTICAL); + if(is_horizontal(he1) && is_horizontal(he2) && he1.first.get(VERTICAL) == he2.first.get(VERTICAL)) + return ::boost::polygon::intersects(rect1.get(HORIZONTAL), rect2.get(HORIZONTAL), false) && + rect1.get(HORIZONTAL) != rect2.get(HORIZONTAL); + return false; + } + + class vertex_half_edge { + public: + typedef typename high_precision_type::type high_precision; + Point pt; + Point other_pt; // 1, 0 or -1 + int count; //dxdydTheta + inline vertex_half_edge() : pt(), other_pt(), count() {} + inline vertex_half_edge(const Point& point, const Point& other_point, int countIn) : pt(point), other_pt(other_point), count(countIn) {} + inline vertex_half_edge(const vertex_half_edge& vertex) : pt(vertex.pt), other_pt(vertex.other_pt), count(vertex.count) {} + inline vertex_half_edge& operator=(const vertex_half_edge& vertex){ + pt = vertex.pt; other_pt = vertex.other_pt; count = vertex.count; return *this; } + inline bool operator==(const vertex_half_edge& vertex) const { + return pt == vertex.pt && other_pt == vertex.other_pt && count == vertex.count; } + inline bool operator!=(const vertex_half_edge& vertex) const { return !((*this) == vertex); } + inline bool operator<(const vertex_half_edge& vertex) const { + if(pt.get(HORIZONTAL) < vertex.pt.get(HORIZONTAL)) return true; + if(pt.get(HORIZONTAL) == vertex.pt.get(HORIZONTAL)) { + if(pt.get(VERTICAL) < vertex.pt.get(VERTICAL)) return true; + if(pt.get(VERTICAL) == vertex.pt.get(VERTICAL)) { return less_slope(pt.get(HORIZONTAL), pt.get(VERTICAL), + other_pt, vertex.other_pt); + } + } + return false; + } + inline bool operator>(const vertex_half_edge& vertex) const { return vertex < (*this); } + inline bool operator<=(const vertex_half_edge& vertex) const { return !((*this) > vertex); } + inline bool operator>=(const vertex_half_edge& vertex) const { return !((*this) < vertex); } + inline high_precision evalAtX(Unit xIn) const { return evalAtXforYlazy(xIn, pt, other_pt); } + inline bool is_vertical() const { + return pt.get(HORIZONTAL) == other_pt.get(HORIZONTAL); + } + inline bool is_begin() const { + return pt.get(HORIZONTAL) < other_pt.get(HORIZONTAL) || + (pt.get(HORIZONTAL) == other_pt.get(HORIZONTAL) && + (pt.get(VERTICAL) < other_pt.get(VERTICAL))); + } + }; + + //when scanning Vertex45 for polygon formation we need a scanline comparator functor + class less_vertex_half_edge { + private: + Unit *x_; //x value at which to apply comparison + int *justBefore_; + public: + typedef vertex_half_edge first_argument_type; + typedef vertex_half_edge second_argument_type; + typedef bool result_type; + inline less_vertex_half_edge() : x_(0), justBefore_(0) {} + inline less_vertex_half_edge(Unit *x, int *justBefore) : x_(x), justBefore_(justBefore) {} + inline less_vertex_half_edge(const less_vertex_half_edge& that) : x_(that.x_), justBefore_(that.justBefore_) {} + inline less_vertex_half_edge& operator=(const less_vertex_half_edge& that) { x_ = that.x_; justBefore_ = that.justBefore_; return *this; } + inline bool operator () (const vertex_half_edge& elm1, const vertex_half_edge& elm2) const { + if((std::max)(elm1.pt.y(), elm1.other_pt.y()) < (std::min)(elm2.pt.y(), elm2.other_pt.y())) + return true; + if((std::min)(elm1.pt.y(), elm1.other_pt.y()) > (std::max)(elm2.pt.y(), elm2.other_pt.y())) + return false; + //check if either x of elem1 is equal to x_ + Unit localx = *x_; + Unit elm1y = 0; + bool elm1_at_x = false; + if(localx == elm1.pt.get(HORIZONTAL)) { + elm1_at_x = true; + elm1y = elm1.pt.get(VERTICAL); + } else if(localx == elm1.other_pt.get(HORIZONTAL)) { + elm1_at_x = true; + elm1y = elm1.other_pt.get(VERTICAL); + } + Unit elm2y = 0; + bool elm2_at_x = false; + if(localx == elm2.pt.get(HORIZONTAL)) { + elm2_at_x = true; + elm2y = elm2.pt.get(VERTICAL); + } else if(localx == elm2.other_pt.get(HORIZONTAL)) { + elm2_at_x = true; + elm2y = elm2.other_pt.get(VERTICAL); + } + bool retval = false; + if(!(elm1_at_x && elm2_at_x)) { + //at least one of the segments doesn't have an end point a the current x + //-1 below, 1 above + int pt1_oab = on_above_or_below(elm1.pt, half_edge(elm2.pt, elm2.other_pt)); + int pt2_oab = on_above_or_below(elm1.other_pt, half_edge(elm2.pt, elm2.other_pt)); + if(pt1_oab == pt2_oab) { + if(pt1_oab == -1) + retval = true; //pt1 is below elm2 so elm1 is below elm2 + } else { + //the segments can't cross so elm2 is on whatever side of elm1 that one of its ends is + int pt3_oab = on_above_or_below(elm2.pt, half_edge(elm1.pt, elm1.other_pt)); + if(pt3_oab == 1) + retval = true; //elm1's point is above elm1 + } + } else { + if(elm1y < elm2y) { + retval = true; + } else if(elm1y == elm2y) { + if(elm1.pt == elm2.pt && elm1.other_pt == elm2.other_pt) + return false; + retval = less_slope(elm1.other_pt.get(HORIZONTAL) - elm1.pt.get(HORIZONTAL), + elm1.other_pt.get(VERTICAL) - elm1.pt.get(VERTICAL), + elm2.other_pt.get(HORIZONTAL) - elm2.pt.get(HORIZONTAL), + elm2.other_pt.get(VERTICAL) - elm2.pt.get(VERTICAL)); + retval = ((*justBefore_) != 0) ^ retval; + } + } + return retval; + } + }; + + }; + + template + class polygon_arbitrary_formation : public scanline_base { + public: + typedef typename scanline_base::Point Point; + typedef typename scanline_base::half_edge half_edge; + typedef typename scanline_base::vertex_half_edge vertex_half_edge; + typedef typename scanline_base::less_vertex_half_edge less_vertex_half_edge; + + class poly_line_arbitrary { + public: + typedef typename std::list::const_iterator iterator; + + // default constructor of point does not initialize x and y + inline poly_line_arbitrary() : points() {} //do nothing default constructor + + // initialize a polygon from x,y values, it is assumed that the first is an x + // and that the input is a well behaved polygon + template + inline poly_line_arbitrary& set(iT inputBegin, iT inputEnd) { + points.clear(); //just in case there was some old data there + while(inputBegin != inputEnd) { + points.insert(points.end(), *inputBegin); + ++inputBegin; + } + return *this; + } + + // copy constructor (since we have dynamic memory) + inline poly_line_arbitrary(const poly_line_arbitrary& that) : points(that.points) {} + + // assignment operator (since we have dynamic memory do a deep copy) + inline poly_line_arbitrary& operator=(const poly_line_arbitrary& that) { + points = that.points; + return *this; + } + + // get begin iterator, returns a pointer to a const Unit + inline iterator begin() const { return points.begin(); } + + // get end iterator, returns a pointer to a const Unit + inline iterator end() const { return points.end(); } + + inline std::size_t size() const { return points.size(); } + + //public data member + std::list points; + }; + + class active_tail_arbitrary { + protected: + //data + poly_line_arbitrary* tailp_; + active_tail_arbitrary *otherTailp_; + std::list holesList_; + bool head_; + public: + + /** + * @brief iterator over coordinates of the figure + */ + typedef typename poly_line_arbitrary::iterator iterator; + + /** + * @brief iterator over holes contained within the figure + */ + typedef typename std::list::const_iterator iteratorHoles; + + //default constructor + inline active_tail_arbitrary() : tailp_(), otherTailp_(), holesList_(), head_() {} + + //constructor + inline active_tail_arbitrary(const vertex_half_edge& vertex, active_tail_arbitrary* otherTailp = 0) : tailp_(), otherTailp_(), holesList_(), head_() { + tailp_ = new poly_line_arbitrary; + tailp_->points.push_back(vertex.pt); + //bool headArray[4] = {false, true, true, true}; + bool inverted = vertex.count == -1; + head_ = (!vertex.is_vertical) ^ inverted; + otherTailp_ = otherTailp; + } + + inline active_tail_arbitrary(Point point, active_tail_arbitrary* otherTailp, bool head = true) : + tailp_(), otherTailp_(), holesList_(), head_() { + tailp_ = new poly_line_arbitrary; + tailp_->points.push_back(point); + head_ = head; + otherTailp_ = otherTailp; + + } + inline active_tail_arbitrary(active_tail_arbitrary* otherTailp) : + tailp_(), otherTailp_(), holesList_(), head_() { + tailp_ = otherTailp->tailp_; + otherTailp_ = otherTailp; + } + + //copy constructor + inline active_tail_arbitrary(const active_tail_arbitrary& that) : + tailp_(), otherTailp_(), holesList_(), head_() { (*this) = that; } + + //destructor + inline ~active_tail_arbitrary() { + destroyContents(); + } + + //assignment operator + inline active_tail_arbitrary& operator=(const active_tail_arbitrary& that) { + tailp_ = new poly_line_arbitrary(*(that.tailp_)); + head_ = that.head_; + otherTailp_ = that.otherTailp_; + holesList_ = that.holesList_; + return *this; + } + + //equivalence operator + inline bool operator==(const active_tail_arbitrary& b) const { + return tailp_ == b.tailp_ && head_ == b.head_; + } + + /** + * @brief get the pointer to the polyline that this is an active tail of + */ + inline poly_line_arbitrary* getTail() const { return tailp_; } + + /** + * @brief get the pointer to the polyline at the other end of the chain + */ + inline poly_line_arbitrary* getOtherTail() const { return otherTailp_->tailp_; } + + /** + * @brief get the pointer to the activetail at the other end of the chain + */ + inline active_tail_arbitrary* getOtherActiveTail() const { return otherTailp_; } + + /** + * @brief test if another active tail is the other end of the chain + */ + inline bool isOtherTail(const active_tail_arbitrary& b) const { return &b == otherTailp_; } + + /** + * @brief update this end of chain pointer to new polyline + */ + inline active_tail_arbitrary& updateTail(poly_line_arbitrary* newTail) { tailp_ = newTail; return *this; } + + inline bool join(active_tail_arbitrary* tail) { + if(tail == otherTailp_) { + //std::cout << "joining to other tail!\n"; + return false; + } + if(tail->head_ == head_) { + //std::cout << "joining head to head!\n"; + return false; + } + if(!tailp_) { + //std::cout << "joining empty tail!\n"; + return false; + } + if(!(otherTailp_->head_)) { + otherTailp_->copyHoles(*tail); + otherTailp_->copyHoles(*this); + } else { + tail->otherTailp_->copyHoles(*this); + tail->otherTailp_->copyHoles(*tail); + } + poly_line_arbitrary* tail1 = tailp_; + poly_line_arbitrary* tail2 = tail->tailp_; + if(head_) std::swap(tail1, tail2); + typename std::list >::reverse_iterator riter = tail1->points.rbegin(); + typename std::list >::iterator iter = tail2->points.begin(); + if(*riter == *iter) { + tail1->points.pop_back(); //remove duplicate point + } + tail1->points.splice(tail1->points.end(), tail2->points); + delete tail2; + otherTailp_->tailp_ = tail1; + tail->otherTailp_->tailp_ = tail1; + otherTailp_->otherTailp_ = tail->otherTailp_; + tail->otherTailp_->otherTailp_ = otherTailp_; + tailp_ = 0; + tail->tailp_ = 0; + tail->otherTailp_ = 0; + otherTailp_ = 0; + return true; + } + + /** + * @brief associate a hole to this active tail by the specified policy + */ + inline active_tail_arbitrary* addHole(active_tail_arbitrary* hole) { + holesList_.push_back(hole); + copyHoles(*hole); + copyHoles(*(hole->otherTailp_)); + return this; + } + + /** + * @brief get the list of holes + */ + inline const std::list& getHoles() const { return holesList_; } + + /** + * @brief copy holes from that to this + */ + inline void copyHoles(active_tail_arbitrary& that) { holesList_.splice(holesList_.end(), that.holesList_); } + + /** + * @brief find out if solid to right + */ + inline bool solidToRight() const { return !head_; } + inline bool solidToLeft() const { return head_; } + + /** + * @brief get vertex + */ + inline Point getPoint() const { + if(head_) return tailp_->points.front(); + return tailp_->points.back(); + } + + /** + * @brief add a coordinate to the polygon at this active tail end, properly handle degenerate edges by removing redundant coordinate + */ + inline void pushPoint(Point point) { + if(head_) { + //if(tailp_->points.size() < 2) { + // tailp_->points.push_front(point); + // return; + //} + typename std::list::iterator iter = tailp_->points.begin(); + if(iter == tailp_->points.end()) { + tailp_->points.push_front(point); + return; + } + ++iter; + if(iter == tailp_->points.end()) { + tailp_->points.push_front(point); + return; + } + --iter; + if(*iter != point) { + tailp_->points.push_front(point); + } + return; + } + //if(tailp_->points.size() < 2) { + // tailp_->points.push_back(point); + // return; + //} + typename std::list::reverse_iterator iter = tailp_->points.rbegin(); + if(iter == tailp_->points.rend()) { + tailp_->points.push_back(point); + return; + } + ++iter; + if(iter == tailp_->points.rend()) { + tailp_->points.push_back(point); + return; + } + --iter; + if(*iter != point) { + tailp_->points.push_back(point); + } + } + + /** + * @brief joins the two chains that the two active tail tails are ends of + * checks for closure of figure and writes out polygons appropriately + * returns a handle to a hole if one is closed + */ + template + static inline active_tail_arbitrary* joinChains(Point point, active_tail_arbitrary* at1, active_tail_arbitrary* at2, bool solid, + cT& output) { + if(at1->otherTailp_ == at2) { + //if(at2->otherTailp_ != at1) std::cout << "half closed error\n"; + //we are closing a figure + at1->pushPoint(point); + at2->pushPoint(point); + if(solid) { + //we are closing a solid figure, write to output + //std::cout << "test1\n"; + at1->copyHoles(*(at1->otherTailp_)); + typename PolyLineArbitraryByConcept::type>::type polyData(at1); + //poly_line_arbitrary_polygon_data polyData(at1); + //std::cout << "test2\n"; + //std::cout << poly << "\n"; + //std::cout << "test3\n"; + typedef typename cT::value_type result_type; + output.push_back(result_type()); + assign(output.back(), polyData); + //std::cout << "test4\n"; + //std::cout << "delete " << at1->otherTailp_ << "\n"; + //at1->print(); + //at1->otherTailp_->print(); + delete at1->otherTailp_; + //at1->print(); + //at1->otherTailp_->print(); + //std::cout << "test5\n"; + //std::cout << "delete " << at1 << "\n"; + delete at1; + //std::cout << "test6\n"; + return 0; + } else { + //we are closing a hole, return the tail end active tail of the figure + return at1; + } + } + //we are not closing a figure + at1->pushPoint(point); + at1->join(at2); + delete at1; + delete at2; + return 0; + } + + inline void destroyContents() { + if(otherTailp_) { + //std::cout << "delete p " << tailp_ << "\n"; + if(tailp_) delete tailp_; + tailp_ = 0; + otherTailp_->otherTailp_ = 0; + otherTailp_->tailp_ = 0; + otherTailp_ = 0; + } + for(typename std::list::iterator itr = holesList_.begin(); itr != holesList_.end(); ++itr) { + //std::cout << "delete p " << (*itr) << "\n"; + if(*itr) { + if((*itr)->otherTailp_) { + delete (*itr)->otherTailp_; + (*itr)->otherTailp_ = 0; + } + delete (*itr); + } + (*itr) = 0; + } + holesList_.clear(); + } + + inline void print() { + //std::cout << this << " " << tailp_ << " " << otherTailp_ << " " << holesList_.size() << " " << head_ << "\n"; + } + + static inline std::pair createActiveTailsAsPair(Point point, bool solid, + active_tail_arbitrary* phole, bool fractureHoles) { + active_tail_arbitrary* at1 = 0; + active_tail_arbitrary* at2 = 0; + if(phole && fractureHoles) { + //std::cout << "adding hole\n"; + at1 = phole; + //assert solid == false, we should be creating a corner with solid below and to the left if there was a hole + at2 = at1->getOtherActiveTail(); + at2->pushPoint(point); + at1->pushPoint(point); + } else { + at1 = new active_tail_arbitrary(point, at2, solid); + at2 = new active_tail_arbitrary(at1); + at1->otherTailp_ = at2; + at2->head_ = !solid; + if(phole) + at2->addHole(phole); //assert fractureHoles == false + } + return std::pair(at1, at2); + } + + }; + + + typedef std::vector > vertex_arbitrary_count; + + class less_half_edge_count { + private: + Point pt_; + public: + typedef vertex_half_edge first_argument_type; + typedef vertex_half_edge second_argument_type; + typedef bool result_type; + inline less_half_edge_count() : pt_() {} + inline less_half_edge_count(Point point) : pt_(point) {} + inline bool operator () (const std::pair& elm1, const std::pair& elm2) const { + return scanline_base::less_slope(pt_.get(HORIZONTAL), pt_.get(VERTICAL), elm1.first, elm2.first); + } + }; + + static inline void sort_vertex_arbitrary_count(vertex_arbitrary_count& count, const Point& pt) { + less_half_edge_count lfec(pt); + polygon_sort(count.begin(), count.end(), lfec); + } + + typedef std::vector, int>, active_tail_arbitrary*> > incoming_count; + + class less_incoming_count { + private: + Point pt_; + public: + typedef std::pair, int>, active_tail_arbitrary*> first_argument_type; + typedef std::pair, int>, active_tail_arbitrary*> second_argument_type; + typedef bool result_type; + inline less_incoming_count() : pt_() {} + inline less_incoming_count(Point point) : pt_(point) {} + inline bool operator () (const std::pair, int>, active_tail_arbitrary*>& elm1, + const std::pair, int>, active_tail_arbitrary*>& elm2) const { + Unit dx1 = elm1.first.first.first.get(HORIZONTAL) - elm1.first.first.second.get(HORIZONTAL); + Unit dx2 = elm2.first.first.first.get(HORIZONTAL) - elm2.first.first.second.get(HORIZONTAL); + Unit dy1 = elm1.first.first.first.get(VERTICAL) - elm1.first.first.second.get(VERTICAL); + Unit dy2 = elm2.first.first.first.get(VERTICAL) - elm2.first.first.second.get(VERTICAL); + return scanline_base::less_slope(dx1, dy1, dx2, dy2); + } + }; + + static inline void sort_incoming_count(incoming_count& count, const Point& pt) { + less_incoming_count lfec(pt); + polygon_sort(count.begin(), count.end(), lfec); + } + + static inline void compact_vertex_arbitrary_count(const Point& pt, vertex_arbitrary_count &count) { + if(count.empty()) return; + vertex_arbitrary_count tmp; + tmp.reserve(count.size()); + tmp.push_back(count[0]); + //merge duplicates + for(std::size_t i = 1; i < count.size(); ++i) { + if(!equal_slope(pt.get(HORIZONTAL), pt.get(VERTICAL), tmp[i-1].first, count[i].first)) { + tmp.push_back(count[i]); + } else { + tmp.back().second += count[i].second; + } + } + count.clear(); + count.swap(tmp); + } + + // inline std::ostream& operator<< (std::ostream& o, const vertex_arbitrary_count& c) { +// for(unsinged int i = 0; i < c.size(); ++i) { +// o << c[i].first << " " << c[i].second << " "; +// } +// return o; +// } + + class vertex_arbitrary_compact { + public: + Point pt; + vertex_arbitrary_count count; + inline vertex_arbitrary_compact() : pt(), count() {} + inline vertex_arbitrary_compact(const Point& point, const Point& other_point, int countIn) : pt(point), count() { + count.push_back(std::pair(other_point, countIn)); + } + inline vertex_arbitrary_compact(const vertex_half_edge& vertex) : pt(vertex.pt), count() { + count.push_back(std::pair(vertex.other_pt, vertex.count)); + } + inline vertex_arbitrary_compact(const vertex_arbitrary_compact& vertex) : pt(vertex.pt), count(vertex.count) {} + inline vertex_arbitrary_compact& operator=(const vertex_arbitrary_compact& vertex){ + pt = vertex.pt; count = vertex.count; return *this; } + inline bool operator==(const vertex_arbitrary_compact& vertex) const { + return pt == vertex.pt && count == vertex.count; } + inline bool operator!=(const vertex_arbitrary_compact& vertex) const { return !((*this) == vertex); } + inline bool operator<(const vertex_arbitrary_compact& vertex) const { + if(pt.get(HORIZONTAL) < vertex.pt.get(HORIZONTAL)) return true; + if(pt.get(HORIZONTAL) == vertex.pt.get(HORIZONTAL)) { + return pt.get(VERTICAL) < vertex.pt.get(VERTICAL); + } + return false; + } + inline bool operator>(const vertex_arbitrary_compact& vertex) const { return vertex < (*this); } + inline bool operator<=(const vertex_arbitrary_compact& vertex) const { return !((*this) > vertex); } + inline bool operator>=(const vertex_arbitrary_compact& vertex) const { return !((*this) < vertex); } + inline bool have_vertex_half_edge(int index) const { return count[index]; } + inline vertex_half_edge operator[](int index) const { return vertex_half_edge(pt, count[index]); } + }; + +// inline std::ostream& operator<< (std::ostream& o, const vertex_arbitrary_compact& c) { +// o << c.pt << ", " << c.count; +// return o; +// } + + protected: + //definitions + typedef std::map scanline_data; + typedef typename scanline_data::iterator iterator; + typedef typename scanline_data::const_iterator const_iterator; + + //data + scanline_data scanData_; + Unit x_; + int justBefore_; + int fractureHoles_; + public: + inline polygon_arbitrary_formation() : + scanData_(), x_((std::numeric_limits::min)()), justBefore_(false), fractureHoles_(0) { + less_vertex_half_edge lessElm(&x_, &justBefore_); + scanData_ = scanline_data(lessElm); + } + inline polygon_arbitrary_formation(bool fractureHoles) : + scanData_(), x_((std::numeric_limits::min)()), justBefore_(false), fractureHoles_(fractureHoles) { + less_vertex_half_edge lessElm(&x_, &justBefore_); + scanData_ = scanline_data(lessElm); + } + inline polygon_arbitrary_formation(const polygon_arbitrary_formation& that) : + scanData_(), x_((std::numeric_limits::min)()), justBefore_(false), fractureHoles_(0) { (*this) = that; } + inline polygon_arbitrary_formation& operator=(const polygon_arbitrary_formation& that) { + x_ = that.x_; + justBefore_ = that.justBefore_; + fractureHoles_ = that.fractureHoles_; + less_vertex_half_edge lessElm(&x_, &justBefore_); + scanData_ = scanline_data(lessElm); + for(const_iterator itr = that.scanData_.begin(); itr != that.scanData_.end(); ++itr){ + scanData_.insert(scanData_.end(), *itr); + } + return *this; + } + + //cT is an output container of Polygon45 or Polygon45WithHoles + //iT is an iterator over vertex_half_edge elements + //inputBegin - inputEnd is a range of sorted iT that represents + //one or more scanline stops worth of data + template + void scan(cT& output, iT inputBegin, iT inputEnd) { + //std::cout << "1\n"; + while(inputBegin != inputEnd) { + //std::cout << "2\n"; + x_ = (*inputBegin).pt.get(HORIZONTAL); + //std::cout << "SCAN FORMATION " << x_ << "\n"; + //std::cout << "x_ = " << x_ << "\n"; + //std::cout << "scan line size: " << scanData_.size() << "\n"; + inputBegin = processEvent_(output, inputBegin, inputEnd); + } + //std::cout << "scan line size: " << scanData_.size() << "\n"; + } + + protected: + //functions + template + inline std::pair, active_tail_arbitrary*> processPoint_(cT& output, cT2& elements, Point point, + incoming_count& counts_from_scanline, vertex_arbitrary_count& incoming_count) { + //std::cout << "\nAT POINT: " << point << "\n"; + //join any closing solid corners + std::vector counts; + std::vector incoming; + std::vector tails; + counts.reserve(counts_from_scanline.size()); + tails.reserve(counts_from_scanline.size()); + incoming.reserve(incoming_count.size()); + for(std::size_t i = 0; i < counts_from_scanline.size(); ++i) { + counts.push_back(counts_from_scanline[i].first.second); + tails.push_back(counts_from_scanline[i].second); + } + for(std::size_t i = 0; i < incoming_count.size(); ++i) { + incoming.push_back(incoming_count[i].second); + if(incoming_count[i].first < point) { + incoming.back() = 0; + } + } + + active_tail_arbitrary* returnValue = 0; + std::pair returnCount(Point(0, 0), 0); + int i_size_less_1 = (int)(incoming.size()) -1; + int c_size_less_1 = (int)(counts.size()) -1; + int i_size = incoming.size(); + int c_size = counts.size(); + + bool have_vertical_tail_from_below = false; + if(c_size && + scanline_base::is_vertical(counts_from_scanline.back().first.first)) { + have_vertical_tail_from_below = true; + } + //assert size = size_less_1 + 1 + //std::cout << tails.size() << " " << incoming.size() << " " << counts_from_scanline.size() << " " << incoming_count.size() << "\n"; + // for(std::size_t i = 0; i < counts.size(); ++i) { + // std::cout << counts_from_scanline[i].first.first.first.get(HORIZONTAL) << ","; + // std::cout << counts_from_scanline[i].first.first.first.get(VERTICAL) << " "; + // std::cout << counts_from_scanline[i].first.first.second.get(HORIZONTAL) << ","; + // std::cout << counts_from_scanline[i].first.first.second.get(VERTICAL) << ":"; + // std::cout << counts_from_scanline[i].first.second << " "; + // } std::cout << "\n"; + // print(incoming_count); + { + for(int i = 0; i < c_size_less_1; ++i) { + //std::cout << i << "\n"; + if(counts[i] == -1) { + //std::cout << "fixed i\n"; + for(int j = i + 1; j < c_size; ++j) { + //std::cout << j << "\n"; + if(counts[j]) { + if(counts[j] == 1) { + //std::cout << "case1: " << i << " " << j << "\n"; + //if a figure is closed it will be written out by this function to output + active_tail_arbitrary::joinChains(point, tails[i], tails[j], true, output); + counts[i] = 0; + counts[j] = 0; + tails[i] = 0; + tails[j] = 0; + } + break; + } + } + } + } + } + //find any pairs of incoming edges that need to create pair for leading solid + //std::cout << "checking case2\n"; + { + for(int i = 0; i < i_size_less_1; ++i) { + //std::cout << i << "\n"; + if(incoming[i] == 1) { + //std::cout << "fixed i\n"; + for(int j = i + 1; j < i_size; ++j) { + //std::cout << j << "\n"; + if(incoming[j]) { + //std::cout << incoming[j] << "\n"; + if(incoming[j] == -1) { + //std::cout << "case2: " << i << " " << j << "\n"; + //std::cout << "creating active tail pair\n"; + std::pair tailPair = + active_tail_arbitrary::createActiveTailsAsPair(point, true, 0, fractureHoles_ != 0); + //tailPair.first->print(); + //tailPair.second->print(); + if(j == i_size_less_1 && incoming_count[j].first.get(HORIZONTAL) == point.get(HORIZONTAL)) { + //vertical active tail becomes return value + returnValue = tailPair.first; + returnCount.first = point; + returnCount.second = 1; + } else { + //std::cout << "new element " << j-1 << " " << -1 << "\n"; + //std::cout << point << " " << incoming_count[j].first << "\n"; + elements.push_back(std::pair(vertex_half_edge(point, + incoming_count[j].first, -1), tailPair.first)); + } + //std::cout << "new element " << i-1 << " " << 1 << "\n"; + //std::cout << point << " " << incoming_count[i].first << "\n"; + elements.push_back(std::pair(vertex_half_edge(point, + incoming_count[i].first, 1), tailPair.second)); + incoming[i] = 0; + incoming[j] = 0; + } + break; + } + } + } + } + } + //find any active tail that needs to pass through to an incoming edge + //we expect to find no more than two pass through + + //find pass through with solid on top + { + //std::cout << "checking case 3\n"; + for(int i = 0; i < c_size; ++i) { + //std::cout << i << "\n"; + if(counts[i] != 0) { + if(counts[i] == 1) { + //std::cout << "fixed i\n"; + for(int j = i_size_less_1; j >= 0; --j) { + if(incoming[j] != 0) { + if(incoming[j] == 1) { + //std::cout << "case3: " << i << " " << j << "\n"; + //tails[i]->print(); + //pass through solid on top + tails[i]->pushPoint(point); + //std::cout << "after push\n"; + if(j == i_size_less_1 && incoming_count[j].first.get(HORIZONTAL) == point.get(HORIZONTAL)) { + returnValue = tails[i]; + returnCount.first = point; + returnCount.second = -1; + } else { + elements.push_back(std::pair(vertex_half_edge(point, + incoming_count[j].first, incoming[j]), tails[i])); + } + tails[i] = 0; + counts[i] = 0; + incoming[j] = 0; + } + break; + } + } + } + break; + } + } + } + //std::cout << "checking case 4\n"; + //find pass through with solid on bottom + { + for(int i = c_size_less_1; i >= 0; --i) { + //std::cout << "i = " << i << " with count " << counts[i] << "\n"; + if(counts[i] != 0) { + if(counts[i] == -1) { + for(int j = 0; j < i_size; ++j) { + if(incoming[j] != 0) { + if(incoming[j] == -1) { + //std::cout << "case4: " << i << " " << j << "\n"; + //pass through solid on bottom + tails[i]->pushPoint(point); + if(j == i_size_less_1 && incoming_count[j].first.get(HORIZONTAL) == point.get(HORIZONTAL)) { + returnValue = tails[i]; + returnCount.first = point; + returnCount.second = 1; + } else { + //std::cout << "new element " << j-1 << " " << incoming[j] << "\n"; + //std::cout << point << " " << incoming_count[j].first << "\n"; + elements.push_back(std::pair(vertex_half_edge(point, + incoming_count[j].first, incoming[j]), tails[i])); + } + tails[i] = 0; + counts[i] = 0; + incoming[j] = 0; + } + break; + } + } + } + break; + } + } + } + //find the end of a hole or the beginning of a hole + + //find end of a hole + { + for(int i = 0; i < c_size_less_1; ++i) { + if(counts[i] != 0) { + for(int j = i+1; j < c_size; ++j) { + if(counts[j] != 0) { + //std::cout << "case5: " << i << " " << j << "\n"; + //we are ending a hole and may potentially close a figure and have to handle the hole + returnValue = active_tail_arbitrary::joinChains(point, tails[i], tails[j], false, output); + if(returnValue) returnCount.first = point; + //std::cout << returnValue << "\n"; + tails[i] = 0; + tails[j] = 0; + counts[i] = 0; + counts[j] = 0; + break; + } + } + break; + } + } + } + //find beginning of a hole + { + for(int i = 0; i < i_size_less_1; ++i) { + if(incoming[i] != 0) { + for(int j = i+1; j < i_size; ++j) { + if(incoming[j] != 0) { + //std::cout << "case6: " << i << " " << j << "\n"; + //we are beginning a empty space + active_tail_arbitrary* holep = 0; + //if(c_size && counts[c_size_less_1] == 0 && + // counts_from_scanline[c_size_less_1].first.first.first.get(HORIZONTAL) == point.get(HORIZONTAL)) + if(have_vertical_tail_from_below) { + holep = tails[c_size_less_1]; + tails[c_size_less_1] = 0; + have_vertical_tail_from_below = false; + } + std::pair tailPair = + active_tail_arbitrary::createActiveTailsAsPair(point, false, holep, fractureHoles_ != 0); + if(j == i_size_less_1 && incoming_count[j].first.get(HORIZONTAL) == point.get(HORIZONTAL)) { + //std::cout << "vertical element " << point << "\n"; + returnValue = tailPair.first; + returnCount.first = point; + //returnCount = incoming_count[j]; + returnCount.second = -1; + } else { + //std::cout << "new element " << j-1 << " " << incoming[j] << "\n"; + //std::cout << point << " " << incoming_count[j].first << "\n"; + elements.push_back(std::pair(vertex_half_edge(point, + incoming_count[j].first, incoming[j]), tailPair.first)); + } + //std::cout << "new element " << i-1 << " " << incoming[i] << "\n"; + //std::cout << point << " " << incoming_count[i].first << "\n"; + elements.push_back(std::pair(vertex_half_edge(point, + incoming_count[i].first, incoming[i]), tailPair.second)); + incoming[i] = 0; + incoming[j] = 0; + break; + } + } + break; + } + } + } + if(have_vertical_tail_from_below) { + if(tails.back()) { + tails.back()->pushPoint(point); + returnValue = tails.back(); + returnCount.first = point; + returnCount.second = counts.back(); + } + } + //assert that tails, counts and incoming are all null + return std::pair, active_tail_arbitrary*>(returnCount, returnValue); + } + + static inline void print(const vertex_arbitrary_count& count) { + for(unsigned i = 0; i < count.size(); ++i) { + //std::cout << count[i].first.get(HORIZONTAL) << ","; + //std::cout << count[i].first.get(VERTICAL) << ":"; + //std::cout << count[i].second << " "; + } //std::cout << "\n"; + } + + static inline void print(const scanline_data& data) { + for(typename scanline_data::const_iterator itr = data.begin(); itr != data.end(); ++itr){ + //std::cout << itr->first.pt << ", " << itr->first.other_pt << "; "; + } //std::cout << "\n"; + } + + template + inline iT processEvent_(cT& output, iT inputBegin, iT inputEnd) { + typedef typename high_precision_type::type high_precision; + //std::cout << "processEvent_\n"; + justBefore_ = true; + //collect up all elements from the tree that are at the y + //values of events in the input queue + //create vector of new elements to add into tree + active_tail_arbitrary* verticalTail = 0; + std::pair verticalCount(Point(0, 0), 0); + iT currentIter = inputBegin; + std::vector elementIters; + std::vector > elements; + while(currentIter != inputEnd && currentIter->pt.get(HORIZONTAL) == x_) { + //std::cout << "loop\n"; + Unit currentY = (*currentIter).pt.get(VERTICAL); + //std::cout << "current Y " << currentY << "\n"; + //std::cout << "scanline size " << scanData_.size() << "\n"; + //print(scanData_); + iterator iter = lookUp_(currentY); + //std::cout << "found element in scanline " << (iter != scanData_.end()) << "\n"; + //int counts[4] = {0, 0, 0, 0}; + incoming_count counts_from_scanline; + //std::cout << "finding elements in tree\n"; + //if(iter != scanData_.end()) + // std::cout << "first iter y is " << iter->first.evalAtX(x_) << "\n"; + while(iter != scanData_.end() && + ((iter->first.pt.x() == x_ && iter->first.pt.y() == currentY) || + (iter->first.other_pt.x() == x_ && iter->first.other_pt.y() == currentY))) { + //iter->first.evalAtX(x_) == (high_precision)currentY) { + //std::cout << "loop2\n"; + elementIters.push_back(iter); + counts_from_scanline.push_back(std::pair, int>, active_tail_arbitrary*> + (std::pair, int>(std::pair(iter->first.pt, + iter->first.other_pt), + iter->first.count), + iter->second)); + ++iter; + } + Point currentPoint(x_, currentY); + //std::cout << "counts_from_scanline size " << counts_from_scanline.size() << "\n"; + sort_incoming_count(counts_from_scanline, currentPoint); + + vertex_arbitrary_count incoming; + //std::cout << "aggregating\n"; + do { + //std::cout << "loop3\n"; + const vertex_half_edge& elem = *currentIter; + incoming.push_back(std::pair(elem.other_pt, elem.count)); + ++currentIter; + } while(currentIter != inputEnd && currentIter->pt.get(VERTICAL) == currentY && + currentIter->pt.get(HORIZONTAL) == x_); + //print(incoming); + sort_vertex_arbitrary_count(incoming, currentPoint); + //std::cout << currentPoint.get(HORIZONTAL) << "," << currentPoint.get(VERTICAL) << "\n"; + //print(incoming); + //std::cout << "incoming counts from input size " << incoming.size() << "\n"; + //compact_vertex_arbitrary_count(currentPoint, incoming); + vertex_arbitrary_count tmp; + tmp.reserve(incoming.size()); + for(std::size_t i = 0; i < incoming.size(); ++i) { + if(currentPoint < incoming[i].first) { + tmp.push_back(incoming[i]); + } + } + incoming.swap(tmp); + //std::cout << "incoming counts from input size " << incoming.size() << "\n"; + //now counts_from_scanline has the data from the left and + //incoming has the data from the right at this point + //cancel out any end points + if(verticalTail) { + //std::cout << "adding vertical tail to counts from scanline\n"; + //std::cout << -verticalCount.second << "\n"; + counts_from_scanline.push_back(std::pair, int>, active_tail_arbitrary*> + (std::pair, int>(std::pair(verticalCount.first, + currentPoint), + -verticalCount.second), + verticalTail)); + } + if(!incoming.empty() && incoming.back().first.get(HORIZONTAL) == x_) { + //std::cout << "inverted vertical event\n"; + incoming.back().second *= -1; + } + //std::cout << "calling processPoint_\n"; + std::pair, active_tail_arbitrary*> result = processPoint_(output, elements, Point(x_, currentY), counts_from_scanline, incoming); + verticalCount = result.first; + verticalTail = result.second; + //if(verticalTail) { + // std::cout << "have vertical tail\n"; + // std::cout << verticalCount.second << "\n"; + //} + if(verticalTail && !(verticalCount.second)) { + //we got a hole out of the point we just processed + //iter is still at the next y element above the current y value in the tree + //std::cout << "checking whether ot handle hole\n"; + if(currentIter == inputEnd || + currentIter->pt.get(HORIZONTAL) != x_ || + scanline_base::on_above_or_below(currentIter->pt, half_edge(iter->first.pt, iter->first.other_pt)) != -1) { + //(high_precision)(currentIter->pt.get(VERTICAL)) >= iter->first.evalAtX(x_)) { + + //std::cout << "handle hole here\n"; + if(fractureHoles_) { + //std::cout << "fracture hole here\n"; + //we need to handle the hole now and not at the next input vertex + active_tail_arbitrary* at = iter->second; + high_precision precise_y = iter->first.evalAtX(x_); + Unit fracture_y = convert_high_precision_type(precise_y); + if(precise_y < fracture_y) --fracture_y; + Point point(x_, fracture_y); + verticalTail->getOtherActiveTail()->pushPoint(point); + iter->second = verticalTail->getOtherActiveTail(); + at->pushPoint(point); + verticalTail->join(at); + delete at; + delete verticalTail; + verticalTail = 0; + } else { + //std::cout << "push hole onto list\n"; + iter->second->addHole(verticalTail); + verticalTail = 0; + } + } + } + } + //std::cout << "erasing\n"; + //erase all elements from the tree + for(typename std::vector::iterator iter = elementIters.begin(); + iter != elementIters.end(); ++iter) { + //std::cout << "erasing loop\n"; + scanData_.erase(*iter); + } + //switch comparison tie breaking policy + justBefore_ = false; + //add new elements into tree + //std::cout << "inserting\n"; + for(typename std::vector >::iterator iter = elements.begin(); + iter != elements.end(); ++iter) { + //std::cout << "inserting loop\n"; + scanData_.insert(scanData_.end(), *iter); + } + //std::cout << "end processEvent\n"; + return currentIter; + } + + inline iterator lookUp_(Unit y){ + //if just before then we need to look from 1 not -1 + //std::cout << "just before " << justBefore_ << "\n"; + return scanData_.lower_bound(vertex_half_edge(Point(x_, y), Point(x_, y+1), 0)); + } + + public: //test functions + + template + static inline bool testPolygonArbitraryFormationRect(stream_type& stdcout) { + stdcout << "testing polygon formation\n"; + polygon_arbitrary_formation pf(true); + std::vector > polys; + std::vector data; + data.push_back(vertex_half_edge(Point(0, 0), Point(10, 0), 1)); + data.push_back(vertex_half_edge(Point(0, 0), Point(0, 10), 1)); + data.push_back(vertex_half_edge(Point(0, 10), Point(0, 0), -1)); + data.push_back(vertex_half_edge(Point(0, 10), Point(10, 10), -1)); + data.push_back(vertex_half_edge(Point(10, 0), Point(0, 0), -1)); + data.push_back(vertex_half_edge(Point(10, 0), Point(10, 10), -1)); + data.push_back(vertex_half_edge(Point(10, 10), Point(10, 0), 1)); + data.push_back(vertex_half_edge(Point(10, 10), Point(0, 10), 1)); + polygon_sort(data.begin(), data.end()); + pf.scan(polys, data.begin(), data.end()); + stdcout << "result size: " << polys.size() << "\n"; + for(std::size_t i = 0; i < polys.size(); ++i) { + stdcout << polys[i] << "\n"; + } + stdcout << "done testing polygon formation\n"; + return true; + } + + template + static inline bool testPolygonArbitraryFormationP1(stream_type& stdcout) { + stdcout << "testing polygon formation P1\n"; + polygon_arbitrary_formation pf(true); + std::vector > polys; + std::vector data; + data.push_back(vertex_half_edge(Point(0, 0), Point(10, 10), 1)); + data.push_back(vertex_half_edge(Point(0, 0), Point(0, 10), 1)); + data.push_back(vertex_half_edge(Point(0, 10), Point(0, 0), -1)); + data.push_back(vertex_half_edge(Point(0, 10), Point(10, 20), -1)); + data.push_back(vertex_half_edge(Point(10, 10), Point(0, 0), -1)); + data.push_back(vertex_half_edge(Point(10, 10), Point(10, 20), -1)); + data.push_back(vertex_half_edge(Point(10, 20), Point(10, 10), 1)); + data.push_back(vertex_half_edge(Point(10, 20), Point(0, 10), 1)); + polygon_sort(data.begin(), data.end()); + pf.scan(polys, data.begin(), data.end()); + stdcout << "result size: " << polys.size() << "\n"; + for(std::size_t i = 0; i < polys.size(); ++i) { + stdcout << polys[i] << "\n"; + } + stdcout << "done testing polygon formation\n"; + return true; + } + + template + static inline bool testPolygonArbitraryFormationP2(stream_type& stdcout) { + stdcout << "testing polygon formation P2\n"; + polygon_arbitrary_formation pf(true); + std::vector > polys; + std::vector data; + data.push_back(vertex_half_edge(Point(-3, 1), Point(2, -4), 1)); + data.push_back(vertex_half_edge(Point(-3, 1), Point(-2, 2), -1)); + data.push_back(vertex_half_edge(Point(-2, 2), Point(2, 4), -1)); + data.push_back(vertex_half_edge(Point(-2, 2), Point(-3, 1), 1)); + data.push_back(vertex_half_edge(Point(2, -4), Point(-3, 1), -1)); + data.push_back(vertex_half_edge(Point(2, -4), Point(2, 4), -1)); + data.push_back(vertex_half_edge(Point(2, 4), Point(-2, 2), 1)); + data.push_back(vertex_half_edge(Point(2, 4), Point(2, -4), 1)); + polygon_sort(data.begin(), data.end()); + pf.scan(polys, data.begin(), data.end()); + stdcout << "result size: " << polys.size() << "\n"; + for(std::size_t i = 0; i < polys.size(); ++i) { + stdcout << polys[i] << "\n"; + } + stdcout << "done testing polygon formation\n"; + return true; + } + + + template + static inline bool testPolygonArbitraryFormationPolys(stream_type& stdcout) { + stdcout << "testing polygon formation polys\n"; + polygon_arbitrary_formation pf(false); + std::vector > polys; + polygon_arbitrary_formation pf2(true); + std::vector > polys2; + std::vector data; + data.push_back(vertex_half_edge(Point(0, 0), Point(100, 1), 1)); + data.push_back(vertex_half_edge(Point(0, 0), Point(1, 100), -1)); + data.push_back(vertex_half_edge(Point(1, 100), Point(0, 0), 1)); + data.push_back(vertex_half_edge(Point(1, 100), Point(101, 101), -1)); + data.push_back(vertex_half_edge(Point(100, 1), Point(0, 0), -1)); + data.push_back(vertex_half_edge(Point(100, 1), Point(101, 101), 1)); + data.push_back(vertex_half_edge(Point(101, 101), Point(100, 1), -1)); + data.push_back(vertex_half_edge(Point(101, 101), Point(1, 100), 1)); + + data.push_back(vertex_half_edge(Point(2, 2), Point(10, 2), -1)); + data.push_back(vertex_half_edge(Point(2, 2), Point(2, 10), -1)); + data.push_back(vertex_half_edge(Point(2, 10), Point(2, 2), 1)); + data.push_back(vertex_half_edge(Point(2, 10), Point(10, 10), 1)); + data.push_back(vertex_half_edge(Point(10, 2), Point(2, 2), 1)); + data.push_back(vertex_half_edge(Point(10, 2), Point(10, 10), 1)); + data.push_back(vertex_half_edge(Point(10, 10), Point(10, 2), -1)); + data.push_back(vertex_half_edge(Point(10, 10), Point(2, 10), -1)); + + data.push_back(vertex_half_edge(Point(2, 12), Point(10, 12), -1)); + data.push_back(vertex_half_edge(Point(2, 12), Point(2, 22), -1)); + data.push_back(vertex_half_edge(Point(2, 22), Point(2, 12), 1)); + data.push_back(vertex_half_edge(Point(2, 22), Point(10, 22), 1)); + data.push_back(vertex_half_edge(Point(10, 12), Point(2, 12), 1)); + data.push_back(vertex_half_edge(Point(10, 12), Point(10, 22), 1)); + data.push_back(vertex_half_edge(Point(10, 22), Point(10, 12), -1)); + data.push_back(vertex_half_edge(Point(10, 22), Point(2, 22), -1)); + + polygon_sort(data.begin(), data.end()); + pf.scan(polys, data.begin(), data.end()); + stdcout << "result size: " << polys.size() << "\n"; + for(std::size_t i = 0; i < polys.size(); ++i) { + stdcout << polys[i] << "\n"; + } + pf2.scan(polys2, data.begin(), data.end()); + stdcout << "result size: " << polys2.size() << "\n"; + for(std::size_t i = 0; i < polys2.size(); ++i) { + stdcout << polys2[i] << "\n"; + } + stdcout << "done testing polygon formation\n"; + return true; + } + + template + static inline bool testPolygonArbitraryFormationSelfTouch1(stream_type& stdcout) { + stdcout << "testing polygon formation self touch 1\n"; + polygon_arbitrary_formation pf(true); + std::vector > polys; + std::vector data; + data.push_back(vertex_half_edge(Point(0, 0), Point(10, 0), 1)); + data.push_back(vertex_half_edge(Point(0, 0), Point(0, 10), 1)); + + data.push_back(vertex_half_edge(Point(0, 10), Point(0, 0), -1)); + data.push_back(vertex_half_edge(Point(0, 10), Point(5, 10), -1)); + + data.push_back(vertex_half_edge(Point(10, 0), Point(0, 0), -1)); + data.push_back(vertex_half_edge(Point(10, 0), Point(10, 5), -1)); + + data.push_back(vertex_half_edge(Point(10, 5), Point(10, 0), 1)); + data.push_back(vertex_half_edge(Point(10, 5), Point(5, 5), 1)); + + data.push_back(vertex_half_edge(Point(5, 10), Point(5, 5), 1)); + data.push_back(vertex_half_edge(Point(5, 10), Point(0, 10), 1)); + + data.push_back(vertex_half_edge(Point(5, 2), Point(5, 5), -1)); + data.push_back(vertex_half_edge(Point(5, 2), Point(7, 2), -1)); + + data.push_back(vertex_half_edge(Point(5, 5), Point(5, 10), -1)); + data.push_back(vertex_half_edge(Point(5, 5), Point(5, 2), 1)); + data.push_back(vertex_half_edge(Point(5, 5), Point(10, 5), -1)); + data.push_back(vertex_half_edge(Point(5, 5), Point(7, 2), 1)); + + data.push_back(vertex_half_edge(Point(7, 2), Point(5, 5), -1)); + data.push_back(vertex_half_edge(Point(7, 2), Point(5, 2), 1)); + + polygon_sort(data.begin(), data.end()); + pf.scan(polys, data.begin(), data.end()); + stdcout << "result size: " << polys.size() << "\n"; + for(std::size_t i = 0; i < polys.size(); ++i) { + stdcout << polys[i] << "\n"; + } + stdcout << "done testing polygon formation\n"; + return true; + } + + template + static inline bool testPolygonArbitraryFormationSelfTouch2(stream_type& stdcout) { + stdcout << "testing polygon formation self touch 2\n"; + polygon_arbitrary_formation pf(true); + std::vector > polys; + std::vector data; + data.push_back(vertex_half_edge(Point(0, 0), Point(10, 0), 1)); + data.push_back(vertex_half_edge(Point(0, 0), Point(0, 10), 1)); + + data.push_back(vertex_half_edge(Point(0, 10), Point(0, 0), -1)); + data.push_back(vertex_half_edge(Point(0, 10), Point(5, 10), -1)); + + data.push_back(vertex_half_edge(Point(10, 0), Point(0, 0), -1)); + data.push_back(vertex_half_edge(Point(10, 0), Point(10, 5), -1)); + + data.push_back(vertex_half_edge(Point(10, 5), Point(10, 0), 1)); + data.push_back(vertex_half_edge(Point(10, 5), Point(5, 5), 1)); + + data.push_back(vertex_half_edge(Point(5, 10), Point(4, 1), -1)); + data.push_back(vertex_half_edge(Point(5, 10), Point(0, 10), 1)); + + data.push_back(vertex_half_edge(Point(4, 1), Point(5, 10), 1)); + data.push_back(vertex_half_edge(Point(4, 1), Point(7, 2), -1)); + + data.push_back(vertex_half_edge(Point(5, 5), Point(10, 5), -1)); + data.push_back(vertex_half_edge(Point(5, 5), Point(7, 2), 1)); + + data.push_back(vertex_half_edge(Point(7, 2), Point(5, 5), -1)); + data.push_back(vertex_half_edge(Point(7, 2), Point(4, 1), 1)); + + polygon_sort(data.begin(), data.end()); + pf.scan(polys, data.begin(), data.end()); + stdcout << "result size: " << polys.size() << "\n"; + for(std::size_t i = 0; i < polys.size(); ++i) { + stdcout << polys[i] << "\n"; + } + stdcout << "done testing polygon formation\n"; + return true; + } + + template + static inline bool testPolygonArbitraryFormationSelfTouch3(stream_type& stdcout) { + stdcout << "testing polygon formation self touch 3\n"; + polygon_arbitrary_formation pf(true); + std::vector > polys; + std::vector data; + data.push_back(vertex_half_edge(Point(0, 0), Point(10, 0), 1)); + data.push_back(vertex_half_edge(Point(0, 0), Point(0, 10), 1)); + + data.push_back(vertex_half_edge(Point(0, 10), Point(0, 0), -1)); + data.push_back(vertex_half_edge(Point(0, 10), Point(6, 10), -1)); + + data.push_back(vertex_half_edge(Point(10, 0), Point(0, 0), -1)); + data.push_back(vertex_half_edge(Point(10, 0), Point(10, 5), -1)); + + data.push_back(vertex_half_edge(Point(10, 5), Point(10, 0), 1)); + data.push_back(vertex_half_edge(Point(10, 5), Point(5, 5), 1)); + + data.push_back(vertex_half_edge(Point(6, 10), Point(4, 1), -1)); + data.push_back(vertex_half_edge(Point(6, 10), Point(0, 10), 1)); + + data.push_back(vertex_half_edge(Point(4, 1), Point(6, 10), 1)); + data.push_back(vertex_half_edge(Point(4, 1), Point(7, 2), -1)); + + data.push_back(vertex_half_edge(Point(5, 5), Point(10, 5), -1)); + data.push_back(vertex_half_edge(Point(5, 5), Point(7, 2), 1)); + + data.push_back(vertex_half_edge(Point(7, 2), Point(5, 5), -1)); + data.push_back(vertex_half_edge(Point(7, 2), Point(4, 1), 1)); + + polygon_sort(data.begin(), data.end()); + pf.scan(polys, data.begin(), data.end()); + stdcout << "result size: " << polys.size() << "\n"; + for(std::size_t i = 0; i < polys.size(); ++i) { + stdcout << polys[i] << "\n"; + } + stdcout << "done testing polygon formation\n"; + return true; + } + + template + static inline bool testPolygonArbitraryFormationColinear(stream_type& stdcout) { + stdcout << "testing polygon formation colinear 3\n"; + stdcout << "Polygon Set Data { <-3 2, -2 2>:1 <-3 2, -1 4>:-1 <-2 2, 0 2>:1 <-1 4, 0 2>:-1 } \n"; + polygon_arbitrary_formation pf(true); + std::vector > polys; + std::vector data; + data.push_back(vertex_half_edge(Point(-3, 2), Point(-2, 2), 1)); + data.push_back(vertex_half_edge(Point(-2, 2), Point(-3, 2), -1)); + + data.push_back(vertex_half_edge(Point(-3, 2), Point(-1, 4), -1)); + data.push_back(vertex_half_edge(Point(-1, 4), Point(-3, 2), 1)); + + data.push_back(vertex_half_edge(Point(-2, 2), Point(0, 2), 1)); + data.push_back(vertex_half_edge(Point(0, 2), Point(-2, 2), -1)); + + data.push_back(vertex_half_edge(Point(-1, 4), Point(0, 2), -1)); + data.push_back(vertex_half_edge(Point(0, 2), Point(-1, 4), 1)); + polygon_sort(data.begin(), data.end()); + pf.scan(polys, data.begin(), data.end()); + stdcout << "result size: " << polys.size() << "\n"; + for(std::size_t i = 0; i < polys.size(); ++i) { + stdcout << polys[i] << "\n"; + } + stdcout << "done testing polygon formation\n"; + return true; + } + + template + static inline bool testSegmentIntersection(stream_type& stdcout) { + stdcout << "testing segment intersection\n"; + half_edge he1, he2; + he1.first = Point(0, 0); + he1.second = Point(10, 10); + he2.first = Point(0, 0); + he2.second = Point(10, 20); + Point result; + bool b = scanline_base::compute_intersection(result, he1, he2); + if(!b || result != Point(0, 0)) return false; + he1.first = Point(0, 10); + b = scanline_base::compute_intersection(result, he1, he2); + if(!b || result != Point(5, 10)) return false; + he1.first = Point(0, 11); + b = scanline_base::compute_intersection(result, he1, he2); + if(!b || result != Point(5, 10)) return false; + he1.first = Point(0, 0); + he1.second = Point(1, 9); + he2.first = Point(0, 9); + he2.second = Point(1, 0); + b = scanline_base::compute_intersection(result, he1, he2); + if(!b || result != Point(0, 4)) return false; + + he1.first = Point(0, -10); + he1.second = Point(1, -1); + he2.first = Point(0, -1); + he2.second = Point(1, -10); + b = scanline_base::compute_intersection(result, he1, he2); + if(!b || result != Point(0, -5)) return false; + he1.first = Point((std::numeric_limits::max)(), (std::numeric_limits::max)()-1); + he1.second = Point((std::numeric_limits::min)(), (std::numeric_limits::max)()); + //he1.second = Point(0, (std::numeric_limits::max)()); + he2.first = Point((std::numeric_limits::max)()-1, (std::numeric_limits::max)()); + he2.second = Point((std::numeric_limits::max)(), (std::numeric_limits::min)()); + //he2.second = Point((std::numeric_limits::max)(), 0); + b = scanline_base::compute_intersection(result, he1, he2); + //b is false because of overflow error + he1.first = Point(1000, 2000); + he1.second = Point(1010, 2010); + he2.first = Point(1000, 2000); + he2.second = Point(1010, 2020); + b = scanline_base::compute_intersection(result, he1, he2); + if(!b || result != Point(1000, 2000)) return false; + + return b; + } + + }; + + template + class poly_line_arbitrary_hole_data { + private: + typedef typename polygon_arbitrary_formation::active_tail_arbitrary active_tail_arbitrary; + active_tail_arbitrary* p_; + public: + typedef point_data Point; + typedef Point point_type; + typedef Unit coordinate_type; + typedef typename active_tail_arbitrary::iterator iterator_type; + //typedef iterator_points_to_compact compact_iterator_type; + + typedef iterator_type iterator; + inline poly_line_arbitrary_hole_data() : p_(0) {} + inline poly_line_arbitrary_hole_data(active_tail_arbitrary* p) : p_(p) {} + //use default copy and assign + inline iterator begin() const { return p_->getTail()->begin(); } + inline iterator end() const { return p_->getTail()->end(); } + inline std::size_t size() const { return 0; } + }; + + template + class poly_line_arbitrary_polygon_data { + private: + typedef typename polygon_arbitrary_formation::active_tail_arbitrary active_tail_arbitrary; + active_tail_arbitrary* p_; + public: + typedef point_data Point; + typedef Point point_type; + typedef Unit coordinate_type; + typedef typename active_tail_arbitrary::iterator iterator_type; + //typedef iterator_points_to_compact compact_iterator_type; + typedef typename coordinate_traits::coordinate_distance area_type; + + class iterator_holes_type { + private: + typedef poly_line_arbitrary_hole_data holeType; + mutable holeType hole_; + typename active_tail_arbitrary::iteratorHoles itr_; + + public: + typedef std::forward_iterator_tag iterator_category; + typedef holeType value_type; + typedef std::ptrdiff_t difference_type; + typedef const holeType* pointer; //immutable + typedef const holeType& reference; //immutable + inline iterator_holes_type() : hole_(), itr_() {} + inline iterator_holes_type(typename active_tail_arbitrary::iteratorHoles itr) : hole_(), itr_(itr) {} + inline iterator_holes_type(const iterator_holes_type& that) : hole_(that.hole_), itr_(that.itr_) {} + inline iterator_holes_type& operator=(const iterator_holes_type& that) { + itr_ = that.itr_; + return *this; + } + inline bool operator==(const iterator_holes_type& that) { return itr_ == that.itr_; } + inline bool operator!=(const iterator_holes_type& that) { return itr_ != that.itr_; } + inline iterator_holes_type& operator++() { + ++itr_; + return *this; + } + inline const iterator_holes_type operator++(int) { + iterator_holes_type tmp = *this; + ++(*this); + return tmp; + } + inline reference operator*() { + hole_ = holeType(*itr_); + return hole_; + } + }; + + typedef poly_line_arbitrary_hole_data hole_type; + + inline poly_line_arbitrary_polygon_data() : p_(0) {} + inline poly_line_arbitrary_polygon_data(active_tail_arbitrary* p) : p_(p) {} + //use default copy and assign + inline iterator_type begin() const { return p_->getTail()->begin(); } + inline iterator_type end() const { return p_->getTail()->end(); } + //inline compact_iterator_type begin_compact() const { return p_->getTail()->begin(); } + //inline compact_iterator_type end_compact() const { return p_->getTail()->end(); } + inline iterator_holes_type begin_holes() const { return iterator_holes_type(p_->getHoles().begin()); } + inline iterator_holes_type end_holes() const { return iterator_holes_type(p_->getHoles().end()); } + inline active_tail_arbitrary* yield() { return p_; } + //stub out these four required functions that will not be used but are needed for the interface + inline std::size_t size_holes() const { return 0; } + inline std::size_t size() const { return 0; } + }; + + template + class trapezoid_arbitrary_formation : public polygon_arbitrary_formation { + private: + typedef typename scanline_base::Point Point; + typedef typename scanline_base::half_edge half_edge; + typedef typename scanline_base::vertex_half_edge vertex_half_edge; + typedef typename scanline_base::less_vertex_half_edge less_vertex_half_edge; + + typedef typename polygon_arbitrary_formation::poly_line_arbitrary poly_line_arbitrary; + + typedef typename polygon_arbitrary_formation::active_tail_arbitrary active_tail_arbitrary; + + typedef std::vector > vertex_arbitrary_count; + + typedef typename polygon_arbitrary_formation::less_half_edge_count less_half_edge_count; + + typedef std::vector, int>, active_tail_arbitrary*> > incoming_count; + + typedef typename polygon_arbitrary_formation::less_incoming_count less_incoming_count; + + typedef typename polygon_arbitrary_formation::vertex_arbitrary_compact vertex_arbitrary_compact; + + private: + //definitions + typedef std::map scanline_data; + typedef typename scanline_data::iterator iterator; + typedef typename scanline_data::const_iterator const_iterator; + + //data + public: + inline trapezoid_arbitrary_formation() : polygon_arbitrary_formation() {} + inline trapezoid_arbitrary_formation(const trapezoid_arbitrary_formation& that) : polygon_arbitrary_formation(that) {} + inline trapezoid_arbitrary_formation& operator=(const trapezoid_arbitrary_formation& that) { + * static_cast*>(this) = * static_cast*>(&that); + return *this; + } + + //cT is an output container of Polygon45 or Polygon45WithHoles + //iT is an iterator over vertex_half_edge elements + //inputBegin - inputEnd is a range of sorted iT that represents + //one or more scanline stops worth of data + template + void scan(cT& output, iT inputBegin, iT inputEnd) { + //std::cout << "1\n"; + while(inputBegin != inputEnd) { + //std::cout << "2\n"; + polygon_arbitrary_formation::x_ = (*inputBegin).pt.get(HORIZONTAL); + //std::cout << "SCAN FORMATION " << x_ << "\n"; + //std::cout << "x_ = " << x_ << "\n"; + //std::cout << "scan line size: " << scanData_.size() << "\n"; + inputBegin = processEvent_(output, inputBegin, inputEnd); + } + //std::cout << "scan line size: " << scanData_.size() << "\n"; + } + + private: + //functions + inline void getVerticalPair_(std::pair& verticalPair, + iterator previter) { + active_tail_arbitrary* iterTail = (*previter).second; + Point prevPoint(polygon_arbitrary_formation::x_, + convert_high_precision_type(previter->first.evalAtX(polygon_arbitrary_formation::x_))); + iterTail->pushPoint(prevPoint); + std::pair tailPair = + active_tail_arbitrary::createActiveTailsAsPair(prevPoint, true, 0, false); + verticalPair.first = iterTail; + verticalPair.second = tailPair.first; + (*previter).second = tailPair.second; + } + + template + inline std::pair, active_tail_arbitrary*> + processPoint_(cT& output, cT2& elements, + std::pair& verticalPair, + iterator previter, Point point, incoming_count& counts_from_scanline, + vertex_arbitrary_count& incoming_count) { + //std::cout << "\nAT POINT: " << point << "\n"; + //join any closing solid corners + std::vector counts; + std::vector incoming; + std::vector tails; + counts.reserve(counts_from_scanline.size()); + tails.reserve(counts_from_scanline.size()); + incoming.reserve(incoming_count.size()); + for(std::size_t i = 0; i < counts_from_scanline.size(); ++i) { + counts.push_back(counts_from_scanline[i].first.second); + tails.push_back(counts_from_scanline[i].second); + } + for(std::size_t i = 0; i < incoming_count.size(); ++i) { + incoming.push_back(incoming_count[i].second); + if(incoming_count[i].first < point) { + incoming.back() = 0; + } + } + + active_tail_arbitrary* returnValue = 0; + std::pair verticalPairOut; + verticalPairOut.first = 0; + verticalPairOut.second = 0; + std::pair returnCount(Point(0, 0), 0); + int i_size_less_1 = (int)(incoming.size()) -1; + int c_size_less_1 = (int)(counts.size()) -1; + int i_size = incoming.size(); + int c_size = counts.size(); + + bool have_vertical_tail_from_below = false; + if(c_size && + scanline_base::is_vertical(counts_from_scanline.back().first.first)) { + have_vertical_tail_from_below = true; + } + //assert size = size_less_1 + 1 + //std::cout << tails.size() << " " << incoming.size() << " " << counts_from_scanline.size() << " " << incoming_count.size() << "\n"; + // for(std::size_t i = 0; i < counts.size(); ++i) { + // std::cout << counts_from_scanline[i].first.first.first.get(HORIZONTAL) << ","; + // std::cout << counts_from_scanline[i].first.first.first.get(VERTICAL) << " "; + // std::cout << counts_from_scanline[i].first.first.second.get(HORIZONTAL) << ","; + // std::cout << counts_from_scanline[i].first.first.second.get(VERTICAL) << ":"; + // std::cout << counts_from_scanline[i].first.second << " "; + // } std::cout << "\n"; + // print(incoming_count); + { + for(int i = 0; i < c_size_less_1; ++i) { + //std::cout << i << "\n"; + if(counts[i] == -1) { + //std::cout << "fixed i\n"; + for(int j = i + 1; j < c_size; ++j) { + //std::cout << j << "\n"; + if(counts[j]) { + if(counts[j] == 1) { + //std::cout << "case1: " << i << " " << j << "\n"; + //if a figure is closed it will be written out by this function to output + active_tail_arbitrary::joinChains(point, tails[i], tails[j], true, output); + counts[i] = 0; + counts[j] = 0; + tails[i] = 0; + tails[j] = 0; + } + break; + } + } + } + } + } + //find any pairs of incoming edges that need to create pair for leading solid + //std::cout << "checking case2\n"; + { + for(int i = 0; i < i_size_less_1; ++i) { + //std::cout << i << "\n"; + if(incoming[i] == 1) { + //std::cout << "fixed i\n"; + for(int j = i + 1; j < i_size; ++j) { + //std::cout << j << "\n"; + if(incoming[j]) { + //std::cout << incoming[j] << "\n"; + if(incoming[j] == -1) { + //std::cout << "case2: " << i << " " << j << "\n"; + //std::cout << "creating active tail pair\n"; + std::pair tailPair = + active_tail_arbitrary::createActiveTailsAsPair(point, true, 0, polygon_arbitrary_formation::fractureHoles_ != 0); + //tailPair.first->print(); + //tailPair.second->print(); + if(j == i_size_less_1 && incoming_count[j].first.get(HORIZONTAL) == point.get(HORIZONTAL)) { + //vertical active tail becomes return value + returnValue = tailPair.first; + returnCount.first = point; + returnCount.second = 1; + } else { + //std::cout << "new element " << j-1 << " " << -1 << "\n"; + //std::cout << point << " " << incoming_count[j].first << "\n"; + elements.push_back(std::pair(vertex_half_edge(point, + incoming_count[j].first, -1), tailPair.first)); + } + //std::cout << "new element " << i-1 << " " << 1 << "\n"; + //std::cout << point << " " << incoming_count[i].first << "\n"; + elements.push_back(std::pair(vertex_half_edge(point, + incoming_count[i].first, 1), tailPair.second)); + incoming[i] = 0; + incoming[j] = 0; + } + break; + } + } + } + } + } + //find any active tail that needs to pass through to an incoming edge + //we expect to find no more than two pass through + + //find pass through with solid on top + { + //std::cout << "checking case 3\n"; + for(int i = 0; i < c_size; ++i) { + //std::cout << i << "\n"; + if(counts[i] != 0) { + if(counts[i] == 1) { + //std::cout << "fixed i\n"; + for(int j = i_size_less_1; j >= 0; --j) { + if(incoming[j] != 0) { + if(incoming[j] == 1) { + //std::cout << "case3: " << i << " " << j << "\n"; + //tails[i]->print(); + //pass through solid on top + tails[i]->pushPoint(point); + //std::cout << "after push\n"; + if(j == i_size_less_1 && incoming_count[j].first.get(HORIZONTAL) == point.get(HORIZONTAL)) { + returnValue = tails[i]; + returnCount.first = point; + returnCount.second = -1; + } else { + std::pair tailPair = + active_tail_arbitrary::createActiveTailsAsPair(point, true, 0, false); + verticalPairOut.first = tails[i]; + verticalPairOut.second = tailPair.first; + elements.push_back(std::pair(vertex_half_edge(point, + incoming_count[j].first, incoming[j]), tailPair.second)); + } + tails[i] = 0; + counts[i] = 0; + incoming[j] = 0; + } + break; + } + } + } + break; + } + } + } + //std::cout << "checking case 4\n"; + //find pass through with solid on bottom + { + for(int i = c_size_less_1; i >= 0; --i) { + //std::cout << "i = " << i << " with count " << counts[i] << "\n"; + if(counts[i] != 0) { + if(counts[i] == -1) { + for(int j = 0; j < i_size; ++j) { + if(incoming[j] != 0) { + if(incoming[j] == -1) { + //std::cout << "case4: " << i << " " << j << "\n"; + //pass through solid on bottom + + //if count from scanline is vertical + if(i == c_size_less_1 && + counts_from_scanline[i].first.first.first.get(HORIZONTAL) == + point.get(HORIZONTAL)) { + //if incoming count is vertical + if(j == i_size_less_1 && + incoming_count[j].first.get(HORIZONTAL) == point.get(HORIZONTAL)) { + returnValue = tails[i]; + returnCount.first = point; + returnCount.second = 1; + } else { + tails[i]->pushPoint(point); + elements.push_back(std::pair(vertex_half_edge(point, + incoming_count[j].first, incoming[j]), tails[i])); + } + } else if(j == i_size_less_1 && + incoming_count[j].first.get(HORIZONTAL) == + point.get(HORIZONTAL)) { + if(verticalPair.first == 0) { + getVerticalPair_(verticalPair, previter); + } + active_tail_arbitrary::joinChains(point, tails[i], verticalPair.first, true, output); + returnValue = verticalPair.second; + returnCount.first = point; + returnCount.second = 1; + } else { + //neither is vertical + if(verticalPair.first == 0) { + getVerticalPair_(verticalPair, previter); + } + active_tail_arbitrary::joinChains(point, tails[i], verticalPair.first, true, output); + verticalPair.second->pushPoint(point); + elements.push_back(std::pair(vertex_half_edge(point, + incoming_count[j].first, incoming[j]), verticalPair.second)); + } + tails[i] = 0; + counts[i] = 0; + incoming[j] = 0; + } + break; + } + } + } + break; + } + } + } + //find the end of a hole or the beginning of a hole + + //find end of a hole + { + for(int i = 0; i < c_size_less_1; ++i) { + if(counts[i] != 0) { + for(int j = i+1; j < c_size; ++j) { + if(counts[j] != 0) { + //std::cout << "case5: " << i << " " << j << "\n"; + //we are ending a hole and may potentially close a figure and have to handle the hole + tails[i]->pushPoint(point); + verticalPairOut.first = tails[i]; + if(j == c_size_less_1 && + counts_from_scanline[j].first.first.first.get(HORIZONTAL) == + point.get(HORIZONTAL)) { + verticalPairOut.second = tails[j]; + } else { + //need to close a trapezoid below + if(verticalPair.first == 0) { + getVerticalPair_(verticalPair, previter); + } + active_tail_arbitrary::joinChains(point, tails[j], verticalPair.first, true, output); + verticalPairOut.second = verticalPair.second; + } + tails[i] = 0; + tails[j] = 0; + counts[i] = 0; + counts[j] = 0; + break; + } + } + break; + } + } + } + //find beginning of a hole + { + for(int i = 0; i < i_size_less_1; ++i) { + if(incoming[i] != 0) { + for(int j = i+1; j < i_size; ++j) { + if(incoming[j] != 0) { + //std::cout << "case6: " << i << " " << j << "\n"; + //we are beginning a empty space + if(verticalPair.first == 0) { + getVerticalPair_(verticalPair, previter); + } + verticalPair.second->pushPoint(point); + if(j == i_size_less_1 && + incoming_count[j].first.get(HORIZONTAL) == point.get(HORIZONTAL)) { + returnValue = verticalPair.first; + returnCount.first = point; + returnCount.second = -1; + } else { + std::pair tailPair = + active_tail_arbitrary::createActiveTailsAsPair(point, false, 0, false); + elements.push_back(std::pair(vertex_half_edge(point, + incoming_count[j].first, incoming[j]), tailPair.second)); + verticalPairOut.second = tailPair.first; + verticalPairOut.first = verticalPair.first; + } + elements.push_back(std::pair(vertex_half_edge(point, + incoming_count[i].first, incoming[i]), verticalPair.second)); + incoming[i] = 0; + incoming[j] = 0; + break; + } + } + break; + } + } + } + if(have_vertical_tail_from_below) { + if(tails.back()) { + tails.back()->pushPoint(point); + returnValue = tails.back(); + returnCount.first = point; + returnCount.second = counts.back(); + } + } + verticalPair = verticalPairOut; + //assert that tails, counts and incoming are all null + return std::pair, active_tail_arbitrary*>(returnCount, returnValue); + } + + static inline void print(const vertex_arbitrary_count& count) { + for(unsigned i = 0; i < count.size(); ++i) { + //std::cout << count[i].first.get(HORIZONTAL) << ","; + //std::cout << count[i].first.get(VERTICAL) << ":"; + //std::cout << count[i].second << " "; + } //std::cout << "\n"; + } + + static inline void print(const scanline_data& data) { + for(typename scanline_data::const_iterator itr = data.begin(); itr != data.end(); ++itr){ + //std::cout << itr->first.pt << ", " << itr->first.other_pt << "; "; + } //std::cout << "\n"; + } + + template + inline iT processEvent_(cT& output, iT inputBegin, iT inputEnd) { + //typedef typename high_precision_type::type high_precision; + //std::cout << "processEvent_\n"; + polygon_arbitrary_formation::justBefore_ = true; + //collect up all elements from the tree that are at the y + //values of events in the input queue + //create vector of new elements to add into tree + active_tail_arbitrary* verticalTail = 0; + std::pair verticalPair; + std::pair verticalCount(Point(0, 0), 0); + iT currentIter = inputBegin; + std::vector elementIters; + std::vector > elements; + while(currentIter != inputEnd && currentIter->pt.get(HORIZONTAL) == polygon_arbitrary_formation::x_) { + //std::cout << "loop\n"; + Unit currentY = (*currentIter).pt.get(VERTICAL); + //std::cout << "current Y " << currentY << "\n"; + //std::cout << "scanline size " << scanData_.size() << "\n"; + //print(scanData_); + iterator iter = this->lookUp_(currentY); + //std::cout << "found element in scanline " << (iter != scanData_.end()) << "\n"; + //int counts[4] = {0, 0, 0, 0}; + incoming_count counts_from_scanline; + //std::cout << "finding elements in tree\n"; + //if(iter != scanData_.end()) + // std::cout << "first iter y is " << iter->first.evalAtX(x_) << "\n"; + iterator previter = iter; + if(previter != polygon_arbitrary_formation::scanData_.end() && + previter->first.evalAtX(polygon_arbitrary_formation::x_) >= currentY && + previter != polygon_arbitrary_formation::scanData_.begin()) + --previter; + while(iter != polygon_arbitrary_formation::scanData_.end() && + ((iter->first.pt.x() == polygon_arbitrary_formation::x_ && iter->first.pt.y() == currentY) || + (iter->first.other_pt.x() == polygon_arbitrary_formation::x_ && iter->first.other_pt.y() == currentY))) { + //iter->first.evalAtX(polygon_arbitrary_formation::x_) == (high_precision)currentY) { + //std::cout << "loop2\n"; + elementIters.push_back(iter); + counts_from_scanline.push_back(std::pair, int>, active_tail_arbitrary*> + (std::pair, int>(std::pair(iter->first.pt, + iter->first.other_pt), + iter->first.count), + iter->second)); + ++iter; + } + Point currentPoint(polygon_arbitrary_formation::x_, currentY); + //std::cout << "counts_from_scanline size " << counts_from_scanline.size() << "\n"; + this->sort_incoming_count(counts_from_scanline, currentPoint); + + vertex_arbitrary_count incoming; + //std::cout << "aggregating\n"; + do { + //std::cout << "loop3\n"; + const vertex_half_edge& elem = *currentIter; + incoming.push_back(std::pair(elem.other_pt, elem.count)); + ++currentIter; + } while(currentIter != inputEnd && currentIter->pt.get(VERTICAL) == currentY && + currentIter->pt.get(HORIZONTAL) == polygon_arbitrary_formation::x_); + //print(incoming); + this->sort_vertex_arbitrary_count(incoming, currentPoint); + //std::cout << currentPoint.get(HORIZONTAL) << "," << currentPoint.get(VERTICAL) << "\n"; + //print(incoming); + //std::cout << "incoming counts from input size " << incoming.size() << "\n"; + //compact_vertex_arbitrary_count(currentPoint, incoming); + vertex_arbitrary_count tmp; + tmp.reserve(incoming.size()); + for(std::size_t i = 0; i < incoming.size(); ++i) { + if(currentPoint < incoming[i].first) { + tmp.push_back(incoming[i]); + } + } + incoming.swap(tmp); + //std::cout << "incoming counts from input size " << incoming.size() << "\n"; + //now counts_from_scanline has the data from the left and + //incoming has the data from the right at this point + //cancel out any end points + if(verticalTail) { + //std::cout << "adding vertical tail to counts from scanline\n"; + //std::cout << -verticalCount.second << "\n"; + counts_from_scanline.push_back(std::pair, int>, active_tail_arbitrary*> + (std::pair, int>(std::pair(verticalCount.first, + currentPoint), + -verticalCount.second), + verticalTail)); + } + if(!incoming.empty() && incoming.back().first.get(HORIZONTAL) == polygon_arbitrary_formation::x_) { + //std::cout << "inverted vertical event\n"; + incoming.back().second *= -1; + } + //std::cout << "calling processPoint_\n"; + std::pair, active_tail_arbitrary*> result = processPoint_(output, elements, verticalPair, previter, Point(polygon_arbitrary_formation::x_, currentY), counts_from_scanline, incoming); + verticalCount = result.first; + verticalTail = result.second; + if(verticalPair.first != 0 && iter != polygon_arbitrary_formation::scanData_.end() && + (currentIter == inputEnd || currentIter->pt.x() != polygon_arbitrary_formation::x_ || + currentIter->pt.y() > (*iter).first.evalAtX(polygon_arbitrary_formation::x_))) { + //splice vertical pair into edge above + active_tail_arbitrary* tailabove = (*iter).second; + Point point(polygon_arbitrary_formation::x_, + convert_high_precision_type((*iter).first.evalAtX(polygon_arbitrary_formation::x_))); + verticalPair.second->pushPoint(point); + active_tail_arbitrary::joinChains(point, tailabove, verticalPair.first, true, output); + (*iter).second = verticalPair.second; + verticalPair.first = 0; + verticalPair.second = 0; + } + } + //std::cout << "erasing\n"; + //erase all elements from the tree + for(typename std::vector::iterator iter = elementIters.begin(); + iter != elementIters.end(); ++iter) { + //std::cout << "erasing loop\n"; + polygon_arbitrary_formation::scanData_.erase(*iter); + } + //switch comparison tie breaking policy + polygon_arbitrary_formation::justBefore_ = false; + //add new elements into tree + //std::cout << "inserting\n"; + for(typename std::vector >::iterator iter = elements.begin(); + iter != elements.end(); ++iter) { + //std::cout << "inserting loop\n"; + polygon_arbitrary_formation::scanData_.insert(polygon_arbitrary_formation::scanData_.end(), *iter); + } + //std::cout << "end processEvent\n"; + return currentIter; + } + public: + template + static inline bool testTrapezoidArbitraryFormationRect(stream_type& stdcout) { + stdcout << "testing trapezoid formation\n"; + trapezoid_arbitrary_formation pf; + std::vector > polys; + std::vector data; + data.push_back(vertex_half_edge(Point(0, 0), Point(10, 0), 1)); + data.push_back(vertex_half_edge(Point(0, 0), Point(0, 10), 1)); + data.push_back(vertex_half_edge(Point(0, 10), Point(0, 0), -1)); + data.push_back(vertex_half_edge(Point(0, 10), Point(10, 10), -1)); + data.push_back(vertex_half_edge(Point(10, 0), Point(0, 0), -1)); + data.push_back(vertex_half_edge(Point(10, 0), Point(10, 10), -1)); + data.push_back(vertex_half_edge(Point(10, 10), Point(10, 0), 1)); + data.push_back(vertex_half_edge(Point(10, 10), Point(0, 10), 1)); + polygon_sort(data.begin(), data.end()); + pf.scan(polys, data.begin(), data.end()); + stdcout << "result size: " << polys.size() << "\n"; + for(std::size_t i = 0; i < polys.size(); ++i) { + stdcout << polys[i] << "\n"; + } + stdcout << "done testing trapezoid formation\n"; + return true; + } + template + static inline bool testTrapezoidArbitraryFormationP1(stream_type& stdcout) { + stdcout << "testing trapezoid formation P1\n"; + trapezoid_arbitrary_formation pf; + std::vector > polys; + std::vector data; + data.push_back(vertex_half_edge(Point(0, 0), Point(10, 10), 1)); + data.push_back(vertex_half_edge(Point(0, 0), Point(0, 10), 1)); + data.push_back(vertex_half_edge(Point(0, 10), Point(0, 0), -1)); + data.push_back(vertex_half_edge(Point(0, 10), Point(10, 20), -1)); + data.push_back(vertex_half_edge(Point(10, 10), Point(0, 0), -1)); + data.push_back(vertex_half_edge(Point(10, 10), Point(10, 20), -1)); + data.push_back(vertex_half_edge(Point(10, 20), Point(10, 10), 1)); + data.push_back(vertex_half_edge(Point(10, 20), Point(0, 10), 1)); + polygon_sort(data.begin(), data.end()); + pf.scan(polys, data.begin(), data.end()); + stdcout << "result size: " << polys.size() << "\n"; + for(std::size_t i = 0; i < polys.size(); ++i) { + stdcout << polys[i] << "\n"; + } + stdcout << "done testing trapezoid formation\n"; + return true; + } + template + static inline bool testTrapezoidArbitraryFormationP2(stream_type& stdcout) { + stdcout << "testing trapezoid formation P2\n"; + trapezoid_arbitrary_formation pf; + std::vector > polys; + std::vector data; + data.push_back(vertex_half_edge(Point(-3, 1), Point(2, -4), 1)); + data.push_back(vertex_half_edge(Point(-3, 1), Point(-2, 2), -1)); + data.push_back(vertex_half_edge(Point(-2, 2), Point(2, 4), -1)); + data.push_back(vertex_half_edge(Point(-2, 2), Point(-3, 1), 1)); + data.push_back(vertex_half_edge(Point(2, -4), Point(-3, 1), -1)); + data.push_back(vertex_half_edge(Point(2, -4), Point(2, 4), -1)); + data.push_back(vertex_half_edge(Point(2, 4), Point(-2, 2), 1)); + data.push_back(vertex_half_edge(Point(2, 4), Point(2, -4), 1)); + polygon_sort(data.begin(), data.end()); + pf.scan(polys, data.begin(), data.end()); + stdcout << "result size: " << polys.size() << "\n"; + for(std::size_t i = 0; i < polys.size(); ++i) { + stdcout << polys[i] << "\n"; + } + stdcout << "done testing trapezoid formation\n"; + return true; + } + + template + static inline bool testTrapezoidArbitraryFormationPolys(stream_type& stdcout) { + stdcout << "testing trapezoid formation polys\n"; + trapezoid_arbitrary_formation pf; + std::vector > polys; + //trapezoid_arbitrary_formation pf2(true); + //std::vector > polys2; + std::vector data; + data.push_back(vertex_half_edge(Point(0, 0), Point(100, 1), 1)); + data.push_back(vertex_half_edge(Point(0, 0), Point(1, 100), -1)); + data.push_back(vertex_half_edge(Point(1, 100), Point(0, 0), 1)); + data.push_back(vertex_half_edge(Point(1, 100), Point(101, 101), -1)); + data.push_back(vertex_half_edge(Point(100, 1), Point(0, 0), -1)); + data.push_back(vertex_half_edge(Point(100, 1), Point(101, 101), 1)); + data.push_back(vertex_half_edge(Point(101, 101), Point(100, 1), -1)); + data.push_back(vertex_half_edge(Point(101, 101), Point(1, 100), 1)); + + data.push_back(vertex_half_edge(Point(2, 2), Point(10, 2), -1)); + data.push_back(vertex_half_edge(Point(2, 2), Point(2, 10), -1)); + data.push_back(vertex_half_edge(Point(2, 10), Point(2, 2), 1)); + data.push_back(vertex_half_edge(Point(2, 10), Point(10, 10), 1)); + data.push_back(vertex_half_edge(Point(10, 2), Point(2, 2), 1)); + data.push_back(vertex_half_edge(Point(10, 2), Point(10, 10), 1)); + data.push_back(vertex_half_edge(Point(10, 10), Point(10, 2), -1)); + data.push_back(vertex_half_edge(Point(10, 10), Point(2, 10), -1)); + + data.push_back(vertex_half_edge(Point(2, 12), Point(10, 12), -1)); + data.push_back(vertex_half_edge(Point(2, 12), Point(2, 22), -1)); + data.push_back(vertex_half_edge(Point(2, 22), Point(2, 12), 1)); + data.push_back(vertex_half_edge(Point(2, 22), Point(10, 22), 1)); + data.push_back(vertex_half_edge(Point(10, 12), Point(2, 12), 1)); + data.push_back(vertex_half_edge(Point(10, 12), Point(10, 22), 1)); + data.push_back(vertex_half_edge(Point(10, 22), Point(10, 12), -1)); + data.push_back(vertex_half_edge(Point(10, 22), Point(2, 22), -1)); + + polygon_sort(data.begin(), data.end()); + pf.scan(polys, data.begin(), data.end()); + stdcout << "result size: " << polys.size() << "\n"; + for(std::size_t i = 0; i < polys.size(); ++i) { + stdcout << polys[i] << "\n"; + } + //pf2.scan(polys2, data.begin(), data.end()); + //stdcout << "result size: " << polys2.size() << "\n"; + //for(std::size_t i = 0; i < polys2.size(); ++i) { + // stdcout << polys2[i] << "\n"; + //} + stdcout << "done testing trapezoid formation\n"; + return true; + } + + template + static inline bool testTrapezoidArbitraryFormationSelfTouch1(stream_type& stdcout) { + stdcout << "testing trapezoid formation self touch 1\n"; + trapezoid_arbitrary_formation pf; + std::vector > polys; + std::vector data; + data.push_back(vertex_half_edge(Point(0, 0), Point(10, 0), 1)); + data.push_back(vertex_half_edge(Point(0, 0), Point(0, 10), 1)); + + data.push_back(vertex_half_edge(Point(0, 10), Point(0, 0), -1)); + data.push_back(vertex_half_edge(Point(0, 10), Point(5, 10), -1)); + + data.push_back(vertex_half_edge(Point(10, 0), Point(0, 0), -1)); + data.push_back(vertex_half_edge(Point(10, 0), Point(10, 5), -1)); + + data.push_back(vertex_half_edge(Point(10, 5), Point(10, 0), 1)); + data.push_back(vertex_half_edge(Point(10, 5), Point(5, 5), 1)); + + data.push_back(vertex_half_edge(Point(5, 10), Point(5, 5), 1)); + data.push_back(vertex_half_edge(Point(5, 10), Point(0, 10), 1)); + + data.push_back(vertex_half_edge(Point(5, 2), Point(5, 5), -1)); + data.push_back(vertex_half_edge(Point(5, 2), Point(7, 2), -1)); + + data.push_back(vertex_half_edge(Point(5, 5), Point(5, 10), -1)); + data.push_back(vertex_half_edge(Point(5, 5), Point(5, 2), 1)); + data.push_back(vertex_half_edge(Point(5, 5), Point(10, 5), -1)); + data.push_back(vertex_half_edge(Point(5, 5), Point(7, 2), 1)); + + data.push_back(vertex_half_edge(Point(7, 2), Point(5, 5), -1)); + data.push_back(vertex_half_edge(Point(7, 2), Point(5, 2), 1)); + + polygon_sort(data.begin(), data.end()); + pf.scan(polys, data.begin(), data.end()); + stdcout << "result size: " << polys.size() << "\n"; + for(std::size_t i = 0; i < polys.size(); ++i) { + stdcout << polys[i] << "\n"; + } + stdcout << "done testing trapezoid formation\n"; + return true; + } + }; + + template + struct PolyLineArbitraryByConcept { typedef poly_line_arbitrary_polygon_data type; }; + template + struct PolyLineArbitraryByConcept { typedef poly_line_arbitrary_hole_data type; }; + + template + struct geometry_concept > { typedef polygon_45_with_holes_concept type; }; + template + struct geometry_concept > { typedef polygon_45_concept type; }; +} +} +#endif diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/detail/polygon_formation.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/detail/polygon_formation.hpp new file mode 100644 index 0000000..f4c0d70 --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/detail/polygon_formation.hpp @@ -0,0 +1,2287 @@ +/* + Copyright 2008 Intel Corporation + + Use, modification and distribution are subject to the Boost Software License, + Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at + http://www.boost.org/LICENSE_1_0.txt). +*/ +#include +#include +#ifndef BOOST_POLYGON_POLYGON_FORMATION_HPP +#define BOOST_POLYGON_POLYGON_FORMATION_HPP +namespace boost { namespace polygon{ + +namespace polygon_formation { + + /* + * End has two states, HEAD and TAIL as is represented by a bool + */ + typedef bool End; + + /* + * HEAD End is represented as false because it is the lesser state + */ + const End HEAD = false; + + /* + * TAIL End is represented by true because TAIL comes after head and 1 after 0 + */ + const End TAIL = true; + + /* + * 2D turning direction, left and right sides (is a boolean value since it has two states.) + */ + typedef bool Side; + + /* + * LEFT Side is 0 because we inuitively think left to right; left < right + */ + const Side LEFT = false; + + /* + * RIGHT Side is 1 so that right > left + */ + const Side RIGHT = true; + + /* + * The PolyLine class is data storage and services for building and representing partial polygons. + * As the polyline is added to it extends its storage to accomodate the data. + * PolyLines can be joined head-to-head/head-to-tail when it is determined that two polylines are + * part of the same polygon. + * PolyLines keep state information about what orientation their incomplete head and tail geometry have, + * which side of the polyline is solid and whether the polyline is joined head-to-head and tail-to-head. + * PolyLines have nothing whatsoever to do with holes. + * It may be valuable to collect a histogram of PolyLine lengths used by an algorithm on its typical data + * sets and tune the allocation of the initial vector of coordinate data to be greater than or equal to + * the mean, median, mode, or mean plus some number of standard deviation, or just generally large enough + * to prevent too much unnecesary reallocations, but not too big that it wastes a lot of memory and degrades cache + * performance. + */ + template + class PolyLine { + private: + //data + + /* + * ptdata_ a vector of coordiantes + * if VERTICAL_HEAD, first coordiante is an X + * else first coordinate is a Y + */ + std::vector ptdata_; + + /* + * head and tail points to other polylines before and after this in a chain + */ + PolyLine* headp_; + PolyLine* tailp_; + + /* + * state bitmask + * bit zero is orientation, 0 H, 1 V + * bit 1 is head connectivity, 0 for head, 1 for tail + * bit 2 is tail connectivity, 0 for head, 1 for tail + * bit 3 is solid to left of PolyLine when 1, right when 0 + */ + int state_; + + public: + /* + * default constructor (for preallocation) + */ + PolyLine(); + + /* + * constructor that takes the orientation, coordiante and side to which there is solid + */ + PolyLine(orientation_2d orient, Unit coord, Side side); + + //copy constructor + PolyLine(const PolyLine& pline); + + //destructor + ~PolyLine(); + + //assignment operator + PolyLine& operator=(const PolyLine& that); + + //equivalence operator + bool operator==(const PolyLine& b) const; + + /* + * valid PolyLine (only default constructed polylines are invalid.) + */ + bool isValid() const; + + /* + * Orientation of Head + */ + orientation_2d headOrient() const; + + /* + * returns true if first coordinate is an X value (first segment is vertical) + */ + bool verticalHead() const; + + /* + * returns the orientation_2d fo the tail + */ + orientation_2d tailOrient() const; + + /* + * returns true if last coordinate is an X value (last segment is vertical) + */ + bool verticalTail() const; + + /* + * retrun true if PolyLine has odd number of coordiantes + */ + bool oddLength() const; + + /* + * retrun the End of the other polyline that the specified end of this polyline is connected to + */ + End endConnectivity(End end) const; + + /* + * retrun true if the head of this polyline is connect to the tail of a polyline + */ + bool headToTail() const; + /* + * retrun true if the head of this polyline is connect to the head of a polyline + */ + bool headToHead() const; + + /* + * retrun true if the tail of this polyline is connect to the tail of a polyline + */ + bool tailToTail() const; + /* + * retrun true if the tail of this polyline is connect to the head of a polyline + */ + bool tailToHead() const; + + /* + * retrun the side on which there is solid for this polyline + */ + Side solidSide() const; + + /* + * retrun true if there is solid to the right of this polyline + */ + bool solidToRight() const; + + /* + * returns true if the polyline tail is not connected + */ + bool active() const; + + /* + * adds a coordinate value to the end of the polyline changing the tail orientation + */ + PolyLine& pushCoordinate(Unit coord); + + /* + * removes a coordinate value at the end of the polyline changing the tail orientation + */ + PolyLine& popCoordinate(); + + /* + * extends the tail of the polyline to include the point, changing orientation if needed + */ + PolyLine& pushPoint(const point_data& point); + + /* + * changes the last coordinate of the tail of the polyline by the amount of the delta + */ + PolyLine& extendTail(Unit delta); + + /* + * join thisEnd of this polyline to that polyline's end + */ + PolyLine& joinTo(End thisEnd, PolyLine& that, End end); + + /* + * join an end of this polyline to the tail of that polyline + */ + PolyLine& joinToTail(PolyLine& that, End end); + + /* + * join an end of this polyline to the head of that polyline + */ + PolyLine& joinToHead(PolyLine& that, End end); + + /* + * join the head of this polyline to the head of that polyline + */ + //join this to that in the given way + PolyLine& joinHeadToHead(PolyLine& that); + + /* + * join the head of this polyline to the tail of that polyline + */ + PolyLine& joinHeadToTail(PolyLine& that); + + /* + * join the tail of this polyline to the head of that polyline + */ + PolyLine& joinTailToHead(PolyLine& that); + + /* + * join the tail of this polyline to the tail of that polyline + */ + PolyLine& joinTailToTail(PolyLine& that); + + /* + * dissconnect the tail at the end of the polygon + */ + PolyLine& disconnectTails(); + + /* + * get the coordinate at one end of this polyline, by default the tail end + */ + Unit getEndCoord(End end = TAIL) const; + + /* + * get the point on the polyline at the given index (polylines have the same number of coordinates as points + */ + point_data getPoint(unsigned int index) const; + + /* + * get the point on one end of the polyline, by default the tail + */ + point_data getEndPoint(End end = TAIL) const; + + /* + * get the orientation of a segment by index + */ + orientation_2d segmentOrient(unsigned int index = 0) const; + + /* + * get a coordinate by index using the square bracket operator + */ + Unit operator[] (unsigned int index) const; + + /* + * get the number of segments/points/coordinates in the polyline + */ + unsigned int numSegments() const; + + /* + * get the pointer to the next polyline at one end of this + */ + PolyLine* next(End end) const; + + /* + * write out coordinates of this and all attached polylines to a single vector + */ + PolyLine* writeOut(std::vector& outVec, End startEnd = TAIL) const; + + private: + //methods + PolyLine& joinTo_(End thisEnd, PolyLine& that, End end); + }; + + //forward declaration + template + class PolyLinePolygonData; + + //forward declaration + template + class PolyLinePolygonWithHolesData; + + /* + * ActiveTail represents an edge of an incomplete polygon. + * + * An ActiveTail object is the active tail end of a polyline object, which may (should) be the attached to + * a chain of polyline objects through a pointer. The ActiveTail class provides an abstraction between + * and algorithm that builds polygons and the PolyLine data representation of incomplete polygons that are + * being built. It does this by providing an iterface to access the information about the last edge at the + * tail of the PolyLine it is associated with. To a polygon constructing algorithm, an ActiveTail is a floating + * edge of an incomplete polygon and has an orientation and coordinate value, as well as knowing which side of + * that edge is supposed to be solid or space. Any incomplete polygon will have two active tails. Active tails + * may be joined together to merge two incomplete polygons into a larger incomplete polygon. If two active tails + * that are to be merged are the oppositve ends of the same incomplete polygon that indicates that the polygon + * has been closed and is complete. The active tail keeps a pointer to the other active tail of its incomplete + * polygon so that it is easy to check this condition. These pointers are updated when active tails are joined. + * The active tail also keeps a list of pointers to active tail objects that serve as handles to closed holes. In + * this way a hole can be associated to another incomplete polygon, which will eventually be its enclosing shell, + * or reassociate the hole to another incomplete polygon in the case that it become a hole itself. Alternately, + * the active tail may add a filiment to stitch a hole into a shell and "fracture" the hole out of the interior + * of a polygon. The active tail maintains a static output buffer to temporarily write polygon data to when + * it outputs a figure so that outputting a polygon does not require the allocation of a temporary buffer. This + * static buffer should be destroyed whenever the program determines that it won't need it anymore and would prefer to + * release the memory it has allocated back to the system. + */ + template + class ActiveTail { + private: + //data + PolyLine* tailp_; + ActiveTail *otherTailp_; + std::list holesList_; + //Sum of all the polylines which constitute the active tail (including holes)// + size_t polyLineSize_; + public: + + inline size_t getPolyLineSize(){ + return polyLineSize_; + } + + inline void setPolyLineSize(int delta){ + polyLineSize_ = delta; + } + + inline void addPolyLineSize(int delta){ + polyLineSize_ += delta; + } + + /* + * iterator over coordinates of the figure + */ + class iterator { + private: + const PolyLine* pLine_; + const PolyLine* pLineEnd_; + unsigned int index_; + unsigned int indexEnd_; + End startEnd_; + public: + inline iterator() : pLine_(), pLineEnd_(), index_(), indexEnd_(), startEnd_() {} + inline iterator(const ActiveTail* at, bool isHole, orientation_2d orient) : + pLine_(), pLineEnd_(), index_(), indexEnd_(), startEnd_() { + //if it is a hole and orientation is vertical or it is not a hole and orientation is horizontal + //we want to use this active tail, otherwise we want to use the other active tail + startEnd_ = TAIL; + if(!isHole ^ (orient == HORIZONTAL)) { + //switch winding direction + at = at->getOtherActiveTail(); + } + //now we have the right winding direction + //if it is horizontal we need to skip the first element + pLine_ = at->getTail(); + + if(at->getTail()->numSegments() > 0) + index_ = at->getTail()->numSegments() - 1; + + if((at->getOrient() == HORIZONTAL) ^ (orient == HORIZONTAL)) { + pLineEnd_ = at->getTail(); + indexEnd_ = pLineEnd_->numSegments() - 1; + if(index_ == 0) { + pLine_ = at->getTail()->next(HEAD); + if(at->getTail()->endConnectivity(HEAD) == TAIL) { + index_ = pLine_->numSegments() -1; + } else { + startEnd_ = HEAD; + index_ = 0; + } + } else { --index_; } + } else { + pLineEnd_ = at->getOtherActiveTail()->getTail(); + if(pLineEnd_->numSegments() > 0) + indexEnd_ = pLineEnd_->numSegments() - 1; + } + at->getTail()->joinTailToTail(*(at->getOtherActiveTail()->getTail())); + } + + inline size_t size(void){ + size_t count = 0; + End dir = startEnd_; + PolyLine const * currLine = pLine_; + size_t ops = 0; + while(currLine != pLineEnd_){ + ops++; + count += currLine->numSegments(); + currLine = currLine->next(dir == HEAD ? TAIL : HEAD); + dir = currLine->endConnectivity(dir == HEAD ? TAIL : HEAD); + } + count += pLineEnd_->numSegments(); + return count; //no. of vertices + } + + //use bitwise copy and assign provided by the compiler + inline iterator& operator++() { + if(pLine_ == pLineEnd_ && index_ == indexEnd_) { + pLine_ = 0; + index_ = 0; + return *this; + } + if(startEnd_ == HEAD) { + ++index_; + if(index_ == pLine_->numSegments()) { + End end = pLine_->endConnectivity(TAIL); + pLine_ = pLine_->next(TAIL); + if(end == TAIL) { + startEnd_ = TAIL; + index_ = pLine_->numSegments() -1; + } else { + index_ = 0; + } + } + } else { + if(index_ == 0) { + End end = pLine_->endConnectivity(HEAD); + pLine_ = pLine_->next(HEAD); + if(end == TAIL) { + index_ = pLine_->numSegments() -1; + } else { + startEnd_ = HEAD; + index_ = 0; + } + } else { + --index_; + } + } + return *this; + } + inline const iterator operator++(int) { + iterator tmp(*this); + ++(*this); + return tmp; + } + inline bool operator==(const iterator& that) const { + return pLine_ == that.pLine_ && index_ == that.index_; + } + inline bool operator!=(const iterator& that) const { + return pLine_ != that.pLine_ || index_ != that.index_; + } + inline Unit operator*() { return (*pLine_)[index_]; } + }; + + /* + * iterator over holes contained within the figure + */ + typedef typename std::list::const_iterator iteratorHoles; + + //default constructor + ActiveTail(); + + //constructor + ActiveTail(orientation_2d orient, Unit coord, Side solidToRight, ActiveTail* otherTailp); + + //constructor + ActiveTail(PolyLine* active, ActiveTail* otherTailp); + + //copy constructor + ActiveTail(const ActiveTail& that); + + //destructor + ~ActiveTail(); + + //assignment operator + ActiveTail& operator=(const ActiveTail& that); + + //equivalence operator + bool operator==(const ActiveTail& b) const; + + /* + * comparison operators, ActiveTail objects are sortable by geometry + */ + bool operator<(const ActiveTail& b) const; + bool operator<=(const ActiveTail& b) const; + bool operator>(const ActiveTail& b) const; + bool operator>=(const ActiveTail& b) const; + + /* + * get the pointer to the polyline that this is an active tail of + */ + PolyLine* getTail() const; + + /* + * get the pointer to the polyline at the other end of the chain + */ + PolyLine* getOtherTail() const; + + /* + * get the pointer to the activetail at the other end of the chain + */ + ActiveTail* getOtherActiveTail() const; + + /* + * test if another active tail is the other end of the chain + */ + bool isOtherTail(const ActiveTail& b); + + /* + * update this end of chain pointer to new polyline + */ + ActiveTail& updateTail(PolyLine* newTail); + + /* + * associate a hole to this active tail by the specified policy + */ + ActiveTail* addHole(ActiveTail* hole, bool fractureHoles); + + /* + * get the list of holes + */ + const std::list& getHoles() const; + + /* + * copy holes from that to this + */ + void copyHoles(ActiveTail& that); + + /* + * find out if solid to right + */ + bool solidToRight() const; + + /* + * get coordinate (getCoord and getCoordinate are aliases for eachother) + */ + Unit getCoord() const; + Unit getCoordinate() const; + + /* + * get the tail orientation + */ + orientation_2d getOrient() const; + + /* + * add a coordinate to the polygon at this active tail end, properly handle degenerate edges by removing redundant coordinate + */ + void pushCoordinate(Unit coord); + + /* + * write the figure that this active tail points to out to the temp buffer + */ + void writeOutFigure(std::vector& outVec, bool isHole = false) const; + + /* + * write the figure that this active tail points to out through iterators + */ + void writeOutFigureItrs(iterator& beginOut, iterator& endOut, bool isHole = false, orientation_2d orient = VERTICAL) const; + iterator begin(bool isHole, orientation_2d orient) const; + iterator end() const; + + /* + * write the holes that this active tail points to out through iterators + */ + void writeOutFigureHoleItrs(iteratorHoles& beginOut, iteratorHoles& endOut) const; + iteratorHoles beginHoles() const; + iteratorHoles endHoles() const; + + /* + * joins the two chains that the two active tail tails are ends of + * checks for closure of figure and writes out polygons appropriately + * returns a handle to a hole if one is closed + */ + static ActiveTail* joinChains(ActiveTail* at1, ActiveTail* at2, bool solid, std::vector& outBufferTmp); + template + static ActiveTail* joinChains(ActiveTail* at1, ActiveTail* at2, bool solid, typename std::vector& outBufferTmp); + + /* + * deallocate temp buffer + */ + static void destroyOutBuffer(); + + /* + * deallocate all polygon data this active tail points to (deep delete, call only from one of a pair of active tails) + */ + void destroyContents(); + }; + + /* allocate a polyline object */ + template + PolyLine* createPolyLine(orientation_2d orient, Unit coord, Side side); + + /* deallocate a polyline object */ + template + void destroyPolyLine(PolyLine* pLine); + + /* allocate an activetail object */ + template + ActiveTail* createActiveTail(); + + /* deallocate an activetail object */ + template + void destroyActiveTail(ActiveTail* aTail); + + template + class PolyLineHoleData { + private: + ActiveTail* p_; + public: + typedef Unit coordinate_type; + typedef typename ActiveTail::iterator compact_iterator_type; + typedef iterator_compact_to_points > iterator_type; + inline PolyLineHoleData() : p_(0) {} + inline PolyLineHoleData(ActiveTail* p) : p_(p) {} + //use default copy and assign + inline compact_iterator_type begin_compact() const { return p_->begin(true, (orientT ? VERTICAL : HORIZONTAL)); } + inline compact_iterator_type end_compact() const { return p_->end(); } + inline iterator_type begin() const { return iterator_type(begin_compact(), end_compact()); } + inline iterator_type end() const { return iterator_type(end_compact(), end_compact()); } + inline std::size_t size() const { + return p_->getPolyLineSize(); + } + inline ActiveTail* yield() { return p_; } + }; + + template + class PolyLinePolygonWithHolesData { + private: + ActiveTail* p_; + public: + typedef Unit coordinate_type; + typedef typename ActiveTail::iterator compact_iterator_type; + typedef iterator_compact_to_points > iterator_type; + typedef PolyLineHoleData hole_type; + typedef typename coordinate_traits::area_type area_type; + class iteratorHoles { + private: + typename ActiveTail::iteratorHoles itr_; + public: + inline iteratorHoles() : itr_() {} + inline iteratorHoles(typename ActiveTail::iteratorHoles itr) : itr_(itr) {} + //use bitwise copy and assign provided by the compiler + inline iteratorHoles& operator++() { + ++itr_; + return *this; + } + inline const iteratorHoles operator++(int) { + iteratorHoles tmp(*this); + ++(*this); + return tmp; + } + inline bool operator==(const iteratorHoles& that) const { + return itr_ == that.itr_; + } + inline bool operator!=(const iteratorHoles& that) const { + return itr_ != that.itr_; + } + inline PolyLineHoleData operator*() { return PolyLineHoleData(*itr_);} + }; + typedef iteratorHoles iterator_holes_type; + + inline PolyLinePolygonWithHolesData() : p_(0) {} + inline PolyLinePolygonWithHolesData(ActiveTail* p) : p_(p) {} + //use default copy and assign + inline compact_iterator_type begin_compact() const { return p_->begin(false, (orientT ? VERTICAL : HORIZONTAL)); } + inline compact_iterator_type end_compact() const { return p_->end(); } + inline iterator_type begin() const { return iterator_type(begin_compact(), end_compact()); } + inline iterator_type end() const { return iterator_type(end_compact(), end_compact()); } + inline iteratorHoles begin_holes() const { return iteratorHoles(p_->beginHoles()); } + inline iteratorHoles end_holes() const { return iteratorHoles(p_->endHoles()); } + inline ActiveTail* yield() { return p_; } + //stub out these four required functions that will not be used but are needed for the interface + inline std::size_t size_holes() const { return 0; } + inline std::size_t size() const { return 0; } + }; + + + template + struct PolyLineType { }; + template + struct PolyLineType { typedef PolyLinePolygonWithHolesData type; }; + template + struct PolyLineType { typedef PolyLinePolygonWithHolesData type; }; + template + struct PolyLineType { typedef PolyLinePolygonWithHolesData type; }; + template + struct PolyLineType { typedef PolyLineHoleData type; }; + template + struct PolyLineType { typedef PolyLineHoleData type; }; + template + struct PolyLineType { typedef PolyLineHoleData type; }; + + template + class ScanLineToPolygonItrs { + private: + std::map*> tailMap_; + typedef typename PolyLineType::type PolyLinePolygonData; + std::vector outputPolygons_; + bool fractureHoles_; + public: + typedef typename std::vector::iterator iterator; + inline ScanLineToPolygonItrs() : tailMap_(), outputPolygons_(), fractureHoles_(false) {} + /* construct a scanline with the proper offsets, protocol and options */ + inline ScanLineToPolygonItrs(bool fractureHoles) : tailMap_(), outputPolygons_(), fractureHoles_(fractureHoles) {} + + ~ScanLineToPolygonItrs() { clearOutput_(); } + + /* process all vertical edges, left and right, at a unique x coordinate, edges must be sorted low to high */ + void processEdges(iterator& beginOutput, iterator& endOutput, + Unit currentX, std::vector >& leftEdges, + std::vector >& rightEdges, + size_t vertexThreshold=(std::numeric_limits::max)() ); + + /********************************************************************** + *methods implementing new polygon formation code + * + **********************************************************************/ + void updatePartialSimplePolygonsWithRightEdges(Unit currentX, + const std::vector >& leftEdges, size_t threshold); + + void updatePartialSimplePolygonsWithLeftEdges(Unit currentX, + const std::vector >& leftEdges, size_t threshold); + + void closePartialSimplePolygon(Unit, ActiveTail*, ActiveTail*); + + void maintainPartialSimplePolygonInvariant(iterator& ,iterator& ,Unit, + const std::vector >&, + const std::vector >&, + size_t vertexThreshold=(std::numeric_limits::max)()); + + void insertNewLeftEdgeIntoTailMap(Unit, Unit, Unit, + typename std::map*>::iterator &); + /**********************************************************************/ + + inline size_t getTailMapSize(){ + typename std::map* >::const_iterator itr; + size_t tsize = 0; + for(itr=tailMap_.begin(); itr!=tailMap_.end(); ++itr){ + tsize += (itr->second)->getPolyLineSize(); + } + return tsize; + } + /*print the active tails in this map:*/ + inline void print(){ + typename std::map* >::const_iterator itr; + printf("=========TailMap[%lu]=========\n", tailMap_.size()); + for(itr=tailMap_.begin(); itr!=tailMap_.end(); ++itr){ + std::cout<< "[" << itr->first << "] : " << std::endl; + //print active tail// + ActiveTail const *t = (itr->second); + PolyLine const *pBegin = t->getTail(); + PolyLine const *pEnd = t->getOtherActiveTail()->getTail(); + std::string sorient = pBegin->solidToRight() ? "RIGHT" : "LEFT"; + std::cout<< " ActiveTail.tailp_ (solid= " << sorient ; + End dir = TAIL; + while(pBegin!=pEnd){ + std::cout << pBegin << "={ "; + for(size_t i=0; inumSegments(); i++){ + point_data u = pBegin->getPoint(i); + std::cout << "(" << u.x() << "," << u.y() << ") "; + } + std::cout << "} "; + pBegin = pBegin->next(dir == HEAD ? TAIL : HEAD); + dir = pBegin->endConnectivity(dir == HEAD ? TAIL : HEAD); + } + if(pEnd){ + std::cout << pEnd << "={ "; + for(size_t i=0; inumSegments(); i++){ + point_data u = pEnd->getPoint(i); + std::cout << "(" << u.x() << "," << u.y() << ") "; + } + std::cout << "} "; + } + std::cout << " end= " << pEnd << std::endl; + } + } + + private: + void clearOutput_(); + }; + + /* + * ScanLine does all the work of stitching together polygons from incoming vertical edges + */ +// template +// class ScanLineToPolygons { +// private: +// ScanLineToPolygonItrs scanline_; +// public: +// inline ScanLineToPolygons() : scanline_() {} +// /* construct a scanline with the proper offsets, protocol and options */ +// inline ScanLineToPolygons(bool fractureHoles) : scanline_(fractureHoles) {} + +// /* process all vertical edges, left and right, at a unique x coordinate, edges must be sorted low to high */ +// inline void processEdges(std::vector& outBufferTmp, Unit currentX, std::vector >& leftEdges, +// std::vector >& rightEdges) { +// typename ScanLineToPolygonItrs::iterator itr, endItr; +// scanline_.processEdges(itr, endItr, currentX, leftEdges, rightEdges); +// //copy data into outBufferTmp +// while(itr != endItr) { +// typename PolyLinePolygonData::iterator pditr; +// outBufferTmp.push_back(0); +// unsigned int sizeIndex = outBufferTmp.size() - 1; +// int count = 0; +// for(pditr = (*itr).begin(); pditr != (*itr).end(); ++pditr) { +// outBufferTmp.push_back(*pditr); +// ++count; +// } +// outBufferTmp[sizeIndex] = count; +// typename PolyLinePolygonData::iteratorHoles pdHoleItr; +// for(pdHoleItr = (*itr).beginHoles(); pdHoleItr != (*itr).endHoles(); ++pdHoleItr) { +// outBufferTmp.push_back(0); +// unsigned int sizeIndex2 = outBufferTmp.size() - 1; +// int count2 = 0; +// for(pditr = (*pdHoleItr).begin(); pditr != (*pdHoleItr).end(); ++pditr) { +// outBufferTmp.push_back(*pditr); +// ++count2; +// } +// outBufferTmp[sizeIndex2] = -count; +// } +// ++itr; +// } +// } +// }; + + const int VERTICAL_HEAD = 1, HEAD_TO_TAIL = 2, TAIL_TO_TAIL = 4, SOLID_TO_RIGHT = 8; + + //EVERY FUNCTION in this DEF file should be explicitly defined as inline + + //microsoft compiler improperly warns whenever you cast an integer to bool + //call this function on an integer to convert it to bool without a warning + template + inline bool to_bool(const T& val) { return val != 0; } + + //default constructor (for preallocation) + template + inline PolyLine::PolyLine() : ptdata_() ,headp_(0), tailp_(0), state_(-1) {} + + //constructor + template + inline PolyLine::PolyLine(orientation_2d orient, Unit coord, Side side) : + ptdata_(1, coord), + headp_(0), + tailp_(0), + state_(orient.to_int() + + (side << 3)){} + + //copy constructor + template + inline PolyLine::PolyLine(const PolyLine& pline) : ptdata_(pline.ptdata_), + headp_(pline.headp_), + tailp_(pline.tailp_), + state_(pline.state_) {} + + //destructor + template + inline PolyLine::~PolyLine() { + //clear out data just in case it is read later + headp_ = tailp_ = 0; + state_ = 0; + } + + template + inline PolyLine& PolyLine::operator=(const PolyLine& that) { + if(!(this == &that)) { + headp_ = that.headp_; + tailp_ = that.tailp_; + ptdata_ = that.ptdata_; + state_ = that.state_; + } + return *this; + } + + template + inline bool PolyLine::operator==(const PolyLine& b) const { + return this == &b || (state_ == b.state_ && + headp_ == b.headp_ && + tailp_ == b.tailp_); + } + + //valid PolyLine + template + inline bool PolyLine::isValid() const { + return state_ > -1; } + + //first coordinate is an X value + //first segment is vertical + template + inline bool PolyLine::verticalHead() const { + return state_ & VERTICAL_HEAD; + } + + //retrun true is PolyLine has odd number of coordiantes + template + inline bool PolyLine::oddLength() const { + return to_bool((ptdata_.size()-1) % 2); + } + + //last coordiante is an X value + //last segment is vertical + template + inline bool PolyLine::verticalTail() const { + return to_bool(verticalHead() ^ oddLength()); + } + + template + inline orientation_2d PolyLine::tailOrient() const { + return (verticalTail() ? VERTICAL : HORIZONTAL); + } + + template + inline orientation_2d PolyLine::headOrient() const { + return (verticalHead() ? VERTICAL : HORIZONTAL); + } + + template + inline End PolyLine::endConnectivity(End end) const { + //Tail should be defined as true + if(end) { return tailToTail(); } + return headToTail(); + } + + template + inline bool PolyLine::headToTail() const { + return to_bool(state_ & HEAD_TO_TAIL); + } + + template + inline bool PolyLine::headToHead() const { + return to_bool(!headToTail()); + } + + template + inline bool PolyLine::tailToHead() const { + return to_bool(!tailToTail()); + } + + template + inline bool PolyLine::tailToTail() const { + return to_bool(state_ & TAIL_TO_TAIL); + } + + template + inline Side PolyLine::solidSide() const { + return solidToRight(); } + + template + inline bool PolyLine::solidToRight() const { + return to_bool(state_ & SOLID_TO_RIGHT) != 0; + } + + template + inline bool PolyLine::active() const { + return !to_bool(tailp_); + } + + template + inline PolyLine& PolyLine::pushCoordinate(Unit coord) { + ptdata_.push_back(coord); + return *this; + } + + template + inline PolyLine& PolyLine::popCoordinate() { + ptdata_.pop_back(); + return *this; + } + + template + inline PolyLine& PolyLine::pushPoint(const point_data& point) { + if(numSegments()){ + point_data endPt = getEndPoint(); + //vertical is true, horizontal is false + if((tailOrient().to_int() ? point.get(VERTICAL) == endPt.get(VERTICAL) : point.get(HORIZONTAL) == endPt.get(HORIZONTAL))) { + //we were pushing a colinear segment + return popCoordinate(); + } + } + return pushCoordinate(tailOrient().to_int() ? point.get(VERTICAL) : point.get(HORIZONTAL)); + } + + template + inline PolyLine& PolyLine::extendTail(Unit delta) { + ptdata_.back() += delta; + return *this; + } + + //private member function that creates a link from this PolyLine to that + template + inline PolyLine& PolyLine::joinTo_(End thisEnd, PolyLine& that, End end) { + if(thisEnd){ + tailp_ = &that; + state_ &= ~TAIL_TO_TAIL; //clear any previous state_ of bit (for safety) + state_ |= (end << 2); //place bit into mask + } else { + headp_ = &that; + state_ &= ~HEAD_TO_TAIL; //clear any previous state_ of bit (for safety) + state_ |= (end << 1); //place bit into mask + } + return *this; + } + + //join two PolyLines (both ways of the association) + template + inline PolyLine& PolyLine::joinTo(End thisEnd, PolyLine& that, End end) { + joinTo_(thisEnd, that, end); + that.joinTo_(end, *this, thisEnd); + return *this; + } + + //convenience functions for joining PolyLines + template + inline PolyLine& PolyLine::joinToTail(PolyLine& that, End end) { + return joinTo(TAIL, that, end); + } + template + inline PolyLine& PolyLine::joinToHead(PolyLine& that, End end) { + return joinTo(HEAD, that, end); + } + template + inline PolyLine& PolyLine::joinHeadToHead(PolyLine& that) { + return joinToHead(that, HEAD); + } + template + inline PolyLine& PolyLine::joinHeadToTail(PolyLine& that) { + return joinToHead(that, TAIL); + } + template + inline PolyLine& PolyLine::joinTailToHead(PolyLine& that) { + return joinToTail(that, HEAD); + } + template + inline PolyLine& PolyLine::joinTailToTail(PolyLine& that) { + return joinToTail(that, TAIL); + } + + template + inline PolyLine& PolyLine::disconnectTails() { + next(TAIL)->state_ &= !TAIL_TO_TAIL; + next(TAIL)->tailp_ = 0; + state_ &= !TAIL_TO_TAIL; + tailp_ = 0; + return *this; + } + + template + inline Unit PolyLine::getEndCoord(End end) const { + if(end) + return ptdata_.back(); + return ptdata_.front(); + } + + template + inline orientation_2d PolyLine::segmentOrient(unsigned int index) const { + return (to_bool((unsigned int)verticalHead() ^ (index % 2)) ? VERTICAL : HORIZONTAL); + } + + template + inline point_data PolyLine::getPoint(unsigned int index) const { + //assert(isValid() && headp_->isValid()) ("PolyLine: headp_ must be valid"); + point_data pt; + pt.set(HORIZONTAL, ptdata_[index]); + pt.set(VERTICAL, ptdata_[index]); + Unit prevCoord; + if(index == 0) { + prevCoord = headp_->getEndCoord(headToTail()); + } else { + prevCoord = ptdata_[index-1]; + } + pt.set(segmentOrient(index), prevCoord); + return pt; + } + + template + inline point_data PolyLine::getEndPoint(End end) const { + return getPoint((end ? numSegments() - 1 : (unsigned int)0)); + } + + template + inline Unit PolyLine::operator[] (unsigned int index) const { + //assert(ptdata_.size() > index) ("PolyLine: out of bounds index"); + return ptdata_[index]; + } + + template + inline unsigned int PolyLine::numSegments() const { + return ptdata_.size(); + } + + template + inline PolyLine* PolyLine::next(End end) const { + return (end ? tailp_ : headp_); + } + + template + inline ActiveTail::ActiveTail() : tailp_(0), otherTailp_(0), holesList_(), + polyLineSize_(0) {} + + template + inline ActiveTail::ActiveTail(orientation_2d orient, Unit coord, Side solidToRight, ActiveTail* otherTailp) : + tailp_(0), otherTailp_(0), holesList_(), polyLineSize_(0) { + tailp_ = createPolyLine(orient, coord, solidToRight); + otherTailp_ = otherTailp; + polyLineSize_ = tailp_->numSegments(); + } + + template + inline ActiveTail::ActiveTail(PolyLine* active, ActiveTail* otherTailp) : + tailp_(active), otherTailp_(otherTailp), holesList_(), + polyLineSize_(0) {} + + //copy constructor + template + inline ActiveTail::ActiveTail(const ActiveTail& that) : tailp_(that.tailp_), otherTailp_(that.otherTailp_), holesList_(), polyLineSize_(that.polyLineSize_) {} + + //destructor + template + inline ActiveTail::~ActiveTail() { + //clear them in case the memory is read later + tailp_ = 0; otherTailp_ = 0; + } + + template + inline ActiveTail& ActiveTail::operator=(const ActiveTail& that) { + //self assignment is safe in this case + tailp_ = that.tailp_; + otherTailp_ = that.otherTailp_; + polyLineSize_ = that.polyLineSize_; + return *this; + } + + template + inline bool ActiveTail::operator==(const ActiveTail& b) const { + return tailp_ == b.tailp_ && otherTailp_ == b.otherTailp_; + } + + template + inline bool ActiveTail::operator<(const ActiveTail& b) const { + return tailp_->getEndPoint().get(VERTICAL) < b.tailp_->getEndPoint().get(VERTICAL); + } + + template + inline bool ActiveTail::operator<=(const ActiveTail& b) const { + return !(*this > b); } + + template + inline bool ActiveTail::operator>(const ActiveTail& b) const { + return b < (*this); } + + template + inline bool ActiveTail::operator>=(const ActiveTail& b) const { + return !(*this < b); } + + template + inline PolyLine* ActiveTail::getTail() const { + return tailp_; } + + template + inline PolyLine* ActiveTail::getOtherTail() const { + return otherTailp_->tailp_; } + + template + inline ActiveTail* ActiveTail::getOtherActiveTail() const { + return otherTailp_; } + + template + inline bool ActiveTail::isOtherTail(const ActiveTail& b) { + // assert( (tailp_ == b.getOtherTail() && getOtherTail() == b.tailp_) || + // (tailp_ != b.getOtherTail() && getOtherTail() != b.tailp_)) + // ("ActiveTail: Active tails out of sync"); + return otherTailp_ == &b; + } + + template + inline ActiveTail& ActiveTail::updateTail(PolyLine* newTail) { + //subtract the old size and add new size// + int delta = newTail->numSegments() - tailp_->numSegments(); + addPolyLineSize(delta); + otherTailp_->addPolyLineSize(delta); + tailp_ = newTail; + return *this; + } + + template + inline ActiveTail* ActiveTail::addHole(ActiveTail* hole, bool fractureHoles) { + + if(!fractureHoles){ + holesList_.push_back(hole); + copyHoles(*hole); + copyHoles(*(hole->getOtherActiveTail())); + return this; + } + ActiveTail* h, *v; + ActiveTail* other = hole->getOtherActiveTail(); + if(other->getOrient() == VERTICAL) { + //assert that hole.getOrient() == HORIZONTAL + //this case should never happen + h = hole; + v = other; + } else { + //assert that hole.getOrient() == VERTICAL + h = other; + v = hole; + } + h->pushCoordinate(v->getCoordinate()); + //assert that h->getOrient() == VERTICAL + //v->pushCoordinate(getCoordinate()); + //assert that v->getOrient() == VERTICAL + //I can't close a figure by adding a hole, so pass zero for xMin and yMin + std::vector tmpVec; + ActiveTail::joinChains(this, h, false, tmpVec); + return v; + } + + template + inline const std::list*>& ActiveTail::getHoles() const { + return holesList_; + } + + template + inline void ActiveTail::copyHoles(ActiveTail& that) { + holesList_.splice(holesList_.end(), that.holesList_); //splice the two lists together + } + + template + inline bool ActiveTail::solidToRight() const { + return getTail()->solidToRight(); } + + template + inline Unit ActiveTail::getCoord() const { + return getTail()->getEndCoord(); } + + template + inline Unit ActiveTail::getCoordinate() const { + return getCoord(); } + + template + inline orientation_2d ActiveTail::getOrient() const { + return getTail()->tailOrient(); } + + template + inline void ActiveTail::pushCoordinate(Unit coord) { + //appropriately handle any co-linear polyline segments by calling push point internally + point_data p; + p.set(HORIZONTAL, coord); + p.set(VERTICAL, coord); + //if we are vertical assign the last coordinate (an X) to p.x, else to p.y + p.set(getOrient().get_perpendicular(), getCoordinate()); + int oldSegments = tailp_->numSegments(); + tailp_->pushPoint(p); + int delta = tailp_->numSegments() - oldSegments; + addPolyLineSize(delta); + otherTailp_->addPolyLineSize(delta); + } + + + //global utility functions + template + inline PolyLine* createPolyLine(orientation_2d orient, Unit coord, Side side) { + return new PolyLine(orient, coord, side); + } + + template + inline void destroyPolyLine(PolyLine* pLine) { + delete pLine; + } + + template + inline ActiveTail* createActiveTail() { + //consider replacing system allocator with ActiveTail memory pool + return new ActiveTail(); + } + + template + inline void destroyActiveTail(ActiveTail* aTail) { + delete aTail; + } + + + //no recursion, to prevent max recursion depth errors + template + inline void ActiveTail::destroyContents() { + tailp_->disconnectTails(); + PolyLine* nextPolyLinep = tailp_->next(HEAD); + End end = tailp_->endConnectivity(HEAD); + destroyPolyLine(tailp_); + while(nextPolyLinep) { + End nextEnd = nextPolyLinep->endConnectivity(!end); //get the direction of next polyLine + PolyLine* nextNextPolyLinep = nextPolyLinep->next(!end); //get the next polyline + destroyPolyLine(nextPolyLinep); //destroy the current polyline + end = nextEnd; + nextPolyLinep = nextNextPolyLinep; + } + } + + template + inline typename ActiveTail::iterator ActiveTail::begin(bool isHole, orientation_2d orient) const { + return iterator(this, isHole, orient); + } + + template + inline typename ActiveTail::iterator ActiveTail::end() const { + return iterator(); + } + + template + inline typename ActiveTail::iteratorHoles ActiveTail::beginHoles() const { + return holesList_.begin(); + } + + template + inline typename ActiveTail::iteratorHoles ActiveTail::endHoles() const { + return holesList_.end(); + } + + template + inline void ActiveTail::writeOutFigureItrs(iterator& beginOut, iterator& endOut, bool isHole, orientation_2d orient) const { + beginOut = begin(isHole, orient); + endOut = end(); + } + + template + inline void ActiveTail::writeOutFigureHoleItrs(iteratorHoles& beginOut, iteratorHoles& endOut) const { + beginOut = beginHoles(); + endOut = endHoles(); + } + + template + inline void ActiveTail::writeOutFigure(std::vector& outVec, bool isHole) const { + //we start writing out the polyLine that this active tail points to at its tail + std::size_t size = outVec.size(); + outVec.push_back(0); //place holder for size + PolyLine* nextPolyLinep = 0; + if(!isHole){ + nextPolyLinep = otherTailp_->tailp_->writeOut(outVec); + } else { + nextPolyLinep = tailp_->writeOut(outVec); + } + Unit firsty = outVec[size + 1]; + if((getOrient() == HORIZONTAL) ^ !isHole) { + //our first coordinate is a y value, so we need to rotate it to the end + typename std::vector::iterator tmpItr = outVec.begin(); + tmpItr += size; + outVec.erase(++tmpItr); //erase the 2nd element + } + End startEnd = tailp_->endConnectivity(HEAD); + if(isHole) startEnd = otherTailp_->tailp_->endConnectivity(HEAD); + while(nextPolyLinep) { + bool nextStartEnd = nextPolyLinep->endConnectivity(!startEnd); + nextPolyLinep = nextPolyLinep->writeOut(outVec, startEnd); + startEnd = nextStartEnd; + } + if((getOrient() == HORIZONTAL) ^ !isHole) { + //we want to push the y value onto the end since we ought to have ended with an x + outVec.push_back(firsty); //should never be executed because we want first value to be an x + } + //the vector contains the coordinates of the linked list of PolyLines in the correct order + //first element is supposed to be the size + outVec[size] = outVec.size() - 1 - size; //number of coordinates in vector + //assert outVec[size] % 2 == 0 //it should be even + //make the size negative for holes + outVec[size] *= (isHole ? -1 : 1); + } + + //no recursion to prevent max recursion depth errors + template + inline PolyLine* PolyLine::writeOut(std::vector& outVec, End startEnd) const { + if(startEnd == HEAD){ + //forward order + outVec.insert(outVec.end(), ptdata_.begin(), ptdata_.end()); + return tailp_; + }else{ + //reverse order + //do not reserve because we expect outVec to be large enough already + for(int i = ptdata_.size() - 1; i >= 0; --i){ + outVec.push_back(ptdata_[i]); + } + //NT didn't know about this version of the API.... + //outVec.insert(outVec.end(), ptdata_.rbegin(), ptdata_.rend()); + return headp_; + } + } + + //solid indicates if it was joined by a solit or a space + template + inline ActiveTail* ActiveTail::joinChains(ActiveTail* at1, ActiveTail* at2, bool solid, std::vector& outBufferTmp) + { + //checks to see if we closed a figure + if(at1->isOtherTail(*at2)){ + //value of solid tells us if we closed solid or hole + //and output the solid or handle the hole appropriately + //if the hole needs to fracture across horizontal partition boundary we need to notify + //the calling context to do so + if(solid) { + //the chains are being joined because there is solid to the right + //this means that if the figure is closed at this point it must be a hole + //because otherwise it would have to have another vertex to the right of this one + //and would not be closed at this point + return at1; + } else { + //assert pG != 0 + //the figure that was closed is a shell + at1->writeOutFigure(outBufferTmp); + //process holes of the polygon + at1->copyHoles(*at2); //there should not be holes on at2, but if there are, copy them over + const std::list*>& holes = at1->getHoles(); + for(typename std::list*>::const_iterator litr = holes.begin(); litr != holes.end(); ++litr) { + (*litr)->writeOutFigure(outBufferTmp, true); + //delete the hole + (*litr)->destroyContents(); + destroyActiveTail((*litr)->getOtherActiveTail()); + destroyActiveTail((*litr)); + } + //delete the polygon + at1->destroyContents(); + //at2 contents are the same as at1, so it should not destroy them + destroyActiveTail(at1); + destroyActiveTail(at2); + } + return 0; + } + //join the two partial polygons into one large partial polygon + at1->getTail()->joinTailToTail(*(at2->getTail())); + *(at1->getOtherActiveTail()) = ActiveTail(at1->getOtherTail(), at2->getOtherActiveTail()); + *(at2->getOtherActiveTail()) = ActiveTail(at2->getOtherTail(), at1->getOtherActiveTail()); + + int accumulate = at2->getPolyLineSize() + at1->getPolyLineSize(); + (at1->getOtherActiveTail())->setPolyLineSize(accumulate); + (at2->getOtherActiveTail())->setPolyLineSize(accumulate); + + at1->getOtherActiveTail()->copyHoles(*at1); + at1->getOtherActiveTail()->copyHoles(*at2); + destroyActiveTail(at1); + destroyActiveTail(at2); + return 0; + } + + //solid indicates if it was joined by a solit or a space + template + template + inline ActiveTail* ActiveTail::joinChains(ActiveTail* at1, ActiveTail* at2, bool solid, + std::vector& outBufferTmp) { + //checks to see if we closed a figure + if(at1->isOtherTail(*at2)){ + //value of solid tells us if we closed solid or hole + //and output the solid or handle the hole appropriately + //if the hole needs to fracture across horizontal partition boundary we need to notify + //the calling context to do so + if(solid) { + //the chains are being joined because there is solid to the right + //this means that if the figure is closed at this point it must be a hole + //because otherwise it would have to have another vertex to the right of this one + //and would not be closed at this point + return at1; + } else { + //assert pG != 0 + //the figure that was closed is a shell + outBufferTmp.push_back(at1); + at1->copyHoles(*at2); //there should not be holes on at2, but if there are, copy them over + } + return 0; + } + //join the two partial polygons into one large partial polygon + at1->getTail()->joinTailToTail(*(at2->getTail())); + *(at1->getOtherActiveTail()) = ActiveTail(at1->getOtherTail(), at2->getOtherActiveTail()); + *(at2->getOtherActiveTail()) = ActiveTail(at2->getOtherTail(), at1->getOtherActiveTail()); + + int accumulate = at2->getPolyLineSize() + at1->getPolyLineSize(); + (at1->getOtherActiveTail())->setPolyLineSize(accumulate); + (at2->getOtherActiveTail())->setPolyLineSize(accumulate); + + at1->getOtherActiveTail()->copyHoles(*at1); + at1->getOtherActiveTail()->copyHoles(*at2); + destroyActiveTail(at1); + destroyActiveTail(at2); + return 0; + } + + template inline typename std::map::iterator findAtNext(std::map& theMap, + typename std::map::iterator pos, const TKey& key) + { + if(pos == theMap.end()) return theMap.find(key); + //if they match the mapItr is pointing to the correct position + if(pos->first < key) { + return theMap.find(key); + } + if(pos->first > key) { + return theMap.end(); + } + //else they are equal and no need to do anything to the iterator + return pos; + } + + // createActiveTailsAsPair is called in these two end cases of geometry + // 1. lower left concave corner + // ###| + // ###| + // ###|### + // ###|### + // 2. lower left convex corner + // |### + // |### + // | + // | + // In case 1 there may be a hole propigated up from the bottom. If the fracture option is enabled + // the two active tails that form the filament fracture line edges can become the new active tail pair + // by pushing x and y onto them. Otherwise the hole simply needs to be associated to one of the new active tails + // with add hole + template + inline std::pair*, ActiveTail*> createActiveTailsAsPair(Unit x, Unit y, bool solid, ActiveTail* phole, bool fractureHoles) { + ActiveTail* at1 = 0; + ActiveTail* at2 = 0; + if(!phole || !fractureHoles){ + at1 = createActiveTail(); + at2 = createActiveTail(); + (*at1) = ActiveTail(VERTICAL, x, solid, at2); + (*at2) = ActiveTail(HORIZONTAL, y, !solid, at1); + //provide a function through activeTail class to provide this + at1->getTail()->joinHeadToHead(*(at2->getTail())); + + at1->addPolyLineSize(1); + at2->addPolyLineSize(1); + + if(phole) + at1->addHole(phole, fractureHoles); //assert fractureHoles == false + return std::pair*, ActiveTail*>(at1, at2); + } + //assert phole is not null + //assert fractureHoles is true + if(phole->getOrient() == VERTICAL) { + at2 = phole; + } else { + at2 = phole->getOtherActiveTail(); //should never be executed since orientation is expected to be vertical + } + //assert solid == false, we should be creating a corner with solid below and to the left if there was a hole + at1 = at2->getOtherActiveTail(); + //assert at1 is horizontal + at1->pushCoordinate(x); + //assert at2 is vertical + at2->pushCoordinate(y); + + return std::pair*, ActiveTail*>(at1, at2); + } + + /* + * | + * | + * = + * |######## + * |######## (add a new ActiveTail in the tailMap_). + * |######## + * |######## + * |######## + * = + * | + * | + * + * NOTE: Call this only if you are sure that the $ledege$ is not in the tailMap_ + */ + template + inline void ScanLineToPolygonItrs:: + insertNewLeftEdgeIntoTailMap(Unit currentX, Unit yBegin, Unit yEnd, + typename std::map *>::iterator &hint){ + ActiveTail *currentTail = NULL; + std::pair*, ActiveTail*> tailPair = + createActiveTailsAsPair(currentX, yBegin, true, currentTail, + fractureHoles_); + currentTail = tailPair.first; + if(!tailMap_.empty()){ + ++hint; + } + hint = tailMap_.insert(hint, std::make_pair(yBegin, tailPair.second)); + currentTail->pushCoordinate(yEnd); ++hint; + hint = tailMap_.insert(hint, std::make_pair(yEnd, currentTail)); + } + + template + inline void ScanLineToPolygonItrs:: + closePartialSimplePolygon(Unit currentX, ActiveTail*pfig, + ActiveTail*ppfig){ + pfig->pushCoordinate(currentX); + ActiveTail::joinChains(pfig, ppfig, false, outputPolygons_); + } + /* + * If the invariant is maintained correctly then left edges can do the + * following. + * + * =### + * ####### + * ####### + * ####### + * ####### + * =### + * |### (input left edge) + * |### + * =### + * ####### + * ####### + * =### + */ + template + inline void ScanLineToPolygonItrs:: + updatePartialSimplePolygonsWithLeftEdges(Unit currentX, + const std::vector > &leftEdges, size_t vertexThreshold){ + typename std::map* >::iterator succ, succ1; + typename std::map* >::iterator pred, pred1, hint; + Unit begin, end; + ActiveTail *pfig, *ppfig; + std::pair*, ActiveTail*> tailPair; + size_t pfig_size = 0; + + hint = tailMap_.begin(); + for(size_t i=0; i < leftEdges.size(); i++){ + begin = leftEdges[i].get(LOW); end = leftEdges[i].get(HIGH); + succ = findAtNext(tailMap_, hint, begin); + pred = findAtNext(tailMap_, hint, end); + + if(succ != tailMap_.end() && pred != tailMap_.end()){ //CASE-1// + //join the corresponding active tails// + pfig = succ->second; ppfig = pred->second; + pfig_size = pfig->getPolyLineSize() + ppfig->getPolyLineSize(); + + if(pfig_size >= vertexThreshold){ + size_t bsize = pfig->getPolyLineSize(); + size_t usize = ppfig->getPolyLineSize(); + + if(usize+2 < vertexThreshold){ + //cut-off the lower piece (succ1, succ) join (succ1, pred)// + succ1 = succ; --succ1; + assert((succ1 != tailMap_.end()) && + ((succ->second)->getOtherActiveTail() == succ1->second)); + closePartialSimplePolygon(currentX, succ1->second, succ->second); + tailPair = createActiveTailsAsPair(currentX, succ1->first, + true, NULL, fractureHoles_); + + //just update the succ1 with new ActiveTail*// + succ1->second = tailPair.second; + ActiveTail::joinChains(tailPair.first, pred->second, true, + outputPolygons_); + }else if(bsize+2 < vertexThreshold){ + //cut-off the upper piece () join ()// + pred1 = pred; ++pred1; + assert(pred1 != tailMap_.end() && + ((pred1->second)->getOtherActiveTail() == pred->second)); + closePartialSimplePolygon(currentX, pred->second, pred1->second); + + //just update the pred1 with ActiveTail* = pfig// + pred1->second = pfig; + pfig->pushCoordinate(currentX); + pfig->pushCoordinate(pred1->first); + }else{ + //cut both and create an left edge between (pred->first, succ1)// + succ1 = succ; --succ1; + pred1 = pred; ++pred1; + assert(pred1 != tailMap_.end() && succ1 != tailMap_.end()); + assert((pred1->second)->getOtherActiveTail() == pred->second); + assert((succ1->second)->getOtherActiveTail() == succ->second); + + closePartialSimplePolygon(currentX, succ1->second, succ->second); + closePartialSimplePolygon(currentX, pred->second, pred1->second); + + tailPair = createActiveTailsAsPair(currentX, succ1->first, + true, NULL, fractureHoles_); + succ1->second = tailPair.second; + pred1->second = tailPair.first; + (tailPair.first)->pushCoordinate(pred1->first); + } + }else{ + //just join them with closing// + pfig->pushCoordinate(currentX); + ActiveTail::joinChains(pfig, ppfig, true, outputPolygons_); + } + hint = pred; ++hint; + tailMap_.erase(succ); tailMap_.erase(pred); + }else if(succ == tailMap_.end() && pred != tailMap_.end()){ //CASE-2// + //succ is missing in the map, first insert it into the map// + tailPair = createActiveTailsAsPair(currentX, begin, true, NULL, + fractureHoles_); + hint = pred; ++hint; + hint = tailMap_.insert(hint, std::make_pair(begin, tailPair.second)); + + pfig = pred->second; + pfig_size = pfig->getPolyLineSize() + 2; + if(pfig_size >= vertexThreshold){ + //cut-off piece from [pred, pred1] , add [begin, pred1]// + pred1 = pred; ++pred1; + assert((pred1 != tailMap_.end()) && + ((pred1->second)->getOtherActiveTail() == pred->second)); + closePartialSimplePolygon(currentX, pred->second, pred1->second); + + //update: we need left edge between (begin, pred1->first)// + pred1->second = tailPair.first; + (tailPair.first)->pushCoordinate(pred1->first); + }else{ + //just join// + ActiveTail::joinChains(tailPair.first, pfig, + true, outputPolygons_); + } + tailMap_.erase(pred); + }else if(succ != tailMap_.end() && pred == tailMap_.end()){ //CASE-3// + //pred is missing in the map, first insert it into the map// + hint = succ; ++hint; + hint = tailMap_.insert(hint, std::make_pair(end, (ActiveTail *) NULL)); + pfig = succ->second; + pfig_size = pfig->getPolyLineSize() + 2; + if(pfig_size >= vertexThreshold){ + //this figure needs cutting here// + succ1 = succ; --succ1; + assert((succ1 != tailMap_.end()) && + (succ1->second == pfig->getOtherActiveTail())); + ppfig = succ1->second; + closePartialSimplePolygon(currentX, ppfig, pfig); + + //update: we need a left edge between (succ1->first, end)// + tailPair = createActiveTailsAsPair(currentX, succ1->first, + true, NULL, fractureHoles_); + succ1->second = tailPair.second; + hint->second = tailPair.first; + (tailPair.first)->pushCoordinate(end); + }else{ + //no cutting needed// + hint->second = pfig; + pfig->pushCoordinate(currentX); + pfig->pushCoordinate(end); + } + tailMap_.erase(succ); + }else{ + //insert both pred and succ// + insertNewLeftEdgeIntoTailMap(currentX, begin, end, hint); + } + } + } + + template + inline void ScanLineToPolygonItrs:: + updatePartialSimplePolygonsWithRightEdges(Unit currentX, + const std::vector > &rightEdges, size_t vertexThreshold) + { + + typename std::map* >::iterator succ, pred, hint; + std::pair*, ActiveTail*> tailPair; + Unit begin, end; + size_t i = 0; + //If rightEdges is non-empty Then tailMap_ is non-empty // + assert(rightEdges.empty() || !tailMap_.empty() ); + + while( i < rightEdges.size() ){ + //find the interval in the tailMap which contains this interval// + pred = tailMap_.lower_bound(rightEdges[i].get(HIGH)); + assert(pred != tailMap_.end()); + succ = pred; --succ; + assert(pred != succ); + end = pred->first; begin = succ->first; + + //we now have a [begin, end] // + bool found_solid_opening = false; + bool erase_succ = true, erase_pred = true; + Unit solid_opening_begin = 0; + Unit solid_opening_end = 0; + size_t j = i+1; + ActiveTail *pfig = succ->second; + ActiveTail *ppfig = pred->second; + size_t partial_fig_size = pfig->getPolyLineSize(); + //Invariant:// + assert(succ->second && (pfig)->getOtherActiveTail() == ppfig); + + hint = succ; + Unit key = rightEdges[i].get(LOW); + if(begin != key){ + found_solid_opening = true; + solid_opening_begin = begin; solid_opening_end = key; + } + + while(j < rightEdges.size() && rightEdges[j].get(HIGH) <= end){ + if(rightEdges[j-1].get(HIGH) != rightEdges[j].get(LOW)){ + if(!found_solid_opening){ + found_solid_opening = true; + solid_opening_begin = rightEdges[j-1].get(HIGH); + solid_opening_end = rightEdges[j].get(LOW); + }else{ + ++hint; + insertNewLeftEdgeIntoTailMap(currentX, + rightEdges[j-1].get(HIGH), rightEdges[j].get(LOW), hint); + } + } + j++; + } + + //trailing edge// + if(end != rightEdges[j-1].get(HIGH)){ + if(!found_solid_opening){ + found_solid_opening = true; + solid_opening_begin = rightEdges[j-1].get(HIGH); solid_opening_end = end; + }else{ + // a solid opening has been found already, we need to insert a new left + // between [rightEdges[j-1].get(HIGH), end] + Unit lbegin = rightEdges[j-1].get(HIGH); + tailPair = createActiveTailsAsPair(currentX, lbegin, true, NULL, + fractureHoles_); + hint = tailMap_.insert(pred, std::make_pair(lbegin, tailPair.second)); + pred->second = tailPair.first; + (tailPair.first)->pushCoordinate(end); + erase_pred = false; + } + } + + size_t vertex_delta = ((begin != solid_opening_begin) && + (end != solid_opening_end)) ? 4 : 2; + + if(!found_solid_opening){ + //just close the figure, TODO: call closePartialPolygon// + pfig->pushCoordinate(currentX); + ActiveTail::joinChains(pfig, ppfig, false, outputPolygons_); + hint = pred; ++hint; + }else if(partial_fig_size+vertex_delta >= vertexThreshold){ + //close the figure and add a pseudo left-edge// + closePartialSimplePolygon(currentX, pfig, ppfig); + assert(begin != solid_opening_begin || end != solid_opening_end); + + if(begin != solid_opening_begin && end != solid_opening_end){ + insertNewLeftEdgeIntoTailMap(currentX, solid_opening_begin, + solid_opening_end, hint); + }else if(begin == solid_opening_begin){ + //we just need to update the succ in the tailMap_// + tailPair = createActiveTailsAsPair(currentX, solid_opening_begin, + true, NULL, fractureHoles_); + succ->second = tailPair.second; + hint = succ; ++hint; + hint = tailMap_.insert(pred, std::make_pair(solid_opening_end, + tailPair.first)); + (tailPair.first)->pushCoordinate(solid_opening_end); + erase_succ = false; + }else{ + //we just need to update the pred in the tailMap_// + tailPair = createActiveTailsAsPair(currentX, solid_opening_begin, + true, NULL, fractureHoles_); + hint = tailMap_.insert(pred, std::make_pair(solid_opening_begin, + tailPair.second)); + pred->second = tailPair.first; + (tailPair.first)->pushCoordinate(solid_opening_end); + erase_pred = false; + } + }else{ + //continue the figure (by adding at-most two new vertices)// + if(begin != solid_opening_begin){ + pfig->pushCoordinate(currentX); + pfig->pushCoordinate(solid_opening_begin); + //insert solid_opening_begin// + hint = succ; ++hint; + hint = tailMap_.insert(hint, std::make_pair(solid_opening_begin, pfig)); + }else{ + erase_succ = false; + } + + if(end != solid_opening_end){ + std::pair*, ActiveTail*> tailPair = + createActiveTailsAsPair(currentX, solid_opening_end, false, + NULL, fractureHoles_); + hint = pred; ++hint; + hint = tailMap_.insert(hint, std::make_pair(solid_opening_end, + tailPair.second)); + ActiveTail::joinChains(tailPair.first, ppfig, false, + outputPolygons_); + }else{ + erase_pred = false; + } + } + + //Remove the pred and succ if necessary// + if(erase_succ){ + tailMap_.erase(succ); + } + if(erase_pred){ + tailMap_.erase(pred); + } + i = j; + } + } + + // Maintains the following invariant: + // a. All the partial polygons formed at any state can be closed + // by a single edge. + template + inline void ScanLineToPolygonItrs:: + maintainPartialSimplePolygonInvariant(iterator& beginOutput, + iterator& endOutput, Unit currentX, const std::vector >& l, + const std::vector >& r, size_t vertexThreshold) { + + clearOutput_(); + if(!l.empty()){ + updatePartialSimplePolygonsWithLeftEdges(currentX, l, vertexThreshold); + } + + if(!r.empty()){ + updatePartialSimplePolygonsWithRightEdges(currentX, r, vertexThreshold); + } + beginOutput = outputPolygons_.begin(); + endOutput = outputPolygons_.end(); + + } + + //Process edges connects vertical input edges (right or left edges of figures) to horizontal edges stored as member + //data of the scanline object. It also creates now horizontal edges as needed to construct figures from edge data. + // + //There are only 12 geometric end cases where the scanline intersects a horizontal edge and even fewer unique + //actions to take: + // 1. Solid on both sides of the vertical partition after the current position and space on both sides before + // ###|### + // ###|### + // | + // | + // This case does not need to be handled because there is no vertical edge at the current x coordinate. + // + // 2. Solid on both sides of the vertical partition before the current position and space on both sides after + // | + // | + // ###|### + // ###|### + // This case does not need to be handled because there is no vertical edge at the current x coordinate. + // + // 3. Solid on the left of the vertical partition after the current position and space elsewhere + // ###| + // ###| + // | + // | + // The horizontal edge from the left is found and turns upward because of the vertical right edge to become + // the currently active vertical edge. + // + // 4. Solid on the left of the vertical partion before the current position and space elsewhere + // | + // | + // ###| + // ###| + // The horizontal edge from the left is found and joined to the currently active vertical edge. + // + // 5. Solid to the right above and below and solid to the left above current position. + // ###|### + // ###|### + // |### + // |### + // The horizontal edge from the left is found and joined to the currently active vertical edge, + // potentially closing a hole. + // + // 6. Solid on the left of the vertical partion before the current position and solid to the right above and below + // |### + // |### + // ###|### + // ###|### + // The horizontal edge from the left is found and turns upward because of the vertical right edge to become + // the currently active vertical edge. + // + // 7. Solid on the right of the vertical partition after the current position and space elsewhere + // |### + // |### + // | + // | + // Create two new ActiveTails, one is added to the horizontal edges and the other becomes the vertical currentTail + // + // 8. Solid on the right of the vertical partion before the current position and space elsewhere + // | + // | + // |### + // |### + // The currentTail vertical edge turns right and is added to the horizontal edges data + // + // 9. Solid to the right above and solid to the left above and below current position. + // ###|### + // ###|### + // ###| + // ###| + // The currentTail vertical edge turns right and is added to the horizontal edges data + // + // 10. Solid on the left of the vertical partion above and below the current position and solid to the right below + // ###| + // ###| + // ###|### + // ###|### + // Create two new ActiveTails, one is added to the horizontal edges data and the other becomes the vertical currentTail + // + // 11. Solid to the right above and solid to the left below current position. + // |### + // |### + // ###| + // ###| + // The currentTail vertical edge joins the horizontal edge from the left (may close a polygon) + // Create two new ActiveTails, one is added to the horizontal edges data and the other becomes the vertical currentTail + // + // 12. Solid on the left of the vertical partion above the current position and solid to the right below + // ###| + // ###| + // |### + // |### + // The currentTail vertical edge turns right and is added to the horizontal edges data. + // The horizontal edge from the left turns upward and becomes the currentTail vertical edge + // + template + inline void ScanLineToPolygonItrs:: + processEdges(iterator& beginOutput, iterator& endOutput, + Unit currentX, std::vector >& leftEdges, + std::vector >& rightEdges, + size_t vertexThreshold) { + clearOutput_(); + typename std::map*>::iterator nextMapItr; + //foreach edge + unsigned int leftIndex = 0; + unsigned int rightIndex = 0; + bool bottomAlreadyProcessed = false; + ActiveTail* currentTail = 0; + const Unit UnitMax = (std::numeric_limits::max)(); + + if(vertexThreshold < (std::numeric_limits::max)()){ + maintainPartialSimplePolygonInvariant(beginOutput, endOutput, currentX, + leftEdges, rightEdges, vertexThreshold); + return; + } + + nextMapItr = tailMap_.begin(); + while(leftIndex < leftEdges.size() || rightIndex < rightEdges.size()) { + interval_data edges[2] = {interval_data (UnitMax, UnitMax), + interval_data (UnitMax, UnitMax)}; + bool haveNextEdge = true; + if(leftIndex < leftEdges.size()) + edges[0] = leftEdges[leftIndex]; + else + haveNextEdge = false; + if(rightIndex < rightEdges.size()) + edges[1] = rightEdges[rightIndex]; + else + haveNextEdge = false; + bool trailingEdge = edges[1].get(LOW) < edges[0].get(LOW); + interval_data & edge = edges[trailingEdge]; + interval_data & nextEdge = edges[!trailingEdge]; + //process this edge + if(!bottomAlreadyProcessed) { + //assert currentTail = 0 + + //process the bottom end of this edge + typename std::map*>::iterator thisMapItr = findAtNext(tailMap_, nextMapItr, edge.get(LOW)); + if(thisMapItr != tailMap_.end()) { + //there is an edge in the map at the low end of this edge + //it needs to turn upward and become the current tail + ActiveTail* tail = thisMapItr->second; + if(currentTail) { + //stitch currentTail into this tail + currentTail = tail->addHole(currentTail, fractureHoles_); + if(!fractureHoles_) + currentTail->pushCoordinate(currentX); + } else { + currentTail = tail; + currentTail->pushCoordinate(currentX); + } + //assert currentTail->getOrient() == VERTICAL + nextMapItr = thisMapItr; //set nextMapItr to the next position after this one + ++nextMapItr; + //remove thisMapItr from the map + tailMap_.erase(thisMapItr); + } else { + //there is no edge in the map at the low end of this edge + //we need to create one and another one to be the current vertical tail + //if this is a trailing edge then there is space to the right of the vertical edge + //so pass the inverse of trailingEdge to indicate solid to the right + std::pair*, ActiveTail*> tailPair = + createActiveTailsAsPair(currentX, edge.get(LOW), !trailingEdge, currentTail, fractureHoles_); + currentTail = tailPair.first; + tailMap_.insert(nextMapItr, std::pair*>(edge.get(LOW), tailPair.second)); + // leave nextMapItr unchanged + } + + } + if(haveNextEdge && edge.get(HIGH) == nextEdge.get(LOW)) { + //the top of this edge is equal to the bottom of the next edge, process them both + bottomAlreadyProcessed = true; + typename std::map*>::iterator thisMapItr = findAtNext(tailMap_, nextMapItr, edge.get(HIGH)); + if(thisMapItr == tailMap_.end()) //assert this should never happen + return; + if(trailingEdge) { + //geometry at this position + // |## + // |## + // ----- + // ##| + // ##| + //current tail should join thisMapItr tail + ActiveTail* tail = thisMapItr->second; + //pass false because they are being joined because space is to the right and it will close a solid figure + ActiveTail::joinChains(currentTail, tail, false, outputPolygons_); + //two new tails are created, the vertical becomes current tail, the horizontal becomes thisMapItr tail + //pass true becuase they are created at the lower left corner of some solid + //pass null because there is no hole pointer possible + std::pair*, ActiveTail*> tailPair = + createActiveTailsAsPair(currentX, edge.get(HIGH), true, 0, fractureHoles_); + currentTail = tailPair.first; + thisMapItr->second = tailPair.second; + } else { + //geometry at this position + // ##| + // ##| + // ----- + // |## + // |## + //current tail should turn right + currentTail->pushCoordinate(edge.get(HIGH)); + //thisMapItr tail should turn up + thisMapItr->second->pushCoordinate(currentX); + //thisMapItr tail becomes current tail and current tail becomes thisMapItr tail + std::swap(currentTail, thisMapItr->second); + } + nextMapItr = thisMapItr; //set nextMapItr to the next position after this one + ++nextMapItr; + } else { + //there is a gap between the top of this edge and the bottom of the next, process the top of this edge + bottomAlreadyProcessed = false; + //process the top of this edge + typename std::map*>::iterator thisMapItr = findAtNext(tailMap_, nextMapItr, edge.get(HIGH)); + if(thisMapItr != tailMap_.end()) { + //thisMapItr is pointing to a horizontal edge in the map at the top of this vertical edge + //we need to join them and potentially close a figure + //assert currentTail != 0 + ActiveTail* tail = thisMapItr->second; + //pass the opositve of trailing edge to mean that they are joined because of solid to the right + currentTail = ActiveTail::joinChains(currentTail, tail, !trailingEdge, outputPolygons_); + nextMapItr = thisMapItr; //set nextMapItr to the next position after this one + ++nextMapItr; + if(currentTail) { //figure is not closed// + Unit nextItrY = UnitMax; + if(nextMapItr != tailMap_.end()) { + nextItrY = nextMapItr->first; + } + //for it to be a hole this must have been a left edge + Unit leftY = UnitMax; + if(leftIndex + 1 < leftEdges.size()) + leftY = leftEdges[leftIndex+1].get(LOW); + Unit rightY = nextEdge.get(LOW); + if(!haveNextEdge || (nextItrY < leftY && nextItrY < rightY)) { + //we need to add it to the next edge above it in the map + tail = nextMapItr->second; + tail = tail->addHole(currentTail, fractureHoles_); + if(fractureHoles_) { + //some small additional work stitching in the filament + tail->pushCoordinate(nextItrY); + nextMapItr->second = tail; + } + //set current tail to null + currentTail = 0; + } + } + //delete thisMapItr from the map + tailMap_.erase(thisMapItr); + } else { + //currentTail must turn right and be added into the map + currentTail->pushCoordinate(edge.get(HIGH)); + //assert currentTail->getOrient() == HORIZONTAL + tailMap_.insert(nextMapItr, std::pair*>(edge.get(HIGH), currentTail)); + //set currentTail to null + currentTail = 0; + //leave nextMapItr unchanged, it is still next + } + } + + //increment index + leftIndex += !trailingEdge; + rightIndex += trailingEdge; + } //end while + beginOutput = outputPolygons_.begin(); + endOutput = outputPolygons_.end(); + } //end function + + template + inline void ScanLineToPolygonItrs::clearOutput_() { + for(std::size_t i = 0; i < outputPolygons_.size(); ++i) { + ActiveTail* at1 = outputPolygons_[i].yield(); + const std::list*>& holes = at1->getHoles(); + for(typename std::list*>::const_iterator litr = holes.begin(); litr != holes.end(); ++litr) { + //delete the hole + (*litr)->destroyContents(); + destroyActiveTail((*litr)->getOtherActiveTail()); + destroyActiveTail((*litr)); + } + //delete the polygon + at1->destroyContents(); + //at2 contents are the same as at1, so it should not destroy them + destroyActiveTail((at1)->getOtherActiveTail()); + destroyActiveTail(at1); + } + outputPolygons_.clear(); + } + +} //polygon_formation namespace + + template + struct geometry_concept > { + typedef polygon_90_with_holes_concept type; + }; + + template + struct geometry_concept > { + typedef polygon_90_concept type; + }; + + //public API to access polygon formation algorithm + template + unsigned int get_polygons(output_container& container, + iterator_type begin, iterator_type end, orientation_2d orient, + bool fracture_holes, concept_type, + size_t sliceThreshold = (std::numeric_limits::max)() ) { + typedef typename output_container::value_type polygon_type; + typedef typename std::iterator_traits::value_type::first_type coordinate_type; + polygon_type poly; + unsigned int countPolygons = 0; + typedef typename geometry_concept::type polygon_concept_type; + polygon_formation::ScanLineToPolygonItrs scanlineToPolygonItrsV(fracture_holes); + polygon_formation::ScanLineToPolygonItrs scanlineToPolygonItrsH(fracture_holes); + std::vector > leftEdges; + std::vector > rightEdges; + coordinate_type prevPos = (std::numeric_limits::max)(); + coordinate_type prevY = (std::numeric_limits::max)(); + int count = 0; + for(iterator_type itr = begin; + itr != end; ++ itr) { + coordinate_type pos = (*itr).first; + if(pos != prevPos) { + if(orient == VERTICAL) { + typename polygon_formation::ScanLineToPolygonItrs::iterator itrPoly, itrPolyEnd; + scanlineToPolygonItrsV.processEdges(itrPoly, itrPolyEnd, prevPos, + leftEdges, rightEdges, sliceThreshold); + for( ; itrPoly != itrPolyEnd; ++ itrPoly) { + ++countPolygons; + assign(poly, *itrPoly); + container.insert(container.end(), poly); + } + } else { + typename polygon_formation::ScanLineToPolygonItrs::iterator itrPoly, itrPolyEnd; + scanlineToPolygonItrsH.processEdges(itrPoly, itrPolyEnd, prevPos, + leftEdges, rightEdges, sliceThreshold); + for( ; itrPoly != itrPolyEnd; ++ itrPoly) { + ++countPolygons; + assign(poly, *itrPoly); + container.insert(container.end(), poly); + } + } + leftEdges.clear(); + rightEdges.clear(); + prevPos = pos; + prevY = (*itr).second.first; + count = (*itr).second.second; + continue; + } + coordinate_type y = (*itr).second.first; + if(count != 0 && y != prevY) { + std::pair, int> element(interval_data(prevY, y), count); + if(element.second == 1) { + if(leftEdges.size() && leftEdges.back().high() == element.first.low()) { + encompass(leftEdges.back(), element.first); + } else { + leftEdges.push_back(element.first); + } + } else { + if(rightEdges.size() && rightEdges.back().high() == element.first.low()) { + encompass(rightEdges.back(), element.first); + } else { + rightEdges.push_back(element.first); + } + } + + } + prevY = y; + count += (*itr).second.second; + } + if(orient == VERTICAL) { + typename polygon_formation::ScanLineToPolygonItrs::iterator itrPoly, itrPolyEnd; + scanlineToPolygonItrsV.processEdges(itrPoly, itrPolyEnd, prevPos, leftEdges, rightEdges, sliceThreshold); + for( ; itrPoly != itrPolyEnd; ++ itrPoly) { + ++countPolygons; + assign(poly, *itrPoly); + container.insert(container.end(), poly); + } + } else { + typename polygon_formation::ScanLineToPolygonItrs::iterator itrPoly, itrPolyEnd; + scanlineToPolygonItrsH.processEdges(itrPoly, itrPolyEnd, prevPos, leftEdges, rightEdges, sliceThreshold); + + for( ; itrPoly != itrPolyEnd; ++ itrPoly) { + ++countPolygons; + assign(poly, *itrPoly); + container.insert(container.end(), poly); + } + } + return countPolygons; + } + +} +} +#endif diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/detail/polygon_set_view.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/detail/polygon_set_view.hpp new file mode 100644 index 0000000..7d27091 --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/detail/polygon_set_view.hpp @@ -0,0 +1,222 @@ +/* + Copyright 2008 Intel Corporation + + Use, modification and distribution are subject to the Boost Software License, + Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at + http://www.boost.org/LICENSE_1_0.txt). +*/ +#ifndef BOOST_POLYGON_POLYGON_SET_VIEW_HPP +#define BOOST_POLYGON_POLYGON_SET_VIEW_HPP +namespace boost { namespace polygon{ + + + template + inline void polygon_set_data::clean() const { + if(dirty_) { + //polygon_45_set_data tmp; + //very important: + //the 45 degree algorithm does not satisfy + //the precondition of arbitrary polygon formation + //that vertices be "linearly consistent" + //therefore it doesn't work to fall back on 45-degree + //booleans for arbitrary angle polygons + //if(0) { //downcast(tmp) ) { + // tmp.clean(); + // data_.clear(); + // is_45_ = true; + // polygon_set_data tmp2; + // tmp2.insert(tmp); + // data_.swap(tmp2.data_); + // dirty_ = false; + // sort(); + //} else { + sort(); + arbitrary_boolean_op abo; + polygon_set_data tmp2; + abo.execute(tmp2, begin(), end(), end(), end(), 0); + data_.swap(tmp2.data_); + is_45_ = tmp2.is_45_; + dirty_ = false; + //} + } + } + + template <> + inline void polygon_set_data::clean() const { + if(dirty_) { + sort(); + arbitrary_boolean_op abo; + polygon_set_data tmp2; + abo.execute(tmp2, begin(), end(), end(), end(), 0); + data_.swap(tmp2.data_); + is_45_ = tmp2.is_45_; + dirty_ = false; + } + } + + template + inline void insert_into_view_arg(value_type& dest, const arg_type& arg); + + template + class polygon_set_view; + + template + struct polygon_set_traits > { + typedef typename polygon_set_view::coordinate_type coordinate_type; + typedef typename polygon_set_view::iterator_type iterator_type; + typedef typename polygon_set_view::operator_arg_type operator_arg_type; + + static inline iterator_type begin(const polygon_set_view& polygon_set); + static inline iterator_type end(const polygon_set_view& polygon_set); + + static inline bool clean(const polygon_set_view& polygon_set); + + static inline bool sort(const polygon_set_view& polygon_set); + }; + + //template + //void execute_boolean_op(value_type& output_, const geometry_type_1& lvalue_, const geometry_type_2& rvalue_, + // double coord) { + // typedef geometry_type_1 ltype; + // typedef geometry_type_2 rtype; + // typedef typename polygon_set_traits::coordinate_type coordinate_type; + // value_type linput_; + // value_type rinput_; + // insert_into_view_arg(linput_, lvalue_); + // insert_into_view_arg(rinput_, rvalue_); + // arbitrary_boolean_op abo; + // abo.execute(output_, linput_.begin(), linput_.end(), + // rinput_.begin(), rinput_.end(), op_type); + //} + + template + void execute_boolean_op(value_type& output_, const geometry_type_1& lvalue_, const geometry_type_2& rvalue_) { + typedef geometry_type_1 ltype; + //typedef geometry_type_2 rtype; + typedef typename polygon_set_traits::coordinate_type coordinate_type; + value_type linput_; + value_type rinput_; + insert_into_view_arg(linput_, lvalue_); + insert_into_view_arg(rinput_, rvalue_); + polygon_45_set_data l45, r45, o45; +// if(linput_.downcast(l45) && rinput_.downcast(r45)) { +// //the op codes are screwed up between 45 and arbitrary +//#ifdef BOOST_POLYGON_MSVC +//#pragma warning (push) +//#pragma warning (disable: 4127) +//#endif +// if(op_type < 2) +// l45.template applyAdaptiveBoolean_(o45, r45); +// else if(op_type == 2) +// l45.template applyAdaptiveBoolean_<3>(o45, r45); +// else +// l45.template applyAdaptiveBoolean_<2>(o45, r45); +//#ifdef BOOST_POLYGON_MSVC +//#pragma warning (pop) +//#endif +// output_.insert(o45); +// } else { + arbitrary_boolean_op abo; + abo.execute(output_, linput_.begin(), linput_.end(), + rinput_.begin(), rinput_.end(), op_type); +// } + } + + template + class polygon_set_view { + public: + typedef typename polygon_set_traits::coordinate_type coordinate_type; + typedef polygon_set_data value_type; + typedef typename value_type::iterator_type iterator_type; + typedef polygon_set_view operator_arg_type; + private: + const ltype& lvalue_; + const rtype& rvalue_; + mutable value_type output_; + mutable bool evaluated_; + polygon_set_view& operator=(const polygon_set_view&); + public: + polygon_set_view(const ltype& lvalue, + const rtype& rvalue ) : + lvalue_(lvalue), rvalue_(rvalue), output_(), evaluated_(false) {} + + // get iterator to begin vertex data + public: + const value_type& value() const { + if(!evaluated_) { + evaluated_ = true; + execute_boolean_op(output_, lvalue_, rvalue_); + } + return output_; + } + public: + iterator_type begin() const { return value().begin(); } + iterator_type end() const { return value().end(); } + + bool dirty() const { return false; } //result of a boolean is clean + bool sorted() const { return true; } //result of a boolean is sorted + + void sort() const {} //is always sorted + }; + + template + typename polygon_set_traits >::iterator_type + polygon_set_traits >:: + begin(const polygon_set_view& polygon_set) { + return polygon_set.begin(); + } + template + typename polygon_set_traits >::iterator_type + polygon_set_traits >:: + end(const polygon_set_view& polygon_set) { + return polygon_set.end(); + } + template + bool polygon_set_traits >:: + clean(const polygon_set_view& ) { + return true; } + template + bool polygon_set_traits >:: + sort(const polygon_set_view& ) { + return true; } + + template + inline void insert_into_view_arg(value_type& dest, const arg_type& arg) { + typedef typename polygon_set_traits::iterator_type literator; + literator itr1, itr2; + itr1 = polygon_set_traits::begin(arg); + itr2 = polygon_set_traits::end(arg); + dest.insert(itr1, itr2); + } + + template + geometry_type_1& self_assignment_boolean_op(geometry_type_1& lvalue_, const geometry_type_2& rvalue_) { + typedef geometry_type_1 ltype; + typedef typename polygon_set_traits::coordinate_type coordinate_type; + typedef polygon_set_data value_type; + value_type output_; + execute_boolean_op(output_, lvalue_, rvalue_); + polygon_set_mutable_traits::set(lvalue_, output_.begin(), output_.end()); + return lvalue_; + } + + // copy constructor + template + template + polygon_set_data::polygon_set_data(const polygon_set_view& that) : + data_(that.value().data_), dirty_(that.value().dirty_), unsorted_(that.value().unsorted_), is_45_(that.value().is_45_) {} + + // equivalence operator + template + inline bool polygon_set_data::operator==(const polygon_set_data& p) const { + typedef polygon_set_data value_type; + value_type output_; + execute_boolean_op(output_, (*this), p); + return output_.data_.empty(); + } + + template + struct geometry_concept > { typedef polygon_set_concept type; }; +} +} +#endif diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/detail/polygon_simplify.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/detail/polygon_simplify.hpp new file mode 100644 index 0000000..4871f50 --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/detail/polygon_simplify.hpp @@ -0,0 +1,116 @@ +// Copyright 2011, Andrew Ross +// +// Use, modification and distribution are subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt). +#ifndef BOOST_POLYGON_DETAIL_SIMPLIFY_HPP +#define BOOST_POLYGON_DETAIL_SIMPLIFY_HPP +#include + +namespace boost { namespace polygon { namespace detail { namespace simplify_detail { + + // Does a simplification/optimization pass on the polygon. If a given + // vertex lies within "len" of the line segment joining its neighbor + // vertices, it is removed. + template //T is a model of point concept + std::size_t simplify(std::vector& dst, const std::vector& src, + typename coordinate_traits< + typename point_traits::coordinate_type + >::coordinate_distance len) + { + using namespace boost::polygon; + typedef typename point_traits::coordinate_type coordinate_type; + typedef typename coordinate_traits::area_type ftype; + typedef typename std::vector::const_iterator iter; + + std::vector out; + out.reserve(src.size()); + dst = src; + std::size_t final_result = 0; + std::size_t orig_size = src.size(); + + //I can't use == if T doesn't provide it, so use generic point concept compare + bool closed = equivalence(src.front(), src.back()); + + //we need to keep smoothing until we don't find points to remove + //because removing points in the first iteration through the + //polygon may leave it in a state where more removal is possible + bool not_done = true; + while(not_done) { + if(dst.size() < 3) { + dst.clear(); + return orig_size; + } + + // Start with the second, test for the last point + // explicitly, and exit after looping back around to the first. + ftype len2 = ftype(len) * ftype(len); + for(iter prev=dst.begin(), i=prev+1, next; /**/; i = next) { + next = i+1; + if(next == dst.end()) + next = dst.begin(); + + // points A, B, C + ftype ax = x(*prev), ay = y(*prev); + ftype bx = x(*i), by = y(*i); + ftype cx = x(*next), cy = y(*next); + + // vectors AB, BC and AC: + ftype abx = bx-ax, aby = by-ay; + ftype bcx = cx-bx, bcy = cy-by; + ftype acx = cx-ax, acy = cy-ay; + + // dot products + ftype ab_ab = abx*abx + aby*aby; + ftype bc_bc = bcx*bcx + bcy*bcy; + ftype ac_ac = acx*acx + acy*acy; + ftype ab_ac = abx*acx + aby*acy; + + // projection of AB along AC + ftype projf = ab_ac / ac_ac; + ftype projx = acx * projf, projy = acy * projf; + + // perpendicular vector from the line AC to point B (i.e. AB - proj) + ftype perpx = abx - projx, perpy = aby - projy; + + // Squared fractional distance of projection. FIXME: can + // remove this division, the decisions below can be made with + // just the sign of the quotient and a check to see if + // abs(numerator) is greater than abs(divisor). + ftype f2 = (projx*acx + projy*acx) / ac_ac; + + // Square of the relevant distance from point B: + ftype dist2; + if (f2 < 0) dist2 = ab_ab; + else if(f2 > 1) dist2 = bc_bc; + else dist2 = perpx*perpx + perpy*perpy; + + if(dist2 > len2) { + prev = i; // bump prev, we didn't remove the segment + out.push_back(*i); + } + + if(i == dst.begin()) + break; + } + std::size_t result = dst.size() - out.size(); + if(result == 0) { + not_done = false; + } else { + final_result += result; + dst = out; + out.clear(); + } + } //end of while loop + if(closed) { + //if the input was closed we want the output to be closed + --final_result; + dst.push_back(dst.front()); + } + return final_result; + } + + +}}}} + +#endif diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/detail/polygon_sort_adaptor.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/detail/polygon_sort_adaptor.hpp new file mode 100644 index 0000000..b3561f8 --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/detail/polygon_sort_adaptor.hpp @@ -0,0 +1,67 @@ +/* + Copyright 2008 Intel Corporation + + Use, modification and distribution are subject to the Boost Software License, + Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at + http://www.boost.org/LICENSE_1_0.txt). +*/ +#ifndef BOOST_POLYGON_SORT_ADAPTOR_HPP +#define BOOST_POLYGON_SORT_ADAPTOR_HPP +#ifdef __ICC +#pragma warning(disable:2022) +#pragma warning(disable:2023) +#endif + +#include + +//! @brief polygon_sort_adaptor default implementation that calls std::sort +namespace boost { + namespace polygon { + + template + struct dummy_to_delay_instantiation{ + typedef int unit_type; // default GTL unit + }; + + //! @brief polygon_sort_adaptor default implementation that calls std::sort + template + struct polygon_sort_adaptor { + //! @brief wrapper that mimics std::sort() function and takes + // the same arguments + template + static void sort(RandomAccessIterator_Type _First, + RandomAccessIterator_Type _Last) + { + std::sort(_First, _Last); + } + //! @brief wrapper that mimics std::sort() function overload and takes + // the same arguments + template + static void sort(RandomAccessIterator_Type _First, + RandomAccessIterator_Type _Last, + const Pred_Type& _Comp) + { + std::sort(_First, _Last, _Comp); + } + }; + + //! @brief user level wrapper for sorting quantities + template + void polygon_sort(iter_type _b_, iter_type _e_) + { + polygon_sort_adaptor::unit_type>::sort(_b_, _e_); + } + + //! @brief user level wrapper for sorting quantities that takes predicate + // as additional argument + template + void polygon_sort(iter_type _b_, iter_type _e_, const pred_type& _pred_) + { + polygon_sort_adaptor::unit_type>::sort(_b_, _e_, _pred_); + } + + + + } // namespace polygon +} // namespace boost +#endif diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/detail/property_merge.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/detail/property_merge.hpp new file mode 100644 index 0000000..6ea0161 --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/detail/property_merge.hpp @@ -0,0 +1,588 @@ +/* + Copyright 2008 Intel Corporation + + Use, modification and distribution are subject to the Boost Software License, + Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at + http://www.boost.org/LICENSE_1_0.txt). +*/ +#ifndef BOOST_POLYGON_PROPERTY_MERGE_HPP +#define BOOST_POLYGON_PROPERTY_MERGE_HPP +namespace boost { namespace polygon{ + +template +class property_merge_point { +private: + coordinate_type x_, y_; +public: + inline property_merge_point() : x_(), y_() {} + inline property_merge_point(coordinate_type x, coordinate_type y) : x_(x), y_(y) {} + //use builtin assign and copy + inline bool operator==(const property_merge_point& that) const { return x_ == that.x_ && y_ == that.y_; } + inline bool operator!=(const property_merge_point& that) const { return !((*this) == that); } + inline bool operator<(const property_merge_point& that) const { + if(x_ < that.x_) return true; + if(x_ > that.x_) return false; + return y_ < that.y_; + } + inline coordinate_type x() const { return x_; } + inline coordinate_type y() const { return y_; } + inline void x(coordinate_type value) { x_ = value; } + inline void y(coordinate_type value) { y_ = value; } +}; + +template +class property_merge_interval { +private: + coordinate_type low_, high_; +public: + inline property_merge_interval() : low_(), high_() {} + inline property_merge_interval(coordinate_type low, coordinate_type high) : low_(low), high_(high) {} + //use builtin assign and copy + inline bool operator==(const property_merge_interval& that) const { return low_ == that.low_ && high_ == that.high_; } + inline bool operator!=(const property_merge_interval& that) const { return !((*this) == that); } + inline bool operator<(const property_merge_interval& that) const { + if(low_ < that.low_) return true; + if(low_ > that.low_) return false; + return high_ < that.high_; + } + inline coordinate_type low() const { return low_; } + inline coordinate_type high() const { return high_; } + inline void low(coordinate_type value) { low_ = value; } + inline void high(coordinate_type value) { high_ = value; } +}; + +template > +class merge_scanline { +public: + //definitions + + typedef keytype property_set; + typedef std::vector > property_map; + typedef std::pair, std::pair > vertex_property; + typedef std::pair, property_map> vertex_data; + typedef std::vector property_merge_data; + //typedef std::map Result; + typedef std::map scanline_type; + typedef typename scanline_type::iterator scanline_iterator; + typedef std::pair, std::pair > edge_property; + typedef std::vector edge_property_vector; + + //static public member functions + + template + static inline void + populate_property_merge_data(property_merge_data& pmd, iT input_begin, iT input_end, + const property_type& property, orientation_2d_type orient) { + for( ; input_begin != input_end; ++input_begin) { + std::pair, std::pair > element; + if(orient == HORIZONTAL) + element.first = property_merge_point((*input_begin).second.first, (*input_begin).first); + else + element.first = property_merge_point((*input_begin).first, (*input_begin).second.first); + element.second.first = property; + element.second.second = (*input_begin).second.second; + pmd.push_back(element); + } + } + + //public member functions + + merge_scanline() : output(), scanline(), currentVertex(), tmpVector(), previousY(), countFromBelow(), scanlinePosition() {} + merge_scanline(const merge_scanline& that) : + output(that.output), + scanline(that.scanline), + currentVertex(that.currentVertex), + tmpVector(that.tmpVector), + previousY(that.previousY), + countFromBelow(that.countFromBelow), + scanlinePosition(that.scanlinePosition) + {} + merge_scanline& operator=(const merge_scanline& that) { + output = that.output; + scanline = that.scanline; + currentVertex = that.currentVertex; + tmpVector = that.tmpVector; + previousY = that.previousY; + countFromBelow = that.countFromBelow; + scanlinePosition = that.scanlinePosition; + return *this; + } + + template + inline void perform_merge(result_type& result, property_merge_data& data) { + if(data.empty()) return; + //sort + polygon_sort(data.begin(), data.end(), less_vertex_data()); + //scanline + bool firstIteration = true; + scanlinePosition = scanline.end(); + for(std::size_t i = 0; i < data.size(); ++i) { + if(firstIteration) { + mergeProperty(currentVertex.second, data[i].second); + currentVertex.first = data[i].first; + firstIteration = false; + } else { + if(data[i].first != currentVertex.first) { + if(data[i].first.x() != currentVertex.first.x()) { + processVertex(output); + //std::cout << scanline.size() << " "; + countFromBelow.clear(); //should already be clear + writeOutput(currentVertex.first.x(), result, output); + currentVertex.second.clear(); + mergeProperty(currentVertex.second, data[i].second); + currentVertex.first = data[i].first; + //std::cout << assertRedundant(scanline) << "/" << scanline.size() << " "; + } else { + processVertex(output); + currentVertex.second.clear(); + mergeProperty(currentVertex.second, data[i].second); + currentVertex.first = data[i].first; + } + } else { + mergeProperty(currentVertex.second, data[i].second); + } + } + } + processVertex(output); + writeOutput(currentVertex.first.x(), result, output); + //std::cout << assertRedundant(scanline) << "/" << scanline.size() << "\n"; + //std::cout << scanline.size() << "\n"; + } + +private: + //private supporting types + + template + class less_vertex_data { + public: + less_vertex_data() {} + bool operator()(const T& lvalue, const T& rvalue) const { + if(lvalue.first.x() < rvalue.first.x()) return true; + if(lvalue.first.x() > rvalue.first.x()) return false; + if(lvalue.first.y() < rvalue.first.y()) return true; + return false; + } + }; + + template + struct lessPropertyCount { + lessPropertyCount() {} + bool operator()(const T& a, const T& b) { + return a.first < b.first; + } + }; + + //private static member functions + + static inline void mergeProperty(property_map& lvalue, std::pair& rvalue) { + typename property_map::iterator itr = std::lower_bound(lvalue.begin(), lvalue.end(), rvalue, + lessPropertyCount >()); + if(itr == lvalue.end() || + (*itr).first != rvalue.first) { + lvalue.insert(itr, rvalue); + } else { + (*itr).second += rvalue.second; + if((*itr).second == 0) + lvalue.erase(itr); + } +// if(assertSorted(lvalue)) { +// std::cout << "in mergeProperty\n"; +// exit(0); +// } + } + +// static inline bool assertSorted(property_map& pset) { +// bool result = false; +// for(std::size_t i = 1; i < pset.size(); ++i) { +// if(pset[i] < pset[i-1]) { +// std::cout << "Out of Order Error "; +// result = true; +// } +// if(pset[i].first == pset[i-1].first) { +// std::cout << "Duplicate Property Error "; +// result = true; +// } +// if(pset[0].second == 0 || pset[1].second == 0) { +// std::cout << "Empty Property Error "; +// result = true; +// } +// } +// return result; +// } + + static inline void setProperty(property_set& pset, property_map& pmap) { + for(typename property_map::iterator itr = pmap.begin(); itr != pmap.end(); ++itr) { + if((*itr).second > 0) { + pset.insert(pset.end(), (*itr).first); + } + } + } + + //private data members + + edge_property_vector output; + scanline_type scanline; + vertex_data currentVertex; + property_map tmpVector; + coordinate_type previousY; + property_map countFromBelow; + scanline_iterator scanlinePosition; + + //private member functions + + inline void mergeCount(property_map& lvalue, property_map& rvalue) { + typename property_map::iterator litr = lvalue.begin(); + typename property_map::iterator ritr = rvalue.begin(); + tmpVector.clear(); + while(litr != lvalue.end() && ritr != rvalue.end()) { + if((*litr).first <= (*ritr).first) { + if(!tmpVector.empty() && + (*litr).first == tmpVector.back().first) { + tmpVector.back().second += (*litr).second; + } else { + tmpVector.push_back(*litr); + } + ++litr; + } else if((*ritr).first <= (*litr).first) { + if(!tmpVector.empty() && + (*ritr).first == tmpVector.back().first) { + tmpVector.back().second += (*ritr).second; + } else { + tmpVector.push_back(*ritr); + } + ++ritr; + } + } + while(litr != lvalue.end()) { + if(!tmpVector.empty() && + (*litr).first == tmpVector.back().first) { + tmpVector.back().second += (*litr).second; + } else { + tmpVector.push_back(*litr); + } + ++litr; + } + while(ritr != rvalue.end()) { + if(!tmpVector.empty() && + (*ritr).first == tmpVector.back().first) { + tmpVector.back().second += (*ritr).second; + } else { + tmpVector.push_back(*ritr); + } + ++ritr; + } + lvalue.clear(); + for(std::size_t i = 0; i < tmpVector.size(); ++i) { + if(tmpVector[i].second != 0) { + lvalue.push_back(tmpVector[i]); + } + } +// if(assertSorted(lvalue)) { +// std::cout << "in mergeCount\n"; +// exit(0); +// } + } + + inline void processVertex(edge_property_vector& output) { + if(!countFromBelow.empty()) { + //we are processing an interval of change in scanline state between + //previous vertex position and current vertex position where + //count from below represents the change on the interval + //foreach scanline element from previous to current we + //write the interval on the scanline that is changing + //the old value and the new value to output + property_merge_interval currentInterval(previousY, currentVertex.first.y()); + coordinate_type currentY = currentInterval.low(); + if(scanlinePosition == scanline.end() || + (*scanlinePosition).first != previousY) { + scanlinePosition = scanline.lower_bound(previousY); + } + scanline_iterator previousScanlinePosition = scanlinePosition; + ++scanlinePosition; + while(scanlinePosition != scanline.end()) { + coordinate_type elementY = (*scanlinePosition).first; + if(elementY <= currentInterval.high()) { + property_map& countOnLeft = (*previousScanlinePosition).second; + edge_property element; + output.push_back(element); + output.back().first = property_merge_interval((*previousScanlinePosition).first, elementY); + setProperty(output.back().second.first, countOnLeft); + mergeCount(countOnLeft, countFromBelow); + setProperty(output.back().second.second, countOnLeft); + if(output.back().second.first == output.back().second.second) { + output.pop_back(); //it was an internal vertical edge, not to be output + } + else if(output.size() > 1) { + edge_property& secondToLast = output[output.size()-2]; + if(secondToLast.first.high() == output.back().first.low() && + secondToLast.second.first == output.back().second.first && + secondToLast.second.second == output.back().second.second) { + //merge output onto previous output because properties are + //identical on both sides implying an internal horizontal edge + secondToLast.first.high(output.back().first.high()); + output.pop_back(); + } + } + if(previousScanlinePosition == scanline.begin()) { + if(countOnLeft.empty()) { + scanline.erase(previousScanlinePosition); + } + } else { + scanline_iterator tmpitr = previousScanlinePosition; + --tmpitr; + if((*tmpitr).second == (*previousScanlinePosition).second) + scanline.erase(previousScanlinePosition); + } + + } else if(currentY < currentInterval.high()){ + //elementY > currentInterval.high() + //split the interval between previous and current scanline elements + std::pair elementScan; + elementScan.first = currentInterval.high(); + elementScan.second = (*previousScanlinePosition).second; + scanlinePosition = scanline.insert(scanlinePosition, elementScan); + continue; + } else { + break; + } + previousScanlinePosition = scanlinePosition; + currentY = previousY = elementY; + ++scanlinePosition; + if(scanlinePosition == scanline.end() && + currentY < currentInterval.high()) { + //insert a new element for top of range + std::pair elementScan; + elementScan.first = currentInterval.high(); + scanlinePosition = scanline.insert(scanline.end(), elementScan); + } + } + if(scanlinePosition == scanline.end() && + currentY < currentInterval.high()) { + //handle case where we iterated to end of the scanline + //we need to insert an element into the scanline at currentY + //with property value coming from below + //and another one at currentInterval.high() with empty property value + mergeCount(scanline[currentY], countFromBelow); + std::pair elementScan; + elementScan.first = currentInterval.high(); + scanline.insert(scanline.end(), elementScan); + + edge_property element; + output.push_back(element); + output.back().first = property_merge_interval(currentY, currentInterval.high()); + setProperty(output.back().second.second, countFromBelow); + mergeCount(countFromBelow, currentVertex.second); + } else { + mergeCount(countFromBelow, currentVertex.second); + if(countFromBelow.empty()) { + if(previousScanlinePosition == scanline.begin()) { + if((*previousScanlinePosition).second.empty()) { + scanline.erase(previousScanlinePosition); + //previousScanlinePosition = scanline.end(); + //std::cout << "ERASE_A "; + } + } else { + scanline_iterator tmpitr = previousScanlinePosition; + --tmpitr; + if((*tmpitr).second == (*previousScanlinePosition).second) { + scanline.erase(previousScanlinePosition); + //previousScanlinePosition = scanline.end(); + //std::cout << "ERASE_B "; + } + } + } + } + } else { + //count from below is empty, we are starting a new interval of change + countFromBelow = currentVertex.second; + scanlinePosition = scanline.lower_bound(currentVertex.first.y()); + if(scanlinePosition != scanline.end()) { + if((*scanlinePosition).first != currentVertex.first.y()) { + if(scanlinePosition != scanline.begin()) { + //decrement to get the lower position of the first interval this vertex intersects + --scanlinePosition; + //insert a new element into the scanline for the incoming vertex + property_map& countOnLeft = (*scanlinePosition).second; + std::pair element(currentVertex.first.y(), countOnLeft); + scanlinePosition = scanline.insert(scanlinePosition, element); + } else { + property_map countOnLeft; + std::pair element(currentVertex.first.y(), countOnLeft); + scanlinePosition = scanline.insert(scanlinePosition, element); + } + } + } else { + property_map countOnLeft; + std::pair element(currentVertex.first.y(), countOnLeft); + scanlinePosition = scanline.insert(scanlinePosition, element); + } + } + previousY = currentVertex.first.y(); + } + + template + inline int assertRedundant(T& t) { + if(t.empty()) return 0; + int count = 0; + typename T::iterator itr = t.begin(); + if((*itr).second.empty()) + ++count; + typename T::iterator itr2 = itr; + ++itr2; + while(itr2 != t.end()) { + if((*itr).second == (*itr2).second) + ++count; + itr = itr2; + ++itr2; + } + return count; + } + + template + inline void performExtract(T& result, property_merge_data& data) { + if(data.empty()) return; + //sort + polygon_sort(data.begin(), data.end(), less_vertex_data()); + + //scanline + bool firstIteration = true; + scanlinePosition = scanline.end(); + for(std::size_t i = 0; i < data.size(); ++i) { + if(firstIteration) { + mergeProperty(currentVertex.second, data[i].second); + currentVertex.first = data[i].first; + firstIteration = false; + } else { + if(data[i].first != currentVertex.first) { + if(data[i].first.x() != currentVertex.first.x()) { + processVertex(output); + //std::cout << scanline.size() << " "; + countFromBelow.clear(); //should already be clear + writeGraph(result, output, scanline); + currentVertex.second.clear(); + mergeProperty(currentVertex.second, data[i].second); + currentVertex.first = data[i].first; + } else { + processVertex(output); + currentVertex.second.clear(); + mergeProperty(currentVertex.second, data[i].second); + currentVertex.first = data[i].first; + } + } else { + mergeProperty(currentVertex.second, data[i].second); + } + } + } + processVertex(output); + writeGraph(result, output, scanline); + //std::cout << scanline.size() << "\n"; + } + + template + inline void insertEdges(T& graph, property_set& p1, property_set& p2) { + for(typename property_set::iterator itr = p1.begin(); itr != p1.end(); ++itr) { + for(typename property_set::iterator itr2 = p2.begin(); itr2 != p2.end(); ++itr2) { + if(*itr != *itr2) { + graph[*itr].insert(*itr2); + graph[*itr2].insert(*itr); + } + } + } + } + + template + inline void propertySetAbove(coordinate_type y, property_set& ps, T& scanline) { + ps.clear(); + typename T::iterator itr = scanline.find(y); + if(itr != scanline.end()) + setProperty(ps, (*itr).second); + } + + template + inline void propertySetBelow(coordinate_type y, property_set& ps, T& scanline) { + ps.clear(); + typename T::iterator itr = scanline.find(y); + if(itr != scanline.begin()) { + --itr; + setProperty(ps, (*itr).second); + } + } + + template + inline void writeGraph(T& graph, edge_property_vector& output, T2& scanline) { + if(output.empty()) return; + edge_property* previousEdgeP = &(output[0]); + bool firstIteration = true; + property_set ps; + for(std::size_t i = 0; i < output.size(); ++i) { + edge_property& previousEdge = *previousEdgeP; + edge_property& edge = output[i]; + if(previousEdge.first.high() == edge.first.low()) { + //horizontal edge + insertEdges(graph, edge.second.first, previousEdge.second.first); + //corner 1 + insertEdges(graph, edge.second.first, previousEdge.second.second); + //other horizontal edge + insertEdges(graph, edge.second.second, previousEdge.second.second); + //corner 2 + insertEdges(graph, edge.second.second, previousEdge.second.first); + } else { + if(!firstIteration){ + //look up regions above previous edge + propertySetAbove(previousEdge.first.high(), ps, scanline); + insertEdges(graph, ps, previousEdge.second.first); + insertEdges(graph, ps, previousEdge.second.second); + } + //look up regions below current edge in the scanline + propertySetBelow(edge.first.high(), ps, scanline); + insertEdges(graph, ps, edge.second.first); + insertEdges(graph, ps, edge.second.second); + } + firstIteration = false; + //vertical edge + insertEdges(graph, edge.second.second, edge.second.first); + //shared region to left + insertEdges(graph, edge.second.second, edge.second.second); + //shared region to right + insertEdges(graph, edge.second.first, edge.second.first); + previousEdgeP = &(output[i]); + } + edge_property& previousEdge = *previousEdgeP; + propertySetAbove(previousEdge.first.high(), ps, scanline); + insertEdges(graph, ps, previousEdge.second.first); + insertEdges(graph, ps, previousEdge.second.second); + output.clear(); + } + + template + inline void writeOutput(coordinate_type x, Result& result, edge_property_vector& output) { + for(std::size_t i = 0; i < output.size(); ++i) { + edge_property& edge = output[i]; + //edge.second.first is the property set on the left of the edge + if(!edge.second.first.empty()) { + typename Result::iterator itr = result.find(edge.second.first); + if(itr == result.end()) { + std::pair element(edge.second.first, polygon_set_type(VERTICAL)); + itr = result.insert(result.end(), element); + } + std::pair, int> element2(interval_data(edge.first.low(), edge.first.high()), -1); //right edge of figure + (*itr).second.insert(x, element2); + } + if(!edge.second.second.empty()) { + //edge.second.second is the property set on the right of the edge + typename Result::iterator itr = result.find(edge.second.second); + if(itr == result.end()) { + std::pair element(edge.second.second, polygon_set_type(VERTICAL)); + itr = result.insert(result.end(), element); + } + std::pair, int> element3(interval_data(edge.first.low(), edge.first.high()), 1); //left edge of figure + (*itr).second.insert(x, element3); + } + } + output.clear(); + } +}; + +} +} +#endif diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/detail/property_merge_45.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/detail/property_merge_45.hpp new file mode 100644 index 0000000..c2feffc --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/detail/property_merge_45.hpp @@ -0,0 +1,160 @@ +/* + Copyright 2008 Intel Corporation + + Use, modification and distribution are subject to the Boost Software License, + Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at + http://www.boost.org/LICENSE_1_0.txt). +*/ +#ifndef BOOST_POLYGON_PROPERTY_MERGE_45_HPP +#define BOOST_POLYGON_PROPERTY_MERGE_45_HPP +namespace boost { namespace polygon{ + + template + struct polygon_45_property_merge { + + typedef point_data Point; + typedef typename coordinate_traits::manhattan_area_type LongUnit; + + template + static inline void merge_property_maps(property_map& mp, const property_map& mp2, bool subtract = false) { + polygon_45_touch::merge_property_maps(mp, mp2, subtract); + } + + class CountMerge { + public: + inline CountMerge() : counts() {} + //inline CountMerge(int count) { counts[0] = counts[1] = count; } + //inline CountMerge(int count1, int count2) { counts[0] = count1; counts[1] = count2; } + inline CountMerge(const CountMerge& count) : counts(count.counts) {} + inline bool operator==(const CountMerge& count) const { return counts == count.counts; } + inline bool operator!=(const CountMerge& count) const { return !((*this) == count); } + //inline CountMerge& operator=(int count) { counts[0] = counts[1] = count; return *this; } + inline CountMerge& operator=(const CountMerge& count) { counts = count.counts; return *this; } + inline int& operator[](property_type index) { + std::vector >::iterator itr = lower_bound(counts.begin(), counts.end(), std::make_pair(index, int(0))); + if(itr != counts.end() && itr->first == index) { + return itr->second; + } + itr = counts.insert(itr, std::make_pair(index, int(0))); + return itr->second; + } +// inline int operator[](int index) const { +// std::vector >::const_iterator itr = counts.begin(); +// for( ; itr != counts.end() && itr->first <= index; ++itr) { +// if(itr->first == index) { +// return itr->second; +// } +// } +// return 0; +// } + inline CountMerge& operator+=(const CountMerge& count){ + merge_property_maps(counts, count.counts, false); + return *this; + } + inline CountMerge& operator-=(const CountMerge& count){ + merge_property_maps(counts, count.counts, true); + return *this; + } + inline CountMerge operator+(const CountMerge& count) const { + return CountMerge(*this)+=count; + } + inline CountMerge operator-(const CountMerge& count) const { + return CountMerge(*this)-=count; + } + inline CountMerge invert() const { + CountMerge retval; + retval -= *this; + return retval; + } + std::vector > counts; + }; + + //output is a std::map, polygon_45_set_data > + struct merge_45_output_functor { + template + void operator()(cT& output, const CountMerge& count1, const CountMerge& count2, + const Point& pt, int rise, direction_1d end) { + typedef typename cT::key_type keytype; + keytype left; + keytype right; + int edgeType = end == LOW ? -1 : 1; + for(typename std::vector >::const_iterator itr = count1.counts.begin(); + itr != count1.counts.end(); ++itr) { + left.insert(left.end(), (*itr).first); + } + for(typename std::vector >::const_iterator itr = count2.counts.begin(); + itr != count2.counts.end(); ++itr) { + right.insert(right.end(), (*itr).first); + } + if(left == right) return; + if(!left.empty()) { + //std::cout << pt.x() << " " << pt.y() << " " << rise << " " << edgeType << std::endl; + output[left].insert_clean(typename boolean_op_45::Vertex45(pt, rise, -edgeType)); + } + if(!right.empty()) { + //std::cout << pt.x() << " " << pt.y() << " " << rise << " " << -edgeType << std::endl; + output[right].insert_clean(typename boolean_op_45::Vertex45(pt, rise, edgeType)); + } + } + }; + + typedef typename std::pair::template Scan45CountT > Vertex45Compact; + typedef std::vector MergeSetData; + + struct lessVertex45Compact { + bool operator()(const Vertex45Compact& l, const Vertex45Compact& r) { + return l.first < r.first; + } + }; + + template + static void performMerge(output_type& result, MergeSetData& tsd) { + + polygon_sort(tsd.begin(), tsd.end(), lessVertex45Compact()); + typedef std::vector::template Scan45CountT > > TSD; + TSD tsd_; + tsd_.reserve(tsd.size()); + for(typename MergeSetData::iterator itr = tsd.begin(); itr != tsd.end(); ) { + typename MergeSetData::iterator itr2 = itr; + ++itr2; + for(; itr2 != tsd.end() && itr2->first == itr->first; ++itr2) { + (itr->second) += (itr2->second); //accumulate + } + tsd_.push_back(std::make_pair(itr->first, itr->second)); + itr = itr2; + } + typename boolean_op_45::template Scan45 scanline; + for(typename TSD::iterator itr = tsd_.begin(); itr != tsd_.end(); ) { + typename TSD::iterator itr2 = itr; + ++itr2; + while(itr2 != tsd_.end() && itr2->first.x() == itr->first.x()) { + ++itr2; + } + scanline.scan(result, itr, itr2); + itr = itr2; + } + } + + template + static void populateMergeSetData(MergeSetData& tsd, iT begin, iT end, property_type property) { + for( ; begin != end; ++begin) { + Vertex45Compact vertex; + vertex.first = typename Vertex45Compact::first_type(begin->pt.x() * 2, begin->pt.y() * 2); + tsd.push_back(vertex); + for(unsigned int i = 0; i < 4; ++i) { + if(begin->count[i]) { + tsd.back().second[i][property] += begin->count[i]; + } + } + } + } + + }; + + + +} +} + +#endif diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/detail/rectangle_formation.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/detail/rectangle_formation.hpp new file mode 100644 index 0000000..07a2209 --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/detail/rectangle_formation.hpp @@ -0,0 +1,266 @@ +/* + Copyright 2008 Intel Corporation + + Use, modification and distribution are subject to the Boost Software License, + Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at + http://www.boost.org/LICENSE_1_0.txt). +*/ +#ifndef BOOST_POLYGON_RECTANGLE_FORMATION_HPP +#define BOOST_POLYGON_RECTANGLE_FORMATION_HPP +namespace boost { namespace polygon{ + +namespace rectangle_formation { + template + class ScanLineToRects { + public: + typedef T rectangle_type; + typedef typename rectangle_traits::coordinate_type coordinate_type; + typedef rectangle_data scan_rect_type; + private: + + typedef std::set > ScanData; + ScanData scanData_; + bool haveCurrentRect_; + scan_rect_type currentRect_; + orientation_2d orient_; + typename rectangle_traits::coordinate_type currentCoordinate_; + public: + inline ScanLineToRects() : scanData_(), haveCurrentRect_(), currentRect_(), orient_(), currentCoordinate_() {} + + inline ScanLineToRects(orientation_2d orient, rectangle_type model) : + scanData_(orientation_2d(orient.to_int() ? VERTICAL : HORIZONTAL)), + haveCurrentRect_(false), currentRect_(), orient_(orient), currentCoordinate_() { + assign(currentRect_, model); + currentCoordinate_ = (std::numeric_limits::max)(); + } + + template + inline ScanLineToRects& processEdge(CT& rectangles, const interval_data& edge); + + inline ScanLineToRects& nextMajorCoordinate(coordinate_type currentCoordinate) { + if(haveCurrentRect_) { + scanData_.insert(scanData_.end(), currentRect_); + haveCurrentRect_ = false; + } + currentCoordinate_ = currentCoordinate; + return *this; + } + + }; + + template inline CT& + processEdge_(CT& rectangles, ST& scanData, const interval_type& edge, + bool& haveCurrentRect, rectangle_type& currentRect, coordinate_type currentCoordinate, orientation_2d orient) + { + typedef typename CT::value_type result_type; + bool edgeProcessed = false; + if(!scanData.empty()) { + + //process all rectangles in the scanData that touch the edge + typename ST::iterator dataIter = scanData.lower_bound(rectangle_type(edge, edge)); + //decrement beginIter until its low is less than edge's low + while((dataIter == scanData.end() || (*dataIter).get(orient).get(LOW) > edge.get(LOW)) && + dataIter != scanData.begin()) + { + --dataIter; + } + //process each rectangle until the low end of the rectangle + //is greater than the high end of the edge + while(dataIter != scanData.end() && + (*dataIter).get(orient).get(LOW) <= edge.get(HIGH)) + { + const rectangle_type& rect = *dataIter; + //if the rectangle data intersects the edge at all + if(rect.get(orient).get(HIGH) >= edge.get(LOW)) { + if(contains(rect.get(orient), edge, true)) { + //this is a closing edge + //we need to write out the intersecting rectangle and + //insert between 0 and 2 rectangles into the scanData + //write out rectangle + rectangle_type tmpRect = rect; + + if(rect.get(orient.get_perpendicular()).get(LOW) < currentCoordinate) { + //set the high coordinate perpedicular to slicing orientation + //to the current coordinate of the scan event + tmpRect.set(orient.get_perpendicular().get_direction(HIGH), + currentCoordinate); + result_type result; + assign(result, tmpRect); + rectangles.insert(rectangles.end(), result); + } + //erase the rectangle from the scan data + typename ST::iterator nextIter = dataIter; + ++nextIter; + scanData.erase(dataIter); + if(tmpRect.get(orient).get(LOW) < edge.get(LOW)) { + //insert a rectangle for the overhang of the bottom + //of the rectangle back into scan data + rectangle_type lowRect(tmpRect); + lowRect.set(orient.get_perpendicular(), interval_data(currentCoordinate, + currentCoordinate)); + lowRect.set(orient.get_direction(HIGH), edge.get(LOW)); + scanData.insert(nextIter, lowRect); + } + if(tmpRect.get(orient).get(HIGH) > edge.get(HIGH)) { + //insert a rectangle for the overhang of the top + //of the rectangle back into scan data + rectangle_type highRect(tmpRect); + highRect.set(orient.get_perpendicular(), interval_data(currentCoordinate, + currentCoordinate)); + highRect.set(orient.get_direction(LOW), edge.get(HIGH)); + scanData.insert(nextIter, highRect); + } + //we are done with this edge + edgeProcessed = true; + break; + } else { + //it must be an opening edge + //assert that rect does not overlap the edge but only touches + //write out rectangle + rectangle_type tmpRect = rect; + //set the high coordinate perpedicular to slicing orientation + //to the current coordinate of the scan event + if(tmpRect.get(orient.get_perpendicular().get_direction(LOW)) < currentCoordinate) { + tmpRect.set(orient.get_perpendicular().get_direction(HIGH), + currentCoordinate); + result_type result; + assign(result, tmpRect); + rectangles.insert(rectangles.end(), result); + } + //erase the rectangle from the scan data + typename ST::iterator nextIter = dataIter; + ++nextIter; + scanData.erase(dataIter); + dataIter = nextIter; + if(haveCurrentRect) { + if(currentRect.get(orient).get(HIGH) >= edge.get(LOW)){ + if(!edgeProcessed && currentRect.get(orient.get_direction(HIGH)) > edge.get(LOW)){ + rectangle_type tmpRect2(currentRect); + tmpRect2.set(orient.get_direction(HIGH), edge.get(LOW)); + scanData.insert(nextIter, tmpRect2); + if(currentRect.get(orient.get_direction(HIGH)) > edge.get(HIGH)) { + currentRect.set(orient, interval_data(edge.get(HIGH), currentRect.get(orient.get_direction(HIGH)))); + } else { + haveCurrentRect = false; + } + } else { + //extend the top of current rect + currentRect.set(orient.get_direction(HIGH), + (std::max)(edge.get(HIGH), + tmpRect.get(orient.get_direction(HIGH)))); + } + } else { + //insert current rect into the scanData + scanData.insert(nextIter, currentRect); + //create a new current rect + currentRect.set(orient.get_perpendicular(), interval_data(currentCoordinate, + currentCoordinate)); + currentRect.set(orient, interval_data((std::min)(tmpRect.get(orient).get(LOW), + edge.get(LOW)), + (std::max)(tmpRect.get(orient).get(HIGH), + edge.get(HIGH)))); + } + } else { + haveCurrentRect = true; + currentRect.set(orient.get_perpendicular(), interval_data(currentCoordinate, + currentCoordinate)); + currentRect.set(orient, interval_data((std::min)(tmpRect.get(orient).get(LOW), + edge.get(LOW)), + (std::max)(tmpRect.get(orient).get(HIGH), + edge.get(HIGH)))); + } + //skip to nextIter position + edgeProcessed = true; + continue; + } + //edgeProcessed = true; + } + ++dataIter; + } //end while edge intersects rectangle data + + } + if(!edgeProcessed) { + if(haveCurrentRect) { + if(currentRect.get(orient.get_perpendicular().get_direction(HIGH)) + == currentCoordinate && + currentRect.get(orient.get_direction(HIGH)) >= edge.get(LOW)) + { + if(currentRect.get(orient.get_direction(HIGH)) > edge.get(LOW)){ + rectangle_type tmpRect(currentRect); + tmpRect.set(orient.get_direction(HIGH), edge.get(LOW)); + scanData.insert(scanData.end(), tmpRect); + if(currentRect.get(orient.get_direction(HIGH)) > edge.get(HIGH)) { + currentRect.set(orient, + interval_data(edge.get(HIGH), + currentRect.get(orient.get_direction(HIGH)))); + return rectangles; + } else { + haveCurrentRect = false; + return rectangles; + } + } + //extend current rect + currentRect.set(orient.get_direction(HIGH), edge.get(HIGH)); + return rectangles; + } + scanData.insert(scanData.end(), currentRect); + haveCurrentRect = false; + } + rectangle_type tmpRect(currentRect); + tmpRect.set(orient.get_perpendicular(), interval_data(currentCoordinate, + currentCoordinate)); + tmpRect.set(orient, edge); + scanData.insert(tmpRect); + return rectangles; + } + return rectangles; + + } + + template + template + inline + ScanLineToRects& ScanLineToRects::processEdge(CT& rectangles, const interval_data& edge) + { + processEdge_(rectangles, scanData_, edge, haveCurrentRect_, currentRect_, currentCoordinate_, orient_); + return *this; + } + + +} //namespace rectangle_formation + + template + struct get_coordinate_type_for_rectangles { + typedef typename polygon_traits::coordinate_type type; + }; + template + struct get_coordinate_type_for_rectangles { + typedef typename rectangle_traits::coordinate_type type; + }; + + template + void form_rectangles(output_container& output, iterator_type begin, iterator_type end, + orientation_2d orient, rectangle_concept ) { + typedef typename output_container::value_type rectangle_type; + typedef typename get_coordinate_type_for_rectangles::type>::type Unit; + rectangle_data model; + Unit prevPos = (std::numeric_limits::max)(); + rectangle_formation::ScanLineToRects > scanlineToRects(orient, model); + for(iterator_type itr = begin; + itr != end; ++ itr) { + Unit pos = (*itr).first; + if(pos != prevPos) { + scanlineToRects.nextMajorCoordinate(pos); + prevPos = pos; + } + Unit lowy = (*itr).second.first; + iterator_type tmp_itr = itr; + ++itr; + Unit highy = (*itr).second.first; + scanlineToRects.processEdge(output, interval_data(lowy, highy)); + if(std::abs((*itr).second.second) > 1) itr = tmp_itr; //next edge begins from this vertex + } + } +} +} +#endif diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/detail/scan_arbitrary.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/detail/scan_arbitrary.hpp new file mode 100644 index 0000000..86f7778 --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/detail/scan_arbitrary.hpp @@ -0,0 +1,2861 @@ +/* + Copyright 2008 Intel Corporation + + Use, modification and distribution are subject to the Boost Software License, + Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at + http://www.boost.org/LICENSE_1_0.txt). +*/ +#ifndef BOOST_POLYGON_SCAN_ARBITRARY_HPP +#define BOOST_POLYGON_SCAN_ARBITRARY_HPP +#ifdef BOOST_POLYGON_DEBUG_FILE +#include +#endif +#include "polygon_sort_adaptor.hpp" +namespace boost { namespace polygon{ + + template + class line_intersection : public scanline_base { + private: + typedef typename scanline_base::Point Point; + + //the first point is the vertex and and second point establishes the slope of an edge eminating from the vertex + //typedef std::pair half_edge; + typedef typename scanline_base::half_edge half_edge; + + //scanline comparator functor + typedef typename scanline_base::less_half_edge less_half_edge; + typedef typename scanline_base::less_point less_point; + + //when parallel half edges are encounterd the set of segments is expanded + //when a edge leaves the scanline it is removed from the set + //when the set is empty the element is removed from the map + typedef int segment_id; + typedef std::pair > scanline_element; + typedef std::map, less_half_edge> edge_scanline; + typedef typename edge_scanline::iterator iterator; + +// std::map > vertical_data_; +// edge_scanline edge_scanline_; +// Unit x_; +// int just_before_; +// segment_id segment_id_; +// std::vector > event_edges_; +// std::set intersection_queue_; + public: +// inline line_intersection() : vertical_data_(), edge_scanline_(), x_((std::numeric_limits::max)()), just_before_(0), segment_id_(0), event_edges_(), intersection_queue_() { +// less_half_edge lessElm(&x_, &just_before_); +// edge_scanline_ = edge_scanline(lessElm); +// } +// inline line_intersection(const line_intersection& that) : vertical_data_(), edge_scanline_(), x_(), just_before_(), segment_id_(), event_edges_(), intersection_queue_() { (*this) = that; } +// inline line_intersection& operator=(const line_intersection& that) { +// x_ = that.x_; +// just_before_ = that.just_before_; +// segment_id_ = that.segment_id_; + +// //I cannot simply copy that.edge_scanline_ to this edge_scanline_ becuase the functor store pointers to other members! +// less_half_edge lessElm(&x_, &just_before_); +// edge_scanline_ = edge_scanline(lessElm); + +// edge_scanline_.insert(that.edge_scanline_.begin(), that.edge_scanline_.end()); +// return *this; +// } + +// static inline void between(Point pt, Point pt1, Point pt2) { +// less_point lp; +// if(lp(pt1, pt2)) +// return lp(pt, pt2) && lp(pt1, pt); +// return lp(pt, pt1) && lp(pt2, pt); +// } + + template + static inline void compute_histogram_in_y(iT begin, iT end, std::size_t size, std::vector > >& histogram) { + std::vector > ends; + ends.reserve(size * 2); + for(iT itr = begin ; itr != end; ++itr) { + int count = (*itr).first.first.y() < (*itr).first.second.y() ? 1 : -1; + ends.push_back(std::make_pair((*itr).first.first.y(), count)); + ends.push_back(std::make_pair((*itr).first.second.y(), -count)); + } + polygon_sort(ends.begin(), ends.end()); + histogram.reserve(ends.size()); + histogram.push_back(std::make_pair(ends.front().first, std::make_pair(0, 0))); + for(typename std::vector >::iterator itr = ends.begin(); itr != ends.end(); ++itr) { + if((*itr).first != histogram.back().first) { + histogram.push_back(std::make_pair((*itr).first, histogram.back().second)); + } + if((*itr).second < 0) + histogram.back().second.second -= (*itr).second; + histogram.back().second.first += (*itr).second; + } + } + + template + static inline void compute_y_cuts(std::vector& y_cuts, iT begin, iT end, std::size_t size) { + if(begin == end) return; + if(size < 30) return; //30 is empirically chosen, but the algorithm is not sensitive to this constant + std::size_t min_cut = size; + iT cut = begin; + std::size_t position = 0; + std::size_t cut_size = 0; + std::size_t histogram_size = std::distance(begin, end); + for(iT itr = begin; itr != end; ++itr, ++position) { + if(position < histogram_size / 3) + continue; + if(histogram_size - position < histogram_size / 3) break; + if((*itr).second.first < min_cut) { + cut = itr; + min_cut = (*cut).second.first; + cut_size = position; + } + } + if(cut_size == 0 || (*cut).second.first > size / 9) //nine is empirically chosen + return; + compute_y_cuts(y_cuts, begin, cut, (*cut).second.first + (*cut).second.second); + y_cuts.push_back((*cut).first); + compute_y_cuts(y_cuts, cut, end, size - (*cut).second.second); + } + + template + static inline void validate_scan_divide_and_conquer(std::vector >& intersection_points, + iT begin, iT end) { + std::vector > > histogram; + compute_histogram_in_y(begin, end, std::distance(begin, end), histogram); + std::vector y_cuts; + compute_y_cuts(y_cuts, histogram.begin(), histogram.end(), std::distance(begin, end)); + std::map > > bins; + bins[histogram.front().first] = std::vector >(); + for(typename std::vector::iterator itr = y_cuts.begin(); itr != y_cuts.end(); ++itr) { + bins[*itr] = std::vector >(); + } + for(iT itr = begin; itr != end; ++itr) { + typename std::map > >::iterator lb = + bins.lower_bound((std::min)((*itr).first.first.y(), (*itr).first.second.y())); + if(lb != bins.begin()) + --lb; + typename std::map > >::iterator ub = + bins.upper_bound((std::max)((*itr).first.first.y(), (*itr).first.second.y())); + for( ; lb != ub; ++lb) { + (*lb).second.push_back(*itr); + } + } + validate_scan(intersection_points, bins[histogram.front().first].begin(), bins[histogram.front().first].end()); + for(typename std::vector::iterator itr = y_cuts.begin(); itr != y_cuts.end(); ++itr) { + validate_scan(intersection_points, bins[*itr].begin(), bins[*itr].end(), *itr); + } + } + + template + static inline void validate_scan(std::vector >& intersection_points, + iT begin, iT end) { + validate_scan(intersection_points, begin, end, (std::numeric_limits::min)()); + } + //quadratic algorithm to do same work as optimal scan for cross checking + template + static inline void validate_scan(std::vector >& intersection_points, + iT begin, iT end, Unit min_y) { + std::vector pts; + std::vector > data(begin, end); + for(std::size_t i = 0; i < data.size(); ++i) { + if(data[i].first.second < data[i].first.first) { + std::swap(data[i].first.first, data[i].first.second); + } + } + typename scanline_base::compute_intersection_pack pack_; + polygon_sort(data.begin(), data.end()); + //find all intersection points + for(typename std::vector >::iterator outer = data.begin(); + outer != data.end(); ++outer) { + const half_edge& he1 = (*outer).first; + //its own end points + pts.push_back(he1.first); + pts.push_back(he1.second); + std::set& segmentpts = intersection_points[(*outer).second]; + for(typename std::set::iterator itr = segmentpts.begin(); itr != segmentpts.end(); ++itr) { + if ((*itr).y() >= min_y) { + pts.push_back(*itr); + } + } + bool have_first_y = he1.first.y() >= min_y && he1.second.y() >= min_y; + for(typename std::vector >::iterator inner = outer; + inner != data.end(); ++inner) { + const half_edge& he2 = (*inner).first; + if(have_first_y || (he2.first.y() >= min_y && he2.second.y() >= min_y)) { + //at least one segment has a low y value within the range + if(he1 == he2) continue; + if((std::min)(he2. first.get(HORIZONTAL), + he2.second.get(HORIZONTAL)) >= + (std::max)(he1.second.get(HORIZONTAL), + he1.first.get(HORIZONTAL))) + break; + if(he1.first == he2.first || he1.second == he2.second) + continue; + Point intersection; + if(pack_.compute_intersection(intersection, he1, he2)) { + //their intersection point + pts.push_back(intersection); + intersection_points[(*inner).second].insert(intersection); + intersection_points[(*outer).second].insert(intersection); + } + } + } + } + polygon_sort(pts.begin(), pts.end()); + typename std::vector::iterator newend = std::unique(pts.begin(), pts.end()); + typename std::vector::iterator lfinger = pts.begin(); + //find all segments that interact with intersection points + for(typename std::vector >::iterator outer = data.begin(); + outer != data.end(); ++outer) { + const half_edge& he1 = (*outer).first; + segment_id id1 = (*outer).second; + //typedef rectangle_data Rectangle; + //Rectangle rect1; + //set_points(rect1, he1.first, he1.second); + //typename std::vector::iterator itr = lower_bound(pts.begin(), newend, (std::min)(he1.first, he1.second)); + //typename std::vector::iterator itr2 = upper_bound(pts.begin(), newend, (std::max)(he1.first, he1.second)); + Point startpt = (std::min)(he1.first, he1.second); + Point stoppt = (std::max)(he1.first, he1.second); + //while(itr != newend && itr != pts.begin() && (*itr).get(HORIZONTAL) >= (std::min)(he1.first.get(HORIZONTAL), he1.second.get(HORIZONTAL))) --itr; + //while(itr2 != newend && (*itr2).get(HORIZONTAL) <= (std::max)(he1.first.get(HORIZONTAL), he1.second.get(HORIZONTAL))) ++itr2; + //itr = pts.begin(); + //itr2 = pts.end(); + while(lfinger != newend && (*lfinger).x() < startpt.x()) ++lfinger; + for(typename std::vector::iterator itr = lfinger ; itr != newend && (*itr).x() <= stoppt.x(); ++itr) { + if(scanline_base::intersects_grid(*itr, he1)) + intersection_points[id1].insert(*itr); + } + } + } + + template + static inline void validate_scan(std::vector > >& output_segments, + iT begin, iT end) { + std::vector > input_properties; + std::vector > input_segments, intermediate_segments; + int index = 0; + for( ; begin != end; ++begin) { + input_properties.push_back((*begin).second); + input_segments.push_back(std::make_pair((*begin).first, index++)); + } + validate_scan(intermediate_segments, input_segments.begin(), input_segments.end()); + for(std::size_t i = 0; i < intermediate_segments.size(); ++i) { + output_segments.push_back(std::make_pair(intermediate_segments[i].first, + input_properties[intermediate_segments[i].second])); + less_point lp; + if(lp(output_segments.back().first.first, output_segments.back().first.second) != + lp(input_segments[intermediate_segments[i].second].first.first, + input_segments[intermediate_segments[i].second].first.second)) { + //edge changed orientation, invert count on edge + output_segments.back().second.second *= -1; + } + if(!scanline_base::is_vertical(input_segments[intermediate_segments[i].second].first) && + scanline_base::is_vertical(output_segments.back().first)) { + output_segments.back().second.second *= -1; + } + if(lp(output_segments.back().first.second, output_segments.back().first.first)) { + std::swap(output_segments.back().first.first, output_segments.back().first.second); + } + } + } + + template + static inline void validate_scan(std::vector >& output_segments, + iT begin, iT end) { + std::vector > intersection_points(std::distance(begin, end)); + validate_scan_divide_and_conquer(intersection_points, begin, end); + //validate_scan(intersection_points, begin, end); + segment_intersections(output_segments, intersection_points, begin, end); +// std::pair offenders; +// if(!verify_scan(offenders, output_segments.begin(), output_segments.end())) { +// std::cout << "break here!\n"; +// for(typename std::set::iterator itr = intersection_points[offenders.first].begin(); +// itr != intersection_points[offenders.first].end(); ++itr) { +// std::cout << (*itr).x() << " " << (*itr).y() << " "; +// } std::cout << "\n"; +// for(typename std::set::iterator itr = intersection_points[offenders.second].begin(); +// itr != intersection_points[offenders.second].end(); ++itr) { +// std::cout << (*itr).x() << " " << (*itr).y() << " "; +// } std::cout << "\n"; +// exit(1); +// } + } + + //quadratic algorithm to find intersections + template + static inline bool verify_scan(std::pair& offenders, + iT begin, iT end) { + + std::vector > data(begin, end); + for(std::size_t i = 0; i < data.size(); ++i) { + if(data[i].first.second < data[i].first.first) { + std::swap(data[i].first.first, data[i].first.second); + } + } + polygon_sort(data.begin(), data.end()); + for(typename std::vector >::iterator outer = data.begin(); + outer != data.end(); ++outer) { + const half_edge& he1 = (*outer).first; + segment_id id1 = (*outer).second; + for(typename std::vector >::iterator inner = outer; + inner != data.end(); ++inner) { + const half_edge& he2 = (*inner).first; + if(he1 == he2) continue; + if((std::min)(he2. first.get(HORIZONTAL), + he2.second.get(HORIZONTAL)) > + (std::max)(he1.second.get(HORIZONTAL), + he1.first.get(HORIZONTAL))) + break; + segment_id id2 = (*inner).second; + if(scanline_base::intersects(he1, he2)) { + offenders.first = id1; + offenders.second = id2; + //std::cout << he1.first.x() << " " << he1.first.y() << " " << he1.second.x() << " " << he1.second.y() << " " << he2.first.x() << " " << he2.first.y() << " " << he2.second.x() << " " << he2.second.y() << "\n"; + return false; + } + } + } + return true; + } + + class less_point_down_slope { + public: + typedef Point first_argument_type; + typedef Point second_argument_type; + typedef bool result_type; + inline less_point_down_slope() {} + inline bool operator () (const Point& pt1, const Point& pt2) const { + if(pt1.get(HORIZONTAL) < pt2.get(HORIZONTAL)) return true; + if(pt1.get(HORIZONTAL) == pt2.get(HORIZONTAL)) { + if(pt1.get(VERTICAL) > pt2.get(VERTICAL)) return true; + } + return false; + } + }; + + template + static inline void segment_edge(std::vector >& output_segments, + const half_edge& , segment_id id, iT begin, iT end) { + iT current = begin; + iT next = begin; + ++next; + while(next != end) { + output_segments.push_back(std::make_pair(half_edge(*current, *next), id)); + current = next; + ++next; + } + } + + template + static inline void segment_intersections(std::vector >& output_segments, + std::vector >& intersection_points, + iT begin, iT end) { + for(iT iter = begin; iter != end; ++iter) { + //less_point lp; + const half_edge& he = (*iter).first; + //if(lp(he.first, he.second)) { + // //it is the begin event + segment_id id = (*iter).second; + const std::set& pts = intersection_points[id]; + Point hpt(he.first.get(HORIZONTAL)+1, he.first.get(VERTICAL)); + if(!scanline_base::is_vertical(he) && scanline_base::less_slope(he.first.get(HORIZONTAL), he.first.get(VERTICAL), + he.second, hpt)) { + //slope is below horizontal + std::vector tmpPts; + tmpPts.reserve(pts.size()); + tmpPts.insert(tmpPts.end(), pts.begin(), pts.end()); + less_point_down_slope lpds; + polygon_sort(tmpPts.begin(), tmpPts.end(), lpds); + segment_edge(output_segments, he, id, tmpPts.begin(), tmpPts.end()); + } else { + segment_edge(output_segments, he, id, pts.begin(), pts.end()); + } + //} + } + } + +// //iT iterator over unsorted pair representing line segments of input +// //output_segments is populated with fully intersected output line segment half +// //edges and the index of the input segment that they are assoicated with +// //duplicate output half edges with different ids will be generated in the case +// //that parallel input segments intersection +// //outputs are in sorted order and include both begin and end events for +// //each segment +// template +// inline void scan(std::vector >& output_segments, +// iT begin, iT end) { +// std::map > intersection_points; +// scan(intersection_points, begin, end); +// segment_intersections(output_segments, intersection_points, begin, end); +// } + +// //iT iterator over sorted sequence of half edge, segment id pairs representing segment begin and end points +// //intersection points provides a mapping from input segment id (vector index) to the set +// //of intersection points assocated with that input segment +// template +// inline void scan(std::map >& intersection_points, +// iT begin, iT end) { +// for(iT iter = begin; iter != end; ++iter) { +// const std::pair& elem = *iter; +// const half_edge& he = elem.first; +// Unit current_x = he.first.get(HORIZONTAL); +// if(current_x != x_) { +// process_scan_event(intersection_points); +// while(!intersection_queue_.empty() && +// (*(intersection_queue_.begin()).get(HORIZONTAL) < current_x)) { +// x_ = *(intersection_queue_.begin()).get(HORIZONTAL); +// process_intersections_at_scan_event(intersection_points); +// } +// x_ = current_x; +// } +// event_edges_.push_back(elem); +// } +// process_scan_event(intersection_points); +// } + +// inline iterator lookup(const half_edge& he) { +// return edge_scanline_.find(he); +// } + +// inline void insert_into_scanline(const half_edge& he, int id) { +// edge_scanline_[he].insert(id); +// } + +// inline void lookup_and_remove(const half_edge& he, int id) { +// iterator remove_iter = lookup(he); +// if(remove_iter == edge_scanline_.end()) { +// //std::cout << "failed to find removal segment in scanline\n"; +// return; +// } +// std::set& ids = (*remove_iter).second; +// std::set::iterator id_iter = ids.find(id); +// if(id_iter == ids.end()) { +// //std::cout << "failed to find removal segment id in scanline set\n"; +// return; +// } +// ids.erase(id_iter); +// if(ids.empty()) +// edge_scanline_.erase(remove_iter); +// } + +// static inline void update_segments(std::map >& intersection_points, +// const std::set& segments, Point pt) { +// for(std::set::const_iterator itr = segments.begin(); itr != segments.end(); ++itr) { +// intersection_points[*itr].insert(pt); +// } +// } + +// inline void process_intersections_at_scan_event(std::map >& intersection_points) { +// //there may be additional intersection points at this x location that haven't been +// //found yet if vertical or near vertical line segments intersect more than +// //once before the next x location +// just_before_ = true; +// std::set intersecting_elements; +// std::set intersection_locations; +// typedef typename std::set::iterator intersection_iterator; +// intersection_iterator iter; +// //first find all secondary intersection locations and all scanline iterators +// //that are intersecting +// for(iter = intersection_queue_.begin(); +// iter != intersection_queue_.end() && (*iter).get(HORIZONTAL) == x_; ++iter) { +// Point pt = *iter; +// Unit y = pt.get(VERTICAL); +// intersection_locations.insert(y); +// //if x_ is max there can be only end events and no sloping edges +// if(x_ != (std::numeric_limits::max)()) { +// //deal with edges that project to the right of scanline +// //first find the edges in the scanline adjacent to primary intersectin points +// //lookup segment in scanline at pt +// iterator itr = edge_scanline_.lower_bound(half_edge(pt, Point(x_+1, y))); +// //look above pt in scanline until reaching end or segment that doesn't intersect +// //1x1 grid upper right of pt +// //look below pt in scanline until reaching begin or segment that doesn't interset +// //1x1 grid upper right of pt + +// //second find edges in scanline on the y interval of each edge found in the previous +// //step for x_ to x_ + 1 + +// //third find overlaps in the y intervals of all found edges to find all +// //secondary intersection points + +// } +// } +// //erase the intersection points from the queue +// intersection_queue_.erase(intersection_queue_.begin(), iter); +// std::vector insertion_edges; +// insertion_edges.reserve(intersecting_elements.size()); +// std::vector > sloping_ends; +// //do all the work of updating the output of all intersecting +// for(typename std::set::iterator inter_iter = intersecting_elements.begin(); +// inter_iter != intersecting_elements.end(); ++inter_iter) { +// //if it is horizontal update it now and continue +// if(is_horizontal((*inter_iter).first)) { +// update_segments(intersection_points, (*inter_iter).second, Point(x_, (*inter_iter).first.get(VERTICAL))); +// } else { +// //if x_ is max there can be only end events and no sloping edges +// if(x_ != (std::numeric_limits::max)()) { +// //insert its end points into the vector of sloping ends +// const half_edge& he = (*inter_iter).first; +// Unit y = evalAtXforY(x_, he.first, he.second); +// Unit y2 = evalAtXforY(x_+1, he.first, he.second); +// if(y2 >= y) y2 +=1; //we round up, in exact case we don't worry about overbite of one +// else y += 1; //downward sloping round up +// sloping_ends.push_back(std::make_pair(y, inter_iter)); +// sloping_ends.push_back(std::make_pair(y2, inter_iter)); +// } +// } +// } + +// //merge sloping element data +// polygon_sort(sloping_ends.begin(), sloping_ends.end()); +// std::map > sloping_elements; +// std::set merge_elements; +// for(typename std::vector >::iterator slop_iter = sloping_ends.begin(); +// slop_iter == sloping_ends.end(); ++slop_iter) { +// //merge into sloping elements +// typename std::set::iterator merge_iterator = merge_elements.find((*slop_iter).second); +// if(merge_iterator == merge_elements.end()) { +// merge_elements.insert((*slop_iter).second); +// } else { +// merge_elements.erase(merge_iterator); +// } +// sloping_elements[(*slop_iter).first] = merge_elements; +// } + +// //scan intersection points +// typename std::map >::iterator vertical_iter = vertical_data_.begin(); +// typename std::map >::iterator sloping_iter = sloping_elements.begin(); +// for(typename std::set::iterator position_iter = intersection_locations.begin(); +// position_iter == intersection_locations.end(); ++position_iter) { +// //look for vertical segments that intersect this point and update them +// Unit y = *position_iter; +// Point pt(x_, y); +// //handle vertical segments +// if(vertical_iter != vertical_data_.end()) { +// typename std::map >::iterator next_vertical = vertical_iter; +// for(++next_vertical; next_vertical != vertical_data_.end() && +// (*next_vertical).first < y; ++next_vertical) { +// vertical_iter = next_vertical; +// } +// if((*vertical_iter).first < y && !(*vertical_iter).second.empty()) { +// update_segments(intersection_points, (*vertical_iter).second, pt); +// ++vertical_iter; +// if(vertical_iter != vertical_data_.end() && (*vertical_iter).first == y) +// update_segments(intersection_points, (*vertical_iter).second, pt); +// } +// } +// //handle sloping segments +// if(sloping_iter != sloping_elements.end()) { +// typename std::map >::iterator next_sloping = sloping_iter; +// for(++next_sloping; next_sloping != sloping_elements.end() && +// (*next_sloping).first < y; ++next_sloping) { +// sloping_iter = next_sloping; +// } +// if((*sloping_iter).first < y && !(*sloping_iter).second.empty()) { +// for(typename std::set::iterator element_iter = (*sloping_iter).second.begin(); +// element_iter != (*sloping_iter).second.end(); ++element_iter) { +// const half_edge& he = (*element_iter).first; +// if(intersects_grid(pt, he)) { +// update_segments(intersection_points, (*element_iter).second, pt); +// } +// } +// ++sloping_iter; +// if(sloping_iter != sloping_elements.end() && (*sloping_iter).first == y && +// !(*sloping_iter).second.empty()) { +// for(typename std::set::iterator element_iter = (*sloping_iter).second.begin(); +// element_iter != (*sloping_iter).second.end(); ++element_iter) { +// const half_edge& he = (*element_iter).first; +// if(intersects_grid(pt, he)) { +// update_segments(intersection_points, (*element_iter).second, pt); +// } +// } +// } +// } +// } +// } + +// //erase and reinsert edges into scanline with check for future intersection +// } + +// inline void process_scan_event(std::map >& intersection_points) { +// just_before_ = true; + +// //process end events by removing those segments from the scanline +// //and insert vertices of all events into intersection queue +// Point prev_point((std::numeric_limits::min)(), (std::numeric_limits::min)()); +// less_point lp; +// std::set vertical_ids; +// vertical_data_.clear(); +// for(std::size_t i = 0; i < event_edges_.size(); ++i) { +// segment_id id = event_edges_[i].second; +// const half_edge& he = event_edges_[i].first; +// //vertical half edges are handled during intersection processing because +// //they cannot be inserted into the scanline +// if(!is_vertical(he)) { +// if(lp(he.second, he.first)) { +// //half edge is end event +// lookup_and_remove(he, id); +// } else { +// //half edge is begin event +// insert_into_scanline(he, id); +// //note that they will be immediately removed and reinserted after +// //handling their intersection (vertex) +// //an optimization would allow them to be processed specially to avoid the redundant +// //removal and reinsertion +// } +// } else { +// //common case if you are lucky +// //update the map of y to set of segment id +// if(lp(he.second, he.first)) { +// //half edge is end event +// std::set::iterator itr = vertical_ids.find(id); +// if(itr == vertical_ids.end()) { +// //std::cout << "Failed to find end event id in vertical ids\n"; +// } else { +// vertical_ids.erase(itr); +// vertical_data_[he.first.get(HORIZONTAL)] = vertical_ids; +// } +// } else { +// //half edge is a begin event +// vertical_ids.insert(id); +// vertical_data_[he.first.get(HORIZONTAL)] = vertical_ids; +// } +// } +// //prevent repeated insertion of same vertex into intersection queue +// if(prev_point != he.first) +// intersection_queue_.insert(he.first); +// else +// prev_point = he.first; +// // process intersections at scan event +// process_intersections_at_scan_event(intersection_points); +// } +// event_edges_.clear(); +// } + + public: + template + static inline bool test_validate_scan(stream_type& stdcout) { + std::vector > input, edges; + input.push_back(std::make_pair(half_edge(Point(0, 0), Point(0, 10)), 0)); + input.push_back(std::make_pair(half_edge(Point(0, 0), Point(10, 10)), 1)); + std::pair result; + validate_scan(edges, input.begin(), input.end()); + if(!verify_scan(result, edges.begin(), edges.end())) { + stdcout << "s fail1 " << result.first << " " << result.second << "\n"; + return false; + } + input.push_back(std::make_pair(half_edge(Point(0, 5), Point(5, 5)), 2)); + edges.clear(); + validate_scan(edges, input.begin(), input.end()); + if(!verify_scan(result, edges.begin(), edges.end())) { + stdcout << "s fail2 " << result.first << " " << result.second << "\n"; + return false; + } + input.pop_back(); + input.push_back(std::make_pair(half_edge(Point(1, 0), Point(11, 11)), input.size())); + edges.clear(); + validate_scan(edges, input.begin(), input.end()); + if(!verify_scan(result, edges.begin(), edges.end())) { + stdcout << "s fail3 " << result.first << " " << result.second << "\n"; + return false; + } + input.push_back(std::make_pair(half_edge(Point(1, 0), Point(10, 11)), input.size())); + edges.clear(); + validate_scan(edges, input.begin(), input.end()); + if(!verify_scan(result, edges.begin(), edges.end())) { + stdcout << "s fail4 " << result.first << " " << result.second << "\n"; + return false; + } + input.pop_back(); + input.push_back(std::make_pair(half_edge(Point(1, 2), Point(11, 11)), input.size())); + edges.clear(); + validate_scan(edges, input.begin(), input.end()); + if(!verify_scan(result, edges.begin(), edges.end())) { + stdcout << "s fail5 " << result.first << " " << result.second << "\n"; + return false; + } + input.push_back(std::make_pair(half_edge(Point(0, 5), Point(0, 11)), input.size())); + edges.clear(); + validate_scan(edges, input.begin(), input.end()); + if(!verify_scan(result, edges.begin(), edges.end())) { + stdcout << "s fail6 " << result.first << " " << result.second << "\n"; + return false; + } + input.pop_back(); + for(std::size_t i = 0; i < input.size(); ++i) { + std::swap(input[i].first.first, input[i].first.second); + } + edges.clear(); + validate_scan(edges, input.begin(), input.end()); + if(!verify_scan(result, edges.begin(), edges.end())) { + stdcout << "s fail5 2 " << result.first << " " << result.second << "\n"; + return false; + } + for(std::size_t i = 0; i < input.size(); ++i) { + input[i].first.first = Point(input[i].first.first.get(HORIZONTAL) * -1, + input[i].first.first.get(VERTICAL) * -1); + input[i].first.second = Point(input[i].first.second.get(HORIZONTAL) * -1, + input[i].first.second.get(VERTICAL) * -1); + } + edges.clear(); + validate_scan(edges, input.begin(), input.end()); + stdcout << edges.size() << "\n"; + if(!verify_scan(result, edges.begin(), edges.end())) { + stdcout << "s fail5 3 " << result.first << " " << result.second << "\n"; + return false; + } + input.clear(); + edges.clear(); + input.push_back(std::make_pair(half_edge(Point(5, 7), Point(7, 6)), 0)); + input.push_back(std::make_pair(half_edge(Point(2, 4), Point(6, 7)), 1)); + validate_scan(edges, input.begin(), input.end()); + if(!verify_scan(result, edges.begin(), edges.end())) { + stdcout << "s fail2 1 " << result.first << " " << result.second << "\n"; + print(input); + print(edges); + return false; + } + input.clear(); + edges.clear(); + input.push_back(std::make_pair(half_edge(Point(3, 2), Point(1, 7)), 0)); + input.push_back(std::make_pair(half_edge(Point(0, 6), Point(7, 4)), 1)); + validate_scan(edges, input.begin(), input.end()); + if(!verify_scan(result, edges.begin(), edges.end())) { + stdcout << "s fail2 2 " << result.first << " " << result.second << "\n"; + print(input); + print(edges); + return false; + } + input.clear(); + edges.clear(); + input.push_back(std::make_pair(half_edge(Point(6, 6), Point(1, 0)), 0)); + input.push_back(std::make_pair(half_edge(Point(3, 6), Point(2, 3)), 1)); + validate_scan(edges, input.begin(), input.end()); + if(!verify_scan(result, edges.begin(), edges.end())) { + stdcout << "s fail2 3 " << result.first << " " << result.second << "\n"; + print(input); + print(edges); + return false; + } + input.clear(); + edges.clear(); + input.push_back(std::make_pair(half_edge(Point(0, 0), Point(7, 0)), 0)); + input.push_back(std::make_pair(half_edge(Point(6, 0), Point(2, 0)), 1)); + validate_scan(edges, input.begin(), input.end()); + if(!verify_scan(result, edges.begin(), edges.end())) { + stdcout << "s fail2 4 " << result.first << " " << result.second << "\n"; + print(input); + print(edges); + return false; + } + input.clear(); + edges.clear(); + input.push_back(std::make_pair(half_edge(Point(-17333131 - -17208131, -10316869 - -10191869), Point(0, 0)), 0)); + input.push_back(std::make_pair(half_edge(Point(-17291260 - -17208131, -10200000 - -10191869), Point(-17075000 - -17208131, -10200000 - -10191869)), 1)); + validate_scan(edges, input.begin(), input.end()); + if(!verify_scan(result, edges.begin(), edges.end())) { + stdcout << "s fail2 5 " << result.first << " " << result.second << "\n"; + print(input); + print(edges); + return false; + } + input.clear(); + edges.clear(); + input.push_back(std::make_pair(half_edge(Point(-17333131, -10316869), Point(-17208131, -10191869)), 0)); + input.push_back(std::make_pair(half_edge(Point(-17291260, -10200000), Point(-17075000, -10200000)), 1)); + validate_scan(edges, input.begin(), input.end()); + if(!verify_scan(result, edges.begin(), edges.end())) { + stdcout << "s fail2 6 " << result.first << " " << result.second << "\n"; + print(input); + print(edges); + return false; + } + input.clear(); + edges.clear(); + input.push_back(std::make_pair(half_edge(Point(-9850009+9853379, -286971+290340), Point(-12777869+9853379, -3214831+290340)), 0)); + input.push_back(std::make_pair(half_edge(Point(-5223510+9853379, -290340+290340), Point(-9858140+9853379, -290340+290340)), 1)); + validate_scan(edges, input.begin(), input.end()); + print(edges); + if(!verify_scan(result, edges.begin(), edges.end())) { + stdcout << "s fail2 7 " << result.first << " " << result.second << "\n"; + print(input); + print(edges); + return false; + } + input.clear(); + edges.clear(); + input.push_back(std::make_pair(half_edge(Point(-9850009, -286971), Point(-12777869, -3214831)), 0)); + input.push_back(std::make_pair(half_edge(Point(-5223510, -290340), Point(-9858140, -290340)), 1)); + validate_scan(edges, input.begin(), input.end()); + if(!verify_scan(result, edges.begin(), edges.end())) { + stdcout << "s fail2 8 " << result.first << " " << result.second << "\n"; + print(input); + print(edges); + return false; + } + //3 3 2 2: 0; 4 2 0 6: 1; 0 3 6 3: 2; 4 1 5 5: 3; + input.clear(); + edges.clear(); + input.push_back(std::make_pair(half_edge(Point(3, 3), Point(2, 2)), 0)); + input.push_back(std::make_pair(half_edge(Point(4, 2), Point(0, 6)), 1)); + input.push_back(std::make_pair(half_edge(Point(0, 3), Point(6, 3)), 2)); + input.push_back(std::make_pair(half_edge(Point(4, 1), Point(5, 5)), 3)); + validate_scan(edges, input.begin(), input.end()); + if(!verify_scan(result, edges.begin(), edges.end())) { + stdcout << "s fail4 1 " << result.first << " " << result.second << "\n"; + print(input); + print(edges); + return false; + } + //5 7 1 3: 0; 4 5 2 1: 1; 2 5 2 1: 2; 4 1 5 3: 3; + input.clear(); + edges.clear(); + input.push_back(std::make_pair(half_edge(Point(5, 7), Point(1, 3)), 0)); + input.push_back(std::make_pair(half_edge(Point(4, 5), Point(2, 1)), 1)); + input.push_back(std::make_pair(half_edge(Point(2, 5), Point(2, 1)), 2)); + input.push_back(std::make_pair(half_edge(Point(4, 1), Point(5, 3)), 3)); + validate_scan(edges, input.begin(), input.end()); + if(!verify_scan(result, edges.begin(), edges.end())) { + stdcout << "s fail4 2 " << result.first << " " << result.second << "\n"; + print(input); + print(edges); + return false; + } + //1 0 -4 -1: 0; 0 0 2 -1: 1; + input.clear(); + edges.clear(); + input.push_back(std::make_pair(half_edge(Point(1, 0), Point(-4, -1)), 0)); + input.push_back(std::make_pair(half_edge(Point(0, 0), Point(2, -1)), 1)); + validate_scan(edges, input.begin(), input.end()); + if(!verify_scan(result, edges.begin(), edges.end())) { + stdcout << "s fail2 5 " << result.first << " " << result.second << "\n"; + print(input); + print(edges); + return false; + } + Unit min_c =0; + Unit max_c =0; + for(unsigned int outer = 0; outer < 1000; ++outer) { + input.clear(); + for(unsigned int i = 0; i < 4; ++i) { + Unit x1 = rand(); + Unit x2 = rand(); + Unit y1 = rand(); + Unit y2 = rand(); + int neg1 = rand() % 2; + if(neg1) x1 *= -1; + int neg2 = rand() % 2; + if(neg2) x2 *= -1; + int neg3 = rand() % 2; + if(neg3) y1 *= -1; + int neg4 = rand() % 2; + if(neg4) y2 *= -1; + if(x1 < min_c) min_c = x1; + if(x2 < min_c) min_c = x2; + if(y1 < min_c) min_c = y1; + if(y2 < min_c) min_c = y2; + if(x1 > max_c) max_c = x1; + if(x2 > max_c) max_c = x2; + if(y1 > max_c) max_c = y1; + if(y2 > max_c) max_c = y2; + Point pt1(x1, y1); + Point pt2(x2, y2); + if(pt1 != pt2) + input.push_back(std::make_pair(half_edge(pt1, pt2), i)); + } + edges.clear(); + validate_scan(edges, input.begin(), input.end()); + if(!verify_scan(result, edges.begin(), edges.end())) { + stdcout << "s fail9 " << outer << ": " << result.first << " " << result.second << "\n"; + print(input); + print(edges); + return false; + } + } + return true; + } + + //static void print(const std::pair& segment) { + //std::cout << segment.first.first << " " << segment.first.second << ": " << segment.second << "; "; + //} + static void print(const std::vector >& vec) { + for(std::size_t i = 0; i < vec.size(); ++ i) { + // print(vec[i]); + } + //std::cout << "\n"; + } + + template + static inline bool test_verify_scan(stream_type& stdcout) { + std::vector > edges; + edges.push_back(std::make_pair(half_edge(Point(0, 0), Point(0, 10)), 0)); + edges.push_back(std::make_pair(half_edge(Point(0, 0), Point(10, 10)), 1)); + std::pair result; + if(!verify_scan(result, edges.begin(), edges.end())) { + stdcout << "fail1\n"; + return false; + } + edges.push_back(std::make_pair(half_edge(Point(0, 5), Point(5, 5)), 2)); + if(verify_scan(result, edges.begin(), edges.end())) { + stdcout << "fail2\n"; + return false; + } + edges.pop_back(); + edges.push_back(std::make_pair(half_edge(Point(1, 0), Point(11, 11)), (segment_id)edges.size())); + if(!verify_scan(result, edges.begin(), edges.end())) { + stdcout << "fail3\n"; + return false; + } + edges.push_back(std::make_pair(half_edge(Point(1, 0), Point(10, 11)), (segment_id)edges.size())); + if(verify_scan(result, edges.begin(), edges.end())) { + stdcout << "fail4\n"; + return false; + } + edges.pop_back(); + edges.push_back(std::make_pair(half_edge(Point(1, 2), Point(11, 11)), (segment_id)edges.size())); + if(!verify_scan(result, edges.begin(), edges.end())) { + stdcout << "fail5 " << result.first << " " << result.second << "\n"; + return false; + } + edges.push_back(std::make_pair(half_edge(Point(0, 5), Point(0, 11)), (segment_id)edges.size())); + if(verify_scan(result, edges.begin(), edges.end())) { + stdcout << "fail6 " << result.first << " " << result.second << "\n"; + return false; + } + edges.pop_back(); + for(std::size_t i = 0; i < edges.size(); ++i) { + std::swap(edges[i].first.first, edges[i].first.second); + } + if(!verify_scan(result, edges.begin(), edges.end())) { + stdcout << "fail5 2 " << result.first << " " << result.second << "\n"; + return false; + } + for(std::size_t i = 0; i < edges.size(); ++i) { + edges[i].first.first = Point(edges[i].first.first.get(HORIZONTAL) * -1, + edges[i].first.first.get(VERTICAL) * -1); + edges[i].first.second = Point(edges[i].first.second.get(HORIZONTAL) * -1, + edges[i].first.second.get(VERTICAL) * -1); + } + if(!verify_scan(result, edges.begin(), edges.end())) { + stdcout << "fail5 3 " << result.first << " " << result.second << "\n"; + return false; + } + return true; + } + + }; + + //scanline consumes the "flattened" fully intersected line segments produced by + //a pass of line_intersection along with property and count information and performs a + //useful operation like booleans or property merge or connectivity extraction + template > + class scanline : public scanline_base { + public: + //definitions + typedef typename scanline_base::Point Point; + + //the first point is the vertex and and second point establishes the slope of an edge eminating from the vertex + //typedef std::pair half_edge; + typedef typename scanline_base::half_edge half_edge; + + //scanline comparator functor + typedef typename scanline_base::less_half_edge less_half_edge; + typedef typename scanline_base::less_point less_point; + + typedef keytype property_set; + //this is the data type used internally to store the combination of property counts at a given location + typedef std::vector > property_map; + //this data structure assocates a property and count to a half edge + typedef std::pair > vertex_property; + //this data type is used internally to store the combined property data for a given half edge + typedef std::pair vertex_data; + //this data type stores the combination of many half edges + typedef std::vector property_merge_data; + //this data structure stores end points of edges in the scanline + typedef std::set end_point_queue; + + //this is the output data type that is created by the scanline before it is post processed based on content of property sets + typedef std::pair > half_edge_property; + + //this is the scanline data structure + typedef std::map scanline_type; + typedef std::pair scanline_element; + typedef typename scanline_type::iterator iterator; + typedef typename scanline_type::const_iterator const_iterator; + + //data + scanline_type scan_data_; + std::vector removal_set_; //edges to be removed at the current scanline stop + std::vector insertion_set_; //edge to be inserted after current scanline stop + end_point_queue end_point_queue_; + Unit x_; + Unit y_; + int just_before_; + typename scanline_base::evalAtXforYPack evalAtXforYPack_; + public: + inline scanline() : scan_data_(), removal_set_(), insertion_set_(), end_point_queue_(), + x_((std::numeric_limits::max)()), y_((std::numeric_limits::max)()), just_before_(false), evalAtXforYPack_() { + less_half_edge lessElm(&x_, &just_before_, &evalAtXforYPack_); + scan_data_ = scanline_type(lessElm); + } + inline scanline(const scanline& that) : scan_data_(), removal_set_(), insertion_set_(), end_point_queue_(), + x_((std::numeric_limits::max)()), y_((std::numeric_limits::max)()), just_before_(false), evalAtXforYPack_() { + (*this) = that; } + inline scanline& operator=(const scanline& that) { + x_ = that.x_; + y_ = that.y_; + just_before_ = that.just_before_; + end_point_queue_ = that.end_point_queue_; + //I cannot simply copy that.scanline_type to this scanline_type becuase the functor store pointers to other members! + less_half_edge lessElm(&x_, &just_before_); + scan_data_ = scanline_type(lessElm); + + scan_data_.insert(that.scan_data_.begin(), that.scan_data_.end()); + return *this; + } + + template + void write_out(result_type& result, result_functor rf, const half_edge& he, + const property_map& pm_left, const property_map& pm_right) { + //std::cout << "write out "; + //std::cout << he.first << ", " << he.second << "\n"; + property_set ps_left, ps_right; + set_unique_property(ps_left, pm_left); + set_unique_property(ps_right, pm_right); + if(ps_left != ps_right) { + //std::cout << "!equivalent\n"; + rf(result, he, ps_left, ps_right); + } + } + + template + iT handle_input_events(result_type& result, result_functor rf, iT begin, iT end) { + //typedef typename high_precision_type::type high_precision; + //for each event + property_map vertical_properties_above; + property_map vertical_properties_below; + half_edge vertical_edge_above; + half_edge vertical_edge_below; + std::vector insertion_elements; + //current_iter should increase monotonically toward end as we process scanline stop + iterator current_iter = scan_data_.begin(); + just_before_ = true; + Unit y = (std::numeric_limits::min)(); + bool first_iteration = true; + //we want to return from inside the loop when we hit end or new x +#ifdef BOOST_POLYGON_MSVC +#pragma warning (push) +#pragma warning (disable: 4127) +#endif + while(true) { + if(begin == end || (!first_iteration && ((*begin).first.first.get(VERTICAL) != y || + (*begin).first.first.get(HORIZONTAL) != x_))) { + //lookup iterator range in scanline for elements coming in from the left + //that end at this y + Point pt(x_, y); + //grab the properties coming in from below + property_map properties_below; + if(current_iter != scan_data_.end()) { + //make sure we are looking at element in scanline just below y + //if(evalAtXforY(x_, (*current_iter).first.first, (*current_iter).first.second) != y) { + if(scanline_base::on_above_or_below(Point(x_, y), (*current_iter).first) != 0) { + Point e2(pt); + if(e2.get(VERTICAL) != (std::numeric_limits::max)()) + e2.set(VERTICAL, e2.get(VERTICAL) + 1); + else + e2.set(VERTICAL, e2.get(VERTICAL) - 1); + half_edge vhe(pt, e2); + current_iter = scan_data_.lower_bound(vhe); + } + if(current_iter != scan_data_.end()) { + //get the bottom iterator for elements at this point + //while(evalAtXforY(x_, (*current_iter).first.first, (*current_iter).first.second) >= (high_precision)y && + while(scanline_base::on_above_or_below(Point(x_, y), (*current_iter).first) != 1 && + current_iter != scan_data_.begin()) { + --current_iter; + } + //if(evalAtXforY(x_, (*current_iter).first.first, (*current_iter).first.second) >= (high_precision)y) { + if(scanline_base::on_above_or_below(Point(x_, y), (*current_iter).first) != 1) { + properties_below.clear(); + } else { + properties_below = (*current_iter).second; + //move back up to y or one past y + ++current_iter; + } + } + } + std::vector edges_from_left; + while(current_iter != scan_data_.end() && + //can only be true if y is integer + //evalAtXforY(x_, (*current_iter).first.first, (*current_iter).first.second) == y) { + scanline_base::on_above_or_below(Point(x_, y), (*current_iter).first) == 0) { + //removal_set_.push_back(current_iter); + ++current_iter; + } + //merge vertical count with count from below + if(!vertical_properties_below.empty()) { + merge_property_maps(vertical_properties_below, properties_below); + //write out vertical edge + write_out(result, rf, vertical_edge_below, properties_below, vertical_properties_below); + } else { + merge_property_maps(vertical_properties_below, properties_below); + } + //iteratively add intertion element counts to count from below + //and write them to insertion set + for(std::size_t i = 0; i < insertion_elements.size(); ++i) { + if(i == 0) { + merge_property_maps(insertion_elements[i].second, vertical_properties_below); + write_out(result, rf, insertion_elements[i].first, insertion_elements[i].second, vertical_properties_below); + } else { + merge_property_maps(insertion_elements[i].second, insertion_elements[i-1].second); + write_out(result, rf, insertion_elements[i].first, insertion_elements[i].second, insertion_elements[i-1].second); + } + insertion_set_.push_back(insertion_elements[i]); + } + if((begin == end || (*begin).first.first.get(HORIZONTAL) != x_)) { + if(vertical_properties_above.empty()) { + return begin; + } else { + y = vertical_edge_above.second.get(VERTICAL); + vertical_properties_below.clear(); + vertical_properties_above.swap(vertical_properties_below); + vertical_edge_below = vertical_edge_above; + insertion_elements.clear(); + continue; + } + } + vertical_properties_below.clear(); + vertical_properties_above.swap(vertical_properties_below); + vertical_edge_below = vertical_edge_above; + insertion_elements.clear(); + } + if(begin != end) { + const vertex_property& vp = *begin; + const half_edge& he = vp.first; + y = he.first.get(VERTICAL); + first_iteration = false; + if(! vertical_properties_below.empty() && + vertical_edge_below.second.get(VERTICAL) < y) { + y = vertical_edge_below.second.get(VERTICAL); + continue; + } + if(scanline_base::is_vertical(he)) { + update_property_map(vertical_properties_above, vp.second); + vertical_edge_above = he; + } else { + if(insertion_elements.empty() || + insertion_elements.back().first != he) { + insertion_elements.push_back(scanline_element(he, property_map())); + } + update_property_map(insertion_elements.back().second, vp.second); + } + ++begin; + } + } +#ifdef BOOST_POLYGON_MSVC +#pragma warning (pop) +#endif + + } + + inline void erase_end_events(typename end_point_queue::iterator epqi) { + end_point_queue_.erase(end_point_queue_.begin(), epqi); + for(typename std::vector::iterator retire_itr = removal_set_.begin(); + retire_itr != removal_set_.end(); ++retire_itr) { + scan_data_.erase(*retire_itr); + } + removal_set_.clear(); + } + + + inline void remove_retired_edges_from_scanline() { + just_before_ = true; + typename end_point_queue::iterator epqi = end_point_queue_.begin(); + Unit current_x = x_; + Unit previous_x = x_; + while(epqi != end_point_queue_.end() && + (*epqi).get(HORIZONTAL) <= current_x) { + x_ = (*epqi).get(HORIZONTAL); + if(x_ != previous_x) erase_end_events(epqi); + previous_x = x_; + //lookup elements + Point e2(*epqi); + if(e2.get(VERTICAL) != (std::numeric_limits::max)()) + e2.set(VERTICAL, e2.get(VERTICAL) + 1); + else + e2.set(VERTICAL, e2.get(VERTICAL) - 1); + half_edge vhe_e(*epqi, e2); + iterator current_iter = scan_data_.lower_bound(vhe_e); + while(current_iter != scan_data_.end() && (*current_iter).first.second == (*epqi)) { + //evalAtXforY(x_, (*current_iter).first.first, (*current_iter).first.second) == (*epqi).get(VERTICAL)) { + removal_set_.push_back(current_iter); + ++current_iter; + } + ++epqi; + } + x_ = current_x; + erase_end_events(epqi); + } + + inline void insert_new_edges_into_scanline() { + just_before_ = false; + for(typename std::vector::iterator insert_itr = insertion_set_.begin(); + insert_itr != insertion_set_.end(); ++insert_itr) { + scan_data_.insert(*insert_itr); + end_point_queue_.insert((*insert_itr).first.second); + } + insertion_set_.clear(); + } + + //iterator over range of vertex property elements and call result functor + //passing edge to be output, the merged data on both sides and the result + template + void scan(result_type& result, result_functor rf, iT begin, iT end) { + while(begin != end) { + x_ = (*begin).first.first.get(HORIZONTAL); //update scanline stop location + //print_scanline(); + --x_; + remove_retired_edges_from_scanline(); + ++x_; + begin = handle_input_events(result, rf, begin, end); + remove_retired_edges_from_scanline(); + //print_scanline(); + insert_new_edges_into_scanline(); + } + //print_scanline(); + x_ = (std::numeric_limits::max)(); + remove_retired_edges_from_scanline(); + } + + //inline void print_scanline() { + // std::cout << "scanline at " << x_ << ": "; + // for(iterator itr = scan_data_.begin(); itr != scan_data_.end(); ++itr) { + // const scanline_element& se = *itr; + // const half_edge& he = se.first; + // const property_map& mp = se.second; + // std::cout << he.first << ", " << he.second << " ( "; + // for(std::size_t i = 0; i < mp.size(); ++i) { + // std::cout << mp[i].first << ":" << mp[i].second << " "; + // } std::cout << ") "; + // } std::cout << "\n"; + //} + + static inline void merge_property_maps(property_map& mp, const property_map& mp2) { + property_map newmp; + newmp.reserve(mp.size() + mp2.size()); + unsigned int i = 0; + unsigned int j = 0; + while(i != mp.size() && j != mp2.size()) { + if(mp[i].first < mp2[j].first) { + newmp.push_back(mp[i]); + ++i; + } else if(mp[i].first > mp2[j].first) { + newmp.push_back(mp2[j]); + ++j; + } else { + int count = mp[i].second; + count += mp2[j].second; + if(count) { + newmp.push_back(mp[i]); + newmp.back().second = count; + } + ++i; + ++j; + } + } + while(i != mp.size()) { + newmp.push_back(mp[i]); + ++i; + } + while(j != mp2.size()) { + newmp.push_back(mp2[j]); + ++j; + } + mp.swap(newmp); + } + + static inline void update_property_map(property_map& mp, const std::pair& prop_data) { + property_map newmp; + newmp.reserve(mp.size() +1); + bool consumed = false; + for(std::size_t i = 0; i < mp.size(); ++i) { + if(!consumed && prop_data.first == mp[i].first) { + consumed = true; + int count = prop_data.second + mp[i].second; + if(count) + newmp.push_back(std::make_pair(prop_data.first, count)); + } else if(!consumed && prop_data.first < mp[i].first) { + consumed = true; + newmp.push_back(prop_data); + newmp.push_back(mp[i]); + } else { + newmp.push_back(mp[i]); + } + } + if(!consumed) newmp.push_back(prop_data); + mp.swap(newmp); + } + + static inline void set_unique_property(property_set& unqiue_property, const property_map& property) { + unqiue_property.clear(); + for(typename property_map::const_iterator itr = property.begin(); itr != property.end(); ++itr) { + if((*itr).second > 0) + unqiue_property.insert(unqiue_property.end(), (*itr).first); + } + } + + static inline bool common_vertex(const half_edge& he1, const half_edge& he2) { + return he1.first == he2.first || + he1.first == he2.second || + he1.second == he2.first || + he1.second == he2.second; + } + + typedef typename scanline_base::vertex_half_edge vertex_half_edge; + template + static inline void convert_segments_to_vertex_half_edges(std::vector& output, iT begin, iT end) { + for( ; begin != end; ++begin) { + const half_edge& he = (*begin).first; + int count = (*begin).second; + output.push_back(vertex_half_edge(he.first, he.second, count)); + output.push_back(vertex_half_edge(he.second, he.first, -count)); + } + polygon_sort(output.begin(), output.end()); + } + + class test_functor { + public: + inline test_functor() {} + inline void operator()(std::vector > >& result, + const half_edge& he, const property_set& ps_left, const property_set& ps_right) { + result.push_back(std::make_pair(he, std::make_pair(ps_left, ps_right))); + } + }; + template + static inline bool test_scanline(stream_type& stdcout) { + std::vector > > result; + std::vector > > input; + input.push_back(std::make_pair(half_edge(Point(0, 0), Point(0, 10)), std::make_pair(0, 1))); + input.push_back(std::make_pair(half_edge(Point(0, 0), Point(10, 0)), std::make_pair(0, 1))); + input.push_back(std::make_pair(half_edge(Point(0, 10), Point(10, 10)), std::make_pair(0, -1))); + input.push_back(std::make_pair(half_edge(Point(10, 0), Point(10, 10)), std::make_pair(0, -1))); + scanline sl; + test_functor tf; + sl.scan(result, tf, input.begin(), input.end()); + stdcout << "scanned\n"; + for(std::size_t i = 0; i < result.size(); ++i) { + stdcout << result[i].first.first << ", " << result[i].first.second << "; "; + } stdcout << "\n"; + input.clear(); + result.clear(); + input.push_back(std::make_pair(half_edge(Point(-1, -1), Point(10, 0)), std::make_pair(0, 1))); + input.push_back(std::make_pair(half_edge(Point(-1, -1), Point(0, 10)), std::make_pair(0, -1))); + input.push_back(std::make_pair(half_edge(Point(0, 10), Point(11, 11)), std::make_pair(0, -1))); + input.push_back(std::make_pair(half_edge(Point(10, 0), Point(11, 11)), std::make_pair(0, 1))); + scanline sl2; + sl2.scan(result, tf, input.begin(), input.end()); + stdcout << "scanned\n"; + for(std::size_t i = 0; i < result.size(); ++i) { + stdcout << result[i].first.first << ", " << result[i].first.second << "; "; + } stdcout << "\n"; + input.clear(); + result.clear(); + input.push_back(std::make_pair(half_edge(Point(0, 0), Point(0, 10)), std::make_pair(0, 1))); + input.push_back(std::make_pair(half_edge(Point(0, 0), Point(10, 0)), std::make_pair(0, 1))); + input.push_back(std::make_pair(half_edge(Point(0, 10), Point(10, 10)), std::make_pair(0, -1))); + input.push_back(std::make_pair(half_edge(Point(1, 1), Point(8, 2)), std::make_pair(1, 1))); + input.push_back(std::make_pair(half_edge(Point(1, 1), Point(2, 8)), std::make_pair(1, -1))); + input.push_back(std::make_pair(half_edge(Point(2, 8), Point(9, 9)), std::make_pair(1, -1))); + input.push_back(std::make_pair(half_edge(Point(8, 2), Point(9, 9)), std::make_pair(1, 1))); + input.push_back(std::make_pair(half_edge(Point(10, 0), Point(10, 10)), std::make_pair(0, -1))); + scanline sl3; + sl3.scan(result, tf, input.begin(), input.end()); + stdcout << "scanned\n"; + for(std::size_t i = 0; i < result.size(); ++i) { + stdcout << result[i].first.first << ", " << result[i].first.second << "; "; + } stdcout << "\n"; + input.clear(); + result.clear(); + input.push_back(std::make_pair(half_edge(Point(0, 0), Point(0, 10)), std::make_pair(0, 1))); + input.push_back(std::make_pair(half_edge(Point(0, 0), Point(10, 0)), std::make_pair(0, 1))); + input.push_back(std::make_pair(half_edge(Point(0, 10), Point(10, 10)), std::make_pair(0, -1))); + input.push_back(std::make_pair(half_edge(Point(1, 1), Point(8, 2)), std::make_pair(0, 1))); + input.push_back(std::make_pair(half_edge(Point(1, 1), Point(2, 8)), std::make_pair(0, -1))); + input.push_back(std::make_pair(half_edge(Point(2, 8), Point(9, 9)), std::make_pair(0, -1))); + input.push_back(std::make_pair(half_edge(Point(8, 2), Point(9, 9)), std::make_pair(0, 1))); + input.push_back(std::make_pair(half_edge(Point(10, 0), Point(10, 10)), std::make_pair(0, -1))); + scanline sl4; + sl4.scan(result, tf, input.begin(), input.end()); + stdcout << "scanned\n"; + for(std::size_t i = 0; i < result.size(); ++i) { + stdcout << result[i].first.first << ", " << result[i].first.second << "; "; + } stdcout << "\n"; + input.clear(); + result.clear(); + input.push_back(std::make_pair(half_edge(Point(0, 0), Point(10, 0)), std::make_pair(0, 1))); + input.push_back(std::make_pair(half_edge(Point(0, 0), Point(9, 1)), std::make_pair(0, 1))); + input.push_back(std::make_pair(half_edge(Point(0, 0), Point(1, 9)), std::make_pair(0, -1))); + input.push_back(std::make_pair(half_edge(Point(0, 0), Point(0, 10)), std::make_pair(0, 1))); + input.push_back(std::make_pair(half_edge(Point(0, 10), Point(10, 10)), std::make_pair(0, -1))); + input.push_back(std::make_pair(half_edge(Point(1, 9), Point(10, 10)), std::make_pair(0, -1))); + input.push_back(std::make_pair(half_edge(Point(9, 1), Point(10, 10)), std::make_pair(0, 1))); + input.push_back(std::make_pair(half_edge(Point(10, 0), Point(10, 10)), std::make_pair(0, -1))); + scanline sl5; + sl5.scan(result, tf, input.begin(), input.end()); + stdcout << "scanned\n"; + for(std::size_t i = 0; i < result.size(); ++i) { + stdcout << result[i].first.first << ", " << result[i].first.second << "; "; + } stdcout << "\n"; + input.clear(); + result.clear(); + input.push_back(std::make_pair(half_edge(Point(0, 0), Point(10, 0)), std::make_pair(0, 1))); + input.push_back(std::make_pair(half_edge(Point(0, 0), Point(9, 1)), std::make_pair(1, 1))); + input.push_back(std::make_pair(half_edge(Point(0, 0), Point(1, 9)), std::make_pair(1, -1))); + input.push_back(std::make_pair(half_edge(Point(0, 0), Point(0, 10)), std::make_pair(0, 1))); + input.push_back(std::make_pair(half_edge(Point(0, 10), Point(10, 10)), std::make_pair(0, -1))); + input.push_back(std::make_pair(half_edge(Point(1, 9), Point(10, 10)), std::make_pair(1, -1))); + input.push_back(std::make_pair(half_edge(Point(9, 1), Point(10, 10)), std::make_pair(1, 1))); + input.push_back(std::make_pair(half_edge(Point(10, 0), Point(10, 10)), std::make_pair(0, -1))); + scanline sl6; + sl6.scan(result, tf, input.begin(), input.end()); + stdcout << "scanned\n"; + for(std::size_t i = 0; i < result.size(); ++i) { + stdcout << result[i].first.first << ", " << result[i].first.second << "; "; + } stdcout << "\n"; + input.clear(); + result.clear(); + input.push_back(std::make_pair(half_edge(Point(0, 0), Point(10, 0)), std::make_pair(0, 1))); + input.push_back(std::make_pair(half_edge(Point(0, 0), Point(9, 1)), std::make_pair(1, 1))); + input.push_back(std::make_pair(half_edge(Point(0, 0), Point(1, 9)), std::make_pair(1, -1))); + input.push_back(std::make_pair(half_edge(Point(0, 0), Point(0, 10)), std::make_pair(0, 1))); + input.push_back(std::make_pair(half_edge(Point(0, 10), Point(10, 10)), std::make_pair(0, -1))); + input.push_back(std::make_pair(half_edge(Point(0, 20), Point(10, 20)), std::make_pair(0, 1))); + input.push_back(std::make_pair(half_edge(Point(0, 20), Point(9, 21)), std::make_pair(1, 1))); + input.push_back(std::make_pair(half_edge(Point(0, 20), Point(1, 29)), std::make_pair(1, -1))); + input.push_back(std::make_pair(half_edge(Point(0, 20), Point(0, 30)), std::make_pair(0, 1))); + input.push_back(std::make_pair(half_edge(Point(0, 30), Point(10, 30)), std::make_pair(0, -1))); + input.push_back(std::make_pair(half_edge(Point(1, 9), Point(10, 10)), std::make_pair(1, -1))); + input.push_back(std::make_pair(half_edge(Point(1, 29), Point(10, 30)), std::make_pair(1, -1))); + input.push_back(std::make_pair(half_edge(Point(9, 1), Point(10, 10)), std::make_pair(1, 1))); + input.push_back(std::make_pair(half_edge(Point(9, 21), Point(10, 30)), std::make_pair(1, 1))); + input.push_back(std::make_pair(half_edge(Point(10, 20), Point(10, 30)), std::make_pair(0, -1))); + input.push_back(std::make_pair(half_edge(Point(10, 20), Point(10, 30)), std::make_pair(0, -1))); + scanline sl7; + sl7.scan(result, tf, input.begin(), input.end()); + stdcout << "scanned\n"; + for(std::size_t i = 0; i < result.size(); ++i) { + stdcout << result[i].first.first << ", " << result[i].first.second << "; "; + } stdcout << "\n"; + input.clear(); + result.clear(); + input.push_back(std::make_pair(half_edge(Point(-1, -1), Point(10, 0)), std::make_pair(0, 1))); //a + input.push_back(std::make_pair(half_edge(Point(-1, -1), Point(0, 10)), std::make_pair(0, -1))); //a + input.push_back(std::make_pair(half_edge(Point(0, 10), Point(11, 11)), std::make_pair(0, -1))); //a + input.push_back(std::make_pair(half_edge(Point(10, 0), Point(20, 0)), std::make_pair(0, 1))); //b + input.push_back(std::make_pair(half_edge(Point(10, 0), Point(11, 11)), std::make_pair(0, -1))); //b + input.push_back(std::make_pair(half_edge(Point(10, 0), Point(11, 11)), std::make_pair(0, 1))); //a + input.push_back(std::make_pair(half_edge(Point(11, 11), Point(20, 10)), std::make_pair(0, -1))); //b + input.push_back(std::make_pair(half_edge(Point(20, 0), Point(30, 0)), std::make_pair(0, 1))); //c + input.push_back(std::make_pair(half_edge(Point(20, 0), Point(20, 10)), std::make_pair(0, -1))); //b + input.push_back(std::make_pair(half_edge(Point(20, 0), Point(20, 10)), std::make_pair(0, 1))); //c + input.push_back(std::make_pair(half_edge(Point(20, 10), Point(30, 10)), std::make_pair(0, -1))); //c + input.push_back(std::make_pair(half_edge(Point(30, 0), Point(30, 10)), std::make_pair(0, -1))); //c + scanline sl8; + sl8.scan(result, tf, input.begin(), input.end()); + stdcout << "scanned\n"; + for(std::size_t i = 0; i < result.size(); ++i) { + stdcout << result[i].first.first << ", " << result[i].first.second << "; "; + } stdcout << "\n"; + return true; + } + + }; + + template + class merge_output_functor { + public: + typedef typename scanline_base::half_edge half_edge; + merge_output_functor() {} + template + void operator()(result_type& result, const half_edge& edge, const key_type& left, const key_type& right) { + typename std::pair elem; + elem.first = edge; + elem.second = 1; + if(edge.second < edge.first) elem.second *= -1; + if(scanline_base::is_vertical(edge)) elem.second *= -1; + if(!left.empty()) + result[left].insert_clean(elem); + elem.second *= -1; + if(!right.empty()) + result[right].insert_clean(elem); + } + }; + + template , + typename output_functor_type = merge_output_functor > + class property_merge : public scanline_base { + protected: + typedef typename scanline_base::Point Point; + + //the first point is the vertex and and second point establishes the slope of an edge eminating from the vertex + //typedef std::pair half_edge; + typedef typename scanline_base::half_edge half_edge; + + //scanline comparator functor + typedef typename scanline_base::less_half_edge less_half_edge; + typedef typename scanline_base::less_point less_point; + + //this data structure assocates a property and count to a half edge + typedef std::pair > vertex_property; + //this data type stores the combination of many half edges + typedef std::vector property_merge_data; + + //this is the data type used internally to store the combination of property counts at a given location + typedef std::vector > property_map; + //this data type is used internally to store the combined property data for a given half edge + typedef std::pair vertex_data; + + property_merge_data pmd; + typename scanline_base::evalAtXforYPack evalAtXforYPack_; + + template + class less_vertex_data { + typename scanline_base::evalAtXforYPack* pack_; + public: + less_vertex_data() : pack_() {} + less_vertex_data(typename scanline_base::evalAtXforYPack* pack) : pack_(pack) {} + bool operator() (const vertex_data_type& lvalue, const vertex_data_type& rvalue) const { + less_point lp; + if(lp(lvalue.first.first, rvalue.first.first)) return true; + if(lp(rvalue.first.first, lvalue.first.first)) return false; + Unit x = lvalue.first.first.get(HORIZONTAL); + int just_before_ = 0; + less_half_edge lhe(&x, &just_before_, pack_); + return lhe(lvalue.first, rvalue.first); + } + }; + + + inline void sort_property_merge_data() { + less_vertex_data lvd(&evalAtXforYPack_); + polygon_sort(pmd.begin(), pmd.end(), lvd); + } + public: + inline property_merge_data& get_property_merge_data() { return pmd; } + inline property_merge() : pmd(), evalAtXforYPack_() {} + inline property_merge(const property_merge& pm) : pmd(pm.pmd), evalAtXforYPack_(pm.evalAtXforYPack_) {} + inline property_merge& operator=(const property_merge& pm) { pmd = pm.pmd; return *this; } + + template + void insert(const polygon_type& polygon_object, const property_type& property_value, bool is_hole = false) { + insert(polygon_object, property_value, is_hole, typename geometry_concept::type()); + } + + //result type should be std::map, polygon_set_type> + //or std::map, polygon_set_type> + template + void merge(result_type& result) { + if(pmd.empty()) return; + //intersect data + property_merge_data tmp_pmd; + line_intersection::validate_scan(tmp_pmd, pmd.begin(), pmd.end()); + pmd.swap(tmp_pmd); + sort_property_merge_data(); + scanline sl; + output_functor_type mof; + sl.scan(result, mof, pmd.begin(), pmd.end()); + } + + inline bool verify1() { + std::pair offenders; + std::vector > lines; + int count = 0; + for(std::size_t i = 0; i < pmd.size(); ++i) { + lines.push_back(std::make_pair(pmd[i].first, count++)); + } + if(!line_intersection::verify_scan(offenders, lines.begin(), lines.end())) { + //stdcout << "Intersection failed!\n"; + //stdcout << offenders.first << " " << offenders.second << "\n"; + return false; + } + std::vector pts; + for(std::size_t i = 0; i < lines.size(); ++i) { + pts.push_back(lines[i].first.first); + pts.push_back(lines[i].first.second); + } + polygon_sort(pts.begin(), pts.end()); + for(std::size_t i = 0; i < pts.size(); i+=2) { + if(pts[i] != pts[i+1]) { + //stdcout << "Non-closed figures after line intersection!\n"; + return false; + } + } + return true; + } + + void clear() {*this = property_merge();} + + protected: + template + void insert(const polygon_type& polygon_object, const property_type& property_value, bool is_hole, + polygon_concept ) { + bool first_iteration = true; + bool second_iteration = true; + Point first_point; + Point second_point; + Point previous_previous_point; + Point previous_point; + Point current_point; + direction_1d winding_dir = winding(polygon_object); + for(typename polygon_traits::iterator_type itr = begin_points(polygon_object); + itr != end_points(polygon_object); ++itr) { + assign(current_point, *itr); + if(first_iteration) { + first_iteration = false; + first_point = previous_point = current_point; + } else if(second_iteration) { + if(previous_point != current_point) { + second_iteration = false; + previous_previous_point = previous_point; + second_point = previous_point = current_point; + } + } else { + if(previous_point != current_point) { + create_vertex(pmd, previous_point, current_point, winding_dir, + is_hole, property_value); + previous_previous_point = previous_point; + previous_point = current_point; + } + } + } + current_point = first_point; + if(!first_iteration && !second_iteration) { + if(previous_point != current_point) { + create_vertex(pmd, previous_point, current_point, winding_dir, + is_hole, property_value); + previous_previous_point = previous_point; + previous_point = current_point; + } + current_point = second_point; + create_vertex(pmd, previous_point, current_point, winding_dir, + is_hole, property_value); + previous_previous_point = previous_point; + previous_point = current_point; + } + } + + template + void insert(const polygon_with_holes_type& polygon_with_holes_object, const property_type& property_value, bool is_hole, + polygon_with_holes_concept) { + insert(polygon_with_holes_object, property_value, is_hole, polygon_concept()); + for(typename polygon_with_holes_traits::iterator_holes_type itr = + begin_holes(polygon_with_holes_object); + itr != end_holes(polygon_with_holes_object); ++itr) { + insert(*itr, property_value, !is_hole, polygon_concept()); + } + } + + template + void insert(const rectangle_type& rectangle_object, const property_type& property_value, bool is_hole, + rectangle_concept ) { + polygon_90_data poly; + assign(poly, rectangle_object); + insert(poly, property_value, is_hole, polygon_concept()); + } + + public: //change to private when done testing + + static inline void create_vertex(property_merge_data& pmd, + const Point& current_point, + const Point& next_point, + direction_1d winding, + bool is_hole, const property_type& property) { + if(current_point == next_point) return; + vertex_property current_vertex; + current_vertex.first.first = current_point; + current_vertex.first.second = next_point; + current_vertex.second.first = property; + int multiplier = 1; + if(winding == CLOCKWISE) + multiplier = -1; + if(is_hole) + multiplier *= -1; + if(current_point < next_point) { + multiplier *= -1; + std::swap(current_vertex.first.first, current_vertex.first.second); + } + current_vertex.second.second = multiplier * (euclidean_distance(next_point, current_point, HORIZONTAL) == 0 ? -1: 1); + pmd.push_back(current_vertex); + //current_vertex.first.second = previous_point; + //current_vertex.second.second *= -1; + //pmd.push_back(current_vertex); + } + + static inline void sort_vertex_half_edges(vertex_data& vertex) { + less_half_edge_pair lessF(vertex.first); + polygon_sort(vertex.second.begin(), vertex.second.end(), lessF); + } + + class less_half_edge_pair { + private: + Point pt_; + public: + less_half_edge_pair(const Point& pt) : pt_(pt) {} + bool operator()(const half_edge& e1, const half_edge& e2) { + const Point& pt1 = e1.first; + const Point& pt2 = e2.first; + if(get(pt1, HORIZONTAL) == + get(pt_, HORIZONTAL)) { + //vertical edge is always largest + return false; + } + if(get(pt2, HORIZONTAL) == + get(pt_, HORIZONTAL)) { + //if half edge 1 is not vertical its slope is less than that of half edge 2 + return get(pt1, HORIZONTAL) != get(pt2, HORIZONTAL); + } + return scanline_base::less_slope(get(pt_, HORIZONTAL), + get(pt_, VERTICAL), pt1, pt2); + } + }; + + public: + //test functions + template + static stream_type& print (stream_type& o, const property_map& c) + { + o << "count: {"; + for(typename property_map::const_iterator itr = c.begin(); itr != c.end(); ++itr) { + o << ((*itr).first) << ":" << ((*itr).second) << " "; + } + return o << "} "; + } + + + template + static stream_type& print (stream_type& o, const half_edge& he) + { + o << "half edge: ("; + o << (he.first); + return o << ", " << (he.second) << ") "; + } + + template + static stream_type& print (stream_type& o, const vertex_property& c) + { + o << "vertex property: {"; + print(o, c.first); + o << ", " << c.second.first << ":" << c.second.second << " "; + return o; + } + + template + static stream_type& print (stream_type& o, const std::vector& hev) + { + o << "vertex properties: {"; + for(std::size_t i = 0; i < hev.size(); ++i) { + print(o, (hev[i])) << " "; + } + return o << "} "; + } + + template + static stream_type& print (stream_type& o, const std::vector& hev) + { + o << "half edges: {"; + for(std::size_t i = 0; i < hev.size(); ++i) { + print(o, (hev[i])) << " "; + } + return o << "} "; + } + + template + static stream_type& print (stream_type& o, const vertex_data& v) + { + return print(o << "vertex: <" << (v.first) << ", ", (v.second)) << "> "; + } + + template + static stream_type& print (stream_type& o, const std::vector& vv) + { + o << "vertices: {"; + for(std::size_t i = 0; i < vv.size(); ++i) { + print(o, (vv[i])) << " "; + } + return o << "} "; + } + + + + template + static inline bool test_insertion(stream_type& stdcout) { + property_merge si; + rectangle_data rect; + xl(rect, 0); + yl(rect, 1); + xh(rect, 10); + yh(rect, 11); + + si.insert(rect, 333); + print(stdcout, si.pmd) << "\n"; + + Point pts[4] = {Point(0, 0), Point(10,-3), Point(13, 8), Point(0, 0) }; + polygon_data poly; + property_merge si2; + poly.set(pts, pts+3); + si2.insert(poly, 444); + si2.sort_property_merge_data(); + print(stdcout, si2.pmd) << "\n"; + property_merge si3; + poly.set(pts, pts+4); + si3.insert(poly, 444); + si3.sort_property_merge_data(); + stdcout << (si2.pmd == si3.pmd) << "\n"; + std::reverse(pts, pts+4); + property_merge si4; + poly.set(pts, pts+4); + si4.insert(poly, 444); + si4.sort_property_merge_data(); + print(stdcout, si4.pmd) << "\n"; + stdcout << (si2.pmd == si4.pmd) << "\n"; + std::reverse(pts, pts+3); + property_merge si5; + poly.set(pts, pts+4); + si5.insert(poly, 444); + si5.sort_property_merge_data(); + stdcout << (si2.pmd == si5.pmd) << "\n"; + + return true; + } + + template + static inline bool test_merge(stream_type& stdcout) { + property_merge si; + rectangle_data rect; + xl(rect, 0); + yl(rect, 1); + xh(rect, 10); + yh(rect, 11); + + si.insert(rect, 333); + std::map, polygon_set_data > result; + si.merge(result); + print(stdcout, si.pmd) << "\n"; + polygon_set_data psd = (*(result.begin())).second; + std::vector > polys; + psd.get(polys); + if(polys.size() != 1) { + stdcout << "fail merge 1\n"; + return false; + } + stdcout << (polys[0]) << "\n"; + si.clear(); + std::vector pts; + pts.push_back(Point(0, 0)); + pts.push_back(Point(10, -10)); + pts.push_back(Point(10, 10)); + polygon_data poly; + poly.set(pts.begin(), pts.end()); + si.insert(poly, 444); + pts.clear(); + pts.push_back(Point(5, 0)); + pts.push_back(Point(-5, -10)); + pts.push_back(Point(-5, 10)); + poly.set(pts.begin(), pts.end()); + si.insert(poly, 444); + result.clear(); + si.merge(result); + print(stdcout, si.pmd) << "\n"; + psd = (*(result.begin())).second; + stdcout << psd << "\n"; + polys.clear(); + psd.get(polys); + if(polys.size() != 1) { + stdcout << "fail merge 2\n"; + return false; + } + //Polygon { -4 -1, 3 3, -2 3 } + //Polygon { 0 -4, -4 -2, -2 1 } + si.clear(); + pts.clear(); + pts.push_back(Point(-4, -1)); + pts.push_back(Point(3, 3)); + pts.push_back(Point(-2, 3)); + poly.set(pts.begin(), pts.end()); + si.insert(poly, 444); + pts.clear(); + pts.push_back(Point(0, -4)); + pts.push_back(Point(-4, -2)); + pts.push_back(Point(-2, 1)); + poly.set(pts.begin(), pts.end()); + si.insert(poly, 444); + result.clear(); + si.merge(result); + print(stdcout, si.pmd) << "\n"; + psd = (*(result.begin())).second; + stdcout << psd << "\n"; + polys.clear(); + psd.get(polys); + if(polys.size() != 1) { + stdcout << "fail merge 3\n"; + return false; + } + stdcout << "Polygon { -2 2, -2 2, 1 4 } \n"; + stdcout << "Polygon { 2 4, 2 -4, -3 1 } \n"; + si.clear(); + pts.clear(); + pts.push_back(Point(-2, 2)); + pts.push_back(Point(-2, 2)); + pts.push_back(Point(1, 4)); + poly.set(pts.begin(), pts.end()); + si.insert(poly, 444); + pts.clear(); + pts.push_back(Point(2, 4)); + pts.push_back(Point(2, -4)); + pts.push_back(Point(-3, 1)); + poly.set(pts.begin(), pts.end()); + si.insert(poly, 444); + result.clear(); + si.merge(result); + print(stdcout, si.pmd) << "\n"; + psd = (*(result.begin())).second; + stdcout << psd << "\n"; + polys.clear(); + psd.get(polys); + if(polys.size() != 1) { + stdcout << "fail merge 4\n"; + return false; + } + stdcout << (polys[0]) << "\n"; + stdcout << "Polygon { -4 0, -2 -3, 3 -4 } \n"; + stdcout << "Polygon { -1 1, 1 -2, -4 -3 } \n"; + si.clear(); + pts.clear(); + pts.push_back(Point(-4, 0)); + pts.push_back(Point(-2, -3)); + pts.push_back(Point(3, -4)); + poly.set(pts.begin(), pts.end()); + si.insert(poly, 444); + pts.clear(); + pts.push_back(Point(-1, 1)); + pts.push_back(Point(1, -2)); + pts.push_back(Point(-4, -3)); + poly.set(pts.begin(), pts.end()); + si.insert(poly, 444); + result.clear(); + si.merge(result); + print(stdcout, si.pmd) << "\n"; + psd = (*(result.begin())).second; + stdcout << psd << "\n"; + polys.clear(); + psd.get(polys); + if(polys.size() != 1) { + stdcout << "fail merge 5\n"; + return false; + } + stdcout << "Polygon { 2 2, -2 0, 0 1 } \n"; + stdcout << "Polygon { 4 -2, 3 -1, 2 3 } \n"; + si.clear(); + pts.clear(); + pts.push_back(Point(2, 2)); + pts.push_back(Point(-2, 0)); + pts.push_back(Point(0, 1)); + poly.set(pts.begin(), pts.end()); + si.insert(poly, 444); + pts.clear(); + pts.push_back(Point(4, -2)); + pts.push_back(Point(3, -1)); + pts.push_back(Point(2, 3)); + poly.set(pts.begin(), pts.end()); + si.insert(poly, 444); + result.clear(); + si.merge(result); + print(stdcout, si.pmd) << "\n"; + if(!result.empty()) { + psd = (*(result.begin())).second; + stdcout << psd << "\n"; + polys.clear(); + psd.get(polys); + if(polys.size() != 1) { + stdcout << "fail merge 6\n"; + return false; + } + stdcout << (polys[0]) << "\n"; + } + stdcout << "Polygon { 0 2, 3 -1, 4 1 } \n"; + stdcout << "Polygon { -4 3, 3 3, 4 2 } \n"; + si.clear(); + pts.clear(); + pts.push_back(Point(0, 2)); + pts.push_back(Point(3, -1)); + pts.push_back(Point(4, 1)); + poly.set(pts.begin(), pts.end()); + si.insert(poly, 444); + pts.clear(); + pts.push_back(Point(-4, 3)); + pts.push_back(Point(3, 3)); + pts.push_back(Point(4, 2)); + poly.set(pts.begin(), pts.end()); + si.insert(poly, 444); + result.clear(); + si.merge(result); + print(stdcout, si.pmd) << "\n"; + if(!result.empty()) { + psd = (*(result.begin())).second; + stdcout << psd << "\n"; + polys.clear(); + psd.get(polys); + if(polys.size() == 0) { + stdcout << "fail merge 7\n"; + return false; + } + stdcout << (polys[0]) << "\n"; + } +stdcout << "Polygon { 1 -2, -1 4, 3 -2 } \n"; +stdcout << "Polygon { 0 -3, 3 1, -3 -4 } \n"; + si.clear(); + pts.clear(); + pts.push_back(Point(1, -2)); + pts.push_back(Point(-1, 4)); + pts.push_back(Point(3, -2)); + poly.set(pts.begin(), pts.end()); + si.insert(poly, 444); + pts.clear(); + pts.push_back(Point(0, -3)); + pts.push_back(Point(3, 1)); + pts.push_back(Point(-3, -4)); + poly.set(pts.begin(), pts.end()); + si.insert(poly, 444); + result.clear(); + si.merge(result); + print(stdcout, si.pmd) << "\n"; + if(!result.empty()) { + psd = (*(result.begin())).second; + stdcout << psd << "\n"; + polys.clear(); + psd.get(polys); + if(polys.size() == 0) { + stdcout << "fail merge 8\n"; + return false; + } + stdcout << (polys[0]) << "\n"; + } +stdcout << "Polygon { 2 2, 3 0, -3 4 } \n"; +stdcout << "Polygon { -2 -2, 0 0, -1 -1 } \n"; + si.clear(); + pts.clear(); + pts.push_back(Point(2, 2)); + pts.push_back(Point(3, 0)); + pts.push_back(Point(-3, 4)); + poly.set(pts.begin(), pts.end()); + si.insert(poly, 444); + pts.clear(); + pts.push_back(Point(-2, -2)); + pts.push_back(Point(0, 0)); + pts.push_back(Point(-1, -1)); + poly.set(pts.begin(), pts.end()); + si.insert(poly, 444); + result.clear(); + si.merge(result); + print(stdcout, si.pmd) << "\n"; + if(!result.empty()) { + psd = (*(result.begin())).second; + stdcout << psd << "\n"; + polys.clear(); + psd.get(polys); + if(polys.size() == 0) { + stdcout << "fail merge 9\n"; + return false; + } + stdcout << (polys[0]) << "\n"; + } + si.clear(); + pts.clear(); + //5624841,17616200,75000,9125000 + //pts.push_back(Point(5624841,75000)); + //pts.push_back(Point(5624841,9125000)); + //pts.push_back(Point(17616200,9125000)); + //pts.push_back(Point(17616200,75000)); +pts.push_back(Point(12262940, 6652520 )); pts.push_back(Point(12125750, 6652520 )); pts.push_back(Point(12121272, 6652961 )); pts.push_back(Point(12112981, 6656396 )); pts.push_back(Point(12106636, 6662741 )); pts.push_back(Point(12103201, 6671032 )); pts.push_back(Point(12103201, 6680007 )); pts.push_back(Point(12106636, 6688298 )); +pts.push_back(Point(12109500, 6691780 )); pts.push_back(Point(12748600, 7330890 )); pts.push_back(Point(15762600, 7330890 )); pts.push_back(Point(15904620, 7472900 )); pts.push_back(Point(15909200, 7473030 )); pts.push_back(Point(15935830, 7476006 )); pts.push_back(Point(15992796, 7499602 )); pts.push_back(Point(16036397, 7543203 )); +pts.push_back(Point(16059993, 7600169 )); pts.push_back(Point(16059993, 7661830 )); pts.push_back(Point(16036397, 7718796 )); pts.push_back(Point(15992796, 7762397 )); pts.push_back(Point(15935830, 7785993 )); pts.push_back(Point(15874169, 7785993 )); pts.push_back(Point(15817203, 7762397 )); pts.push_back(Point(15773602, 7718796 )); +pts.push_back(Point(15750006, 7661830 )); pts.push_back(Point(15747030, 7635200 )); pts.push_back(Point(15746900, 7630620 )); pts.push_back(Point(15670220, 7553930 )); pts.push_back(Point(14872950, 7553930 )); pts.push_back(Point(14872950, 7626170 )); +pts.push_back(Point(14869973, 7661280 )); pts.push_back(Point(14846377, 7718246 )); pts.push_back(Point(14802776, 7761847 )); pts.push_back(Point(14745810, 7785443 )); pts.push_back(Point(14684149, 7785443 )); pts.push_back(Point(14627183, 7761847 )); pts.push_back(Point(14583582, 7718246 )); +pts.push_back(Point(14559986, 7661280 )); pts.push_back(Point(14557070, 7636660 )); pts.push_back(Point(14556670, 7625570 )); pts.push_back(Point(13703330, 7625570 )); pts.push_back(Point(13702930, 7636660 )); pts.push_back(Point(13699993, 7661830 )); pts.push_back(Point(13676397, 7718796 )); +pts.push_back(Point(13632796, 7762397 )); pts.push_back(Point(13575830, 7785993 )); pts.push_back(Point(13514169, 7785993 )); pts.push_back(Point(13457203, 7762397 )); pts.push_back(Point(13436270, 7745670 )); pts.push_back(Point(13432940, 7742520 )); pts.push_back(Point(12963760, 7742520 )); +pts.push_back(Point(12959272, 7742961 )); pts.push_back(Point(12950981, 7746396 )); pts.push_back(Point(12944636, 7752741 )); pts.push_back(Point(12941201, 7761032 )); pts.push_back(Point(12941201, 7770007 )); pts.push_back(Point(12944636, 7778298 )); pts.push_back(Point(12947490, 7781780 )); +pts.push_back(Point(13425330, 8259620 )); pts.push_back(Point(15601330, 8259620 )); pts.push_back(Point(15904620, 8562900 )); pts.push_back(Point(15909200, 8563030 )); pts.push_back(Point(15935830, 8566006 )); pts.push_back(Point(15992796, 8589602 )); pts.push_back(Point(16036397, 8633203 )); +pts.push_back(Point(16059993, 8690169 )); pts.push_back(Point(16059993, 8751830 )); pts.push_back(Point(16036397, 8808796 )); pts.push_back(Point(15992796, 8852397 )); pts.push_back(Point(15935830, 8875993 )); pts.push_back(Point(15874169, 8875993 )); pts.push_back(Point(15817203, 8852397 )); pts.push_back(Point(15773602, 8808796 )); +pts.push_back(Point(15750006, 8751830 )); pts.push_back(Point(15747030, 8725200 )); pts.push_back(Point(15746900, 8720620 )); pts.push_back(Point(15508950, 8482660 )); pts.push_back(Point(14689890, 8482660 )); pts.push_back(Point(14685412, 8483101 )); pts.push_back(Point(14677121, 8486536 )); +pts.push_back(Point(14670776, 8492881 )); pts.push_back(Point(14667341, 8501172 )); pts.push_back(Point(14667341, 8510147 )); pts.push_back(Point(14670776, 8518438 )); pts.push_back(Point(14673630, 8521920 )); pts.push_back(Point(14714620, 8562900 )); pts.push_back(Point(14719200, 8563030 )); pts.push_back(Point(14745830, 8566006 )); +pts.push_back(Point(14802796, 8589602 )); pts.push_back(Point(14846397, 8633203 )); pts.push_back(Point(14869993, 8690169 )); pts.push_back(Point(14869993, 8751830 )); pts.push_back(Point(14846397, 8808796 )); pts.push_back(Point(14802796, 8852397 )); pts.push_back(Point(14745830, 8875993 )); pts.push_back(Point(14684169, 8875993 )); +pts.push_back(Point(14627203, 8852397 )); pts.push_back(Point(14583602, 8808796 )); pts.push_back(Point(14560006, 8751830 )); pts.push_back(Point(14557030, 8725200 )); pts.push_back(Point(14556900, 8720620 )); pts.push_back(Point(14408270, 8571980 )); pts.push_back(Point(13696320, 8571980 )); pts.push_back(Point(13696320, 8675520 )); +pts.push_back(Point(13699963, 8690161 )); pts.push_back(Point(13699963, 8751818 )); pts.push_back(Point(13676368, 8808781 )); pts.push_back(Point(13632771, 8852378 )); pts.push_back(Point(13575808, 8875973 )); pts.push_back(Point(13514151, 8875973 )); pts.push_back(Point(13457188, 8852378 )); pts.push_back(Point(13436270, 8835670 )); pts.push_back(Point(13432940, 8832520 )); +pts.push_back(Point(13281760, 8832520 )); pts.push_back(Point(13277272, 8832961 )); pts.push_back(Point(13268981, 8836396 )); pts.push_back(Point(13262636, 8842741 )); pts.push_back(Point(13259201, 8851032 )); pts.push_back(Point(13259201, 8860007 )); pts.push_back(Point(13262636, 8868298 )); pts.push_back(Point(13265500, 8871780 )); +pts.push_back(Point(13518710, 9125000 )); pts.push_back(Point(16270720, 9125000 )); pts.push_back(Point(16270720, 8939590 )); pts.push_back(Point(17120780, 8939590 )); pts.push_back(Point(17120780, 9125000 )); pts.push_back(Point(17616200, 9125000 )); pts.push_back(Point(17616200, 75000 )); pts.push_back(Point(16024790, 75000 )); +pts.push_back(Point(16021460, 80700 )); pts.push_back(Point(16016397, 88796 )); pts.push_back(Point(15972796, 132397 )); pts.push_back(Point(15915830, 155993 )); pts.push_back(Point(15908730, 157240 )); pts.push_back(Point(15905000, 157800 )); pts.push_back(Point(15516800, 546000 )); pts.push_back(Point(15905000, 934200 )); +pts.push_back(Point(15908730, 934760 )); pts.push_back(Point(15915830, 936006 )); pts.push_back(Point(15972796, 959602 )); pts.push_back(Point(16016397, 1003203 )); pts.push_back(Point(16039993, 1060169 )); pts.push_back(Point(16039993, 1121830 )); pts.push_back(Point(16016397, 1178796 )); pts.push_back(Point(15972796, 1222397 )); +pts.push_back(Point(15915830, 1245993 )); pts.push_back(Point(15854169, 1245993 )); pts.push_back(Point(15797203, 1222397 )); pts.push_back(Point(15753602, 1178796 )); pts.push_back(Point(15730006, 1121830 )); pts.push_back(Point(15728760, 1114730 )); pts.push_back(Point(15728200, 1111000 )); pts.push_back(Point(15363500, 746300 )); +pts.push_back(Point(14602620, 746300 )); pts.push_back(Point(14598142, 746741 )); pts.push_back(Point(14589851, 750176 )); pts.push_back(Point(14583506, 756521 )); pts.push_back(Point(14580071, 764812 )); pts.push_back(Point(14580071, 773787 )); pts.push_back(Point(14583506, 782078 )); pts.push_back(Point(14586360, 785560 )); +pts.push_back(Point(14586370, 785560 )); pts.push_back(Point(14735000, 934200 )); pts.push_back(Point(14738730, 934760 )); pts.push_back(Point(14745830, 936006 )); pts.push_back(Point(14802796, 959602 )); pts.push_back(Point(14846397, 1003203 )); pts.push_back(Point(14869993, 1060169 )); +pts.push_back(Point(14870450, 1062550 )); pts.push_back(Point(14872170, 1071980 )); pts.push_back(Point(14972780, 1071980 )); pts.push_back(Point(15925000, 2024200 )); pts.push_back(Point(15928730, 2024760 )); pts.push_back(Point(15935830, 2026006 )); pts.push_back(Point(15992796, 2049602 )); +pts.push_back(Point(16036397, 2093203 )); pts.push_back(Point(16059993, 2150169 )); pts.push_back(Point(16059993, 2211830 )); pts.push_back(Point(16036397, 2268796 )); pts.push_back(Point(15992796, 2312397 )); pts.push_back(Point(15935830, 2335993 )); pts.push_back(Point(15874169, 2335993 )); +pts.push_back(Point(15817203, 2312397 )); pts.push_back(Point(15773602, 2268796 )); pts.push_back(Point(15750006, 2211830 )); pts.push_back(Point(15748760, 2204730 )); pts.push_back(Point(15748200, 2201000 )); pts.push_back(Point(14869220, 1322020 )); pts.push_back(Point(14088350, 1322020 )); +pts.push_back(Point(14083862, 1322461 )); pts.push_back(Point(14075571, 1325896 )); pts.push_back(Point(14069226, 1332241 )); pts.push_back(Point(14065791, 1340532 )); pts.push_back(Point(14065791, 1349507 )); pts.push_back(Point(14069226, 1357798 )); pts.push_back(Point(14072080, 1361280 )); +pts.push_back(Point(14072090, 1361280 )); pts.push_back(Point(14735000, 2024200 )); pts.push_back(Point(14738730, 2024760 )); pts.push_back(Point(14745830, 2026006 )); pts.push_back(Point(14802796, 2049602 )); pts.push_back(Point(14846397, 2093203 )); pts.push_back(Point(14869993, 2150169 )); +pts.push_back(Point(14869993, 2211830 )); pts.push_back(Point(14846397, 2268796 )); pts.push_back(Point(14802796, 2312397 )); pts.push_back(Point(14745830, 2335993 )); pts.push_back(Point(14684169, 2335993 )); pts.push_back(Point(14627203, 2312397 )); pts.push_back(Point(14583602, 2268796 )); pts.push_back(Point(14560006, 2211830 )); +pts.push_back(Point(14558760, 2204730 )); pts.push_back(Point(14558200, 2201000 )); pts.push_back(Point(13752220, 1395020 )); pts.push_back(Point(12991340, 1395020 )); pts.push_back(Point(12986862, 1395461 )); pts.push_back(Point(12978571, 1398896 )); pts.push_back(Point(12972226, 1405241 )); +pts.push_back(Point(12968791, 1413532 )); pts.push_back(Point(12968791, 1422507 )); pts.push_back(Point(12972226, 1430798 )); pts.push_back(Point(12975080, 1434280 )); pts.push_back(Point(12975090, 1434280 )); pts.push_back(Point(13565000, 2024200 )); pts.push_back(Point(13568730, 2024760 )); pts.push_back(Point(13575830, 2026006 )); +pts.push_back(Point(13632796, 2049602 )); pts.push_back(Point(13676397, 2093203 )); pts.push_back(Point(13699993, 2150169 )); pts.push_back(Point(13699993, 2211830 )); pts.push_back(Point(13676397, 2268796 )); pts.push_back(Point(13632796, 2312397 )); pts.push_back(Point(13575830, 2335993 )); +pts.push_back(Point(13514169, 2335993 )); pts.push_back(Point(13457203, 2312397 )); pts.push_back(Point(13413602, 2268796 )); pts.push_back(Point(13390006, 2211830 )); pts.push_back(Point(13388760, 2204730 )); pts.push_back(Point(13388200, 2201000 )); pts.push_back(Point(12655220, 1468020 )); +pts.push_back(Point(11894340, 1468020 )); pts.push_back(Point(11889862, 1468461 )); pts.push_back(Point(11881571, 1471896 )); pts.push_back(Point(11875226, 1478241 )); pts.push_back(Point(11871791, 1486532 )); pts.push_back(Point(11871791, 1495507 )); +pts.push_back(Point(11875226, 1503798 )); pts.push_back(Point(11878090, 1507280 )); pts.push_back(Point(12395000, 2024200 )); pts.push_back(Point(12398730, 2024760 )); pts.push_back(Point(12405830, 2026006 )); pts.push_back(Point(12462796, 2049602 )); pts.push_back(Point(12506397, 2093203 )); +pts.push_back(Point(12529993, 2150169 )); pts.push_back(Point(12529993, 2211830 )); pts.push_back(Point(12506397, 2268796 )); pts.push_back(Point(12462796, 2312397 )); pts.push_back(Point(12405830, 2335993 )); pts.push_back(Point(12344169, 2335993 )); +pts.push_back(Point(12287203, 2312397 )); pts.push_back(Point(12243602, 2268796 )); pts.push_back(Point(12220006, 2211830 )); pts.push_back(Point(12218760, 2204730 )); pts.push_back(Point(12218200, 2201000 )); pts.push_back(Point(11558220, 1541020 )); +pts.push_back(Point(10797340, 1541020 )); pts.push_back(Point(10792862, 1541461 )); pts.push_back(Point(10784571, 1544896 )); pts.push_back(Point(10778226, 1551241 )); pts.push_back(Point(10774791, 1559532 )); pts.push_back(Point(10774791, 1568507 )); pts.push_back(Point(10778226, 1576798 )); pts.push_back(Point(10781080, 1580280 )); +pts.push_back(Point(10781090, 1580280 )); pts.push_back(Point(11225000, 2024200 )); pts.push_back(Point(11228730, 2024760 )); pts.push_back(Point(11235830, 2026006 )); pts.push_back(Point(11292796, 2049602 )); pts.push_back(Point(11336397, 2093203 )); pts.push_back(Point(11359993, 2150169 )); +pts.push_back(Point(11359993, 2211830 )); pts.push_back(Point(11336397, 2268796 )); pts.push_back(Point(11292796, 2312397 )); pts.push_back(Point(11235830, 2335993 )); pts.push_back(Point(11174169, 2335993 )); pts.push_back(Point(11117203, 2312397 )); pts.push_back(Point(11073602, 2268796 )); pts.push_back(Point(11050006, 2211830 )); +pts.push_back(Point(11048760, 2204730 )); pts.push_back(Point(11048200, 2201000 )); pts.push_back(Point(10461220, 1614020 )); pts.push_back(Point( 5647400, 1614020 )); pts.push_back(Point( 5642912, 1614461 )); +pts.push_back(Point( 5634621, 1617896 )); pts.push_back(Point( 5628276, 1624241 )); pts.push_back(Point( 5624841, 1632532 )); pts.push_back(Point( 5624841, 1641507 )); pts.push_back(Point( 5628276, 1649798 )); pts.push_back(Point( 5631130, 1653280 )); +pts.push_back(Point( 5688490, 1710640 )); pts.push_back(Point( 9722350, 1710640 )); pts.push_back(Point(10034620, 2022900 )); pts.push_back(Point(10039200, 2023030 )); pts.push_back(Point(10065830, 2026006 )); pts.push_back(Point(10122796, 2049602 )); +pts.push_back(Point(10166397, 2093203 )); pts.push_back(Point(10189993, 2150169 )); pts.push_back(Point(10189993, 2211830 )); pts.push_back(Point(10166397, 2268796 )); pts.push_back(Point(10158620, 2279450 )); pts.push_back(Point(10158620, 2404900 )); pts.push_back(Point(10548950, 2795240 )); +pts.push_back(Point(15586950, 2795240 )); pts.push_back(Point(15904620, 3112900 )); pts.push_back(Point(15909200, 3113030 )); pts.push_back(Point(15935830, 3116006 )); pts.push_back(Point(15992796, 3139602 )); pts.push_back(Point(16036397, 3183203 )); pts.push_back(Point(16059993, 3240169 )); pts.push_back(Point(16059993, 3301830 )); +pts.push_back(Point(16036397, 3358796 )); pts.push_back(Point(15992796, 3402397 )); pts.push_back(Point(15935830, 3425993 )); pts.push_back(Point(15874169, 3425993 )); pts.push_back(Point(15817203, 3402397 )); pts.push_back(Point(15773602, 3358796 )); pts.push_back(Point(15750006, 3301830 )); pts.push_back(Point(15747030, 3275200 )); +pts.push_back(Point(15746900, 3270620 )); pts.push_back(Point(15494570, 3018280 )); pts.push_back(Point(14675510, 3018280 )); pts.push_back(Point(14671032, 3018721 )); pts.push_back(Point(14662741, 3022156 )); pts.push_back(Point(14656396, 3028501 )); pts.push_back(Point(14652961, 3036792 )); +pts.push_back(Point(14652961, 3045767 )); pts.push_back(Point(14656396, 3054058 )); pts.push_back(Point(14659260, 3057540 )); pts.push_back(Point(14714620, 3112900 )); pts.push_back(Point(14719200, 3113030 )); pts.push_back(Point(14745830, 3116006 )); pts.push_back(Point(14802796, 3139602 )); +pts.push_back(Point(14846397, 3183203 )); pts.push_back(Point(14869993, 3240169 )); pts.push_back(Point(14869993, 3301830 )); pts.push_back(Point(14846397, 3358796 )); pts.push_back(Point(14802796, 3402397 )); pts.push_back(Point(14745830, 3425993 )); pts.push_back(Point(14684169, 3425993 )); pts.push_back(Point(14627203, 3402397 )); +pts.push_back(Point(14583602, 3358796 )); pts.push_back(Point(14560006, 3301830 )); pts.push_back(Point(14557030, 3275200 )); pts.push_back(Point(14556900, 3270620 )); pts.push_back(Point(14370700, 3084410 )); pts.push_back(Point(13702830, 3084410 )); pts.push_back(Point(13702830, 3263160 )); +pts.push_back(Point(13700003, 3302210 )); pts.push_back(Point(13676407, 3359176 )); pts.push_back(Point(13632806, 3402777 )); pts.push_back(Point(13575840, 3426373 )); pts.push_back(Point(13514179, 3426373 )); pts.push_back(Point(13457213, 3402777 )); pts.push_back(Point(13413612, 3359176 )); +pts.push_back(Point(13390016, 3302210 )); pts.push_back(Point(13387030, 3275200 )); pts.push_back(Point(13386900, 3270620 )); pts.push_back(Point(13266840, 3150550 )); pts.push_back(Point(12532920, 3150550 )); pts.push_back(Point(12532920, 3264990 )); pts.push_back(Point(12529993, 3301820 )); +pts.push_back(Point(12506397, 3358786 )); pts.push_back(Point(12462796, 3402387 )); pts.push_back(Point(12405830, 3425983 )); pts.push_back(Point(12344169, 3425983 )); pts.push_back(Point(12287203, 3402387 )); pts.push_back(Point(12243602, 3358786 )); pts.push_back(Point(12220006, 3301820 )); pts.push_back(Point(12217030, 3275200 )); +pts.push_back(Point(12216900, 3270620 )); pts.push_back(Point(12157460, 3211170 )); pts.push_back(Point(11362030, 3211170 )); pts.push_back(Point(11360250, 3220520 )); pts.push_back(Point(11359993, 3221830 )); pts.push_back(Point(11336397, 3278796 )); +pts.push_back(Point(11292796, 3322397 )); pts.push_back(Point(11235830, 3345993 )); pts.push_back(Point(11174169, 3345993 )); pts.push_back(Point(11117203, 3322397 )); pts.push_back(Point(11096270, 3305670 )); pts.push_back(Point(11092940, 3302520 )); pts.push_back(Point(10680760, 3302520 )); +pts.push_back(Point(10676272, 3302961 )); pts.push_back(Point(10667981, 3306396 )); pts.push_back(Point(10661636, 3312741 )); pts.push_back(Point(10658201, 3321032 )); pts.push_back(Point(10658201, 3330007 )); pts.push_back(Point(10661636, 3338298 )); pts.push_back(Point(10664500, 3341780 )); +pts.push_back(Point(11264260, 3941550 )); pts.push_back(Point(15643260, 3941550 )); pts.push_back(Point(15904620, 4202900 )); pts.push_back(Point(15909200, 4203030 )); pts.push_back(Point(15935830, 4206006 )); pts.push_back(Point(15992796, 4229602 )); +pts.push_back(Point(16036397, 4273203 )); pts.push_back(Point(16059993, 4330169 )); pts.push_back(Point(16059993, 4391830 )); pts.push_back(Point(16036397, 4448796 )); pts.push_back(Point(15992796, 4492397 )); +pts.push_back(Point(15935830, 4515993 )); pts.push_back(Point(15874169, 4515993 )); pts.push_back(Point(15817203, 4492397 )); pts.push_back(Point(15773602, 4448796 )); pts.push_back(Point(15750006, 4391830 )); pts.push_back(Point(15747030, 4365200 )); pts.push_back(Point(15746900, 4360620 )); +pts.push_back(Point(15550880, 4164590 )); pts.push_back(Point(14825070, 4164590 )); pts.push_back(Point(14825070, 4247610 )); pts.push_back(Point(14846397, 4273213 )); pts.push_back(Point(14869993, 4330179 )); pts.push_back(Point(14869993, 4391840 )); pts.push_back(Point(14846397, 4448806 )); +pts.push_back(Point(14802796, 4492407 )); pts.push_back(Point(14745830, 4516003 )); pts.push_back(Point(14684169, 4516003 )); pts.push_back(Point(14627203, 4492407 )); pts.push_back(Point(14583602, 4448806 )); pts.push_back(Point(14560006, 4391840 )); pts.push_back(Point(14557030, 4365200 )); +pts.push_back(Point(14556900, 4360620 )); pts.push_back(Point(14432520, 4236230 )); pts.push_back(Point(13702830, 4236230 )); pts.push_back(Point(13702830, 4352930 )); pts.push_back(Point(13699993, 4391750 )); pts.push_back(Point(13676397, 4448716 )); +pts.push_back(Point(13632796, 4492317 )); pts.push_back(Point(13575830, 4515913 )); pts.push_back(Point(13514169, 4515913 )); pts.push_back(Point(13457203, 4492317 )); pts.push_back(Point(13413602, 4448716 )); pts.push_back(Point(13390006, 4391750 )); pts.push_back(Point(13387030, 4365200 )); +pts.push_back(Point(13386900, 4360620 )); pts.push_back(Point(13334170, 4307880 )); pts.push_back(Point(12532990, 4307880 )); pts.push_back(Point(12532990, 4357550 )); pts.push_back(Point(12529993, 4391760 )); pts.push_back(Point(12506397, 4448726 )); pts.push_back(Point(12462796, 4492327 )); +pts.push_back(Point(12405830, 4515923 )); pts.push_back(Point(12344169, 4515923 )); pts.push_back(Point(12287203, 4492327 )); pts.push_back(Point(12243602, 4448726 )); pts.push_back(Point(12220006, 4391760 )); pts.push_back(Point(12217970, 4378710 )); pts.push_back(Point(12216810, 4368500 )); +pts.push_back(Point(11363190, 4368500 )); pts.push_back(Point(11362030, 4378710 )); pts.push_back(Point(11359983, 4391828 )); pts.push_back(Point(11336388, 4448791 )); pts.push_back(Point(11292791, 4492388 )); pts.push_back(Point(11235828, 4515983 )); pts.push_back(Point(11174171, 4515983 )); pts.push_back(Point(11117208, 4492388 )); +pts.push_back(Point(11096270, 4475670 )); pts.push_back(Point(11092940, 4472520 )); pts.push_back(Point(11057750, 4472520 )); pts.push_back(Point(11053272, 4472961 )); pts.push_back(Point(11044981, 4476396 )); pts.push_back(Point(11038636, 4482741 )); pts.push_back(Point(11035201, 4491032 )); +pts.push_back(Point(11035201, 4500007 )); pts.push_back(Point(11038636, 4508298 )); pts.push_back(Point(11041490, 4511780 )); pts.push_back(Point(11573490, 5043780 )); pts.push_back(Point(15655490, 5043780 )); pts.push_back(Point(15904620, 5292900 )); +pts.push_back(Point(15909200, 5293030 )); pts.push_back(Point(15935830, 5296006 )); pts.push_back(Point(15992796, 5319602 )); pts.push_back(Point(16036397, 5363203 )); pts.push_back(Point(16059993, 5420169 )); pts.push_back(Point(16059993, 5481830 )); pts.push_back(Point(16036397, 5538796 )); +pts.push_back(Point(15992796, 5582397 )); pts.push_back(Point(15935830, 5605993 )); pts.push_back(Point(15874169, 5605993 )); pts.push_back(Point(15817203, 5582397 )); pts.push_back(Point(15773602, 5538796 )); pts.push_back(Point(15750006, 5481830 )); pts.push_back(Point(15747030, 5455200 )); +pts.push_back(Point(15746900, 5450620 )); pts.push_back(Point(15563110, 5266820 )); pts.push_back(Point(14857380, 5266820 )); pts.push_back(Point(14857380, 5382430 )); pts.push_back(Point(14869993, 5420179 )); pts.push_back(Point(14869993, 5481840 )); pts.push_back(Point(14846397, 5538806 )); pts.push_back(Point(14802796, 5582407 )); +pts.push_back(Point(14745830, 5606003 )); pts.push_back(Point(14684169, 5606003 )); pts.push_back(Point(14627203, 5582407 )); pts.push_back(Point(14583602, 5538806 )); pts.push_back(Point(14560006, 5481840 )); pts.push_back(Point(14557030, 5455200 )); pts.push_back(Point(14556900, 5450620 )); pts.push_back(Point(14444750, 5338460 )); +pts.push_back(Point(13702890, 5338460 )); pts.push_back(Point(13702890, 5364400 )); pts.push_back(Point(13699993, 5401800 )); pts.push_back(Point(13676397, 5458766 )); pts.push_back(Point(13632796, 5502367 )); pts.push_back(Point(13575830, 5525963 )); pts.push_back(Point(13514169, 5525963 )); pts.push_back(Point(13457203, 5502367 )); +pts.push_back(Point(13413602, 5458766 )); pts.push_back(Point(13390006, 5401800 )); pts.push_back(Point(13389230, 5397620 )); pts.push_back(Point(13387590, 5388060 )); pts.push_back(Point(12532960, 5388060 )); pts.push_back(Point(12532960, 5446220 )); pts.push_back(Point(12529993, 5481820 )); +pts.push_back(Point(12506397, 5538786 )); pts.push_back(Point(12462796, 5582387 )); pts.push_back(Point(12405830, 5605983 )); pts.push_back(Point(12344169, 5605983 )); pts.push_back(Point(12287203, 5582387 )); pts.push_back(Point(12266270, 5565670 )); pts.push_back(Point(12262940, 5562520 )); pts.push_back(Point(11737750, 5562520 )); +pts.push_back(Point(11733272, 5562961 )); pts.push_back(Point(11724981, 5566396 )); pts.push_back(Point(11718636, 5572741 )); pts.push_back(Point(11715201, 5581032 )); pts.push_back(Point(11715201, 5590007 )); pts.push_back(Point(11718636, 5598298 )); pts.push_back(Point(11721500, 5601780 )); +pts.push_back(Point(12287760, 6168050 )); pts.push_back(Point(15689760, 6168050 )); pts.push_back(Point(15904620, 6382900 )); pts.push_back(Point(15909200, 6383030 )); pts.push_back(Point(15935830, 6386006 )); pts.push_back(Point(15992796, 6409602 )); +pts.push_back(Point(16036397, 6453203 )); pts.push_back(Point(16059993, 6510169 )); pts.push_back(Point(16059993, 6571830 )); pts.push_back(Point(16036397, 6628796 )); pts.push_back(Point(15992796, 6672397 )); pts.push_back(Point(15935830, 6695993 )); pts.push_back(Point(15874169, 6695993 )); +pts.push_back(Point(15817203, 6672397 )); pts.push_back(Point(15773602, 6628796 )); pts.push_back(Point(15750006, 6571830 )); pts.push_back(Point(15747030, 6545200 )); pts.push_back(Point(15746900, 6540620 )); pts.push_back(Point(15597380, 6391090 )); pts.push_back(Point(14858060, 6391090 )); +pts.push_back(Point(14858060, 6473860 )); pts.push_back(Point(14869993, 6510179 )); pts.push_back(Point(14869993, 6571840 )); pts.push_back(Point(14846397, 6628806 )); pts.push_back(Point(14802796, 6672407 )); pts.push_back(Point(14745830, 6696003 )); pts.push_back(Point(14684169, 6696003 )); +pts.push_back(Point(14627203, 6672407 )); pts.push_back(Point(14583602, 6628806 )); pts.push_back(Point(14560006, 6571840 )); pts.push_back(Point(14557030, 6545200 )); pts.push_back(Point(14556900, 6540620 )); pts.push_back(Point(14479020, 6462730 )); +pts.push_back(Point(13702990, 6462730 )); pts.push_back(Point(13702990, 6537170 )); pts.push_back(Point(13700003, 6571840 )); pts.push_back(Point(13676407, 6628806 )); pts.push_back(Point(13632806, 6672407 )); pts.push_back(Point(13575840, 6696003 )); +pts.push_back(Point(13514179, 6696003 )); pts.push_back(Point(13457213, 6672407 )); pts.push_back(Point(13413612, 6628806 )); pts.push_back(Point(13390016, 6571840 )); pts.push_back(Point(13387040, 6545550 )); pts.push_back(Point(13386710, 6534380 )); +pts.push_back(Point(12533290, 6534380 )); pts.push_back(Point(12532960, 6545550 )); pts.push_back(Point(12529983, 6571828 )); pts.push_back(Point(12506388, 6628791 )); pts.push_back(Point(12462791, 6672388 )); pts.push_back(Point(12405828, 6695983 )); +pts.push_back(Point(12344171, 6695983 )); pts.push_back(Point(12287208, 6672388 )); pts.push_back(Point(12266270, 6655670 )); + poly.set(pts.begin(), pts.end()); + si.insert(poly, 444); + result.clear(); + si.merge(result); + si.verify1(); + print(stdcout, si.pmd) << "\n"; + if(!result.empty()) { + psd = (*(result.begin())).second; + stdcout << psd << "\n"; + std::vector outpts; + for(typename polygon_set_data::iterator_type itr = psd.begin(); + itr != psd.end(); ++itr) { + outpts.push_back((*itr).first.first); + outpts.push_back((*itr).first.second); + } + polygon_sort(outpts.begin(), outpts.end()); + for(std::size_t i = 0; i < outpts.size(); i+=2) { + if(outpts[i] != outpts[i+1]) { + stdcout << "Polygon set not a closed figure\n"; + stdcout << i << "\n"; + stdcout << outpts[i] << " " << outpts[i+1] << "\n"; + return 0; + } + } + polys.clear(); + psd.get(polys); + if(polys.size() == 0) { + stdcout << "fail merge 10\n"; + return false; + } + stdcout << (polys[0]) << "\n"; + } + for(unsigned int i = 0; i < 10; ++i) { + stdcout << "random case # " << i << "\n"; + si.clear(); + pts.clear(); + pts.push_back(Point(rand()%9-4, rand()%9-4)); + pts.push_back(Point(rand()%9-4, rand()%9-4)); + pts.push_back(Point(rand()%9-4, rand()%9-4)); + polygon_data poly1; + poly1.set(pts.begin(), pts.end()); + stdcout << poly1 << "\n"; + si.insert(poly1, 444); + pts.clear(); + pts.push_back(Point(rand()%9-4, rand()%9-4)); + pts.push_back(Point(rand()%9-4, rand()%9-4)); + pts.push_back(Point(rand()%9-4, rand()%9-4)); + polygon_data poly2; + poly2.set(pts.begin(), pts.end()); + stdcout << poly2 << "\n"; + si.insert(poly2, 444); + result.clear(); + si.merge(result); + print(stdcout, si.pmd) << "\n"; + if(!result.empty()) { + psd = (*(result.begin())).second; + stdcout << psd << "\n"; + polys.clear(); + psd.get(polys); + if(polys.size() == 0) { + si.clear(); + si.insert(poly1, 333); + result.clear(); + si.merge(result); + psd = (*(result.begin())).second; + std::vector > polys1; + psd.get(polys1); + si.clear(); + si.insert(poly2, 333); + result.clear(); + si.merge(result); + psd = (*(result.begin())).second; + std::vector > polys2; + psd.get(polys2); + if(!polys1.empty() || !polys2.empty()) { + stdcout << "fail random merge " << i << "\n"; + return false; + } + } + } + if(!polys.empty()) + stdcout << polys.size() << ": " << (polys[0]) << "\n"; + } + return true; + } + + template + static inline bool check_rectangle_trio(rectangle_data rect1, rectangle_data rect2, rectangle_data rect3, stream_type& stdcout) { + property_merge si; + std::map, polygon_set_data > result; + std::vector > polys; + property_merge_90 si90; + std::map, polygon_90_set_data > result90; + std::vector > polys90; + si.insert(rect1, 111); + si90.insert(rect1, 111); + stdcout << rect1 << "\n"; + si.insert(rect2, 222); + si90.insert(rect2, 222); + stdcout << rect2 << "\n"; + si.insert(rect3, 333); + si90.insert(rect3, 333); + stdcout << rect3 << "\n"; + si.merge(result); + si90.merge(result90); + if(result.size() != result90.size()) { + stdcout << "merge failed with size mismatch\n"; + return 0; + } + typename std::map, polygon_90_set_data >::iterator itr90 = result90.begin(); + for(typename std::map, polygon_set_data >::iterator itr = result.begin(); + itr != result.end(); ++itr) { + for(typename std::set::const_iterator set_itr = (*itr).first.begin(); + set_itr != (*itr).first.end(); ++set_itr) { + stdcout << (*set_itr) << " "; + } stdcout << ") \n"; + polygon_set_data psd = (*itr).second; + polygon_90_set_data psd90 = (*itr90).second; + polys.clear(); + polys90.clear(); + psd.get(polys); + psd90.get(polys90); + if(polys.size() != polys90.size()) { + stdcout << "merge failed with polygon count mismatch\n"; + stdcout << psd << "\n"; + for(std::size_t j = 0; j < polys.size(); ++j) { + stdcout << polys[j] << "\n"; + } + stdcout << "reference\n"; + for(std::size_t j = 0; j < polys90.size(); ++j) { + stdcout << polys90[j] << "\n"; + } + return 0; + } + bool failed = false; + for(std::size_t j = 0; j < polys.size(); ++j) { + stdcout << polys[j] << "\n"; + stdcout << polys90[j] << "\n"; +#ifdef BOOST_POLYGON_ICC +#pragma warning (push) +#pragma warning (disable:1572) +#endif + if(area(polys[j]) != area(polys90[j])) { +#ifdef BOOST_POLYGON_ICC +#pragma warning (pop) +#endif + stdcout << "merge failed with area mismatch\n"; + failed = true; + } + } + if(failed) return 0; + ++itr90; + } + return true; + } + + template + static inline bool test_manhattan_intersection(stream_type& stdcout) { + rectangle_data rect1, rect2, rect3; + set_points(rect1, (Point(-1, 2)), (Point(1, 4))); + set_points(rect2, (Point(-1, 2)), (Point(2, 3))); + set_points(rect3, (Point(-3, 0)), (Point(4, 2))); + if(!check_rectangle_trio(rect1, rect2, rect3, stdcout)) { + return false; + } + for(unsigned int i = 0; i < 100; ++i) { + property_merge si; + std::map, polygon_set_data > result; + std::vector > polys; + property_merge_90 si90; + std::map, polygon_90_set_data > result90; + std::vector > polys90; + stdcout << "random case # " << i << "\n"; + set_points(rect1, (Point(rand()%9-4, rand()%9-4)), (Point(rand()%9-4, rand()%9-4))); + set_points(rect2, (Point(rand()%9-4, rand()%9-4)), (Point(rand()%9-4, rand()%9-4))); + set_points(rect3, (Point(rand()%9-4, rand()%9-4)), (Point(rand()%9-4, rand()%9-4))); + if(!check_rectangle_trio(rect1, rect2, rect3, stdcout)) { + return false; + } + } + return true; + } + + template + static inline bool test_intersection(stream_type& stdcout) { + property_merge si; + rectangle_data rect; + xl(rect, 0); + yl(rect, 10); + xh(rect, 30); + yh(rect, 20); + si.insert(rect, 333); + xl(rect, 10); + yl(rect, 0); + xh(rect, 20); + yh(rect, 30); + si.insert(rect, 444); + xl(rect, 15); + yl(rect, 0); + xh(rect, 25); + yh(rect, 30); + si.insert(rect, 555); + std::map, polygon_set_data > result; + si.merge(result); + print(stdcout, si.pmd) << "\n"; + for(typename std::map, polygon_set_data >::iterator itr = result.begin(); + itr != result.end(); ++itr) { + stdcout << "( "; + for(typename std::set::const_iterator set_itr = (*itr).first.begin(); + set_itr != (*itr).first.end(); ++set_itr) { + stdcout << (*set_itr) << " "; + } stdcout << ") \n"; + polygon_set_data psd = (*itr).second; + stdcout << psd << "\n"; + std::vector > polys; + psd.get(polys); + for(std::size_t i = 0; i < polys.size(); ++i) { + stdcout << polys[i] << "\n"; + } + } + std::vector pts; + std::vector > polys; + for(unsigned int i = 0; i < 10; ++i) { + property_merge si2; + stdcout << "random case # " << i << "\n"; + si.clear(); + pts.clear(); + pts.push_back(Point(rand()%9-4, rand()%9-4)); + pts.push_back(Point(rand()%9-4, rand()%9-4)); + pts.push_back(Point(rand()%9-4, rand()%9-4)); + polygon_data poly1; + poly1.set(pts.begin(), pts.end()); + stdcout << poly1 << "\n"; + si.insert(poly1, 444); + si2.insert(poly1, 333); + pts.clear(); + pts.push_back(Point(rand()%9-4, rand()%9-4)); + pts.push_back(Point(rand()%9-4, rand()%9-4)); + pts.push_back(Point(rand()%9-4, rand()%9-4)); + polygon_data poly2; + poly2.set(pts.begin(), pts.end()); + stdcout << poly2 << "\n"; + si.insert(poly2, 444); + si2.insert(poly2, 444); + pts.clear(); + pts.push_back(Point(rand()%9-4, rand()%9-4)); + pts.push_back(Point(rand()%9-4, rand()%9-4)); + pts.push_back(Point(rand()%9-4, rand()%9-4)); + polygon_data poly3; + poly3.set(pts.begin(), pts.end()); + stdcout << poly3 << "\n"; + si.insert(poly3, 444); + si2.insert(poly3, 555); + result.clear(); + std::map, polygon_set_data > result2; + si.merge(result); + si2.merge(result2); + stdcout << "merged result\n"; + for(typename std::map, polygon_set_data >::iterator itr = result.begin(); + itr != result.end(); ++itr) { + stdcout << "( "; + for(typename std::set::const_iterator set_itr = (*itr).first.begin(); + set_itr != (*itr).first.end(); ++set_itr) { + stdcout << (*set_itr) << " "; + } stdcout << ") \n"; + polygon_set_data psd = (*itr).second; + stdcout << psd << "\n"; + std::vector > polys2; + psd.get(polys2); + for(std::size_t ii = 0; ii < polys2.size(); ++ii) { + stdcout << polys2[ii] << "\n"; + } + } + stdcout << "intersected pmd\n"; + print(stdcout, si2.pmd) << "\n"; + stdcout << "intersected result\n"; + for(typename std::map, polygon_set_data >::iterator itr = result2.begin(); + itr != result2.end(); ++itr) { + stdcout << "( "; + for(typename std::set::const_iterator set_itr = (*itr).first.begin(); + set_itr != (*itr).first.end(); ++set_itr) { + stdcout << (*set_itr) << " "; + } stdcout << ") \n"; + polygon_set_data psd = (*itr).second; + stdcout << psd << "\n"; + std::vector > polys2; + psd.get(polys2); + for(std::size_t ii = 0; ii < polys2.size(); ++ii) { + stdcout << polys2[ii] << "\n"; + } + } + si.clear(); + for(typename std::map, polygon_set_data >::iterator itr = result2.begin(); + itr != result2.end(); ++itr) { + polys.clear(); + (*itr).second.get(polys); + for(std::size_t j = 0; j < polys.size(); ++j) { + si.insert(polys[j], 444); + } + } + result2.clear(); + si.merge(result2); + stdcout << "remerged result\n"; + for(typename std::map, polygon_set_data >::iterator itr = result2.begin(); + itr != result2.end(); ++itr) { + stdcout << "( "; + for(typename std::set::const_iterator set_itr = (*itr).first.begin(); + set_itr != (*itr).first.end(); ++set_itr) { + stdcout << (*set_itr) << " "; + } stdcout << ") \n"; + polygon_set_data psd = (*itr).second; + stdcout << psd << "\n"; + std::vector > polys2; + psd.get(polys2); + for(std::size_t ii = 0; ii < polys2.size(); ++ii) { + stdcout << polys2[ii] << "\n"; + } + } + std::vector > polys2; + polys.clear(); + (*(result.begin())).second.get(polys); + (*(result2.begin())).second.get(polys2); + if(!(polys == polys2)) { + stdcout << "failed intersection check # " << i << "\n"; + return false; + } + } + return true; + } + }; + + template + class arbitrary_boolean_op : public scanline_base { + private: + + typedef int property_type; + typedef typename scanline_base::Point Point; + + //the first point is the vertex and and second point establishes the slope of an edge eminating from the vertex + //typedef std::pair half_edge; + typedef typename scanline_base::half_edge half_edge; + + //scanline comparator functor + typedef typename scanline_base::less_half_edge less_half_edge; + typedef typename scanline_base::less_point less_point; + + //this data structure assocates a property and count to a half edge + typedef std::pair > vertex_property; + //this data type stores the combination of many half edges + typedef std::vector property_merge_data; + + //this is the data type used internally to store the combination of property counts at a given location + typedef std::vector > property_map; + //this data type is used internally to store the combined property data for a given half edge + typedef std::pair vertex_data; + + property_merge_data pmd; + typename scanline_base::evalAtXforYPack evalAtXforYPack_; + + template + class less_vertex_data { + typename scanline_base::evalAtXforYPack* pack_; + public: + less_vertex_data() : pack_() {} + less_vertex_data(typename scanline_base::evalAtXforYPack* pack) : pack_(pack) {} + bool operator()(const vertex_data_type& lvalue, const vertex_data_type& rvalue) const { + less_point lp; + if(lp(lvalue.first.first, rvalue.first.first)) return true; + if(lp(rvalue.first.first, lvalue.first.first)) return false; + Unit x = lvalue.first.first.get(HORIZONTAL); + int just_before_ = 0; + less_half_edge lhe(&x, &just_before_, pack_); + return lhe(lvalue.first, rvalue.first); + } + }; + + template + class boolean_output_functor { + public: + boolean_output_functor() {} + void operator()(result_type& result, const half_edge& edge, const key_type& left, const key_type& right) { + typename std::pair elem; + elem.first = edge; + elem.second = 1; + if(edge.second < edge.first) elem.second *= -1; + if(scanline_base::is_vertical(edge)) elem.second *= -1; +#ifdef BOOST_POLYGON_MSVC +#pragma warning (push) +#pragma warning (disable: 4127) +#endif + if(op_type == 0) { //OR + if(!left.empty() && right.empty()) { + result.insert_clean(elem); + } else if(!right.empty() && left.empty()) { + elem.second *= -1; + result.insert_clean(elem); + } + } else if(op_type == 1) { //AND + if(left.size() == 2 && right.size() != 2) { + result.insert_clean(elem); + } else if(right.size() == 2 && left.size() != 2) { + elem.second *= -1; + result.insert_clean(elem); + } + } else if(op_type == 2) { //XOR + if(left.size() == 1 && right.size() != 1) { + result.insert_clean(elem); + } else if(right.size() == 1 && left.size() != 1) { + elem.second *= -1; + result.insert_clean(elem); + } + } else { //SUBTRACT + if(left.size() == 1) { + if((*(left.begin())) == 0) { + result.insert_clean(elem); + } + } +#ifdef BOOST_POLYGON_MSVC +#pragma warning (pop) +#endif + if(right.size() == 1) { + if((*(right.begin())) == 0) { + elem.second *= -1; + result.insert_clean(elem); + } + } + } + } + }; + + inline void sort_property_merge_data() { + less_vertex_data lvd(&evalAtXforYPack_); + polygon_sort(pmd.begin(), pmd.end(), lvd); + } + public: + inline arbitrary_boolean_op() : pmd(), evalAtXforYPack_() {} + inline arbitrary_boolean_op(const arbitrary_boolean_op& pm) : pmd(pm.pmd), evalAtXforYPack_(pm.evalAtXforYPack_) {} + inline arbitrary_boolean_op& operator=(const arbitrary_boolean_op& pm) { pmd = pm.pmd; return *this; } + + enum BOOLEAN_OP_TYPE { + BOOLEAN_OR = 0, + BOOLEAN_AND = 1, + BOOLEAN_XOR = 2, + BOOLEAN_NOT = 3 + }; + template + inline void execute(result_type& result, iT1 b1, iT1 e1, iT2 b2, iT2 e2, int op) { + //intersect data + insert(b1, e1, 0); + insert(b2, e2, 1); + property_merge_data tmp_pmd; + //#define BOOST_POLYGON_DEBUG_FILE +#ifdef BOOST_POLYGON_DEBUG_FILE + std::fstream debug_file; + debug_file.open("gtl_debug.txt", std::ios::out); + property_merge >::print(debug_file, pmd); + debug_file.close(); +#endif + if(pmd.empty()) + return; + line_intersection::validate_scan(tmp_pmd, pmd.begin(), pmd.end()); + pmd.swap(tmp_pmd); + sort_property_merge_data(); + scanline > sl; + if(op == BOOLEAN_OR) { + boolean_output_functor, 0> bof; + sl.scan(result, bof, pmd.begin(), pmd.end()); + } else if(op == BOOLEAN_AND) { + boolean_output_functor, 1> bof; + sl.scan(result, bof, pmd.begin(), pmd.end()); + } else if(op == BOOLEAN_XOR) { + boolean_output_functor, 2> bof; + sl.scan(result, bof, pmd.begin(), pmd.end()); + } else if(op == BOOLEAN_NOT) { + boolean_output_functor, 3> bof; + sl.scan(result, bof, pmd.begin(), pmd.end()); + } + } + + inline void clear() {*this = arbitrary_boolean_op();} + + private: + template + void insert(iT b, iT e, int id) { + for(; + b != e; ++b) { + pmd.push_back(vertex_property(half_edge((*b).first.first, (*b).first.second), + std::pair(id, (*b).second))); + } + } + + }; + + template + bool test_arbitrary_boolean_op(stream_type& stdcout) { + polygon_set_data psd; + rectangle_data rect; + set_points(rect, point_data(0, 0), point_data(10, 10)); + psd.insert(rect); + polygon_set_data psd2; + set_points(rect, point_data(5, 5), point_data(15, 15)); + psd2.insert(rect); + std::vector > pv; + pv.clear(); + arbitrary_boolean_op abo; + polygon_set_data psd3; + abo.execute(psd3, psd.begin(), psd.end(), psd2.begin(), psd2.end(), arbitrary_boolean_op::BOOLEAN_OR); + psd3.get(pv); + for(std::size_t i = 0; i < pv.size(); ++i) { + stdcout << pv[i] << "\n"; + } + pv.clear(); + abo.clear(); + psd3.clear(); + abo.execute(psd3, psd.begin(), psd.end(), psd2.begin(), psd2.end(), arbitrary_boolean_op::BOOLEAN_AND); + psd3.get(pv); + for(std::size_t i = 0; i < pv.size(); ++i) { + stdcout << pv[i] << "\n"; + } + pv.clear(); + abo.clear(); + psd3.clear(); + abo.execute(psd3, psd.begin(), psd.end(), psd2.begin(), psd2.end(), arbitrary_boolean_op::BOOLEAN_XOR); + psd3.get(pv); + for(std::size_t i = 0; i < pv.size(); ++i) { + stdcout << pv[i] << "\n"; + } + pv.clear(); + abo.clear(); + psd3.clear(); + abo.execute(psd3, psd.begin(), psd.end(), psd2.begin(), psd2.end(), arbitrary_boolean_op::BOOLEAN_NOT); + psd3.get(pv); + for(std::size_t i = 0; i < pv.size(); ++i) { + stdcout << pv[i] << "\n"; + } + return true; + } + + + + + + + + + + + + + + + template + class arbitrary_connectivity_extraction : public scanline_base { + private: + + typedef typename scanline_base::Point Point; + + //the first point is the vertex and and second point establishes the slope of an edge eminating from the vertex + //typedef std::pair half_edge; + typedef typename scanline_base::half_edge half_edge; + + //scanline comparator functor + typedef typename scanline_base::less_half_edge less_half_edge; + typedef typename scanline_base::less_point less_point; + + //this data structure assocates a property and count to a half edge + typedef std::pair > vertex_property; + //this data type stores the combination of many half edges + typedef std::vector property_merge_data; + + //this is the data type used internally to store the combination of property counts at a given location + typedef std::vector > property_map; + //this data type is used internally to store the combined property data for a given half edge + typedef std::pair vertex_data; + + property_merge_data pmd; + typename scanline_base::evalAtXforYPack evalAtXforYPack_; + + template + class less_vertex_data { + typename scanline_base::evalAtXforYPack* pack_; + public: + less_vertex_data() : pack_() {} + less_vertex_data(typename scanline_base::evalAtXforYPack* pack) : pack_(pack) {} + bool operator()(const vertex_data_type& lvalue, const vertex_data_type& rvalue) const { + less_point lp; + if(lp(lvalue.first.first, rvalue.first.first)) return true; + if(lp(rvalue.first.first, lvalue.first.first)) return false; + Unit x = lvalue.first.first.get(HORIZONTAL); + int just_before_ = 0; + less_half_edge lhe(&x, &just_before_, pack_); + return lhe(lvalue.first, rvalue.first); + } + }; + + + template + static void process_previous_x(cT& output) { + std::map, std::set >& y_prop_map = output.first.second; + if(y_prop_map.empty()) return; + Unit x = output.first.first; + for(typename std::map, std::set >::iterator itr = + y_prop_map.begin(); itr != y_prop_map.end(); ++itr) { + if((*itr).first.x() < x) { + y_prop_map.erase(y_prop_map.begin(), itr); + continue; + } + for(typename std::set::iterator inner_itr = itr->second.begin(); + inner_itr != itr->second.end(); ++inner_itr) { + std::set& output_edges = (*(output.second))[*inner_itr]; + typename std::set::iterator inner_inner_itr = inner_itr; + ++inner_inner_itr; + for( ; inner_inner_itr != itr->second.end(); ++inner_inner_itr) { + output_edges.insert(output_edges.end(), *inner_inner_itr); + std::set& output_edges_2 = (*(output.second))[*inner_inner_itr]; + output_edges_2.insert(output_edges_2.end(), *inner_itr); + } + } + } + } + + template + class connectivity_extraction_output_functor { + public: + connectivity_extraction_output_functor() {} + void operator()(result_type& result, const half_edge& edge, const key_type& left, const key_type& right) { + Unit& x = result.first.first; + std::map, std::set >& y_prop_map = result.first.second; + point_data pt = edge.first; + if(pt.x() != x) process_previous_x(result); + x = pt.x(); + std::set& output_set = y_prop_map[pt]; + { + for(typename key_type::const_iterator itr1 = + left.begin(); itr1 != left.end(); ++itr1) { + output_set.insert(output_set.end(), *itr1); + } + for(typename key_type::const_iterator itr2 = + right.begin(); itr2 != right.end(); ++itr2) { + output_set.insert(output_set.end(), *itr2); + } + } + std::set& output_set2 = y_prop_map[edge.second]; + for(typename key_type::const_iterator itr1 = + left.begin(); itr1 != left.end(); ++itr1) { + output_set2.insert(output_set2.end(), *itr1); + } + for(typename key_type::const_iterator itr2 = + right.begin(); itr2 != right.end(); ++itr2) { + output_set2.insert(output_set2.end(), *itr2); + } + } + }; + + inline void sort_property_merge_data() { + less_vertex_data lvd(&evalAtXforYPack_); + polygon_sort(pmd.begin(), pmd.end(), lvd); + } + public: + inline arbitrary_connectivity_extraction() : pmd(), evalAtXforYPack_() {} + inline arbitrary_connectivity_extraction + (const arbitrary_connectivity_extraction& pm) : pmd(pm.pmd), evalAtXforYPack_(pm.evalAtXforYPack_) {} + inline arbitrary_connectivity_extraction& operator= + (const arbitrary_connectivity_extraction& pm) { pmd = pm.pmd; return *this; } + + template + inline void execute(result_type& result) { + //intersect data + property_merge_data tmp_pmd; + line_intersection::validate_scan(tmp_pmd, pmd.begin(), pmd.end()); + pmd.swap(tmp_pmd); + sort_property_merge_data(); + scanline > sl; + std::pair, std::set > >, + result_type*> output + (std::make_pair(std::make_pair((std::numeric_limits::max)(), + std::map, + std::set >()), &result)); + connectivity_extraction_output_functor, std::set > >, result_type*>, + std::vector > ceof; + sl.scan(output, ceof, pmd.begin(), pmd.end()); + process_previous_x(output); + } + + inline void clear() {*this = arbitrary_connectivity_extraction();} + + template + void populateTouchSetData(iT begin, iT end, + property_type property) { + for( ; begin != end; ++begin) { + pmd.push_back(vertex_property(half_edge((*begin).first.first, (*begin).first.second), + std::pair(property, (*begin).second))); + } + } + + }; + +} +} +#endif diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/detail/voronoi_ctypes.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/detail/voronoi_ctypes.hpp new file mode 100644 index 0000000..078d935 --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/detail/voronoi_ctypes.hpp @@ -0,0 +1,643 @@ +// Boost.Polygon library detail/voronoi_ctypes.hpp header file + +// Copyright Andrii Sydorchuk 2010-2012. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +#ifndef BOOST_POLYGON_DETAIL_VORONOI_CTYPES +#define BOOST_POLYGON_DETAIL_VORONOI_CTYPES + +#include + +#include +#include +#include +#include +#include + +namespace boost { +namespace polygon { +namespace detail { + +typedef boost::int32_t int32; +typedef boost::int64_t int64; +typedef boost::uint32_t uint32; +typedef boost::uint64_t uint64; +typedef double fpt64; + +// If two floating-point numbers in the same format are ordered (x < y), +// then they are ordered the same way when their bits are reinterpreted as +// sign-magnitude integers. Values are considered to be almost equal if +// their integer bits reinterpretations differ in not more than maxUlps units. +template +struct ulp_comparison; + +template <> +struct ulp_comparison { + enum Result { + LESS = -1, + EQUAL = 0, + MORE = 1 + }; + + Result operator()(fpt64 a, fpt64 b, unsigned int maxUlps) const { + uint64 ll_a, ll_b; + + // Reinterpret double bits as 64-bit signed integer. + std::memcpy(&ll_a, &a, sizeof(fpt64)); + std::memcpy(&ll_b, &b, sizeof(fpt64)); + + // Positive 0.0 is integer zero. Negative 0.0 is 0x8000000000000000. + // Map negative zero to an integer zero representation - making it + // identical to positive zero - the smallest negative number is + // represented by negative one, and downwards from there. + if (ll_a < 0x8000000000000000ULL) + ll_a = 0x8000000000000000ULL - ll_a; + if (ll_b < 0x8000000000000000ULL) + ll_b = 0x8000000000000000ULL - ll_b; + + // Compare 64-bit signed integer representations of input values. + // Difference in 1 Ulp is equivalent to a relative error of between + // 1/4,000,000,000,000,000 and 1/8,000,000,000,000,000. + if (ll_a > ll_b) + return (ll_a - ll_b <= maxUlps) ? EQUAL : LESS; + return (ll_b - ll_a <= maxUlps) ? EQUAL : MORE; + } +}; + +template +struct extened_exponent_fpt_traits; + +template <> +struct extened_exponent_fpt_traits { + public: + typedef int exp_type; + enum { + MAX_SIGNIFICANT_EXP_DIF = 54 + }; +}; + +// Floating point type wrapper. Allows to extend exponent boundaries to the +// integer type range. This class does not handle division by zero, subnormal +// numbers or NaNs. +template > +class extended_exponent_fpt { + public: + typedef _fpt fpt_type; + typedef typename _traits::exp_type exp_type; + + explicit extended_exponent_fpt(fpt_type val) { + val_ = std::frexp(val, &exp_); + } + + extended_exponent_fpt(fpt_type val, exp_type exp) { + val_ = std::frexp(val, &exp_); + exp_ += exp; + } + + bool is_pos() const { + return val_ > 0; + } + + bool is_neg() const { + return val_ < 0; + } + + bool is_zero() const { + return val_ == 0; + } + + extended_exponent_fpt operator-() const { + return extended_exponent_fpt(-val_, exp_); + } + + extended_exponent_fpt operator+(const extended_exponent_fpt& that) const { + if (this->val_ == 0.0 || + that.exp_ > this->exp_ + _traits::MAX_SIGNIFICANT_EXP_DIF) { + return that; + } + if (that.val_ == 0.0 || + this->exp_ > that.exp_ + _traits::MAX_SIGNIFICANT_EXP_DIF) { + return *this; + } + if (this->exp_ >= that.exp_) { + exp_type exp_dif = this->exp_ - that.exp_; + fpt_type val = std::ldexp(this->val_, exp_dif) + that.val_; + return extended_exponent_fpt(val, that.exp_); + } else { + exp_type exp_dif = that.exp_ - this->exp_; + fpt_type val = std::ldexp(that.val_, exp_dif) + this->val_; + return extended_exponent_fpt(val, this->exp_); + } + } + + extended_exponent_fpt operator-(const extended_exponent_fpt& that) const { + if (this->val_ == 0.0 || + that.exp_ > this->exp_ + _traits::MAX_SIGNIFICANT_EXP_DIF) { + return extended_exponent_fpt(-that.val_, that.exp_); + } + if (that.val_ == 0.0 || + this->exp_ > that.exp_ + _traits::MAX_SIGNIFICANT_EXP_DIF) { + return *this; + } + if (this->exp_ >= that.exp_) { + exp_type exp_dif = this->exp_ - that.exp_; + fpt_type val = std::ldexp(this->val_, exp_dif) - that.val_; + return extended_exponent_fpt(val, that.exp_); + } else { + exp_type exp_dif = that.exp_ - this->exp_; + fpt_type val = std::ldexp(-that.val_, exp_dif) + this->val_; + return extended_exponent_fpt(val, this->exp_); + } + } + + extended_exponent_fpt operator*(const extended_exponent_fpt& that) const { + fpt_type val = this->val_ * that.val_; + exp_type exp = this->exp_ + that.exp_; + return extended_exponent_fpt(val, exp); + } + + extended_exponent_fpt operator/(const extended_exponent_fpt& that) const { + fpt_type val = this->val_ / that.val_; + exp_type exp = this->exp_ - that.exp_; + return extended_exponent_fpt(val, exp); + } + + extended_exponent_fpt& operator+=(const extended_exponent_fpt& that) { + return *this = *this + that; + } + + extended_exponent_fpt& operator-=(const extended_exponent_fpt& that) { + return *this = *this - that; + } + + extended_exponent_fpt& operator*=(const extended_exponent_fpt& that) { + return *this = *this * that; + } + + extended_exponent_fpt& operator/=(const extended_exponent_fpt& that) { + return *this = *this / that; + } + + extended_exponent_fpt sqrt() const { + fpt_type val = val_; + exp_type exp = exp_; + if (exp & 1) { + val *= 2.0; + --exp; + } + return extended_exponent_fpt(std::sqrt(val), exp >> 1); + } + + fpt_type d() const { + return std::ldexp(val_, exp_); + } + + private: + fpt_type val_; + exp_type exp_; +}; +typedef extended_exponent_fpt efpt64; + +template +extended_exponent_fpt<_fpt> get_sqrt(const extended_exponent_fpt<_fpt>& that) { + return that.sqrt(); +} + +template +bool is_pos(const extended_exponent_fpt<_fpt>& that) { + return that.is_pos(); +} + +template +bool is_neg(const extended_exponent_fpt<_fpt>& that) { + return that.is_neg(); +} + +template +bool is_zero(const extended_exponent_fpt<_fpt>& that) { + return that.is_zero(); +} + +// Very efficient stack allocated big integer class. +// Supports next set of arithmetic operations: +, -, *. +template +class extended_int { + public: + extended_int() {} + + extended_int(int32 that) { + if (that > 0) { + this->chunks_[0] = that; + this->count_ = 1; + } else if (that < 0) { + this->chunks_[0] = -that; + this->count_ = -1; + } else { + this->count_ = 0; + } + } + + extended_int(int64 that) { + if (that > 0) { + this->chunks_[0] = static_cast(that); + this->chunks_[1] = that >> 32; + this->count_ = this->chunks_[1] ? 2 : 1; + } else if (that < 0) { + that = -that; + this->chunks_[0] = static_cast(that); + this->chunks_[1] = that >> 32; + this->count_ = this->chunks_[1] ? -2 : -1; + } else { + this->count_ = 0; + } + } + + extended_int(const std::vector& chunks, bool plus = true) { + this->count_ = static_cast((std::min)(N, chunks.size())); + for (int i = 0; i < this->count_; ++i) + this->chunks_[i] = chunks[chunks.size() - i - 1]; + if (!plus) + this->count_ = -this->count_; + } + + template + extended_int(const extended_int& that) { + this->count_ = that.count(); + std::memcpy(this->chunks_, that.chunks(), that.size() * sizeof(uint32)); + } + + extended_int& operator=(int32 that) { + if (that > 0) { + this->chunks_[0] = that; + this->count_ = 1; + } else if (that < 0) { + this->chunks_[0] = -that; + this->count_ = -1; + } else { + this->count_ = 0; + } + return *this; + } + + extended_int& operator=(int64 that) { + if (that > 0) { + this->chunks_[0] = static_cast(that); + this->chunks_[1] = that >> 32; + this->count_ = this->chunks_[1] ? 2 : 1; + } else if (that < 0) { + that = -that; + this->chunks_[0] = static_cast(that); + this->chunks_[1] = that >> 32; + this->count_ = this->chunks_[1] ? -2 : -1; + } else { + this->count_ = 0; + } + return *this; + } + + template + extended_int& operator=(const extended_int& that) { + this->count_ = that.count(); + std::memcpy(this->chunks_, that.chunks(), that.size() * sizeof(uint32)); + return *this; + } + + bool is_pos() const { + return this->count_ > 0; + } + + bool is_neg() const { + return this->count_ < 0; + } + + bool is_zero() const { + return this->count_ == 0; + } + + bool operator==(const extended_int& that) const { + if (this->count_ != that.count()) + return false; + for (std::size_t i = 0; i < this->size(); ++i) + if (this->chunks_[i] != that.chunks()[i]) + return false; + return true; + } + + bool operator!=(const extended_int& that) const { + return !(*this == that); + } + + bool operator<(const extended_int& that) const { + if (this->count_ != that.count()) + return this->count_ < that.count(); + std::size_t i = this->size(); + if (!i) + return false; + do { + --i; + if (this->chunks_[i] != that.chunks()[i]) + return (this->chunks_[i] < that.chunks()[i]) ^ (this->count_ < 0); + } while (i); + return false; + } + + bool operator>(const extended_int& that) const { + return that < *this; + } + + bool operator<=(const extended_int& that) const { + return !(that < *this); + } + + bool operator>=(const extended_int& that) const { + return !(*this < that); + } + + extended_int operator-() const { + extended_int ret_val = *this; + ret_val.neg(); + return ret_val; + } + + void neg() { + this->count_ = -this->count_; + } + + extended_int operator+(const extended_int& that) const { + extended_int ret_val; + ret_val.add(*this, that); + return ret_val; + } + + void add(const extended_int& e1, const extended_int& e2) { + if (!e1.count()) { + *this = e2; + return; + } + if (!e2.count()) { + *this = e1; + return; + } + if ((e1.count() > 0) ^ (e2.count() > 0)) { + dif(e1.chunks(), e1.size(), e2.chunks(), e2.size()); + } else { + add(e1.chunks(), e1.size(), e2.chunks(), e2.size()); + } + if (e1.count() < 0) + this->count_ = -this->count_; + } + + extended_int operator-(const extended_int& that) const { + extended_int ret_val; + ret_val.dif(*this, that); + return ret_val; + } + + void dif(const extended_int& e1, const extended_int& e2) { + if (!e1.count()) { + *this = e2; + this->count_ = -this->count_; + return; + } + if (!e2.count()) { + *this = e1; + return; + } + if ((e1.count() > 0) ^ (e2.count() > 0)) { + add(e1.chunks(), e1.size(), e2.chunks(), e2.size()); + } else { + dif(e1.chunks(), e1.size(), e2.chunks(), e2.size()); + } + if (e1.count() < 0) + this->count_ = -this->count_; + } + + extended_int operator*(int32 that) const { + extended_int temp(that); + return (*this) * temp; + } + + extended_int operator*(int64 that) const { + extended_int temp(that); + return (*this) * temp; + } + + extended_int operator*(const extended_int& that) const { + extended_int ret_val; + ret_val.mul(*this, that); + return ret_val; + } + + void mul(const extended_int& e1, const extended_int& e2) { + if (!e1.count() || !e2.count()) { + this->count_ = 0; + return; + } + mul(e1.chunks(), e1.size(), e2.chunks(), e2.size()); + if ((e1.count() > 0) ^ (e2.count() > 0)) + this->count_ = -this->count_; + } + + const uint32* chunks() const { + return chunks_; + } + + int32 count() const { + return count_; + } + + std::size_t size() const { + return (std::abs)(count_); + } + + std::pair p() const { + std::pair ret_val(0, 0); + std::size_t sz = this->size(); + if (!sz) { + return ret_val; + } else { + if (sz == 1) { + ret_val.first = static_cast(this->chunks_[0]); + } else if (sz == 2) { + ret_val.first = static_cast(this->chunks_[1]) * + static_cast(0x100000000LL) + + static_cast(this->chunks_[0]); + } else { + for (std::size_t i = 1; i <= 3; ++i) { + ret_val.first *= static_cast(0x100000000LL); + ret_val.first += static_cast(this->chunks_[sz - i]); + } + ret_val.second = static_cast((sz - 3) << 5); + } + } + if (this->count_ < 0) + ret_val.first = -ret_val.first; + return ret_val; + } + + fpt64 d() const { + std::pair p = this->p(); + return std::ldexp(p.first, p.second); + } + + private: + void add(const uint32* c1, std::size_t sz1, + const uint32* c2, std::size_t sz2) { + if (sz1 < sz2) { + add(c2, sz2, c1, sz1); + return; + } + this->count_ = static_cast(sz1); + uint64 temp = 0; + for (std::size_t i = 0; i < sz2; ++i) { + temp += static_cast(c1[i]) + static_cast(c2[i]); + this->chunks_[i] = static_cast(temp); + temp >>= 32; + } + for (std::size_t i = sz2; i < sz1; ++i) { + temp += static_cast(c1[i]); + this->chunks_[i] = static_cast(temp); + temp >>= 32; + } + if (temp && (this->count_ != N)) { + this->chunks_[this->count_] = static_cast(temp); + ++this->count_; + } + } + + void dif(const uint32* c1, std::size_t sz1, + const uint32* c2, std::size_t sz2, + bool rec = false) { + if (sz1 < sz2) { + dif(c2, sz2, c1, sz1, true); + this->count_ = -this->count_; + return; + } else if ((sz1 == sz2) && !rec) { + do { + --sz1; + if (c1[sz1] < c2[sz1]) { + ++sz1; + dif(c2, sz1, c1, sz1, true); + this->count_ = -this->count_; + return; + } else if (c1[sz1] > c2[sz1]) { + ++sz1; + break; + } + } while (sz1); + if (!sz1) { + this->count_ = 0; + return; + } + sz2 = sz1; + } + this->count_ = static_cast(sz1-1); + bool flag = false; + for (std::size_t i = 0; i < sz2; ++i) { + this->chunks_[i] = c1[i] - c2[i] - (flag?1:0); + flag = (c1[i] < c2[i]) || ((c1[i] == c2[i]) && flag); + } + for (std::size_t i = sz2; i < sz1; ++i) { + this->chunks_[i] = c1[i] - (flag?1:0); + flag = !c1[i] && flag; + } + if (this->chunks_[this->count_]) + ++this->count_; + } + + void mul(const uint32* c1, std::size_t sz1, + const uint32* c2, std::size_t sz2) { + uint64 cur = 0, nxt, tmp; + this->count_ = static_cast((std::min)(N, sz1 + sz2 - 1)); + for (std::size_t shift = 0; shift < static_cast(this->count_); + ++shift) { + nxt = 0; + for (std::size_t first = 0; first <= shift; ++first) { + if (first >= sz1) + break; + std::size_t second = shift - first; + if (second >= sz2) + continue; + tmp = static_cast(c1[first]) * static_cast(c2[second]); + cur += static_cast(tmp); + nxt += tmp >> 32; + } + this->chunks_[shift] = static_cast(cur); + cur = nxt + (cur >> 32); + } + if (cur && (this->count_ != N)) { + this->chunks_[this->count_] = static_cast(cur); + ++this->count_; + } + } + + uint32 chunks_[N]; + int32 count_; +}; + +template +bool is_pos(const extended_int& that) { + return that.count() > 0; +} + +template +bool is_neg(const extended_int& that) { + return that.count() < 0; +} + +template +bool is_zero(const extended_int& that) { + return !that.count(); +} + +struct type_converter_fpt { + template + fpt64 operator()(const T& that) const { + return static_cast(that); + } + + template + fpt64 operator()(const extended_int& that) const { + return that.d(); + } + + fpt64 operator()(const extended_exponent_fpt& that) const { + return that.d(); + } +}; + +struct type_converter_efpt { + template + extended_exponent_fpt operator()(const extended_int& that) const { + std::pair p = that.p(); + return extended_exponent_fpt(p.first, p.second); + } +}; + +// Voronoi coordinate type traits make it possible to extend algorithm +// input coordinate range to any user provided integer type and algorithm +// output coordinate range to any ieee-754 like floating point type. +template +struct voronoi_ctype_traits; + +template <> +struct voronoi_ctype_traits { + typedef int32 int_type; + typedef int64 int_x2_type; + typedef uint64 uint_x2_type; + typedef extended_int<64> big_int_type; + typedef fpt64 fpt_type; + typedef extended_exponent_fpt efpt_type; + typedef ulp_comparison ulp_cmp_type; + typedef type_converter_fpt to_fpt_converter_type; + typedef type_converter_efpt to_efpt_converter_type; +}; +} // detail +} // polygon +} // boost + +#endif // BOOST_POLYGON_DETAIL_VORONOI_CTYPES diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/detail/voronoi_predicates.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/detail/voronoi_predicates.hpp new file mode 100644 index 0000000..b6314d3 --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/detail/voronoi_predicates.hpp @@ -0,0 +1,1533 @@ +// Boost.Polygon library detail/voronoi_predicates.hpp header file + +// Copyright Andrii Sydorchuk 2010-2012. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +#ifndef BOOST_POLYGON_DETAIL_VORONOI_PREDICATES +#define BOOST_POLYGON_DETAIL_VORONOI_PREDICATES + +#include + +#include "voronoi_robust_fpt.hpp" + +namespace boost { +namespace polygon { +namespace detail { + +// Predicate utilities. Operates with the coordinate types that could +// be converted to the 32-bit signed integer without precision loss. +template +class voronoi_predicates { + public: + typedef typename CTYPE_TRAITS::int_type int_type; + typedef typename CTYPE_TRAITS::int_x2_type int_x2_type; + typedef typename CTYPE_TRAITS::uint_x2_type uint_x2_type; + typedef typename CTYPE_TRAITS::big_int_type big_int_type; + typedef typename CTYPE_TRAITS::fpt_type fpt_type; + typedef typename CTYPE_TRAITS::efpt_type efpt_type; + typedef typename CTYPE_TRAITS::ulp_cmp_type ulp_cmp_type; + typedef typename CTYPE_TRAITS::to_fpt_converter_type to_fpt_converter; + typedef typename CTYPE_TRAITS::to_efpt_converter_type to_efpt_converter; + + enum { + ULPS = 64, + ULPSx2 = 128 + }; + + template + static bool is_vertical(const Point& point1, const Point& point2) { + return point1.x() == point2.x(); + } + + template + static bool is_vertical(const Site& site) { + return is_vertical(site.point0(), site.point1()); + } + + // Compute robust cross_product: a1 * b2 - b1 * a2. + // It was mathematically proven that the result is correct + // with epsilon relative error equal to 1EPS. + static fpt_type robust_cross_product(int_x2_type a1_, + int_x2_type b1_, + int_x2_type a2_, + int_x2_type b2_) { + static to_fpt_converter to_fpt; + uint_x2_type a1 = static_cast(is_neg(a1_) ? -a1_ : a1_); + uint_x2_type b1 = static_cast(is_neg(b1_) ? -b1_ : b1_); + uint_x2_type a2 = static_cast(is_neg(a2_) ? -a2_ : a2_); + uint_x2_type b2 = static_cast(is_neg(b2_) ? -b2_ : b2_); + + uint_x2_type l = a1 * b2; + uint_x2_type r = b1 * a2; + + if (is_neg(a1_) ^ is_neg(b2_)) { + if (is_neg(a2_) ^ is_neg(b1_)) + return (l > r) ? -to_fpt(l - r) : to_fpt(r - l); + else + return -to_fpt(l + r); + } else { + if (is_neg(a2_) ^ is_neg(b1_)) + return to_fpt(l + r); + else + return (l < r) ? -to_fpt(r - l) : to_fpt(l - r); + } + } + + struct orientation_test { + public: + // Represents orientation test result. + enum Orientation { + RIGHT = -1, + COLLINEAR = 0, + LEFT = 1 + }; + + // Value is a determinant of two vectors (e.g. x1 * y2 - x2 * y1). + // Return orientation based on the sign of the determinant. + template + static Orientation eval(T value) { + if (is_zero(value)) return COLLINEAR; + return (is_neg(value)) ? RIGHT : LEFT; + } + + static Orientation eval(int_x2_type dif_x1_, + int_x2_type dif_y1_, + int_x2_type dif_x2_, + int_x2_type dif_y2_) { + return eval(robust_cross_product(dif_x1_, dif_y1_, dif_x2_, dif_y2_)); + } + + template + static Orientation eval(const Point& point1, + const Point& point2, + const Point& point3) { + int_x2_type dx1 = static_cast(point1.x()) - + static_cast(point2.x()); + int_x2_type dx2 = static_cast(point2.x()) - + static_cast(point3.x()); + int_x2_type dy1 = static_cast(point1.y()) - + static_cast(point2.y()); + int_x2_type dy2 = static_cast(point2.y()) - + static_cast(point3.y()); + return eval(robust_cross_product(dx1, dy1, dx2, dy2)); + } + }; + typedef orientation_test ot; + + template + class point_comparison_predicate { + public: + typedef Point point_type; + + bool operator()(const point_type& lhs, const point_type& rhs) const { + if (lhs.x() == rhs.x()) + return lhs.y() < rhs.y(); + return lhs.x() < rhs.x(); + } + }; + + template + class event_comparison_predicate { + public: + typedef Site site_type; + typedef Circle circle_type; + + bool operator()(const site_type& lhs, const site_type& rhs) const { + if (lhs.x0() != rhs.x0()) + return lhs.x0() < rhs.x0(); + if (!lhs.is_segment()) { + if (!rhs.is_segment()) + return lhs.y0() < rhs.y0(); + if (is_vertical(rhs)) + return lhs.y0() <= rhs.y0(); + return true; + } else { + if (is_vertical(rhs)) { + if (is_vertical(lhs)) + return lhs.y0() < rhs.y0(); + return false; + } + if (is_vertical(lhs)) + return true; + if (lhs.y0() != rhs.y0()) + return lhs.y0() < rhs.y0(); + return ot::eval(lhs.point1(), lhs.point0(), rhs.point1()) == ot::LEFT; + } + } + + bool operator()(const site_type& lhs, const circle_type& rhs) const { + typename ulp_cmp_type::Result xCmp = + ulp_cmp(to_fpt(lhs.x0()), to_fpt(rhs.lower_x()), ULPS); + return xCmp == ulp_cmp_type::LESS; + } + + bool operator()(const circle_type& lhs, const site_type& rhs) const { + typename ulp_cmp_type::Result xCmp = + ulp_cmp(to_fpt(lhs.lower_x()), to_fpt(rhs.x0()), ULPS); + return xCmp == ulp_cmp_type::LESS; + } + + bool operator()(const circle_type& lhs, const circle_type& rhs) const { + if (lhs.lower_x() != rhs.lower_x()) { + return lhs.lower_x() < rhs.lower_x(); + } + return lhs.y() < rhs.y(); + } + + private: + ulp_cmp_type ulp_cmp; + to_fpt_converter to_fpt; + }; + + template + class distance_predicate { + public: + typedef Site site_type; + typedef typename site_type::point_type point_type; + + // Returns true if a horizontal line going through a new site intersects + // right arc at first, else returns false. If horizontal line goes + // through intersection point of the given two arcs returns false also. + bool operator()(const site_type& left_site, + const site_type& right_site, + const point_type& new_point) const { + if (!left_site.is_segment()) { + if (!right_site.is_segment()) { + return pp(left_site, right_site, new_point); + } else { + return ps(left_site, right_site, new_point, false); + } + } else { + if (!right_site.is_segment()) { + return ps(right_site, left_site, new_point, true); + } else { + return ss(left_site, right_site, new_point); + } + } + } + + private: + // Represents the result of the epsilon robust predicate. If the + // result is undefined some further processing is usually required. + enum kPredicateResult { + LESS = -1, + UNDEFINED = 0, + MORE = 1 + }; + + // Robust predicate, avoids using high-precision libraries. + // Returns true if a horizontal line going through the new point site + // intersects right arc at first, else returns false. If horizontal line + // goes through intersection point of the given two arcs returns false. + bool pp(const site_type& left_site, + const site_type& right_site, + const point_type& new_point) const { + const point_type& left_point = left_site.point0(); + const point_type& right_point = right_site.point0(); + if (left_point.x() > right_point.x()) { + if (new_point.y() <= left_point.y()) + return false; + } else if (left_point.x() < right_point.x()) { + if (new_point.y() >= right_point.y()) + return true; + } else { + return static_cast(left_point.y()) + + static_cast(right_point.y()) < + static_cast(new_point.y()) * 2; + } + + fpt_type dist1 = find_distance_to_point_arc(left_site, new_point); + fpt_type dist2 = find_distance_to_point_arc(right_site, new_point); + + // The undefined ulp range is equal to 3EPS + 3EPS <= 6ULP. + return dist1 < dist2; + } + + bool ps(const site_type& left_site, const site_type& right_site, + const point_type& new_point, bool reverse_order) const { + kPredicateResult fast_res = fast_ps( + left_site, right_site, new_point, reverse_order); + if (fast_res != UNDEFINED) { + return fast_res == LESS; + } + + fpt_type dist1 = find_distance_to_point_arc(left_site, new_point); + fpt_type dist2 = find_distance_to_segment_arc(right_site, new_point); + + // The undefined ulp range is equal to 3EPS + 7EPS <= 10ULP. + return reverse_order ^ (dist1 < dist2); + } + + bool ss(const site_type& left_site, + const site_type& right_site, + const point_type& new_point) const { + // Handle temporary segment sites. + if (left_site.sorted_index() == right_site.sorted_index()) { + return ot::eval( + left_site.point0(), left_site.point1(), new_point) == ot::LEFT; + } + + fpt_type dist1 = find_distance_to_segment_arc(left_site, new_point); + fpt_type dist2 = find_distance_to_segment_arc(right_site, new_point); + + // The undefined ulp range is equal to 7EPS + 7EPS <= 14ULP. + return dist1 < dist2; + } + + fpt_type find_distance_to_point_arc( + const site_type& site, const point_type& point) const { + fpt_type dx = to_fpt(site.x()) - to_fpt(point.x()); + fpt_type dy = to_fpt(site.y()) - to_fpt(point.y()); + // The relative error is at most 3EPS. + return (dx * dx + dy * dy) / (to_fpt(2.0) * dx); + } + + fpt_type find_distance_to_segment_arc( + const site_type& site, const point_type& point) const { + if (is_vertical(site)) { + return (to_fpt(site.x()) - to_fpt(point.x())) * to_fpt(0.5); + } else { + const point_type& segment0 = site.point0(); + const point_type& segment1 = site.point1(); + fpt_type a1 = to_fpt(segment1.x()) - to_fpt(segment0.x()); + fpt_type b1 = to_fpt(segment1.y()) - to_fpt(segment0.y()); + fpt_type k = get_sqrt(a1 * a1 + b1 * b1); + // Avoid subtraction while computing k. + if (!is_neg(b1)) { + k = to_fpt(1.0) / (b1 + k); + } else { + k = (k - b1) / (a1 * a1); + } + // The relative error is at most 7EPS. + return k * robust_cross_product( + static_cast(segment1.x()) - + static_cast(segment0.x()), + static_cast(segment1.y()) - + static_cast(segment0.y()), + static_cast(point.x()) - + static_cast(segment0.x()), + static_cast(point.y()) - + static_cast(segment0.y())); + } + } + + kPredicateResult fast_ps( + const site_type& left_site, const site_type& right_site, + const point_type& new_point, bool reverse_order) const { + const point_type& site_point = left_site.point0(); + const point_type& segment_start = right_site.point0(); + const point_type& segment_end = right_site.point1(); + + if (ot::eval(segment_start, segment_end, new_point) != ot::RIGHT) + return (!right_site.is_inverse()) ? LESS : MORE; + + fpt_type dif_x = to_fpt(new_point.x()) - to_fpt(site_point.x()); + fpt_type dif_y = to_fpt(new_point.y()) - to_fpt(site_point.y()); + fpt_type a = to_fpt(segment_end.x()) - to_fpt(segment_start.x()); + fpt_type b = to_fpt(segment_end.y()) - to_fpt(segment_start.y()); + + if (is_vertical(right_site)) { + if (new_point.y() < site_point.y() && !reverse_order) + return MORE; + else if (new_point.y() > site_point.y() && reverse_order) + return LESS; + return UNDEFINED; + } else { + typename ot::Orientation orientation = ot::eval( + static_cast(segment_end.x()) - + static_cast(segment_start.x()), + static_cast(segment_end.y()) - + static_cast(segment_start.y()), + static_cast(new_point.x()) - + static_cast(site_point.x()), + static_cast(new_point.y()) - + static_cast(site_point.y())); + if (orientation == ot::LEFT) { + if (!right_site.is_inverse()) + return reverse_order ? LESS : UNDEFINED; + return reverse_order ? UNDEFINED : MORE; + } + } + + fpt_type fast_left_expr = a * (dif_y + dif_x) * (dif_y - dif_x); + fpt_type fast_right_expr = (to_fpt(2.0) * b) * dif_x * dif_y; + typename ulp_cmp_type::Result expr_cmp = + ulp_cmp(fast_left_expr, fast_right_expr, 4); + if (expr_cmp != ulp_cmp_type::EQUAL) { + if ((expr_cmp == ulp_cmp_type::MORE) ^ reverse_order) + return reverse_order ? LESS : MORE; + return UNDEFINED; + } + return UNDEFINED; + } + + private: + ulp_cmp_type ulp_cmp; + to_fpt_converter to_fpt; + }; + + template + class node_comparison_predicate { + public: + typedef Node node_type; + typedef typename Node::site_type site_type; + typedef typename site_type::point_type point_type; + typedef typename point_type::coordinate_type coordinate_type; + typedef point_comparison_predicate point_comparison_type; + typedef distance_predicate distance_predicate_type; + + // Compares nodes in the balanced binary search tree. Nodes are + // compared based on the y coordinates of the arcs intersection points. + // Nodes with less y coordinate of the intersection point go first. + // Comparison is only called during the new site events processing. + // That's why one of the nodes will always lie on the sweepline and may + // be represented as a straight horizontal line. + bool operator() (const node_type& node1, + const node_type& node2) const { + // Get x coordinate of the rightmost site from both nodes. + const site_type& site1 = get_comparison_site(node1); + const site_type& site2 = get_comparison_site(node2); + const point_type& point1 = get_comparison_point(site1); + const point_type& point2 = get_comparison_point(site2); + + if (point1.x() < point2.x()) { + // The second node contains a new site. + return distance_predicate_( + node1.left_site(), node1.right_site(), point2); + } else if (point1.x() > point2.x()) { + // The first node contains a new site. + return !distance_predicate_( + node2.left_site(), node2.right_site(), point1); + } else { + // This checks were evaluated experimentally. + if (site1.sorted_index() == site2.sorted_index()) { + // Both nodes are new (inserted during same site event processing). + return get_comparison_y(node1) < get_comparison_y(node2); + } else if (site1.sorted_index() < site2.sorted_index()) { + std::pair y1 = get_comparison_y(node1, false); + std::pair y2 = get_comparison_y(node2, true); + if (y1.first != y2.first) return y1.first < y2.first; + return (!site1.is_segment()) ? (y1.second < 0) : false; + } else { + std::pair y1 = get_comparison_y(node1, true); + std::pair y2 = get_comparison_y(node2, false); + if (y1.first != y2.first) return y1.first < y2.first; + return (!site2.is_segment()) ? (y2.second > 0) : true; + } + } + } + + private: + // Get the newer site. + const site_type& get_comparison_site(const node_type& node) const { + if (node.left_site().sorted_index() > node.right_site().sorted_index()) { + return node.left_site(); + } + return node.right_site(); + } + + const point_type& get_comparison_point(const site_type& site) const { + return point_comparison_(site.point0(), site.point1()) ? + site.point0() : site.point1(); + } + + // Get comparison pair: y coordinate and direction of the newer site. + std::pair get_comparison_y( + const node_type& node, bool is_new_node = true) const { + if (node.left_site().sorted_index() == + node.right_site().sorted_index()) { + return std::make_pair(node.left_site().y0(), 0); + } + if (node.left_site().sorted_index() > node.right_site().sorted_index()) { + if (!is_new_node && + node.left_site().is_segment() && + is_vertical(node.left_site())) { + return std::make_pair(node.left_site().y0(), 1); + } + return std::make_pair(node.left_site().y1(), 1); + } + return std::make_pair(node.right_site().y0(), -1); + } + + point_comparison_type point_comparison_; + distance_predicate_type distance_predicate_; + }; + + template + class circle_existence_predicate { + public: + typedef typename Site::point_type point_type; + typedef Site site_type; + + bool ppp(const site_type& site1, + const site_type& site2, + const site_type& site3) const { + return ot::eval(site1.point0(), + site2.point0(), + site3.point0()) == ot::RIGHT; + } + + bool pps(const site_type& site1, + const site_type& site2, + const site_type& site3, + int segment_index) const { + if (segment_index != 2) { + typename ot::Orientation orient1 = ot::eval( + site1.point0(), site2.point0(), site3.point0()); + typename ot::Orientation orient2 = ot::eval( + site1.point0(), site2.point0(), site3.point1()); + if (segment_index == 1 && site1.x0() >= site2.x0()) { + if (orient1 != ot::RIGHT) + return false; + } else if (segment_index == 3 && site2.x0() >= site1.x0()) { + if (orient2 != ot::RIGHT) + return false; + } else if (orient1 != ot::RIGHT && orient2 != ot::RIGHT) { + return false; + } + } else { + return (site3.point0() != site1.point0()) || + (site3.point1() != site2.point0()); + } + return true; + } + + bool pss(const site_type& site1, + const site_type& site2, + const site_type& site3, + int point_index) const { + if (site2.sorted_index() == site3.sorted_index()) { + return false; + } + if (point_index == 2) { + if (!site2.is_inverse() && site3.is_inverse()) + return false; + if (site2.is_inverse() == site3.is_inverse() && + ot::eval(site2.point0(), + site1.point0(), + site3.point1()) != ot::RIGHT) + return false; + } + return true; + } + + bool sss(const site_type& site1, + const site_type& site2, + const site_type& site3) const { + return (site1.sorted_index() != site2.sorted_index()) && + (site2.sorted_index() != site3.sorted_index()); + } + }; + + template + class mp_circle_formation_functor { + public: + typedef typename Site::point_type point_type; + typedef Site site_type; + typedef Circle circle_type; + typedef robust_sqrt_expr + robust_sqrt_expr_type; + + void ppp(const site_type& site1, + const site_type& site2, + const site_type& site3, + circle_type& circle, + bool recompute_c_x = true, + bool recompute_c_y = true, + bool recompute_lower_x = true) { + big_int_type dif_x[3], dif_y[3], sum_x[2], sum_y[2]; + dif_x[0] = static_cast(site1.x()) - + static_cast(site2.x()); + dif_x[1] = static_cast(site2.x()) - + static_cast(site3.x()); + dif_x[2] = static_cast(site1.x()) - + static_cast(site3.x()); + dif_y[0] = static_cast(site1.y()) - + static_cast(site2.y()); + dif_y[1] = static_cast(site2.y()) - + static_cast(site3.y()); + dif_y[2] = static_cast(site1.y()) - + static_cast(site3.y()); + sum_x[0] = static_cast(site1.x()) + + static_cast(site2.x()); + sum_x[1] = static_cast(site2.x()) + + static_cast(site3.x()); + sum_y[0] = static_cast(site1.y()) + + static_cast(site2.y()); + sum_y[1] = static_cast(site2.y()) + + static_cast(site3.y()); + fpt_type inv_denom = to_fpt(0.5) / to_fpt(static_cast( + dif_x[0] * dif_y[1] - dif_x[1] * dif_y[0])); + big_int_type numer1 = dif_x[0] * sum_x[0] + dif_y[0] * sum_y[0]; + big_int_type numer2 = dif_x[1] * sum_x[1] + dif_y[1] * sum_y[1]; + + if (recompute_c_x || recompute_lower_x) { + big_int_type c_x = numer1 * dif_y[1] - numer2 * dif_y[0]; + circle.x(to_fpt(c_x) * inv_denom); + + if (recompute_lower_x) { + // Evaluate radius of the circle. + big_int_type sqr_r = (dif_x[0] * dif_x[0] + dif_y[0] * dif_y[0]) * + (dif_x[1] * dif_x[1] + dif_y[1] * dif_y[1]) * + (dif_x[2] * dif_x[2] + dif_y[2] * dif_y[2]); + fpt_type r = get_sqrt(to_fpt(sqr_r)); + + // If c_x >= 0 then lower_x = c_x + r, + // else lower_x = (c_x * c_x - r * r) / (c_x - r). + // To guarantee epsilon relative error. + if (!is_neg(circle.x())) { + if (!is_neg(inv_denom)) { + circle.lower_x(circle.x() + r * inv_denom); + } else { + circle.lower_x(circle.x() - r * inv_denom); + } + } else { + big_int_type numer = c_x * c_x - sqr_r; + fpt_type lower_x = to_fpt(numer) * inv_denom / (to_fpt(c_x) + r); + circle.lower_x(lower_x); + } + } + } + + if (recompute_c_y) { + big_int_type c_y = numer2 * dif_x[0] - numer1 * dif_x[1]; + circle.y(to_fpt(c_y) * inv_denom); + } + } + + // Recompute parameters of the circle event using high-precision library. + void pps(const site_type& site1, + const site_type& site2, + const site_type& site3, + int segment_index, + circle_type& c_event, + bool recompute_c_x = true, + bool recompute_c_y = true, + bool recompute_lower_x = true) { + big_int_type cA[4], cB[4]; + big_int_type line_a = static_cast(site3.y1()) - + static_cast(site3.y0()); + big_int_type line_b = static_cast(site3.x0()) - + static_cast(site3.x1()); + big_int_type segm_len = line_a * line_a + line_b * line_b; + big_int_type vec_x = static_cast(site2.y()) - + static_cast(site1.y()); + big_int_type vec_y = static_cast(site1.x()) - + static_cast(site2.x()); + big_int_type sum_x = static_cast(site1.x()) + + static_cast(site2.x()); + big_int_type sum_y = static_cast(site1.y()) + + static_cast(site2.y()); + big_int_type teta = line_a * vec_x + line_b * vec_y; + big_int_type denom = vec_x * line_b - vec_y * line_a; + + big_int_type dif0 = static_cast(site3.y1()) - + static_cast(site1.y()); + big_int_type dif1 = static_cast(site1.x()) - + static_cast(site3.x1()); + big_int_type A = line_a * dif1 - line_b * dif0; + dif0 = static_cast(site3.y1()) - + static_cast(site2.y()); + dif1 = static_cast(site2.x()) - + static_cast(site3.x1()); + big_int_type B = line_a * dif1 - line_b * dif0; + big_int_type sum_AB = A + B; + + if (is_zero(denom)) { + big_int_type numer = teta * teta - sum_AB * sum_AB; + denom = teta * sum_AB; + cA[0] = denom * sum_x * 2 + numer * vec_x; + cB[0] = segm_len; + cA[1] = denom * sum_AB * 2 + numer * teta; + cB[1] = 1; + cA[2] = denom * sum_y * 2 + numer * vec_y; + fpt_type inv_denom = to_fpt(1.0) / to_fpt(denom); + if (recompute_c_x) + c_event.x(to_fpt(0.25) * to_fpt(cA[0]) * inv_denom); + if (recompute_c_y) + c_event.y(to_fpt(0.25) * to_fpt(cA[2]) * inv_denom); + if (recompute_lower_x) { + c_event.lower_x(to_fpt(0.25) * to_fpt(sqrt_expr_.eval2(cA, cB)) * + inv_denom / get_sqrt(to_fpt(segm_len))); + } + return; + } + + big_int_type det = (teta * teta + denom * denom) * A * B * 4; + fpt_type inv_denom_sqr = to_fpt(1.0) / to_fpt(denom); + inv_denom_sqr *= inv_denom_sqr; + + if (recompute_c_x || recompute_lower_x) { + cA[0] = sum_x * denom * denom + teta * sum_AB * vec_x; + cB[0] = 1; + cA[1] = (segment_index == 2) ? -vec_x : vec_x; + cB[1] = det; + if (recompute_c_x) { + c_event.x(to_fpt(0.5) * to_fpt(sqrt_expr_.eval2(cA, cB)) * + inv_denom_sqr); + } + } + + if (recompute_c_y || recompute_lower_x) { + cA[2] = sum_y * denom * denom + teta * sum_AB * vec_y; + cB[2] = 1; + cA[3] = (segment_index == 2) ? -vec_y : vec_y; + cB[3] = det; + if (recompute_c_y) { + c_event.y(to_fpt(0.5) * to_fpt(sqrt_expr_.eval2(&cA[2], &cB[2])) * + inv_denom_sqr); + } + } + + if (recompute_lower_x) { + cB[0] = cB[0] * segm_len; + cB[1] = cB[1] * segm_len; + cA[2] = sum_AB * (denom * denom + teta * teta); + cB[2] = 1; + cA[3] = (segment_index == 2) ? -teta : teta; + cB[3] = det; + c_event.lower_x(to_fpt(0.5) * to_fpt(sqrt_expr_.eval4(cA, cB)) * + inv_denom_sqr / get_sqrt(to_fpt(segm_len))); + } + } + + // Recompute parameters of the circle event using high-precision library. + void pss(const site_type& site1, + const site_type& site2, + const site_type& site3, + int point_index, + circle_type& c_event, + bool recompute_c_x = true, + bool recompute_c_y = true, + bool recompute_lower_x = true) { + big_int_type a[2], b[2], c[2], cA[4], cB[4]; + const point_type& segm_start1 = site2.point1(); + const point_type& segm_end1 = site2.point0(); + const point_type& segm_start2 = site3.point0(); + const point_type& segm_end2 = site3.point1(); + a[0] = static_cast(segm_end1.x()) - + static_cast(segm_start1.x()); + b[0] = static_cast(segm_end1.y()) - + static_cast(segm_start1.y()); + a[1] = static_cast(segm_end2.x()) - + static_cast(segm_start2.x()); + b[1] = static_cast(segm_end2.y()) - + static_cast(segm_start2.y()); + big_int_type orientation = a[1] * b[0] - a[0] * b[1]; + if (is_zero(orientation)) { + fpt_type denom = to_fpt(2.0) * to_fpt( + static_cast(a[0] * a[0] + b[0] * b[0])); + c[0] = b[0] * (static_cast(segm_start2.x()) - + static_cast(segm_start1.x())) - + a[0] * (static_cast(segm_start2.y()) - + static_cast(segm_start1.y())); + big_int_type dx = a[0] * (static_cast(site1.y()) - + static_cast(segm_start1.y())) - + b[0] * (static_cast(site1.x()) - + static_cast(segm_start1.x())); + big_int_type dy = b[0] * (static_cast(site1.x()) - + static_cast(segm_start2.x())) - + a[0] * (static_cast(site1.y()) - + static_cast(segm_start2.y())); + cB[0] = dx * dy; + cB[1] = 1; + + if (recompute_c_y) { + cA[0] = b[0] * ((point_index == 2) ? 2 : -2); + cA[1] = a[0] * a[0] * (static_cast(segm_start1.y()) + + static_cast(segm_start2.y())) - + a[0] * b[0] * (static_cast(segm_start1.x()) + + static_cast(segm_start2.x()) - + static_cast(site1.x()) * 2) + + b[0] * b[0] * (static_cast(site1.y()) * 2); + fpt_type c_y = to_fpt(sqrt_expr_.eval2(cA, cB)); + c_event.y(c_y / denom); + } + + if (recompute_c_x || recompute_lower_x) { + cA[0] = a[0] * ((point_index == 2) ? 2 : -2); + cA[1] = b[0] * b[0] * (static_cast(segm_start1.x()) + + static_cast(segm_start2.x())) - + a[0] * b[0] * (static_cast(segm_start1.y()) + + static_cast(segm_start2.y()) - + static_cast(site1.y()) * 2) + + a[0] * a[0] * (static_cast(site1.x()) * 2); + + if (recompute_c_x) { + fpt_type c_x = to_fpt(sqrt_expr_.eval2(cA, cB)); + c_event.x(c_x / denom); + } + + if (recompute_lower_x) { + cA[2] = is_neg(c[0]) ? -c[0] : c[0]; + cB[2] = a[0] * a[0] + b[0] * b[0]; + fpt_type lower_x = to_fpt(sqrt_expr_.eval3(cA, cB)); + c_event.lower_x(lower_x / denom); + } + } + return; + } + c[0] = b[0] * segm_end1.x() - a[0] * segm_end1.y(); + c[1] = a[1] * segm_end2.y() - b[1] * segm_end2.x(); + big_int_type ix = a[0] * c[1] + a[1] * c[0]; + big_int_type iy = b[0] * c[1] + b[1] * c[0]; + big_int_type dx = ix - orientation * site1.x(); + big_int_type dy = iy - orientation * site1.y(); + if (is_zero(dx) && is_zero(dy)) { + fpt_type denom = to_fpt(orientation); + fpt_type c_x = to_fpt(ix) / denom; + fpt_type c_y = to_fpt(iy) / denom; + c_event = circle_type(c_x, c_y, c_x); + return; + } + + big_int_type sign = ((point_index == 2) ? 1 : -1) * + (is_neg(orientation) ? 1 : -1); + cA[0] = a[1] * -dx + b[1] * -dy; + cA[1] = a[0] * -dx + b[0] * -dy; + cA[2] = sign; + cA[3] = 0; + cB[0] = a[0] * a[0] + b[0] * b[0]; + cB[1] = a[1] * a[1] + b[1] * b[1]; + cB[2] = a[0] * a[1] + b[0] * b[1]; + cB[3] = (a[0] * dy - b[0] * dx) * (a[1] * dy - b[1] * dx) * -2; + fpt_type temp = to_fpt( + sqrt_expr_evaluator_pss4(cA, cB)); + fpt_type denom = temp * to_fpt(orientation); + + if (recompute_c_y) { + cA[0] = b[1] * (dx * dx + dy * dy) - iy * (dx * a[1] + dy * b[1]); + cA[1] = b[0] * (dx * dx + dy * dy) - iy * (dx * a[0] + dy * b[0]); + cA[2] = iy * sign; + fpt_type cy = to_fpt( + sqrt_expr_evaluator_pss4(cA, cB)); + c_event.y(cy / denom); + } + + if (recompute_c_x || recompute_lower_x) { + cA[0] = a[1] * (dx * dx + dy * dy) - ix * (dx * a[1] + dy * b[1]); + cA[1] = a[0] * (dx * dx + dy * dy) - ix * (dx * a[0] + dy * b[0]); + cA[2] = ix * sign; + + if (recompute_c_x) { + fpt_type cx = to_fpt( + sqrt_expr_evaluator_pss4(cA, cB)); + c_event.x(cx / denom); + } + + if (recompute_lower_x) { + cA[3] = orientation * (dx * dx + dy * dy) * (is_neg(temp) ? -1 : 1); + fpt_type lower_x = to_fpt( + sqrt_expr_evaluator_pss4(cA, cB)); + c_event.lower_x(lower_x / denom); + } + } + } + + // Recompute parameters of the circle event using high-precision library. + void sss(const site_type& site1, + const site_type& site2, + const site_type& site3, + circle_type& c_event, + bool recompute_c_x = true, + bool recompute_c_y = true, + bool recompute_lower_x = true) { + big_int_type a[3], b[3], c[3], cA[4], cB[4]; + // cA - corresponds to the cross product. + // cB - corresponds to the squared length. + a[0] = static_cast(site1.x1()) - + static_cast(site1.x0()); + a[1] = static_cast(site2.x1()) - + static_cast(site2.x0()); + a[2] = static_cast(site3.x1()) - + static_cast(site3.x0()); + + b[0] = static_cast(site1.y1()) - + static_cast(site1.y0()); + b[1] = static_cast(site2.y1()) - + static_cast(site2.y0()); + b[2] = static_cast(site3.y1()) - + static_cast(site3.y0()); + + c[0] = static_cast(site1.x0()) * + static_cast(site1.y1()) - + static_cast(site1.y0()) * + static_cast(site1.x1()); + c[1] = static_cast(site2.x0()) * + static_cast(site2.y1()) - + static_cast(site2.y0()) * + static_cast(site2.x1()); + c[2] = static_cast(site3.x0()) * + static_cast(site3.y1()) - + static_cast(site3.y0()) * + static_cast(site3.x1()); + + for (int i = 0; i < 3; ++i) + cB[i] = a[i] * a[i] + b[i] * b[i]; + + for (int i = 0; i < 3; ++i) { + int j = (i+1) % 3; + int k = (i+2) % 3; + cA[i] = a[j] * b[k] - a[k] * b[j]; + } + fpt_type denom = to_fpt(sqrt_expr_.eval3(cA, cB)); + + if (recompute_c_y) { + for (int i = 0; i < 3; ++i) { + int j = (i+1) % 3; + int k = (i+2) % 3; + cA[i] = b[j] * c[k] - b[k] * c[j]; + } + fpt_type c_y = to_fpt(sqrt_expr_.eval3(cA, cB)); + c_event.y(c_y / denom); + } + + if (recompute_c_x || recompute_lower_x) { + cA[3] = 0; + for (int i = 0; i < 3; ++i) { + int j = (i+1) % 3; + int k = (i+2) % 3; + cA[i] = a[j] * c[k] - a[k] * c[j]; + if (recompute_lower_x) { + cA[3] = cA[3] + cA[i] * b[i]; + } + } + + if (recompute_c_x) { + fpt_type c_x = to_fpt(sqrt_expr_.eval3(cA, cB)); + c_event.x(c_x / denom); + } + + if (recompute_lower_x) { + cB[3] = 1; + fpt_type lower_x = to_fpt(sqrt_expr_.eval4(cA, cB)); + c_event.lower_x(lower_x / denom); + } + } + } + + private: + // Evaluates A[3] + A[0] * sqrt(B[0]) + A[1] * sqrt(B[1]) + + // A[2] * sqrt(B[3] * (sqrt(B[0] * B[1]) + B[2])). + template + _fpt sqrt_expr_evaluator_pss4(_int *A, _int *B) { + _int cA[4], cB[4]; + if (is_zero(A[3])) { + _fpt lh = sqrt_expr_.eval2(A, B); + cA[0] = 1; + cB[0] = B[0] * B[1]; + cA[1] = B[2]; + cB[1] = 1; + _fpt rh = sqrt_expr_.eval1(A+2, B+3) * + get_sqrt(sqrt_expr_.eval2(cA, cB)); + if ((!is_neg(lh) && !is_neg(rh)) || (!is_pos(lh) && !is_pos(rh))) + return lh + rh; + cA[0] = A[0] * A[0] * B[0] + A[1] * A[1] * B[1] - + A[2] * A[2] * B[3] * B[2]; + cB[0] = 1; + cA[1] = A[0] * A[1] * 2 - A[2] * A[2] * B[3]; + cB[1] = B[0] * B[1]; + _fpt numer = sqrt_expr_.eval2(cA, cB); + return numer / (lh - rh); + } + cA[0] = 1; + cB[0] = B[0] * B[1]; + cA[1] = B[2]; + cB[1] = 1; + _fpt rh = sqrt_expr_.eval1(A+2, B+3) * get_sqrt(sqrt_expr_.eval2(cA, cB)); + cA[0] = A[0]; + cB[0] = B[0]; + cA[1] = A[1]; + cB[1] = B[1]; + cA[2] = A[3]; + cB[2] = 1; + _fpt lh = sqrt_expr_.eval3(cA, cB); + if ((!is_neg(lh) && !is_neg(rh)) || (!is_pos(lh) && !is_pos(rh))) + return lh + rh; + cA[0] = A[3] * A[0] * 2; + cA[1] = A[3] * A[1] * 2; + cA[2] = A[0] * A[0] * B[0] + A[1] * A[1] * B[1] + + A[3] * A[3] - A[2] * A[2] * B[2] * B[3]; + cA[3] = A[0] * A[1] * 2 - A[2] * A[2] * B[3]; + cB[3] = B[0] * B[1]; + _fpt numer = sqrt_expr_evaluator_pss3<_int, _fpt>(cA, cB); + return numer / (lh - rh); + } + + template + // Evaluates A[0] * sqrt(B[0]) + A[1] * sqrt(B[1]) + + // A[2] + A[3] * sqrt(B[0] * B[1]). + // B[3] = B[0] * B[1]. + _fpt sqrt_expr_evaluator_pss3(_int *A, _int *B) { + _int cA[2], cB[2]; + _fpt lh = sqrt_expr_.eval2(A, B); + _fpt rh = sqrt_expr_.eval2(A+2, B+2); + if ((!is_neg(lh) && !is_neg(rh)) || (!is_pos(lh) && !is_pos(rh))) + return lh + rh; + cA[0] = A[0] * A[0] * B[0] + A[1] * A[1] * B[1] - + A[2] * A[2] - A[3] * A[3] * B[0] * B[1]; + cB[0] = 1; + cA[1] = (A[0] * A[1] - A[2] * A[3]) * 2; + cB[1] = B[3]; + _fpt numer = sqrt_expr_.eval2(cA, cB); + return numer / (lh - rh); + } + + robust_sqrt_expr_type sqrt_expr_; + to_fpt_converter to_fpt; + }; + + template + class lazy_circle_formation_functor { + public: + typedef robust_fpt robust_fpt_type; + typedef robust_dif robust_dif_type; + typedef typename Site::point_type point_type; + typedef Site site_type; + typedef Circle circle_type; + typedef mp_circle_formation_functor + exact_circle_formation_functor_type; + + void ppp(const site_type& site1, + const site_type& site2, + const site_type& site3, + circle_type& c_event) { + fpt_type dif_x1 = to_fpt(site1.x()) - to_fpt(site2.x()); + fpt_type dif_x2 = to_fpt(site2.x()) - to_fpt(site3.x()); + fpt_type dif_y1 = to_fpt(site1.y()) - to_fpt(site2.y()); + fpt_type dif_y2 = to_fpt(site2.y()) - to_fpt(site3.y()); + fpt_type orientation = robust_cross_product( + static_cast(site1.x()) - + static_cast(site2.x()), + static_cast(site2.x()) - + static_cast(site3.x()), + static_cast(site1.y()) - + static_cast(site2.y()), + static_cast(site2.y()) - + static_cast(site3.y())); + robust_fpt_type inv_orientation(to_fpt(0.5) / orientation, to_fpt(2.0)); + fpt_type sum_x1 = to_fpt(site1.x()) + to_fpt(site2.x()); + fpt_type sum_x2 = to_fpt(site2.x()) + to_fpt(site3.x()); + fpt_type sum_y1 = to_fpt(site1.y()) + to_fpt(site2.y()); + fpt_type sum_y2 = to_fpt(site2.y()) + to_fpt(site3.y()); + fpt_type dif_x3 = to_fpt(site1.x()) - to_fpt(site3.x()); + fpt_type dif_y3 = to_fpt(site1.y()) - to_fpt(site3.y()); + robust_dif_type c_x, c_y; + c_x += robust_fpt_type(dif_x1 * sum_x1 * dif_y2, to_fpt(2.0)); + c_x += robust_fpt_type(dif_y1 * sum_y1 * dif_y2, to_fpt(2.0)); + c_x -= robust_fpt_type(dif_x2 * sum_x2 * dif_y1, to_fpt(2.0)); + c_x -= robust_fpt_type(dif_y2 * sum_y2 * dif_y1, to_fpt(2.0)); + c_y += robust_fpt_type(dif_x2 * sum_x2 * dif_x1, to_fpt(2.0)); + c_y += robust_fpt_type(dif_y2 * sum_y2 * dif_x1, to_fpt(2.0)); + c_y -= robust_fpt_type(dif_x1 * sum_x1 * dif_x2, to_fpt(2.0)); + c_y -= robust_fpt_type(dif_y1 * sum_y1 * dif_x2, to_fpt(2.0)); + robust_dif_type lower_x(c_x); + lower_x -= robust_fpt_type(get_sqrt( + (dif_x1 * dif_x1 + dif_y1 * dif_y1) * + (dif_x2 * dif_x2 + dif_y2 * dif_y2) * + (dif_x3 * dif_x3 + dif_y3 * dif_y3)), to_fpt(5.0)); + c_event = circle_type( + c_x.dif().fpv() * inv_orientation.fpv(), + c_y.dif().fpv() * inv_orientation.fpv(), + lower_x.dif().fpv() * inv_orientation.fpv()); + bool recompute_c_x = c_x.dif().ulp() > ULPS; + bool recompute_c_y = c_y.dif().ulp() > ULPS; + bool recompute_lower_x = lower_x.dif().ulp() > ULPS; + if (recompute_c_x || recompute_c_y || recompute_lower_x) { + exact_circle_formation_functor_.ppp( + site1, site2, site3, c_event, + recompute_c_x, recompute_c_y, recompute_lower_x); + } + } + + void pps(const site_type& site1, + const site_type& site2, + const site_type& site3, + int segment_index, + circle_type& c_event) { + fpt_type line_a = to_fpt(site3.y1()) - to_fpt(site3.y0()); + fpt_type line_b = to_fpt(site3.x0()) - to_fpt(site3.x1()); + fpt_type vec_x = to_fpt(site2.y()) - to_fpt(site1.y()); + fpt_type vec_y = to_fpt(site1.x()) - to_fpt(site2.x()); + robust_fpt_type teta(robust_cross_product( + static_cast(site3.y1()) - + static_cast(site3.y0()), + static_cast(site3.x0()) - + static_cast(site3.x1()), + static_cast(site2.x()) - + static_cast(site1.x()), + static_cast(site2.y()) - + static_cast(site1.y())), to_fpt(1.0)); + robust_fpt_type A(robust_cross_product( + static_cast(site3.y0()) - + static_cast(site3.y1()), + static_cast(site3.x0()) - + static_cast(site3.x1()), + static_cast(site3.y1()) - + static_cast(site1.y()), + static_cast(site3.x1()) - + static_cast(site1.x())), to_fpt(1.0)); + robust_fpt_type B(robust_cross_product( + static_cast(site3.y0()) - + static_cast(site3.y1()), + static_cast(site3.x0()) - + static_cast(site3.x1()), + static_cast(site3.y1()) - + static_cast(site2.y()), + static_cast(site3.x1()) - + static_cast(site2.x())), to_fpt(1.0)); + robust_fpt_type denom(robust_cross_product( + static_cast(site1.y()) - + static_cast(site2.y()), + static_cast(site1.x()) - + static_cast(site2.x()), + static_cast(site3.y1()) - + static_cast(site3.y0()), + static_cast(site3.x1()) - + static_cast(site3.x0())), to_fpt(1.0)); + robust_fpt_type inv_segm_len(to_fpt(1.0) / + get_sqrt(line_a * line_a + line_b * line_b), to_fpt(3.0)); + robust_dif_type t; + if (ot::eval(denom) == ot::COLLINEAR) { + t += teta / (robust_fpt_type(to_fpt(8.0)) * A); + t -= A / (robust_fpt_type(to_fpt(2.0)) * teta); + } else { + robust_fpt_type det = ((teta * teta + denom * denom) * A * B).sqrt(); + if (segment_index == 2) { + t -= det / (denom * denom); + } else { + t += det / (denom * denom); + } + t += teta * (A + B) / (robust_fpt_type(to_fpt(2.0)) * denom * denom); + } + robust_dif_type c_x, c_y; + c_x += robust_fpt_type(to_fpt(0.5) * + (to_fpt(site1.x()) + to_fpt(site2.x()))); + c_x += robust_fpt_type(vec_x) * t; + c_y += robust_fpt_type(to_fpt(0.5) * + (to_fpt(site1.y()) + to_fpt(site2.y()))); + c_y += robust_fpt_type(vec_y) * t; + robust_dif_type r, lower_x(c_x); + r -= robust_fpt_type(line_a) * robust_fpt_type(site3.x0()); + r -= robust_fpt_type(line_b) * robust_fpt_type(site3.y0()); + r += robust_fpt_type(line_a) * c_x; + r += robust_fpt_type(line_b) * c_y; + if (r.pos().fpv() < r.neg().fpv()) + r = -r; + lower_x += r * inv_segm_len; + c_event = circle_type( + c_x.dif().fpv(), c_y.dif().fpv(), lower_x.dif().fpv()); + bool recompute_c_x = c_x.dif().ulp() > ULPS; + bool recompute_c_y = c_y.dif().ulp() > ULPS; + bool recompute_lower_x = lower_x.dif().ulp() > ULPS; + if (recompute_c_x || recompute_c_y || recompute_lower_x) { + exact_circle_formation_functor_.pps( + site1, site2, site3, segment_index, c_event, + recompute_c_x, recompute_c_y, recompute_lower_x); + } + } + + void pss(const site_type& site1, + const site_type& site2, + const site_type& site3, + int point_index, + circle_type& c_event) { + const point_type& segm_start1 = site2.point1(); + const point_type& segm_end1 = site2.point0(); + const point_type& segm_start2 = site3.point0(); + const point_type& segm_end2 = site3.point1(); + fpt_type a1 = to_fpt(segm_end1.x()) - to_fpt(segm_start1.x()); + fpt_type b1 = to_fpt(segm_end1.y()) - to_fpt(segm_start1.y()); + fpt_type a2 = to_fpt(segm_end2.x()) - to_fpt(segm_start2.x()); + fpt_type b2 = to_fpt(segm_end2.y()) - to_fpt(segm_start2.y()); + bool recompute_c_x, recompute_c_y, recompute_lower_x; + robust_fpt_type orientation(robust_cross_product( + static_cast(segm_end1.y()) - + static_cast(segm_start1.y()), + static_cast(segm_end1.x()) - + static_cast(segm_start1.x()), + static_cast(segm_end2.y()) - + static_cast(segm_start2.y()), + static_cast(segm_end2.x()) - + static_cast(segm_start2.x())), to_fpt(1.0)); + if (ot::eval(orientation) == ot::COLLINEAR) { + robust_fpt_type a(a1 * a1 + b1 * b1, to_fpt(2.0)); + robust_fpt_type c(robust_cross_product( + static_cast(segm_end1.y()) - + static_cast(segm_start1.y()), + static_cast(segm_end1.x()) - + static_cast(segm_start1.x()), + static_cast(segm_start2.y()) - + static_cast(segm_start1.y()), + static_cast(segm_start2.x()) - + static_cast(segm_start1.x())), to_fpt(1.0)); + robust_fpt_type det( + robust_cross_product( + static_cast(segm_end1.x()) - + static_cast(segm_start1.x()), + static_cast(segm_end1.y()) - + static_cast(segm_start1.y()), + static_cast(site1.x()) - + static_cast(segm_start1.x()), + static_cast(site1.y()) - + static_cast(segm_start1.y())) * + robust_cross_product( + static_cast(segm_end1.y()) - + static_cast(segm_start1.y()), + static_cast(segm_end1.x()) - + static_cast(segm_start1.x()), + static_cast(site1.y()) - + static_cast(segm_start2.y()), + static_cast(site1.x()) - + static_cast(segm_start2.x())), + to_fpt(3.0)); + robust_dif_type t; + t -= robust_fpt_type(a1) * robust_fpt_type(( + to_fpt(segm_start1.x()) + to_fpt(segm_start2.x())) * to_fpt(0.5) - + to_fpt(site1.x())); + t -= robust_fpt_type(b1) * robust_fpt_type(( + to_fpt(segm_start1.y()) + to_fpt(segm_start2.y())) * to_fpt(0.5) - + to_fpt(site1.y())); + if (point_index == 2) { + t += det.sqrt(); + } else { + t -= det.sqrt(); + } + t /= a; + robust_dif_type c_x, c_y; + c_x += robust_fpt_type(to_fpt(0.5) * ( + to_fpt(segm_start1.x()) + to_fpt(segm_start2.x()))); + c_x += robust_fpt_type(a1) * t; + c_y += robust_fpt_type(to_fpt(0.5) * ( + to_fpt(segm_start1.y()) + to_fpt(segm_start2.y()))); + c_y += robust_fpt_type(b1) * t; + robust_dif_type lower_x(c_x); + if (is_neg(c)) { + lower_x -= robust_fpt_type(to_fpt(0.5)) * c / a.sqrt(); + } else { + lower_x += robust_fpt_type(to_fpt(0.5)) * c / a.sqrt(); + } + recompute_c_x = c_x.dif().ulp() > ULPS; + recompute_c_y = c_y.dif().ulp() > ULPS; + recompute_lower_x = lower_x.dif().ulp() > ULPS; + c_event = + circle_type(c_x.dif().fpv(), c_y.dif().fpv(), lower_x.dif().fpv()); + } else { + robust_fpt_type sqr_sum1(get_sqrt(a1 * a1 + b1 * b1), to_fpt(2.0)); + robust_fpt_type sqr_sum2(get_sqrt(a2 * a2 + b2 * b2), to_fpt(2.0)); + robust_fpt_type a(robust_cross_product( + static_cast(segm_end1.x()) - + static_cast(segm_start1.x()), + static_cast(segm_end1.y()) - + static_cast(segm_start1.y()), + static_cast(segm_start2.y()) - + static_cast(segm_end2.y()), + static_cast(segm_end2.x()) - + static_cast(segm_start2.x())), to_fpt(1.0)); + if (!is_neg(a)) { + a += sqr_sum1 * sqr_sum2; + } else { + a = (orientation * orientation) / (sqr_sum1 * sqr_sum2 - a); + } + robust_fpt_type or1(robust_cross_product( + static_cast(segm_end1.y()) - + static_cast(segm_start1.y()), + static_cast(segm_end1.x()) - + static_cast(segm_start1.x()), + static_cast(segm_end1.y()) - + static_cast(site1.y()), + static_cast(segm_end1.x()) - + static_cast(site1.x())), to_fpt(1.0)); + robust_fpt_type or2(robust_cross_product( + static_cast(segm_end2.x()) - + static_cast(segm_start2.x()), + static_cast(segm_end2.y()) - + static_cast(segm_start2.y()), + static_cast(segm_end2.x()) - + static_cast(site1.x()), + static_cast(segm_end2.y()) - + static_cast(site1.y())), to_fpt(1.0)); + robust_fpt_type det = robust_fpt_type(to_fpt(2.0)) * a * or1 * or2; + robust_fpt_type c1(robust_cross_product( + static_cast(segm_end1.y()) - + static_cast(segm_start1.y()), + static_cast(segm_end1.x()) - + static_cast(segm_start1.x()), + static_cast(segm_end1.y()), + static_cast(segm_end1.x())), to_fpt(1.0)); + robust_fpt_type c2(robust_cross_product( + static_cast(segm_end2.x()) - + static_cast(segm_start2.x()), + static_cast(segm_end2.y()) - + static_cast(segm_start2.y()), + static_cast(segm_end2.x()), + static_cast(segm_end2.y())), to_fpt(1.0)); + robust_fpt_type inv_orientation = + robust_fpt_type(to_fpt(1.0)) / orientation; + robust_dif_type t, b, ix, iy; + ix += robust_fpt_type(a2) * c1 * inv_orientation; + ix += robust_fpt_type(a1) * c2 * inv_orientation; + iy += robust_fpt_type(b1) * c2 * inv_orientation; + iy += robust_fpt_type(b2) * c1 * inv_orientation; + + b += ix * (robust_fpt_type(a1) * sqr_sum2); + b += ix * (robust_fpt_type(a2) * sqr_sum1); + b += iy * (robust_fpt_type(b1) * sqr_sum2); + b += iy * (robust_fpt_type(b2) * sqr_sum1); + b -= sqr_sum1 * robust_fpt_type(robust_cross_product( + static_cast(segm_end2.x()) - + static_cast(segm_start2.x()), + static_cast(segm_end2.y()) - + static_cast(segm_start2.y()), + static_cast(-site1.y()), + static_cast(site1.x())), to_fpt(1.0)); + b -= sqr_sum2 * robust_fpt_type(robust_cross_product( + static_cast(segm_end1.x()) - + static_cast(segm_start1.x()), + static_cast(segm_end1.y()) - + static_cast(segm_start1.y()), + static_cast(-site1.y()), + static_cast(site1.x())), to_fpt(1.0)); + t -= b; + if (point_index == 2) { + t += det.sqrt(); + } else { + t -= det.sqrt(); + } + t /= (a * a); + robust_dif_type c_x(ix), c_y(iy); + c_x += t * (robust_fpt_type(a1) * sqr_sum2); + c_x += t * (robust_fpt_type(a2) * sqr_sum1); + c_y += t * (robust_fpt_type(b1) * sqr_sum2); + c_y += t * (robust_fpt_type(b2) * sqr_sum1); + if (t.pos().fpv() < t.neg().fpv()) { + t = -t; + } + robust_dif_type lower_x(c_x); + if (is_neg(orientation)) { + lower_x -= t * orientation; + } else { + lower_x += t * orientation; + } + recompute_c_x = c_x.dif().ulp() > ULPS; + recompute_c_y = c_y.dif().ulp() > ULPS; + recompute_lower_x = lower_x.dif().ulp() > ULPS; + c_event = circle_type( + c_x.dif().fpv(), c_y.dif().fpv(), lower_x.dif().fpv()); + } + if (recompute_c_x || recompute_c_y || recompute_lower_x) { + exact_circle_formation_functor_.pss( + site1, site2, site3, point_index, c_event, + recompute_c_x, recompute_c_y, recompute_lower_x); + } + } + + void sss(const site_type& site1, + const site_type& site2, + const site_type& site3, + circle_type& c_event) { + robust_fpt_type a1(to_fpt(site1.x1()) - to_fpt(site1.x0())); + robust_fpt_type b1(to_fpt(site1.y1()) - to_fpt(site1.y0())); + robust_fpt_type c1(robust_cross_product( + site1.x0(), site1.y0(), + site1.x1(), site1.y1()), to_fpt(1.0)); + + robust_fpt_type a2(to_fpt(site2.x1()) - to_fpt(site2.x0())); + robust_fpt_type b2(to_fpt(site2.y1()) - to_fpt(site2.y0())); + robust_fpt_type c2(robust_cross_product( + site2.x0(), site2.y0(), + site2.x1(), site2.y1()), to_fpt(1.0)); + + robust_fpt_type a3(to_fpt(site3.x1()) - to_fpt(site3.x0())); + robust_fpt_type b3(to_fpt(site3.y1()) - to_fpt(site3.y0())); + robust_fpt_type c3(robust_cross_product( + site3.x0(), site3.y0(), + site3.x1(), site3.y1()), to_fpt(1.0)); + + robust_fpt_type len1 = (a1 * a1 + b1 * b1).sqrt(); + robust_fpt_type len2 = (a2 * a2 + b2 * b2).sqrt(); + robust_fpt_type len3 = (a3 * a3 + b3 * b3).sqrt(); + robust_fpt_type cross_12(robust_cross_product( + static_cast(site1.x1()) - + static_cast(site1.x0()), + static_cast(site1.y1()) - + static_cast(site1.y0()), + static_cast(site2.x1()) - + static_cast(site2.x0()), + static_cast(site2.y1()) - + static_cast(site2.y0())), to_fpt(1.0)); + robust_fpt_type cross_23(robust_cross_product( + static_cast(site2.x1()) - + static_cast(site2.x0()), + static_cast(site2.y1()) - + static_cast(site2.y0()), + static_cast(site3.x1()) - + static_cast(site3.x0()), + static_cast(site3.y1()) - + static_cast(site3.y0())), to_fpt(1.0)); + robust_fpt_type cross_31(robust_cross_product( + static_cast(site3.x1()) - + static_cast(site3.x0()), + static_cast(site3.y1()) - + static_cast(site3.y0()), + static_cast(site1.x1()) - + static_cast(site1.x0()), + static_cast(site1.y1()) - + static_cast(site1.y0())), to_fpt(1.0)); + + // denom = cross_12 * len3 + cross_23 * len1 + cross_31 * len2. + robust_dif_type denom; + denom += cross_12 * len3; + denom += cross_23 * len1; + denom += cross_31 * len2; + + // denom * r = (b2 * c_x - a2 * c_y - c2 * denom) / len2. + robust_dif_type r; + r -= cross_12 * c3; + r -= cross_23 * c1; + r -= cross_31 * c2; + + robust_dif_type c_x; + c_x += a1 * c2 * len3; + c_x -= a2 * c1 * len3; + c_x += a2 * c3 * len1; + c_x -= a3 * c2 * len1; + c_x += a3 * c1 * len2; + c_x -= a1 * c3 * len2; + + robust_dif_type c_y; + c_y += b1 * c2 * len3; + c_y -= b2 * c1 * len3; + c_y += b2 * c3 * len1; + c_y -= b3 * c2 * len1; + c_y += b3 * c1 * len2; + c_y -= b1 * c3 * len2; + + robust_dif_type lower_x = c_x + r; + + robust_fpt_type denom_dif = denom.dif(); + robust_fpt_type c_x_dif = c_x.dif() / denom_dif; + robust_fpt_type c_y_dif = c_y.dif() / denom_dif; + robust_fpt_type lower_x_dif = lower_x.dif() / denom_dif; + + bool recompute_c_x = c_x_dif.ulp() > ULPS; + bool recompute_c_y = c_y_dif.ulp() > ULPS; + bool recompute_lower_x = lower_x_dif.ulp() > ULPS; + c_event = circle_type(c_x_dif.fpv(), c_y_dif.fpv(), lower_x_dif.fpv()); + if (recompute_c_x || recompute_c_y || recompute_lower_x) { + exact_circle_formation_functor_.sss( + site1, site2, site3, c_event, + recompute_c_x, recompute_c_y, recompute_lower_x); + } + } + + private: + exact_circle_formation_functor_type exact_circle_formation_functor_; + to_fpt_converter to_fpt; + }; + + template , + typename CFF = lazy_circle_formation_functor > + class circle_formation_predicate { + public: + typedef Site site_type; + typedef Circle circle_type; + typedef CEP circle_existence_predicate_type; + typedef CFF circle_formation_functor_type; + + // Create a circle event from the given three sites. + // Returns true if the circle event exists, else false. + // If exists circle event is saved into the c_event variable. + bool operator()(const site_type& site1, const site_type& site2, + const site_type& site3, circle_type& circle) { + if (!site1.is_segment()) { + if (!site2.is_segment()) { + if (!site3.is_segment()) { + // (point, point, point) sites. + if (!circle_existence_predicate_.ppp(site1, site2, site3)) + return false; + circle_formation_functor_.ppp(site1, site2, site3, circle); + } else { + // (point, point, segment) sites. + if (!circle_existence_predicate_.pps(site1, site2, site3, 3)) + return false; + circle_formation_functor_.pps(site1, site2, site3, 3, circle); + } + } else { + if (!site3.is_segment()) { + // (point, segment, point) sites. + if (!circle_existence_predicate_.pps(site1, site3, site2, 2)) + return false; + circle_formation_functor_.pps(site1, site3, site2, 2, circle); + } else { + // (point, segment, segment) sites. + if (!circle_existence_predicate_.pss(site1, site2, site3, 1)) + return false; + circle_formation_functor_.pss(site1, site2, site3, 1, circle); + } + } + } else { + if (!site2.is_segment()) { + if (!site3.is_segment()) { + // (segment, point, point) sites. + if (!circle_existence_predicate_.pps(site2, site3, site1, 1)) + return false; + circle_formation_functor_.pps(site2, site3, site1, 1, circle); + } else { + // (segment, point, segment) sites. + if (!circle_existence_predicate_.pss(site2, site1, site3, 2)) + return false; + circle_formation_functor_.pss(site2, site1, site3, 2, circle); + } + } else { + if (!site3.is_segment()) { + // (segment, segment, point) sites. + if (!circle_existence_predicate_.pss(site3, site1, site2, 3)) + return false; + circle_formation_functor_.pss(site3, site1, site2, 3, circle); + } else { + // (segment, segment, segment) sites. + if (!circle_existence_predicate_.sss(site1, site2, site3)) + return false; + circle_formation_functor_.sss(site1, site2, site3, circle); + } + } + } + if (lies_outside_vertical_segment(circle, site1) || + lies_outside_vertical_segment(circle, site2) || + lies_outside_vertical_segment(circle, site3)) { + return false; + } + return true; + } + + private: + bool lies_outside_vertical_segment( + const circle_type& c, const site_type& s) { + if (!s.is_segment() || !is_vertical(s)) { + return false; + } + fpt_type y0 = to_fpt(s.is_inverse() ? s.y1() : s.y0()); + fpt_type y1 = to_fpt(s.is_inverse() ? s.y0() : s.y1()); + return ulp_cmp(c.y(), y0, ULPS) == ulp_cmp_type::LESS || + ulp_cmp(c.y(), y1, ULPS) == ulp_cmp_type::MORE; + } + + private: + to_fpt_converter to_fpt; + ulp_cmp_type ulp_cmp; + circle_existence_predicate_type circle_existence_predicate_; + circle_formation_functor_type circle_formation_functor_; + }; +}; +} // detail +} // polygon +} // boost + +#endif // BOOST_POLYGON_DETAIL_VORONOI_PREDICATES diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/detail/voronoi_robust_fpt.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/detail/voronoi_robust_fpt.hpp new file mode 100644 index 0000000..ce72ba8 --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/detail/voronoi_robust_fpt.hpp @@ -0,0 +1,501 @@ +// Boost.Polygon library detail/voronoi_robust_fpt.hpp header file + +// Copyright Andrii Sydorchuk 2010-2012. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +#ifndef BOOST_POLYGON_DETAIL_VORONOI_ROBUST_FPT +#define BOOST_POLYGON_DETAIL_VORONOI_ROBUST_FPT + +#include +#include + +// Geometry predicates with floating-point variables usually require +// high-precision predicates to retrieve the correct result. +// Epsilon robust predicates give the result within some epsilon relative +// error, but are a lot faster than high-precision predicates. +// To make algorithm robust and efficient epsilon robust predicates are +// used at the first step. In case of the undefined result high-precision +// arithmetic is used to produce required robustness. This approach +// requires exact computation of epsilon intervals within which epsilon +// robust predicates have undefined value. +// There are two ways to measure an error of floating-point calculations: +// relative error and ULPs (units in the last place). +// Let EPS be machine epsilon, then next inequalities have place: +// 1 EPS <= 1 ULP <= 2 EPS (1), 0.5 ULP <= 1 EPS <= 1 ULP (2). +// ULPs are good for measuring rounding errors and comparing values. +// Relative errors are good for computation of general relative +// error of formulas or expressions. So to calculate epsilon +// interval within which epsilon robust predicates have undefined result +// next schema is used: +// 1) Compute rounding errors of initial variables using ULPs; +// 2) Transform ULPs to epsilons using upper bound of the (1); +// 3) Compute relative error of the formula using epsilon arithmetic; +// 4) Transform epsilon to ULPs using upper bound of the (2); +// In case two values are inside undefined ULP range use high-precision +// arithmetic to produce the correct result, else output the result. +// Look at almost_equal function to see how two floating-point variables +// are checked to fit in the ULP range. +// If A has relative error of r(A) and B has relative error of r(B) then: +// 1) r(A + B) <= max(r(A), r(B)), for A * B >= 0; +// 2) r(A - B) <= B*r(A)+A*r(B)/(A-B), for A * B >= 0; +// 2) r(A * B) <= r(A) + r(B); +// 3) r(A / B) <= r(A) + r(B); +// In addition rounding error should be added, that is always equal to +// 0.5 ULP or at most 1 epsilon. As you might see from the above formulas +// subtraction relative error may be extremely large, that's why +// epsilon robust comparator class is used to store floating point values +// and compute subtraction as the final step of the evaluation. +// For further information about relative errors and ULPs try this link: +// http://docs.sun.com/source/806-3568/ncg_goldberg.html + +namespace boost { +namespace polygon { +namespace detail { + +template +T get_sqrt(const T& that) { + return (std::sqrt)(that); +} + +template +bool is_pos(const T& that) { + return that > 0; +} + +template +bool is_neg(const T& that) { + return that < 0; +} + +template +bool is_zero(const T& that) { + return that == 0; +} + +template +class robust_fpt { + public: + typedef _fpt floating_point_type; + typedef _fpt relative_error_type; + + // Rounding error is at most 1 EPS. + enum { + ROUNDING_ERROR = 1 + }; + + robust_fpt() : fpv_(0.0), re_(0.0) {} + explicit robust_fpt(floating_point_type fpv) : + fpv_(fpv), re_(0.0) {} + robust_fpt(floating_point_type fpv, relative_error_type error) : + fpv_(fpv), re_(error) {} + + floating_point_type fpv() const { return fpv_; } + relative_error_type re() const { return re_; } + relative_error_type ulp() const { return re_; } + + bool has_pos_value() const { + return is_pos(fpv_); + } + + bool has_neg_value() const { + return is_neg(fpv_); + } + + bool has_zero_value() const { + return is_zero(fpv_); + } + + robust_fpt operator-() const { + return robust_fpt(-fpv_, re_); + } + + robust_fpt& operator+=(const robust_fpt& that) { + floating_point_type fpv = this->fpv_ + that.fpv_; + if ((!is_neg(this->fpv_) && !is_neg(that.fpv_)) || + (!is_pos(this->fpv_) && !is_pos(that.fpv_))) { + this->re_ = (std::max)(this->re_, that.re_) + ROUNDING_ERROR; + } else { + floating_point_type temp = + (this->fpv_ * this->re_ - that.fpv_ * that.re_) / fpv; + if (is_neg(temp)) + temp = -temp; + this->re_ = temp + ROUNDING_ERROR; + } + this->fpv_ = fpv; + return *this; + } + + robust_fpt& operator-=(const robust_fpt& that) { + floating_point_type fpv = this->fpv_ - that.fpv_; + if ((!is_neg(this->fpv_) && !is_pos(that.fpv_)) || + (!is_pos(this->fpv_) && !is_neg(that.fpv_))) { + this->re_ = (std::max)(this->re_, that.re_) + ROUNDING_ERROR; + } else { + floating_point_type temp = + (this->fpv_ * this->re_ + that.fpv_ * that.re_) / fpv; + if (is_neg(temp)) + temp = -temp; + this->re_ = temp + ROUNDING_ERROR; + } + this->fpv_ = fpv; + return *this; + } + + robust_fpt& operator*=(const robust_fpt& that) { + this->re_ += that.re_ + ROUNDING_ERROR; + this->fpv_ *= that.fpv_; + return *this; + } + + robust_fpt& operator/=(const robust_fpt& that) { + this->re_ += that.re_ + ROUNDING_ERROR; + this->fpv_ /= that.fpv_; + return *this; + } + + robust_fpt operator+(const robust_fpt& that) const { + floating_point_type fpv = this->fpv_ + that.fpv_; + relative_error_type re; + if ((!is_neg(this->fpv_) && !is_neg(that.fpv_)) || + (!is_pos(this->fpv_) && !is_pos(that.fpv_))) { + re = (std::max)(this->re_, that.re_) + ROUNDING_ERROR; + } else { + floating_point_type temp = + (this->fpv_ * this->re_ - that.fpv_ * that.re_) / fpv; + if (is_neg(temp)) + temp = -temp; + re = temp + ROUNDING_ERROR; + } + return robust_fpt(fpv, re); + } + + robust_fpt operator-(const robust_fpt& that) const { + floating_point_type fpv = this->fpv_ - that.fpv_; + relative_error_type re; + if ((!is_neg(this->fpv_) && !is_pos(that.fpv_)) || + (!is_pos(this->fpv_) && !is_neg(that.fpv_))) { + re = (std::max)(this->re_, that.re_) + ROUNDING_ERROR; + } else { + floating_point_type temp = + (this->fpv_ * this->re_ + that.fpv_ * that.re_) / fpv; + if (is_neg(temp)) + temp = -temp; + re = temp + ROUNDING_ERROR; + } + return robust_fpt(fpv, re); + } + + robust_fpt operator*(const robust_fpt& that) const { + floating_point_type fpv = this->fpv_ * that.fpv_; + relative_error_type re = this->re_ + that.re_ + ROUNDING_ERROR; + return robust_fpt(fpv, re); + } + + robust_fpt operator/(const robust_fpt& that) const { + floating_point_type fpv = this->fpv_ / that.fpv_; + relative_error_type re = this->re_ + that.re_ + ROUNDING_ERROR; + return robust_fpt(fpv, re); + } + + robust_fpt sqrt() const { + return robust_fpt(get_sqrt(fpv_), + re_ * static_cast(0.5) + + ROUNDING_ERROR); + } + + private: + floating_point_type fpv_; + relative_error_type re_; +}; + +template +robust_fpt get_sqrt(const robust_fpt& that) { + return that.sqrt(); +} + +template +bool is_pos(const robust_fpt& that) { + return that.has_pos_value(); +} + +template +bool is_neg(const robust_fpt& that) { + return that.has_neg_value(); +} + +template +bool is_zero(const robust_fpt& that) { + return that.has_zero_value(); +} + +// robust_dif consists of two not negative values: value1 and value2. +// The resulting expression is equal to the value1 - value2. +// Subtraction of a positive value is equivalent to the addition to value2 +// and subtraction of a negative value is equivalent to the addition to +// value1. The structure implicitly avoids difference computation. +template +class robust_dif { + public: + robust_dif() : + positive_sum_(0), + negative_sum_(0) {} + + explicit robust_dif(const T& value) : + positive_sum_((value > 0)?value:0), + negative_sum_((value < 0)?-value:0) {} + + robust_dif(const T& pos, const T& neg) : + positive_sum_(pos), + negative_sum_(neg) {} + + T dif() const { + return positive_sum_ - negative_sum_; + } + + T pos() const { + return positive_sum_; + } + + T neg() const { + return negative_sum_; + } + + robust_dif operator-() const { + return robust_dif(negative_sum_, positive_sum_); + } + + robust_dif& operator+=(const T& val) { + if (!is_neg(val)) + positive_sum_ += val; + else + negative_sum_ -= val; + return *this; + } + + robust_dif& operator+=(const robust_dif& that) { + positive_sum_ += that.positive_sum_; + negative_sum_ += that.negative_sum_; + return *this; + } + + robust_dif& operator-=(const T& val) { + if (!is_neg(val)) + negative_sum_ += val; + else + positive_sum_ -= val; + return *this; + } + + robust_dif& operator-=(const robust_dif& that) { + positive_sum_ += that.negative_sum_; + negative_sum_ += that.positive_sum_; + return *this; + } + + robust_dif& operator*=(const T& val) { + if (!is_neg(val)) { + positive_sum_ *= val; + negative_sum_ *= val; + } else { + positive_sum_ *= -val; + negative_sum_ *= -val; + swap(); + } + return *this; + } + + robust_dif& operator*=(const robust_dif& that) { + T positive_sum = this->positive_sum_ * that.positive_sum_ + + this->negative_sum_ * that.negative_sum_; + T negative_sum = this->positive_sum_ * that.negative_sum_ + + this->negative_sum_ * that.positive_sum_; + positive_sum_ = positive_sum; + negative_sum_ = negative_sum; + return *this; + } + + robust_dif& operator/=(const T& val) { + if (!is_neg(val)) { + positive_sum_ /= val; + negative_sum_ /= val; + } else { + positive_sum_ /= -val; + negative_sum_ /= -val; + swap(); + } + return *this; + } + + private: + void swap() { + (std::swap)(positive_sum_, negative_sum_); + } + + T positive_sum_; + T negative_sum_; +}; + +template +robust_dif operator+(const robust_dif& lhs, + const robust_dif& rhs) { + return robust_dif(lhs.pos() + rhs.pos(), lhs.neg() + rhs.neg()); +} + +template +robust_dif operator+(const robust_dif& lhs, const T& rhs) { + if (!is_neg(rhs)) { + return robust_dif(lhs.pos() + rhs, lhs.neg()); + } else { + return robust_dif(lhs.pos(), lhs.neg() - rhs); + } +} + +template +robust_dif operator+(const T& lhs, const robust_dif& rhs) { + if (!is_neg(lhs)) { + return robust_dif(lhs + rhs.pos(), rhs.neg()); + } else { + return robust_dif(rhs.pos(), rhs.neg() - lhs); + } +} + +template +robust_dif operator-(const robust_dif& lhs, + const robust_dif& rhs) { + return robust_dif(lhs.pos() + rhs.neg(), lhs.neg() + rhs.pos()); +} + +template +robust_dif operator-(const robust_dif& lhs, const T& rhs) { + if (!is_neg(rhs)) { + return robust_dif(lhs.pos(), lhs.neg() + rhs); + } else { + return robust_dif(lhs.pos() - rhs, lhs.neg()); + } +} + +template +robust_dif operator-(const T& lhs, const robust_dif& rhs) { + if (!is_neg(lhs)) { + return robust_dif(lhs + rhs.neg(), rhs.pos()); + } else { + return robust_dif(rhs.neg(), rhs.pos() - lhs); + } +} + +template +robust_dif operator*(const robust_dif& lhs, + const robust_dif& rhs) { + T res_pos = lhs.pos() * rhs.pos() + lhs.neg() * rhs.neg(); + T res_neg = lhs.pos() * rhs.neg() + lhs.neg() * rhs.pos(); + return robust_dif(res_pos, res_neg); +} + +template +robust_dif operator*(const robust_dif& lhs, const T& val) { + if (!is_neg(val)) { + return robust_dif(lhs.pos() * val, lhs.neg() * val); + } else { + return robust_dif(-lhs.neg() * val, -lhs.pos() * val); + } +} + +template +robust_dif operator*(const T& val, const robust_dif& rhs) { + if (!is_neg(val)) { + return robust_dif(val * rhs.pos(), val * rhs.neg()); + } else { + return robust_dif(-val * rhs.neg(), -val * rhs.pos()); + } +} + +template +robust_dif operator/(const robust_dif& lhs, const T& val) { + if (!is_neg(val)) { + return robust_dif(lhs.pos() / val, lhs.neg() / val); + } else { + return robust_dif(-lhs.neg() / val, -lhs.pos() / val); + } +} + +// Used to compute expressions that operate with sqrts with predefined +// relative error. Evaluates expressions of the next type: +// sum(i = 1 .. n)(A[i] * sqrt(B[i])), 1 <= n <= 4. +template +class robust_sqrt_expr { + public: + enum MAX_RELATIVE_ERROR { + MAX_RELATIVE_ERROR_EVAL1 = 4, + MAX_RELATIVE_ERROR_EVAL2 = 7, + MAX_RELATIVE_ERROR_EVAL3 = 16, + MAX_RELATIVE_ERROR_EVAL4 = 25 + }; + + // Evaluates expression (re = 4 EPS): + // A[0] * sqrt(B[0]). + _fpt eval1(_int* A, _int* B) { + _fpt a = convert(A[0]); + _fpt b = convert(B[0]); + return a * get_sqrt(b); + } + + // Evaluates expression (re = 7 EPS): + // A[0] * sqrt(B[0]) + A[1] * sqrt(B[1]). + _fpt eval2(_int* A, _int* B) { + _fpt a = eval1(A, B); + _fpt b = eval1(A + 1, B + 1); + if ((!is_neg(a) && !is_neg(b)) || + (!is_pos(a) && !is_pos(b))) + return a + b; + return convert(A[0] * A[0] * B[0] - A[1] * A[1] * B[1]) / (a - b); + } + + // Evaluates expression (re = 16 EPS): + // A[0] * sqrt(B[0]) + A[1] * sqrt(B[1]) + A[2] * sqrt(B[2]). + _fpt eval3(_int* A, _int* B) { + _fpt a = eval2(A, B); + _fpt b = eval1(A + 2, B + 2); + if ((!is_neg(a) && !is_neg(b)) || + (!is_pos(a) && !is_pos(b))) + return a + b; + tA[3] = A[0] * A[0] * B[0] + A[1] * A[1] * B[1] - A[2] * A[2] * B[2]; + tB[3] = 1; + tA[4] = A[0] * A[1] * 2; + tB[4] = B[0] * B[1]; + return eval2(tA + 3, tB + 3) / (a - b); + } + + + // Evaluates expression (re = 25 EPS): + // A[0] * sqrt(B[0]) + A[1] * sqrt(B[1]) + + // A[2] * sqrt(B[2]) + A[3] * sqrt(B[3]). + _fpt eval4(_int* A, _int* B) { + _fpt a = eval2(A, B); + _fpt b = eval2(A + 2, B + 2); + if ((!is_neg(a) && !is_neg(b)) || + (!is_pos(a) && !is_pos(b))) + return a + b; + tA[0] = A[0] * A[0] * B[0] + A[1] * A[1] * B[1] - + A[2] * A[2] * B[2] - A[3] * A[3] * B[3]; + tB[0] = 1; + tA[1] = A[0] * A[1] * 2; + tB[1] = B[0] * B[1]; + tA[2] = A[2] * A[3] * -2; + tB[2] = B[2] * B[3]; + return eval3(tA, tB) / (a - b); + } + + private: + _int tA[5]; + _int tB[5]; + _converter convert; +}; +} // detail +} // polygon +} // boost + +#endif // BOOST_POLYGON_DETAIL_VORONOI_ROBUST_FPT diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/detail/voronoi_structures.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/detail/voronoi_structures.hpp new file mode 100644 index 0000000..f37a454 --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/detail/voronoi_structures.hpp @@ -0,0 +1,450 @@ +// Boost.Polygon library detail/voronoi_structures.hpp header file + +// Copyright Andrii Sydorchuk 2010-2012. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +#ifndef BOOST_POLYGON_DETAIL_VORONOI_STRUCTURES +#define BOOST_POLYGON_DETAIL_VORONOI_STRUCTURES + +#include +#include +#include + +#include "boost/polygon/voronoi_geometry_type.hpp" + +namespace boost { +namespace polygon { +namespace detail { +// Cartesian 2D point data structure. +template +class point_2d { + public: + typedef T coordinate_type; + + point_2d() {} + + point_2d(coordinate_type x, coordinate_type y) : + x_(x), + y_(y) {} + + bool operator==(const point_2d& that) const { + return (this->x_ == that.x()) && (this->y_ == that.y()); + } + + bool operator!=(const point_2d& that) const { + return (this->x_ != that.x()) || (this->y_ != that.y()); + } + + coordinate_type x() const { + return x_; + } + + coordinate_type y() const { + return y_; + } + + point_2d& x(coordinate_type x) { + x_ = x; + return *this; + } + + point_2d& y(coordinate_type y) { + y_ = y; + return *this; + } + + private: + coordinate_type x_; + coordinate_type y_; +}; + +// Site event type. +// Occurs when the sweepline sweeps over one of the initial sites: +// 1) point site +// 2) start-point of the segment site +// 3) endpoint of the segment site +// Implicit segment direction is defined: the start-point of +// the segment compares less than its endpoint. +// Each input segment is divided onto two site events: +// 1) One going from the start-point to the endpoint +// (is_inverse() = false) +// 2) Another going from the endpoint to the start-point +// (is_inverse() = true) +// In beach line data structure segment sites of the first +// type precede sites of the second type for the same segment. +// Members: +// point0_ - point site or segment's start-point +// point1_ - segment's endpoint if site is a segment +// sorted_index_ - the last bit encodes information if the site is inverse; +// the other bits encode site event index among the sorted site events +// initial_index_ - site index among the initial input set +// Note: for all sites is_inverse_ flag is equal to false by default. +template +class site_event { + public: + typedef T coordinate_type; + typedef point_2d point_type; + + site_event() : + point0_(0, 0), + point1_(0, 0), + sorted_index_(0), + flags_(0) {} + + site_event(coordinate_type x, coordinate_type y) : + point0_(x, y), + point1_(x, y), + sorted_index_(0), + flags_(0) {} + + explicit site_event(const point_type& point) : + point0_(point), + point1_(point), + sorted_index_(0), + flags_(0) {} + + site_event(coordinate_type x1, coordinate_type y1, + coordinate_type x2, coordinate_type y2): + point0_(x1, y1), + point1_(x2, y2), + sorted_index_(0), + flags_(0) {} + + site_event(const point_type& point1, const point_type& point2) : + point0_(point1), + point1_(point2), + sorted_index_(0), + flags_(0) {} + + bool operator==(const site_event& that) const { + return (this->point0_ == that.point0_) && + (this->point1_ == that.point1_); + } + + bool operator!=(const site_event& that) const { + return (this->point0_ != that.point0_) || + (this->point1_ != that.point1_); + } + + coordinate_type x() const { + return point0_.x(); + } + + coordinate_type y() const { + return point0_.y(); + } + + coordinate_type x0() const { + return point0_.x(); + } + + coordinate_type y0() const { + return point0_.y(); + } + + coordinate_type x1() const { + return point1_.x(); + } + + coordinate_type y1() const { + return point1_.y(); + } + + const point_type& point0() const { + return point0_; + } + + const point_type& point1() const { + return point1_; + } + + std::size_t sorted_index() const { + return sorted_index_; + } + + site_event& sorted_index(std::size_t index) { + sorted_index_ = index; + return *this; + } + + std::size_t initial_index() const { + return initial_index_; + } + + site_event& initial_index(std::size_t index) { + initial_index_ = index; + return *this; + } + + bool is_inverse() const { + return (flags_ & IS_INVERSE) ? true : false; + } + + site_event& inverse() { + std::swap(point0_, point1_); + flags_ ^= IS_INVERSE; + return *this; + } + + SourceCategory source_category() const { + return static_cast(flags_ & SOURCE_CATEGORY_BITMASK); + } + + site_event& source_category(SourceCategory source_category) { + flags_ |= source_category; + return *this; + } + + bool is_point() const { + return (point0_.x() == point1_.x()) && (point0_.y() == point1_.y()); + } + + bool is_segment() const { + return (point0_.x() != point1_.x()) || (point0_.y() != point1_.y()); + } + + private: + enum Bits { + IS_INVERSE = 0x20 // 32 + }; + + point_type point0_; + point_type point1_; + std::size_t sorted_index_; + std::size_t initial_index_; + std::size_t flags_; +}; + +// Circle event type. +// Occurs when the sweepline sweeps over the rightmost point of the Voronoi +// circle (with the center at the intersection point of the bisectors). +// Circle event is made of the two consecutive nodes in the beach line data +// structure. In case another node was inserted during algorithm execution +// between the given two nodes circle event becomes inactive. +// Variables: +// center_x_ - center x-coordinate; +// center_y_ - center y-coordinate; +// lower_x_ - leftmost x-coordinate; +// is_active_ - states whether circle event is still active. +// NOTE: lower_y coordinate is always equal to center_y. +template +class circle_event { + public: + typedef T coordinate_type; + + circle_event() : is_active_(true) {} + + circle_event(coordinate_type c_x, + coordinate_type c_y, + coordinate_type lower_x) : + center_x_(c_x), + center_y_(c_y), + lower_x_(lower_x), + is_active_(true) {} + + coordinate_type x() const { + return center_x_; + } + + circle_event& x(coordinate_type center_x) { + center_x_ = center_x; + return *this; + } + + coordinate_type y() const { + return center_y_; + } + + circle_event& y(coordinate_type center_y) { + center_y_ = center_y; + return *this; + } + + coordinate_type lower_x() const { + return lower_x_; + } + + circle_event& lower_x(coordinate_type lower_x) { + lower_x_ = lower_x; + return *this; + } + + coordinate_type lower_y() const { + return center_y_; + } + + bool is_active() const { + return is_active_; + } + + circle_event& deactivate() { + is_active_ = false; + return *this; + } + + private: + coordinate_type center_x_; + coordinate_type center_y_; + coordinate_type lower_x_; + bool is_active_; +}; + +// Event queue data structure, holds circle events. +// During algorithm run, some of the circle events disappear (become +// inactive). Priority queue data structure doesn't support +// iterators (there is no direct ability to modify its elements). +// Instead list is used to store all the circle events and priority queue +// of the iterators to the list elements is used to keep the correct circle +// events ordering. +template +class ordered_queue { + public: + ordered_queue() {} + + bool empty() const { + return c_.empty(); + } + + const T &top() const { + return *c_.top(); + } + + void pop() { + list_iterator_type it = c_.top(); + c_.pop(); + c_list_.erase(it); + } + + T &push(const T &e) { + c_list_.push_front(e); + c_.push(c_list_.begin()); + return c_list_.front(); + } + + void clear() { + while (!c_.empty()) + c_.pop(); + c_list_.clear(); + } + + private: + typedef typename std::list::iterator list_iterator_type; + + struct comparison { + bool operator() (const list_iterator_type &it1, + const list_iterator_type &it2) const { + return cmp_(*it1, *it2); + } + Predicate cmp_; + }; + + std::priority_queue< list_iterator_type, + std::vector, + comparison > c_; + std::list c_list_; + + // Disallow copy constructor and operator= + ordered_queue(const ordered_queue&); + void operator=(const ordered_queue&); +}; + +// Represents a bisector node made by two arcs that correspond to the left +// and right sites. Arc is defined as a curve with points equidistant from +// the site and from the sweepline. If the site is a point then arc is +// a parabola, otherwise it's a line segment. A segment site event will +// produce different bisectors based on its direction. +// In general case two sites will create two opposite bisectors. That's +// why the order of the sites is important to define the unique bisector. +// The one site is considered to be newer than the other one if it was +// processed by the algorithm later (has greater index). +template +class beach_line_node_key { + public: + typedef Site site_type; + + // Constructs degenerate bisector, used to search an arc that is above + // the given site. The input to the constructor is the new site point. + explicit beach_line_node_key(const site_type &new_site) : + left_site_(new_site), + right_site_(new_site) {} + + // Constructs a new bisector. The input to the constructor is the two + // sites that create the bisector. The order of sites is important. + beach_line_node_key(const site_type &left_site, + const site_type &right_site) : + left_site_(left_site), + right_site_(right_site) {} + + const site_type &left_site() const { + return left_site_; + } + + site_type &left_site() { + return left_site_; + } + + beach_line_node_key& left_site(const site_type &site) { + left_site_ = site; + return *this; + } + + const site_type &right_site() const { + return right_site_; + } + + site_type &right_site() { + return right_site_; + } + + beach_line_node_key& right_site(const site_type &site) { + right_site_ = site; + return *this; + } + + private: + site_type left_site_; + site_type right_site_; +}; + +// Represents edge data structure from the Voronoi output, that is +// associated as a value with beach line bisector in the beach +// line. Contains pointer to the circle event in the circle event +// queue if the edge corresponds to the right bisector of the circle event. +template +class beach_line_node_data { + public: + explicit beach_line_node_data(Edge* new_edge) : + circle_event_(NULL), + edge_(new_edge) {} + + Circle* circle_event() const { + return circle_event_; + } + + beach_line_node_data& circle_event(Circle* circle_event) { + circle_event_ = circle_event; + return *this; + } + + Edge* edge() const { + return edge_; + } + + beach_line_node_data& edge(Edge* new_edge) { + edge_ = new_edge; + return *this; + } + + private: + Circle* circle_event_; + Edge* edge_; +}; +} // detail +} // polygon +} // boost + +#endif // BOOST_POLYGON_DETAIL_VORONOI_STRUCTURES diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/gmp_override.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/gmp_override.hpp new file mode 100644 index 0000000..322e05d --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/gmp_override.hpp @@ -0,0 +1,128 @@ +/* + Copyright 2008 Intel Corporation + + Use, modification and distribution are subject to the Boost Software License, + Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at + http://www.boost.org/LICENSE_1_0.txt). +*/ +#ifndef BOOST_POLYGON_GMP_OVERRIDE_HPP +#define BOOST_POLYGON_GMP_OVERRIDE_HPP +#include +namespace boost { namespace polygon { + + class gmp_int { + private: + inline gmp_int(const mpq_class& input) : v_(input) {} + public: + inline gmp_int() {} + explicit inline gmp_int(long input) : v_(input) {} + inline gmp_int(const gmp_int& input) : v_(input.v_) {} + inline gmp_int& operator=(const gmp_int& that) { + v_ = that.v_; + return (*this); + } + inline gmp_int& operator=(long that) { + v_ = that; + return (*this); + } + inline operator int() const { + std::cout << "cast\n"; + mpz_class num = v_.get_num(); + mpz_class den = v_.get_den(); + num /= den; + return num.get_si(); + } + inline double get_d() const { + return v_.get_d(); + } + inline int get_num() const { + return v_.get_num().get_si(); + } + inline int get_den() const { + return v_.get_den().get_si(); + } + inline bool operator==(const gmp_int& that) const { + return v_ == that.v_; + } + inline bool operator!=(const gmp_int& that) const { + return v_ != that.v_; + } + inline bool operator<(const gmp_int& that) const { + bool retval = v_ < that.v_; + return retval; + } + inline bool operator<=(const gmp_int& that) const { + return v_ <= that.v_; + } + inline bool operator>(const gmp_int& that) const { + return v_ > that.v_; + } + inline bool operator>=(const gmp_int& that) const { + return v_ >= that.v_; + } + inline gmp_int operator+(const gmp_int& b) { + return gmp_int((*this).v_ + b.v_); + } + inline gmp_int operator-(const gmp_int& b) { + return gmp_int((*this).v_ - b.v_); + } + inline gmp_int operator*(const gmp_int& b) { + return gmp_int((*this).v_ * b.v_); + } + inline gmp_int operator/(const gmp_int& b) { + return gmp_int((*this).v_ / b.v_); + } + inline gmp_int& operator+=(const gmp_int& b) { + (*this).v_ += b.v_; + return (*this); + } + inline gmp_int& operator-=(const gmp_int& b) { + (*this).v_ -= b.v_; + return (*this); + } + inline gmp_int& operator*=(const gmp_int& b) { + (*this).v_ *= b.v_; + return (*this); + } + inline gmp_int& operator/=(const gmp_int& b) { + (*this).v_ /= b.v_; + return (*this); + } + inline gmp_int& operator++() { + ++v_; + return (*this); + } + inline gmp_int& operator--() { + --v_; + return (*this); + } + inline gmp_int operator++(int) { + gmp_int retval(*this); + ++(*this); + return retval; + } + inline gmp_int operator--(int) { + gmp_int retval(*this); + --(*this); + return retval; + } + private: + mpq_class v_; + }; + + template <> + struct high_precision_type { + typedef mpq_class type; + }; + + template <> + int convert_high_precision_type(const mpq_class& v) { + mpz_class num = v.get_num(); + mpz_class den = v.get_den(); + num /= den; + return num.get_si(); + }; + +} +} +#endif diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/gtl.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/gtl.hpp new file mode 100644 index 0000000..3a98d26 --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/gtl.hpp @@ -0,0 +1,35 @@ +/* + Copyright 2008 Intel Corporation + + Use, modification and distribution are subject to the Boost Software License, + Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at + http://www.boost.org/LICENSE_1_0.txt). +*/ +#ifndef BOOST_POLYGON_GTL_HPP +#define BOOST_POLYGON_GTL_HPP + +#ifdef __ICC +#pragma warning (push) +#pragma warning (disable:1125) +#endif + +#ifdef WIN32 +#pragma warning (push) +#pragma warning( disable: 4996 ) +#pragma warning( disable: 4800 ) +#endif + +#define BOOST_POLYGON_NO_DEPS +#include "polygon.hpp" +namespace gtl = boost::polygon; +using namespace boost::polygon::operators; + +#ifdef WIN32 +#pragma warning (pop) +#endif + +#ifdef __ICC +#pragma warning (pop) +#endif + +#endif diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/interval_concept.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/interval_concept.hpp new file mode 100644 index 0000000..3eeec0f --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/interval_concept.hpp @@ -0,0 +1,934 @@ +// Boost.Polygon library interval_concept.hpp header file + +// Copyright (c) Intel Corporation 2008. +// Copyright (c) 2008-2012 Simonson Lucanus. +// Copyright (c) 2012-2012 Andrii Sydorchuk. + +// See http://www.boost.org for updates, documentation, and revision history. +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_POLYGON_INTERVAL_CONCEPT_HPP +#define BOOST_POLYGON_INTERVAL_CONCEPT_HPP + +#include "isotropy.hpp" +#include "interval_traits.hpp" + +namespace boost { +namespace polygon { + +struct interval_concept {}; + +template +struct is_interval_concept { + typedef gtl_no type; +}; + +template <> +struct is_interval_concept { + typedef gtl_yes type; +}; + +template +struct is_mutable_interval_concept { + typedef gtl_no type; +}; + +template <> +struct is_mutable_interval_concept { + typedef gtl_yes type; +}; + +template +struct interval_coordinate_type_by_concept { + typedef void type; +}; + +template +struct interval_coordinate_type_by_concept { + typedef typename interval_traits::coordinate_type type; +}; + +template +struct interval_coordinate_type { + typedef typename interval_coordinate_type_by_concept< + GeometryType, + typename is_interval_concept< + typename geometry_concept::type + >::type + >::type type; +}; + +template +struct interval_difference_type_by_concept { + typedef void type; +}; + +template +struct interval_difference_type_by_concept { + typedef typename coordinate_traits< + typename interval_traits::coordinate_type + >::coordinate_difference type; +}; + +template +struct interval_difference_type { + typedef typename interval_difference_type_by_concept< + GeometryType, + typename is_interval_concept< + typename geometry_concept::type + >::type + >::type type; +}; + +struct y_i_get : gtl_yes {}; + +template +typename enable_if< + typename gtl_and< + y_i_get, + typename is_interval_concept< + typename geometry_concept::type + >::type + >::type, + typename interval_coordinate_type::type +>::type get(const IntervalType& interval, direction_1d dir) { + return interval_traits::get(interval, dir); +} + +struct y_i_set : gtl_yes {}; + +template +typename enable_if< + typename gtl_and< + y_i_set, + typename is_mutable_interval_concept< + typename geometry_concept::type + >::type + >::type, + void +>::type set(IntervalType& interval, direction_1d dir, + typename interval_mutable_traits::coordinate_type value) { + interval_mutable_traits::set(interval, dir, value); +} + +struct y_i_construct : gtl_yes {}; + +template +typename enable_if< + typename gtl_and< + y_i_construct, + typename is_mutable_interval_concept< + typename geometry_concept::type + >::type + >::type, + IntervalType +>::type construct( + typename interval_mutable_traits::coordinate_type low, + typename interval_mutable_traits::coordinate_type high) { + if (low > high) { + (std::swap)(low, high); + } + return interval_mutable_traits::construct(low, high); +} + +struct y_i_copy_construct : gtl_yes {}; + +template +typename enable_if< + typename gtl_and_3< + y_i_copy_construct, + typename is_mutable_interval_concept< + typename geometry_concept::type + >::type, + typename is_interval_concept< + typename geometry_concept::type + >::type + >::type, + IntervalType1 +>::type copy_construct(const IntervalType2& interval) { + return construct(get(interval, LOW), get(interval, HIGH)); +} + +struct y_i_assign : gtl_yes {}; + +template +typename enable_if< + typename gtl_and_3< + y_i_assign, + typename is_mutable_interval_concept< + typename geometry_concept::type + >::type, + typename is_interval_concept< + typename geometry_concept::type + >::type + >::type, + IntervalType1 +>::type& assign(IntervalType1& lvalue, const IntervalType2& rvalue) { + set(lvalue, LOW, get(rvalue, LOW)); + set(lvalue, HIGH, get(rvalue, HIGH)); + return lvalue; +} + +struct y_i_low : gtl_yes {}; + +template +typename enable_if< + typename gtl_and< + y_i_low, + typename is_interval_concept< + typename geometry_concept::type + >::type + >::type, + typename interval_coordinate_type::type +>::type low(const IntervalType& interval) { + return get(interval, LOW); +} + +struct y_i_high : gtl_yes {}; + +template +typename enable_if< + typename gtl_and< + y_i_high, + typename is_interval_concept< + typename geometry_concept::type + >::type + >::type, + typename interval_coordinate_type::type +>::type high(const IntervalType& interval) { + return get(interval, HIGH); +} + +struct y_i_low2 : gtl_yes {}; + +template +typename enable_if< + typename gtl_and< + y_i_low2, + typename is_mutable_interval_concept< + typename geometry_concept::type + >::type + >::type, + void +>::type low(IntervalType& interval, + typename interval_mutable_traits::coordinate_type value) { + set(interval, LOW, value); +} + +struct y_i_high2 : gtl_yes {}; + +template +typename enable_if< + typename gtl_and< + y_i_high2, + typename is_mutable_interval_concept< + typename geometry_concept::type + >::type + >::type, + void +>::type high(IntervalType& interval, + typename interval_mutable_traits::coordinate_type value) { + set(interval, HIGH, value); +} + +struct y_i_equivalence : gtl_yes {}; + +template +typename enable_if< + typename gtl_and_3< + y_i_equivalence, + typename is_interval_concept< + typename geometry_concept::type + >::type, + typename is_interval_concept< + typename geometry_concept::type + >::type + >::type, + bool +>::type equivalence( + const IntervalType1& interval1, + const IntervalType2& interval2) { + return (get(interval1, LOW) == get(interval2, LOW)) && + (get(interval1, HIGH) == get(interval2, HIGH)); +} + +struct y_i_contains : gtl_yes {}; + +template +typename enable_if< + typename gtl_and< + y_i_contains, + typename is_interval_concept< + typename geometry_concept::type + >::type + >::type, + bool +>::type contains( + const IntervalType& interval, + typename interval_coordinate_type::type value, + bool consider_touch = true ) { + if (consider_touch) { + return value <= high(interval) && value >= low(interval); + } else { + return value < high(interval) && value > low(interval); + } +} + +struct y_i_contains2 : gtl_yes {}; + +template +typename enable_if< + typename gtl_and_3< + y_i_contains2, + typename is_interval_concept< + typename geometry_concept::type + >::type, + typename is_interval_concept< + typename geometry_concept::type + >::type + >::type, + bool +>::type contains( + const IntervalType1& interval1, + const IntervalType2& interval2, + bool consider_touch = true) { + return contains(interval1, get(interval2, LOW), consider_touch) && + contains(interval1, get(interval2, HIGH), consider_touch); +} + +struct y_i_center : gtl_yes {}; + +template +typename enable_if< + typename gtl_and< + y_i_center, + typename is_interval_concept< + typename geometry_concept::type + >::type + >::type, + typename interval_coordinate_type::type +>::type center(const IntervalType& interval) { + return (high(interval) + low(interval)) / 2; +} + +struct y_i_delta : gtl_yes {}; + +template +typename enable_if< + typename gtl_and< + y_i_delta, + typename is_interval_concept< + typename geometry_concept::type + >::type + >::type, + typename interval_difference_type::type +>::type delta(const IntervalType& interval) { + typedef typename interval_difference_type::type diff_type; + return static_cast(high(interval)) - + static_cast(low(interval)); +} + +struct y_i_flip : gtl_yes {}; + +template +typename enable_if< + typename gtl_and< + y_i_flip, + typename is_mutable_interval_concept< + typename geometry_concept::type + >::type + >::type, +IntervalType>::type& flip( + IntervalType& interval, + typename interval_coordinate_type::type axis = 0) { + typename interval_coordinate_type::type newLow, newHigh; + newLow = 2 * axis - high(interval); + newHigh = 2 * axis - low(interval); + low(interval, newLow); + high(interval, newHigh); + return interval; +} + +struct y_i_scale_up : gtl_yes {}; + +template +typename enable_if< + typename gtl_and< + y_i_scale_up, + typename is_mutable_interval_concept< + typename geometry_concept::type + >::type + >::type, + IntervalType +>::type& scale_up( + IntervalType& interval, + typename interval_coordinate_type::type factor) { + typename interval_coordinate_type::type newHigh = + high(interval) * factor; + low(interval, low(interval) * factor); + high(interval, (newHigh)); + return interval; +} + +struct y_i_scale_down : gtl_yes {}; + +template +typename enable_if< + typename gtl_and< + y_i_scale_down, + typename is_mutable_interval_concept< + typename geometry_concept::type + >::type + >::type, + IntervalType +>::type& scale_down( + IntervalType& interval, + typename interval_coordinate_type::type factor) { + typename interval_coordinate_type::type newHigh = + high(interval) / factor; + low(interval, low(interval) / factor); + high(interval, (newHigh)); + return interval; +} + +// TODO(asydorchuk): Deprecated. +struct y_i_scale : gtl_yes {}; + +template +typename enable_if< + typename gtl_and< + y_i_scale, + typename is_mutable_interval_concept< + typename geometry_concept::type + >::type + >::type, + IntervalType +>::type& scale(IntervalType& interval, double factor) { + typedef typename interval_coordinate_type::type Unit; + Unit newHigh = scaling_policy::round( + static_cast(high(interval)) * factor); + low(interval, scaling_policy::round( + static_cast(low(interval)) * factor)); + high(interval, (newHigh)); + return interval; +} + +struct y_i_move : gtl_yes {}; + +template +typename enable_if< + typename gtl_and< + y_i_move, + typename is_mutable_interval_concept< + typename geometry_concept::type + >::type + >::type, + IntervalType +>::type& move( + IntervalType& interval, + typename interval_difference_type::type displacement) { + typedef typename interval_coordinate_type::type ctype; + typedef typename coordinate_traits::coordinate_difference Unit; + low(interval, static_cast( + static_cast(low(interval)) + displacement)); + high(interval, static_cast( + static_cast(high(interval)) + displacement)); + return interval; +} + +struct y_i_convolve : gtl_yes {}; + +template +typename enable_if< + typename gtl_and< + y_i_convolve, + typename is_mutable_interval_concept< + typename geometry_concept::type + >::type + >::type, + IntervalType +>::type& convolve( + IntervalType& interval, + typename interval_coordinate_type::type value) { + typedef typename interval_coordinate_type::type Unit; + Unit newLow = low(interval) + value; + Unit newHigh = high(interval) + value; + low(interval, newLow); + high(interval, newHigh); + return interval; +} + +struct y_i_deconvolve : gtl_yes {}; + +template +typename enable_if< + typename gtl_and< + y_i_deconvolve, + typename is_mutable_interval_concept< + typename geometry_concept::type + >::type + >::type, + IntervalType +>::type& deconvolve( + IntervalType& interval, + typename interval_coordinate_type::type value) { + typedef typename interval_coordinate_type::type Unit; + Unit newLow = low(interval) - value; + Unit newHigh = high(interval) - value; + low(interval, newLow); + high(interval, newHigh); + return interval; +} + +struct y_i_convolve2 : gtl_yes {}; + +template +typename enable_if< + typename gtl_and_3< + y_i_convolve2, + typename is_mutable_interval_concept< + typename geometry_concept::type + >::type, + typename is_interval_concept< + typename geometry_concept::type + >::type + >::type, + IntervalType1 +>::type& convolve(IntervalType1& lvalue, const IntervalType2& rvalue) { + typedef typename interval_coordinate_type::type Unit; + Unit newLow = low(lvalue) + low(rvalue); + Unit newHigh = high(lvalue) + high(rvalue); + low(lvalue, newLow); + high(lvalue, newHigh); + return lvalue; +} + +struct y_i_deconvolve2 : gtl_yes {}; + +template +typename enable_if< + typename gtl_and_3< + y_i_deconvolve2, + typename is_mutable_interval_concept< + typename geometry_concept::type + >::type, + typename is_interval_concept< + typename geometry_concept::type + >::type + >::type, + IntervalType1 +>::type& deconvolve(IntervalType1& lvalue, const IntervalType2& rvalue) { + typedef typename interval_coordinate_type::type Unit; + Unit newLow = low(lvalue) - low(rvalue); + Unit newHigh = high(lvalue) - high(rvalue); + low(lvalue, newLow); + high(lvalue, newHigh); + return lvalue; +} + +struct y_i_reconvolve : gtl_yes {}; + +template +typename enable_if< + typename gtl_and_3< + y_i_reconvolve, + typename is_mutable_interval_concept< + typename geometry_concept::type + >::type, + typename is_interval_concept< + typename geometry_concept::type + >::type + >::type, + IntervalType1 +>::type& reflected_convolve( + IntervalType1& lvalue, + const IntervalType2& rvalue) { + typedef typename interval_coordinate_type::type Unit; + Unit newLow = low(lvalue) - high(rvalue); + Unit newHigh = high(lvalue) - low(rvalue); + low(lvalue, newLow); + high(lvalue, newHigh); + return lvalue; +} + +struct y_i_redeconvolve : gtl_yes {}; + +template +typename enable_if< + typename gtl_and_3< + y_i_redeconvolve, + typename is_mutable_interval_concept< + typename geometry_concept::type + >::type, + typename is_interval_concept< + typename geometry_concept::type + >::type + >::type, + IntervalType1 +>::type& reflected_deconvolve( + IntervalType1& lvalue, + const IntervalType2& rvalue) { + typedef typename interval_coordinate_type::type Unit; + Unit newLow = low(lvalue) + high(rvalue); + Unit newHigh = high(lvalue) + low(rvalue); + low(lvalue, newLow); + high(lvalue, newHigh); + return lvalue; +} + +struct y_i_e_dist1 : gtl_yes {}; + +template +typename enable_if< + typename gtl_and::type + >::type + >::type, + typename interval_difference_type::type +>::type euclidean_distance( + const IntervalType& interval, + typename interval_coordinate_type::type position) { + typedef typename interval_difference_type::type Unit; + Unit dist[3] = { + 0, + (Unit)low(interval) - (Unit)position, + (Unit)position - (Unit)high(interval) + }; + return dist[(dist[1] > 0) + ((dist[2] > 0) << 1)]; +} + +struct y_i_e_dist2 : gtl_yes {}; + +template +typename enable_if< + typename gtl_and_3< + y_i_e_dist2, + typename is_interval_concept< + typename geometry_concept::type + >::type, + typename is_interval_concept< + typename geometry_concept::type + >::type + >::type, + typename interval_difference_type::type +>::type euclidean_distance( + const IntervalType1& interval1, + const IntervalType2& interval2) { + typedef typename interval_difference_type::type Unit; + Unit dist[3] = { + 0, + (Unit)low(interval1) - (Unit)high(interval2), + (Unit)low(interval2) - (Unit)high(interval1) + }; + return dist[(dist[1] > 0) + ((dist[2] > 0) << 1)]; +} + +struct y_i_e_intersects : gtl_yes {}; + +template +typename enable_if< + typename gtl_and_3< + y_i_e_intersects, + typename is_interval_concept< + typename geometry_concept::type + >::type, + typename is_interval_concept< + typename geometry_concept::type + >::type + >::type, + bool +>::type intersects( + const IntervalType1& interval1, + const IntervalType2& interval2, + bool consider_touch = true) { + return consider_touch ? + (low(interval1) <= high(interval2)) && + (high(interval1) >= low(interval2)) : + (low(interval1) < high(interval2)) && + (high(interval1) > low(interval2)); +} + +struct y_i_e_bintersect : gtl_yes {}; + +template +typename enable_if< + typename gtl_and_3< + y_i_e_bintersect, + typename is_interval_concept< + typename geometry_concept::type + >::type, + typename is_interval_concept< + typename geometry_concept::type + >::type + >::type, + bool +>::type boundaries_intersect( + const IntervalType1& interval1, + const IntervalType2& interval2, + bool consider_touch = true) { + return (contains(interval1, low(interval2), consider_touch) || + contains(interval1, high(interval2), consider_touch)) && + (contains(interval2, low(interval1), consider_touch) || + contains(interval2, high(interval1), consider_touch)); +} + +struct y_i_intersect : gtl_yes {}; + +template +typename enable_if< + typename gtl_and_3< + y_i_intersect, + typename is_mutable_interval_concept< + typename geometry_concept::type + >::type, + typename is_interval_concept< + typename geometry_concept::type + >::type + >::type, + bool +>::type intersect( + IntervalType1& lvalue, + const IntervalType2& rvalue, + bool consider_touch = true) { + typedef typename interval_coordinate_type::type Unit; + Unit lowVal = (std::max)(low(lvalue), low(rvalue)); + Unit highVal = (std::min)(high(lvalue), high(rvalue)); + bool valid = consider_touch ? lowVal <= highVal : lowVal < highVal; + if (valid) { + low(lvalue, lowVal); + high(lvalue, highVal); + } + return valid; +} + +struct y_i_g_intersect : gtl_yes {}; + +// TODO(asydorchuk): Deprecated. +template +typename enable_if< + typename gtl_and_3< + y_i_g_intersect, + typename is_mutable_interval_concept< + typename geometry_concept::type + >::type, + typename is_interval_concept< + typename geometry_concept::type + >::type + >::type, + IntervalType1 +>::type& generalized_intersect( + IntervalType1& lvalue, + const IntervalType2& rvalue) { + typedef typename interval_coordinate_type::type Unit; + Unit coords[4] = {low(lvalue), high(lvalue), low(rvalue), high(rvalue)}; + // TODO(asydorchuk): consider implementing faster sorting of small + // fixed length range. + polygon_sort(coords, coords+4); + low(lvalue, coords[1]); + high(lvalue, coords[2]); + return lvalue; +} + +struct y_i_abuts1 : gtl_yes {}; + +template +typename enable_if< + typename gtl_and_3< + y_i_abuts1, + typename is_interval_concept< + typename geometry_concept::type + >::type, + typename is_interval_concept< + typename geometry_concept::type + >::type + >::type, + bool +>::type abuts( + const IntervalType1& interval1, + const IntervalType2& interval2, + direction_1d dir) { + return dir.to_int() ? low(interval2) == high(interval1) : + low(interval1) == high(interval2); +} + +struct y_i_abuts2 : gtl_yes {}; + +template +typename enable_if< + typename gtl_and_3< + y_i_abuts2, + typename is_interval_concept< + typename geometry_concept::type + >::type, + typename is_interval_concept< + typename geometry_concept::type + >::type + >::type, + bool +>::type abuts( + const IntervalType1& interval1, + const IntervalType2& interval2) { + return abuts(interval1, interval2, HIGH) || + abuts(interval1, interval2, LOW); +} + +struct y_i_bloat : gtl_yes {}; + +template +typename enable_if< + typename gtl_and< + y_i_bloat, + typename is_mutable_interval_concept< + typename geometry_concept::type + >::type + >::type, + IntervalType +>::type& bloat( + IntervalType& interval, + typename interval_coordinate_type::type bloating) { + low(interval, low(interval) - bloating); + high(interval, high(interval) + bloating); + return interval; +} + +struct y_i_bloat2 : gtl_yes {}; + +template +typename enable_if< + typename gtl_and< + y_i_bloat2, + typename is_mutable_interval_concept< + typename geometry_concept::type + >::type + >::type, + IntervalType +>::type& bloat( + IntervalType& interval, + direction_1d dir, + typename interval_coordinate_type::type bloating) { + set(interval, dir, get(interval, dir) + dir.get_sign() * bloating); + return interval; +} + +struct y_i_shrink : gtl_yes {}; + +template +typename enable_if< + typename gtl_and< + y_i_shrink, + typename is_mutable_interval_concept< + typename geometry_concept::type + >::type + >::type, + IntervalType +>::type& shrink( + IntervalType& interval, + typename interval_coordinate_type::type shrinking) { + return bloat(interval, -shrinking); +} + +struct y_i_shrink2 : gtl_yes {}; + +template +typename enable_if< + typename gtl_and< + y_i_shrink2, + typename is_mutable_interval_concept< + typename geometry_concept::type + >::type + >::type, + IntervalType +>::type& shrink( + IntervalType& interval, + direction_1d dir, + typename interval_coordinate_type::type shrinking) { + return bloat(interval, dir, -shrinking); +} + +struct y_i_encompass : gtl_yes {}; + +template +typename enable_if< + typename gtl_and_3< + y_i_encompass, + typename is_mutable_interval_concept< + typename geometry_concept::type + >::type, + typename is_interval_concept< + typename geometry_concept::type + >::type + >::type, + bool +>::type encompass(IntervalType1& interval1, const IntervalType2& interval2) { + bool retval = !contains(interval1, interval2, true); + low(interval1, (std::min)(low(interval1), low(interval2))); + high(interval1, (std::max)(high(interval1), high(interval2))); + return retval; +} + +struct y_i_encompass2 : gtl_yes {}; + +template +typename enable_if< + typename gtl_and< + y_i_encompass2, + typename is_mutable_interval_concept< + typename geometry_concept::type + >::type + >::type, + bool +>::type encompass( + IntervalType& interval, + typename interval_coordinate_type::type value) { + bool retval = !contains(interval, value, true); + low(interval, (std::min)(low(interval), value)); + high(interval, (std::max)(high(interval), value)); + return retval; +} + +struct y_i_get_half : gtl_yes {}; + +template +typename enable_if< + typename gtl_and< + y_i_get_half, + typename is_mutable_interval_concept< + typename geometry_concept::type + >::type + >::type, + IntervalType +>::type get_half(const IntervalType& interval, direction_1d dir) { + typedef typename interval_coordinate_type::type Unit; + Unit c = (get(interval, LOW) + get(interval, HIGH)) / 2; + return construct( + (dir == LOW) ? get(interval, LOW) : c, + (dir == LOW) ? c : get(interval, HIGH)); +} + +struct y_i_join_with : gtl_yes {}; + +template +typename enable_if< + typename gtl_and_3< + y_i_join_with, + typename is_mutable_interval_concept< + typename geometry_concept::type + >::type, + typename is_interval_concept< + typename geometry_concept::type + >::type>::type, + bool +>::type join_with(IntervalType1& interval1, const IntervalType2& interval2) { + if (abuts(interval1, interval2)) { + encompass(interval1, interval2); + return true; + } + return false; +} +} // polygon +} // boost + +#endif // BOOST_POLYGON_INTERVAL_CONCEPT_HPP diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/interval_data.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/interval_data.hpp new file mode 100644 index 0000000..b297624 --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/interval_data.hpp @@ -0,0 +1,118 @@ +// Boost.Polygon library interval_data.hpp header file + +// Copyright (c) Intel Corporation 2008. +// Copyright (c) 2008-2012 Simonson Lucanus. +// Copyright (c) 2012-2012 Andrii Sydorchuk. + +// See http://www.boost.org for updates, documentation, and revision history. +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_POLYGON_INTERVAL_DATA_HPP +#define BOOST_POLYGON_INTERVAL_DATA_HPP + +#include "isotropy.hpp" +#include "interval_concept.hpp" + +namespace boost { +namespace polygon { + +template +class interval_data { + public: + typedef T coordinate_type; + + interval_data() +#ifndef BOOST_POLYGON_MSVC + : coords_() +#endif + {} + + interval_data(coordinate_type low, coordinate_type high) { + coords_[LOW] = low; + coords_[HIGH] = high; + } + + interval_data(const interval_data& that) { + coords_[0] = that.coords_[0]; + coords_[1] = that.coords_[1]; + } + + interval_data& operator=(const interval_data& that) { + coords_[0] = that.coords_[0]; + coords_[1] = that.coords_[1]; + return *this; + } + + template + interval_data& operator=(const IntervalType& that) { + assign(*this, that); + return *this; + } + + coordinate_type get(direction_1d dir) const { + return coords_[dir.to_int()]; + } + + void set(direction_1d dir, coordinate_type value) { + coords_[dir.to_int()] = value; + } + + coordinate_type low() const { + return coords_[0]; + } + + interval_data& low(coordinate_type value) { + coords_[LOW] = value; + return *this; + } + + coordinate_type high() const { + return coords_[1]; + } + + interval_data& high(coordinate_type value) { + coords_[HIGH] = value; + return *this; + } + + bool operator==(const interval_data& that) const { + return low() == that.low() && high() == that.high(); + } + + bool operator!=(const interval_data& that) const { + return low() != that.low() || high() != that.high(); + } + + bool operator<(const interval_data& that) const { + if (coords_[0] != that.coords_[0]) { + return coords_[0] < that.coords_[0]; + } + return coords_[1] < that.coords_[1]; + } + + bool operator<=(const interval_data& that) const { + return !(that < *this); + } + + bool operator>(const interval_data& that) const { + return that < *this; + } + + bool operator>=(const interval_data& that) const { + return !((*this) < that); + } + + private: + coordinate_type coords_[2]; +}; + +template +struct geometry_concept< interval_data > { + typedef interval_concept type; +}; +} // polygon +} // boost + +#endif // BOOST_POLYGON_INTERVAL_DATA_HPP diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/interval_traits.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/interval_traits.hpp new file mode 100644 index 0000000..9c9062f --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/interval_traits.hpp @@ -0,0 +1,47 @@ +// Boost.Polygon library interval_traits.hpp header file + +// Copyright (c) Intel Corporation 2008. +// Copyright (c) 2008-2012 Simonson Lucanus. +// Copyright (c) 2012-2012 Andrii Sydorchuk. + +// See http://www.boost.org for updates, documentation, and revision history. +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_POLYGON_INTERVAL_TRAITS_HPP +#define BOOST_POLYGON_INTERVAL_TRAITS_HPP + +#include "isotropy.hpp" + +namespace boost { +namespace polygon { + +template +struct interval_traits { + typedef Interval interval_type; + typedef typename interval_type::coordinate_type coordinate_type; + + static coordinate_type get(const interval_type& interval, direction_1d dir) { + return interval.get(dir); + } +}; + +template +struct interval_mutable_traits { + typedef Interval interval_type; + typedef typename interval_type::coordinate_type coordinate_type; + + static void set( + interval_type& interval, direction_1d dir, coordinate_type value) { + interval.set(dir, value); + } + + static interval_type construct(coordinate_type low, coordinate_type high) { + return interval_type(low, high); + } +}; +} // polygon +} // boost + +#endif // BOOST_POLICY_INTERVAL_TRAITS_HPP diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/isotropy.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/isotropy.hpp new file mode 100644 index 0000000..615ae39 --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/isotropy.hpp @@ -0,0 +1,525 @@ +/* + Copyright 2008 Intel Corporation + + Use, modification and distribution are subject to the Boost Software License, + Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at + http://www.boost.org/LICENSE_1_0.txt). +*/ + +#ifndef BOOST_POLYGON_ISOTROPY_HPP +#define BOOST_POLYGON_ISOTROPY_HPP + +//external +#include +#include +#include +#include +#include +#include +#include +#include +//#include +#include +#include +#include +#include + +#ifndef BOOST_POLYGON_NO_DEPS + +#include +#ifdef BOOST_MSVC +#define BOOST_POLYGON_MSVC +#endif +#ifdef BOOST_INTEL +#define BOOST_POLYGON_ICC +#endif +#ifdef BOOST_HAS_LONG_LONG +#define BOOST_POLYGON_USE_LONG_LONG +typedef boost::long_long_type polygon_long_long_type; +typedef boost::ulong_long_type polygon_ulong_long_type; +//typedef long long polygon_long_long_type; +//typedef unsigned long long polygon_ulong_long_type; +#endif +#else + +#ifdef _WIN32 +#define BOOST_POLYGON_MSVC +#endif +#ifdef __ICC +#define BOOST_POLYGON_ICC +#endif +#define BOOST_POLYGON_USE_LONG_LONG +typedef long long polygon_long_long_type; +typedef unsigned long long polygon_ulong_long_type; +#endif + +namespace boost { namespace polygon{ + + enum GEOMETRY_CONCEPT_ID { + COORDINATE_CONCEPT, + INTERVAL_CONCEPT, + POINT_CONCEPT, + POINT_3D_CONCEPT, + RECTANGLE_CONCEPT, + POLYGON_90_CONCEPT, + POLYGON_90_WITH_HOLES_CONCEPT, + POLYGON_45_CONCEPT, + POLYGON_45_WITH_HOLES_CONCEPT, + POLYGON_CONCEPT, + POLYGON_WITH_HOLES_CONCEPT, + POLYGON_90_SET_CONCEPT, + POLYGON_45_SET_CONCEPT, + POLYGON_SET_CONCEPT + }; + + struct undefined_concept {}; + + template + struct geometry_concept { typedef undefined_concept type; }; + + template + struct view_of {}; + + template + view_of view_as(const T2& obj) { return view_of(obj); } + + template + struct coordinate_traits {}; + + //used to override long double with an infinite precision datatype + template + struct high_precision_type { + typedef long double type; + }; + + template + T convert_high_precision_type(const typename high_precision_type::type& v) { + return T(v); + } + + //used to override std::sort with an alternative (parallel) algorithm + template + void polygon_sort(iter_type _b_, iter_type _e_); + + template + void polygon_sort(iter_type _b_, iter_type _e_, const pred_type& _pred_); + + + template <> + struct coordinate_traits { + typedef int coordinate_type; + typedef long double area_type; +#ifdef BOOST_POLYGON_USE_LONG_LONG + typedef polygon_long_long_type manhattan_area_type; + typedef polygon_ulong_long_type unsigned_area_type; + typedef polygon_long_long_type coordinate_difference; +#else + typedef long manhattan_area_type; + typedef unsigned long unsigned_area_type; + typedef long coordinate_difference; +#endif + typedef long double coordinate_distance; + }; + + template<> + struct coordinate_traits { + typedef coordinate_traits cT_; + typedef cT_::coordinate_type coordinate_type; + typedef cT_::area_type area_type; + typedef cT_::manhattan_area_type manhattan_area_type; + typedef cT_::unsigned_area_type unsigned_area_type; + typedef cT_::coordinate_difference coordinate_difference; + typedef cT_::coordinate_distance coordinate_distance; + }; + +#ifdef BOOST_POLYGON_USE_LONG_LONG + template <> + struct coordinate_traits { + typedef polygon_long_long_type coordinate_type; + typedef long double area_type; + typedef polygon_long_long_type manhattan_area_type; + typedef polygon_ulong_long_type unsigned_area_type; + typedef polygon_long_long_type coordinate_difference; + typedef long double coordinate_distance; + }; + + template<> + struct coordinate_traits { + typedef coordinate_traits cT_; + typedef cT_::coordinate_type coordinate_type; + typedef cT_::area_type area_type; + typedef cT_::manhattan_area_type manhattan_area_type; + typedef cT_::unsigned_area_type unsigned_area_type; + typedef cT_::coordinate_difference coordinate_difference; + typedef cT_::coordinate_distance coordinate_distance; + }; +#endif + + template <> + struct coordinate_traits { + typedef float coordinate_type; + typedef float area_type; + typedef float manhattan_area_type; + typedef float unsigned_area_type; + typedef float coordinate_difference; + typedef float coordinate_distance; + }; + + template <> + struct coordinate_traits { + typedef double coordinate_type; + typedef double area_type; + typedef double manhattan_area_type; + typedef double unsigned_area_type; + typedef double coordinate_difference; + typedef double coordinate_distance; + }; + + template <> + struct coordinate_traits { + typedef long double coordinate_type; + typedef long double area_type; + typedef long double manhattan_area_type; + typedef long double unsigned_area_type; + typedef long double coordinate_difference; + typedef long double coordinate_distance; + }; + + template + struct scaling_policy { + template + static inline T round(T2 t2) { + return (T)std::floor(t2+0.5); + } + + static inline T round(T t2) { + return t2; + } + }; + + struct coordinate_concept {}; + + template <> + struct geometry_concept { typedef coordinate_concept type; }; +#ifdef BOOST_POLYGON_USE_LONG_LONG + template <> + struct geometry_concept { typedef coordinate_concept type; }; +#endif + template <> + struct geometry_concept { typedef coordinate_concept type; }; + template <> + struct geometry_concept { typedef coordinate_concept type; }; + template <> + struct geometry_concept { typedef coordinate_concept type; }; + + struct gtl_no { static const bool value = false; }; + struct gtl_yes { typedef gtl_yes type; + static const bool value = true; }; + + template + struct gtl_and_c { typedef gtl_no type; }; + template <> + struct gtl_and_c { typedef gtl_yes type; }; + + template + struct gtl_and : gtl_and_c {}; + template + struct gtl_and_3 { typedef typename gtl_and< + T, typename gtl_and::type>::type type; }; + + template + struct gtl_and_4 { typedef typename gtl_and_3< + T, T2, typename gtl_and::type>::type type; }; + template + struct gtl_or { typedef gtl_yes type; }; + template + struct gtl_or { typedef T type; }; + + template + struct gtl_or_3 { typedef typename gtl_or< + T, typename gtl_or::type>::type type; }; + + template + struct gtl_or_4 { typedef typename gtl_or< + T, typename gtl_or_3::type>::type type; }; + + template + struct gtl_not { typedef gtl_no type; }; + template <> + struct gtl_not { typedef gtl_yes type; }; + + template + struct gtl_if { +#ifdef BOOST_POLYGON_MSVC + typedef gtl_no type; +#endif + }; + template <> + struct gtl_if { typedef gtl_yes type; }; + + template + struct gtl_same_type { typedef gtl_no type; }; + template + struct gtl_same_type { typedef gtl_yes type; }; + template + struct gtl_different_type { typedef typename gtl_not::type>::type type; }; + + struct manhattan_domain {}; + struct forty_five_domain {}; + struct general_domain {}; + + template + struct geometry_domain { typedef general_domain type; }; + + template + struct area_type_by_domain { typedef typename coordinate_traits::area_type type; }; + template + struct area_type_by_domain { + typedef typename coordinate_traits::manhattan_area_type type; }; + + template + struct enable_if_ { + typedef R type; + }; + + template + struct enable_if_ { }; + + template + struct enable_if + : enable_if_ { }; + + struct y_c_edist : gtl_yes {}; + + template + typename enable_if< + typename gtl_and_3::type, coordinate_concept>::type, + typename gtl_same_type::type, coordinate_concept>::type>::type, + typename coordinate_traits::coordinate_difference>::type + euclidean_distance(const coordinate_type_1& lvalue, const coordinate_type_2& rvalue) { + typedef typename coordinate_traits::coordinate_difference Unit; + return (lvalue < rvalue) ? (Unit)rvalue - (Unit)lvalue : (Unit)lvalue - (Unit)rvalue; + } + + + + // predicated_swap swaps a and b if pred is true + + // predicated_swap is guarenteed to behave the same as + // if(pred){ + // T tmp = a; + // a = b; + // b = tmp; + // } + // but will not generate a branch instruction. + // predicated_swap always creates a temp copy of a, but does not + // create more than one temp copy of an input. + // predicated_swap can be used to optimize away branch instructions in C++ + template + inline bool predicated_swap(const bool& pred, + T& a, + T& b) { + const T tmp = a; + const T* input[2] = {&b, &tmp}; + a = *input[!pred]; + b = *input[pred]; + return pred; + } + + enum direction_1d_enum { LOW = 0, HIGH = 1, + LEFT = 0, RIGHT = 1, + CLOCKWISE = 0, COUNTERCLOCKWISE = 1, + REVERSE = 0, FORWARD = 1, + NEGATIVE = 0, POSITIVE = 1 }; + enum orientation_2d_enum { HORIZONTAL = 0, VERTICAL = 1 }; + enum direction_2d_enum { WEST = 0, EAST = 1, SOUTH = 2, NORTH = 3 }; + enum orientation_3d_enum { PROXIMAL = 2 }; + enum direction_3d_enum { DOWN = 4, UP = 5 }; + enum winding_direction { + clockwise_winding = 0, + counterclockwise_winding = 1, + unknown_winding = 2 + }; + + class direction_2d; + class direction_3d; + class orientation_2d; + + class direction_1d { + private: + unsigned int val_; + explicit direction_1d(int d); + public: + inline direction_1d() : val_(LOW) {} + inline direction_1d(const direction_1d& that) : val_(that.val_) {} + inline direction_1d(const direction_1d_enum val) : val_(val) {} + explicit inline direction_1d(const direction_2d& that); + explicit inline direction_1d(const direction_3d& that); + inline direction_1d& operator = (const direction_1d& d) { + val_ = d.val_; return * this; } + inline bool operator==(direction_1d d) const { return (val_ == d.val_); } + inline bool operator!=(direction_1d d) const { return !((*this) == d); } + inline unsigned int to_int(void) const { return val_; } + inline direction_1d& backward() { val_ ^= 1; return *this; } + inline int get_sign() const { return val_ * 2 - 1; } + }; + + class direction_2d; + + class orientation_2d { + private: + unsigned int val_; + explicit inline orientation_2d(int o); + public: + inline orientation_2d() : val_(HORIZONTAL) {} + inline orientation_2d(const orientation_2d& ori) : val_(ori.val_) {} + inline orientation_2d(const orientation_2d_enum val) : val_(val) {} + explicit inline orientation_2d(const direction_2d& that); + inline orientation_2d& operator=(const orientation_2d& ori) { + val_ = ori.val_; return * this; } + inline bool operator==(orientation_2d that) const { return (val_ == that.val_); } + inline bool operator!=(orientation_2d that) const { return (val_ != that.val_); } + inline unsigned int to_int() const { return (val_); } + inline void turn_90() { val_ = val_^ 1; } + inline orientation_2d get_perpendicular() const { + orientation_2d retval = *this; + retval.turn_90(); + return retval; + } + inline direction_2d get_direction(direction_1d dir) const; + }; + + class direction_2d { + private: + int val_; + + public: + + inline direction_2d() : val_(WEST) {} + + inline direction_2d(const direction_2d& that) : val_(that.val_) {} + + inline direction_2d(const direction_2d_enum val) : val_(val) {} + + inline direction_2d& operator=(const direction_2d& d) { + val_ = d.val_; + return * this; + } + + inline ~direction_2d() { } + + inline bool operator==(direction_2d d) const { return (val_ == d.val_); } + inline bool operator!=(direction_2d d) const { return !((*this) == d); } + inline bool operator< (direction_2d d) const { return (val_ < d.val_); } + inline bool operator<=(direction_2d d) const { return (val_ <= d.val_); } + inline bool operator> (direction_2d d) const { return (val_ > d.val_); } + inline bool operator>=(direction_2d d) const { return (val_ >= d.val_); } + + // Casting to int + inline unsigned int to_int(void) const { return val_; } + + inline direction_2d backward() const { + // flip the LSB, toggles 0 - 1 and 2 - 3 + return direction_2d(direction_2d_enum(val_ ^ 1)); + } + + // Returns a direction 90 degree left (LOW) or right(HIGH) to this one + inline direction_2d turn(direction_1d t) const { + return direction_2d(direction_2d_enum(val_ ^ 3 ^ (val_ >> 1) ^ t.to_int())); + } + + // Returns a direction 90 degree left to this one + inline direction_2d left() const {return turn(HIGH);} + + // Returns a direction 90 degree right to this one + inline direction_2d right() const {return turn(LOW);} + + // N, E are positive, S, W are negative + inline bool is_positive() const {return (val_ & 1);} + inline bool is_negative() const {return !is_positive();} + inline int get_sign() const {return ((is_positive()) << 1) -1;} + + }; + + direction_1d::direction_1d(const direction_2d& that) : val_(that.to_int() & 1) {} + + orientation_2d::orientation_2d(const direction_2d& that) : val_(that.to_int() >> 1) {} + + direction_2d orientation_2d::get_direction(direction_1d dir) const { + return direction_2d(direction_2d_enum((val_ << 1) + dir.to_int())); + } + + class orientation_3d { + private: + unsigned int val_; + explicit inline orientation_3d(int o); + public: + inline orientation_3d() : val_((int)HORIZONTAL) {} + inline orientation_3d(const orientation_3d& ori) : val_(ori.val_) {} + inline orientation_3d(orientation_2d ori) : val_(ori.to_int()) {} + inline orientation_3d(const orientation_3d_enum val) : val_(val) {} + explicit inline orientation_3d(const direction_2d& that); + explicit inline orientation_3d(const direction_3d& that); + inline ~orientation_3d() { } + inline orientation_3d& operator=(const orientation_3d& ori) { + val_ = ori.val_; return * this; } + inline bool operator==(orientation_3d that) const { return (val_ == that.val_); } + inline bool operator!=(orientation_3d that) const { return (val_ != that.val_); } + inline unsigned int to_int() const { return (val_); } + inline direction_3d get_direction(direction_1d dir) const; + }; + + class direction_3d { + private: + int val_; + + public: + + inline direction_3d() : val_(WEST) {} + + inline direction_3d(direction_2d that) : val_(that.to_int()) {} + inline direction_3d(const direction_3d& that) : val_(that.val_) {} + + inline direction_3d(const direction_2d_enum val) : val_(val) {} + inline direction_3d(const direction_3d_enum val) : val_(val) {} + + inline direction_3d& operator=(direction_3d d) { + val_ = d.val_; + return * this; + } + + inline ~direction_3d() { } + + inline bool operator==(direction_3d d) const { return (val_ == d.val_); } + inline bool operator!=(direction_3d d) const { return !((*this) == d); } + inline bool operator< (direction_3d d) const { return (val_ < d.val_); } + inline bool operator<=(direction_3d d) const { return (val_ <= d.val_); } + inline bool operator> (direction_3d d) const { return (val_ > d.val_); } + inline bool operator>=(direction_3d d) const { return (val_ >= d.val_); } + + // Casting to int + inline unsigned int to_int(void) const { return val_; } + + inline direction_3d backward() const { + // flip the LSB, toggles 0 - 1 and 2 - 3 and 4 - 5 + return direction_2d(direction_2d_enum(val_ ^ 1)); + } + + // N, E, U are positive, S, W, D are negative + inline bool is_positive() const {return (val_ & 1);} + inline bool is_negative() const {return !is_positive();} + inline int get_sign() const {return ((is_positive()) << 1) -1;} + + }; + + direction_1d::direction_1d(const direction_3d& that) : val_(that.to_int() & 1) {} + orientation_3d::orientation_3d(const direction_3d& that) : val_(that.to_int() >> 1) {} + orientation_3d::orientation_3d(const direction_2d& that) : val_(that.to_int() >> 1) {} + + direction_3d orientation_3d::get_direction(direction_1d dir) const { + return direction_3d(direction_3d_enum((val_ << 1) + dir.to_int())); + } + +} +} +#endif diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/point_concept.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/point_concept.hpp new file mode 100644 index 0000000..4d4c1dd --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/point_concept.hpp @@ -0,0 +1,469 @@ +// Boost.Polygon library point_concept.hpp header file + +// Copyright (c) Intel Corporation 2008. +// Copyright (c) 2008-2012 Simonson Lucanus. +// Copyright (c) 2012-2012 Andrii Sydorchuk. + +// See http://www.boost.org for updates, documentation, and revision history. +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_POLYGON_POINT_CONCEPT_HPP +#define BOOST_POLYGON_POINT_CONCEPT_HPP + +#include "isotropy.hpp" +#include "point_traits.hpp" + +namespace boost { +namespace polygon { + +struct point_concept {}; + +template +struct is_point_concept { + typedef gtl_no type; +}; + +template <> +struct is_point_concept { + typedef gtl_yes type; +}; + +template +struct is_mutable_point_concept { + typedef gtl_no type; +}; + +template <> +struct is_mutable_point_concept { + typedef gtl_yes type; +}; + +template +struct point_coordinate_type_by_concept { + typedef void type; +}; + +template +struct point_coordinate_type_by_concept { + typedef typename point_traits::coordinate_type type; +}; + +template +struct point_coordinate_type { + typedef typename point_coordinate_type_by_concept< + GeometryType, + typename is_point_concept< + typename geometry_concept::type + >::type + >::type type; +}; + +template +struct point_difference_type_by_concept { + typedef void type; +}; + +template +struct point_difference_type_by_concept { + typedef typename coordinate_traits< + typename point_traits::coordinate_type + >::coordinate_difference type; +}; + +template +struct point_difference_type { + typedef typename point_difference_type_by_concept< + GeometryType, + typename is_point_concept< + typename geometry_concept::type + >::type + >::type type; +}; + +template +struct point_distance_type_by_concept { + typedef void type; +}; + +template +struct point_distance_type_by_concept { + typedef typename coordinate_traits< + typename point_coordinate_type::type + >::coordinate_distance type; +}; + +template +struct point_distance_type { + typedef typename point_distance_type_by_concept< + GeometryType, + typename is_point_concept< + typename geometry_concept::type + >::type + >::type type; +}; + +struct y_pt_get : gtl_yes {}; + +template +typename enable_if< + typename gtl_and< + y_pt_get, + typename is_point_concept< + typename geometry_concept::type + >::type + >::type, + typename point_coordinate_type::type +>::type get(const PointType& point, orientation_2d orient) { + return point_traits::get(point, orient); +} + +struct y_pt_set : gtl_yes {}; + +template +typename enable_if< + typename gtl_and< + y_pt_set, + typename is_mutable_point_concept< + typename geometry_concept::type + >::type + >::type, + void +>::type set(PointType& point, orientation_2d orient, + typename point_mutable_traits::coordinate_type value) { + point_mutable_traits::set(point, orient, value); +} + +struct y_pt_construct : gtl_yes {}; + +template +typename enable_if< + typename gtl_and< + y_pt_construct, + typename is_mutable_point_concept< + typename geometry_concept::type + >::type + >::type, +PointType>::type construct( + typename point_mutable_traits::coordinate_type x, + typename point_mutable_traits::coordinate_type y) { + return point_mutable_traits::construct(x, y); +} + +struct y_pt_assign : gtl_yes {}; + +template +typename enable_if< + typename gtl_and_3< + y_pt_assign, + typename is_mutable_point_concept< + typename geometry_concept::type + >::type, + typename is_point_concept< + typename geometry_concept::type + >::type +>::type, +PointType1>::type& assign(PointType1& lvalue, const PointType2& rvalue) { + set(lvalue, HORIZONTAL, get(rvalue, HORIZONTAL)); + set(lvalue, VERTICAL, get(rvalue, VERTICAL)); + return lvalue; +} + +struct y_p_x : gtl_yes {}; + +template +typename enable_if< + typename gtl_and< + y_p_x, + typename is_point_concept< + typename geometry_concept::type + >::type + >::type, + typename point_coordinate_type::type +>::type x(const PointType& point) { + return get(point, HORIZONTAL); +} + +struct y_p_y : gtl_yes {}; + +template +typename enable_if< + typename gtl_and< + y_p_y, + typename is_point_concept< + typename geometry_concept::type + >::type + >::type, + typename point_coordinate_type::type +>::type y(const PointType& point) { + return get(point, VERTICAL); +} + +struct y_p_sx : gtl_yes {}; + +template +typename enable_if< + typename gtl_and< + y_p_sx, + typename is_mutable_point_concept< + typename geometry_concept::type + >::type + >::type, +void>::type x(PointType& point, + typename point_mutable_traits::coordinate_type value) { + set(point, HORIZONTAL, value); +} + +struct y_p_sy : gtl_yes {}; + +template +typename enable_if< + typename gtl_and< + y_p_sy, + typename is_mutable_point_concept< + typename geometry_concept::type + >::type + >::type, +void>::type y(PointType& point, + typename point_mutable_traits::coordinate_type value) { + set(point, VERTICAL, value); +} + +struct y_pt_equiv : gtl_yes {}; + +template +typename enable_if< + typename gtl_and_3< + y_pt_equiv, + typename is_point_concept< + typename geometry_concept::type + >::type, + typename is_point_concept< + typename geometry_concept::type + >::type + >::type, +bool>::type equivalence( + const PointType1& point1, const PointType2& point2) { + return (x(point1) == x(point2)) && (y(point1) == y(point2)); +} + +struct y_pt_man_dist : gtl_yes {}; + +template +typename enable_if< + typename gtl_and_3< + y_pt_man_dist, + typename is_point_concept< + typename geometry_concept::type + >::type, + typename is_point_concept< + typename geometry_concept::type + >::type + >::type, +typename point_difference_type::type>::type +manhattan_distance(const PointType1& point1, const PointType2& point2) { + return euclidean_distance(point1, point2, HORIZONTAL) + + euclidean_distance(point1, point2, VERTICAL); +} + +struct y_pt_ed1 : gtl_yes {}; + +template +typename enable_if< + typename gtl_and_3< + y_pt_ed1, + typename is_point_concept< + typename geometry_concept::type + >::type, + typename is_point_concept< + typename geometry_concept::type + >::type + >::type, +typename point_difference_type::type>::type +euclidean_distance( + const PointType1& point1, + const PointType2& point2, + orientation_2d orient) { + typename point_difference_type::type dif = + get(point1, orient) - get(point2, orient); + return (dif < 0) ? -dif : dif; +} + +struct y_pt_eds : gtl_yes {}; + +template +typename enable_if< + typename gtl_and_3< + y_pt_eds, + typename is_point_concept< + typename geometry_concept::type + >::type, + typename is_point_concept< + typename geometry_concept::type + >::type + >::type, +typename point_difference_type::type>::type +distance_squared(const PointType1& point1, const PointType2& point2) { + typename point_difference_type::type dx = + euclidean_distance(point1, point2, HORIZONTAL); + typename point_difference_type::type dy = + euclidean_distance(point1, point2, VERTICAL); + dx *= dx; + dy *= dy; + return dx + dy; +} + +struct y_pt_ed2 : gtl_yes {}; + +template +typename enable_if< + typename gtl_and_3< + y_pt_ed2, + typename is_point_concept< + typename geometry_concept::type + >::type, + typename is_point_concept< + typename geometry_concept::type + >::type + >::type, +typename point_distance_type::type>::type +euclidean_distance(const PointType1& point1, const PointType2& point2) { + return (std::sqrt)( + static_cast(distance_squared(point1, point2))); +} + +struct y_pt_convolve : gtl_yes {}; + +template +typename enable_if< + typename gtl_and_3< + y_pt_convolve, + typename is_mutable_point_concept< + typename geometry_concept::type + >::type, + typename is_point_concept< + typename geometry_concept::type + >::type + >::type, +PointType1>::type& convolve(PointType1& lvalue, const PointType2& rvalue) { + x(lvalue, x(lvalue) + x(rvalue)); + y(lvalue, y(lvalue) + y(rvalue)); + return lvalue; +} + +struct y_pt_deconvolve : gtl_yes {}; + +template +typename enable_if< + typename gtl_and_3< + y_pt_deconvolve, + typename is_mutable_point_concept< + typename geometry_concept::type + >::type, + typename is_point_concept< + typename geometry_concept::type + >::type + >::type, +PointType1>::type& deconvolve(PointType1& lvalue, const PointType2& rvalue) { + x(lvalue, x(lvalue) - x(rvalue)); + y(lvalue, y(lvalue) - y(rvalue)); + return lvalue; +} + +struct y_pt_scale_up : gtl_yes {}; + +template +typename enable_if< + typename gtl_and< + y_pt_scale_up, + typename is_mutable_point_concept< + typename geometry_concept::type + >::type + >::type, +PointType>::type& scale_up(PointType& point, CType factor) { + typedef typename point_coordinate_type::type Unit; + x(point, x(point) * (Unit)factor); + y(point, y(point) * (Unit)factor); + return point; +} + +struct y_pt_scale_down : gtl_yes {}; + +template +typename enable_if< + typename gtl_and< + y_pt_scale_down, + typename is_mutable_point_concept< + typename geometry_concept::type + >::type + >::type, +PointType>::type& scale_down(PointType& point, CType factor) { + typedef typename point_coordinate_type::type Unit; + typedef typename coordinate_traits::coordinate_distance dt; + x(point, scaling_policy::round((dt)(x(point)) / (dt)factor)); + y(point, scaling_policy::round((dt)(y(point)) / (dt)factor)); + return point; +} + +struct y_pt_scale : gtl_yes {}; + +template +typename enable_if< + typename gtl_and< + y_pt_scale, + typename is_mutable_point_concept< + typename geometry_concept::type + >::type + >::type, +PointType>::type& scale(PointType& point, const ScaleType& scaling) { + typedef typename point_coordinate_type::type Unit; + Unit x_coord(x(point)); + Unit y_coord(y(point)); + scaling.scale(x_coord, y_coord); + x(point, x_coord); + y(point, y_coord); + return point; +} + +struct y_pt_transform : gtl_yes {}; + +template +typename enable_if< + typename gtl_and< + y_pt_transform, + typename is_mutable_point_concept< + typename geometry_concept::type + >::type + >::type, +PointType>::type& transform(PointType& point, const TransformType& transform) { + typedef typename point_coordinate_type::type Unit; + Unit x_coord(x(point)); + Unit y_coord(y(point)); + transform.transform(x_coord, y_coord); + x(point, x_coord); + y(point, y_coord); + return point; +} + +struct y_pt_move : gtl_yes {}; + +template +typename enable_if< + typename gtl_and< + y_pt_move, + typename is_mutable_point_concept< + typename geometry_concept::type + >::type + >::type, +PointType>::type& move(PointType& point, orientation_2d orient, + typename point_coordinate_type::type displacement) { + typedef typename point_coordinate_type::type Unit; + Unit coord = get(point, orient); + set(point, orient, coord + displacement); + return point; +} +} // polygon +} // boost + +#endif // BOOST_POLYGON_POINT_CONCEPT_HPP diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/point_data.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/point_data.hpp new file mode 100644 index 0000000..deda14d --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/point_data.hpp @@ -0,0 +1,138 @@ +// Boost.Polygon library point_data.hpp header file + +// Copyright (c) Intel Corporation 2008. +// Copyright (c) 2008-2012 Simonson Lucanus. +// Copyright (c) 2012-2012 Andrii Sydorchuk. + +// See http://www.boost.org for updates, documentation, and revision history. +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_POLYGON_POINT_DATA_HPP +#define BOOST_POLYGON_POINT_DATA_HPP + +#include "isotropy.hpp" +#include "point_concept.hpp" + +namespace boost { +namespace polygon { + +template +class point_data { + public: + typedef T coordinate_type; + + point_data() +#ifndef BOOST_POLYGON_MSVC + : coords_() +#endif + {} + + point_data(coordinate_type x, coordinate_type y) { + coords_[HORIZONTAL] = x; + coords_[VERTICAL] = y; + } + + explicit point_data(const point_data& that) { + coords_[0] = that.coords_[0]; + coords_[1] = that.coords_[1]; + } + + point_data& operator=(const point_data& that) { + coords_[0] = that.coords_[0]; + coords_[1] = that.coords_[1]; + return *this; + } + +#if defined(__GNUC__) && __GNUC__ < 6 + // "explicit" to work around a bug in GCC < 6: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=63356 + template + explicit point_data(const PointType& that) { + *this = that; + } +#else // __GNUC__ < 6 + template + point_data(const PointType& that) { + *this = that; + } +#endif // __GNUC__ < 6 + + template + point_data& operator=(const PointType& that) { + assign(*this, that); + return *this; + } + + // TODO(asydorchuk): Deprecated. + template + point_data(const point_data& that) { + coords_[HORIZONTAL] = (coordinate_type)that.x(); + coords_[VERTICAL] = (coordinate_type)that.y(); + } + + coordinate_type get(orientation_2d orient) const { + return coords_[orient.to_int()]; + } + + void set(orientation_2d orient, coordinate_type value) { + coords_[orient.to_int()] = value; + } + + coordinate_type x() const { + return coords_[HORIZONTAL]; + } + + point_data& x(coordinate_type value) { + coords_[HORIZONTAL] = value; + return *this; + } + + coordinate_type y() const { + return coords_[VERTICAL]; + } + + point_data& y(coordinate_type value) { + coords_[VERTICAL] = value; + return *this; + } + + bool operator==(const point_data& that) const { + return (coords_[0] == that.coords_[0]) && + (coords_[1] == that.coords_[1]); + } + + bool operator!=(const point_data& that) const { + return !(*this == that); + } + + bool operator<(const point_data& that) const { + return (coords_[0] < that.coords_[0]) || + ((coords_[0] == that.coords_[0]) && + (coords_[1] < that.coords_[1])); + } + + bool operator<=(const point_data& that) const { + return !(that < *this); + } + + bool operator>(const point_data& that) const { + return that < *this; + } + + bool operator>=(const point_data& that) const { + return !(*this < that); + } + + private: + coordinate_type coords_[2]; +}; + +template +struct geometry_concept< point_data > { + typedef point_concept type; +}; +} // polygon +} // boost + +#endif // BOOST_POLYGON_POINT_DATA_HPP diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/point_traits.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/point_traits.hpp new file mode 100644 index 0000000..5bc43d1 --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/point_traits.hpp @@ -0,0 +1,48 @@ +// Boost.Polygon library point_traits.hpp header file + +// Copyright (c) Intel Corporation 2008. +// Copyright (c) 2008-2012 Simonson Lucanus. +// Copyright (c) 2012-2012 Andrii Sydorchuk. + +// See http://www.boost.org for updates, documentation, and revision history. +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_POLYGON_POINT_TRAITS_HPP +#define BOOST_POLYGON_POINT_TRAITS_HPP + +#include "isotropy.hpp" + +namespace boost { +namespace polygon { + +template +struct point_traits { + typedef PointType point_type; + typedef typename point_type::coordinate_type coordinate_type; + + static coordinate_type get( + const point_type& point, orientation_2d orient) { + return point.get(orient); + } +}; + +template +struct point_mutable_traits { + typedef PointType point_type; + typedef typename point_type::coordinate_type coordinate_type; + + static void set( + point_type& point, orientation_2d orient, coordinate_type value) { + point.set(orient, value); + } + + static point_type construct(coordinate_type x, coordinate_type y) { + return point_type(x, y); + } +}; +} // polygon +} // boost + +#endif // BOOST_POLYGON_POINT_TRAITS_HPP diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/polygon.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/polygon.hpp new file mode 100644 index 0000000..90a7c1f --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/polygon.hpp @@ -0,0 +1,92 @@ +/* + Copyright 2008 Intel Corporation + + Use, modification and distribution are subject to the Boost Software License, + Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at + http://www.boost.org/LICENSE_1_0.txt). +*/ +#ifndef BOOST_POLYGON_POLYGON_HPP +#define BOOST_POLYGON_POLYGON_HPP +#define BOOST_POLYGON_VERSION 014401 + +#include "isotropy.hpp" + +//point +#include "point_data.hpp" +#include "point_traits.hpp" +#include "point_concept.hpp" + +#include "transform.hpp" + +//interval +#include "interval_data.hpp" +#include "interval_traits.hpp" +#include "interval_concept.hpp" + +//rectangle +#include "rectangle_data.hpp" +#include "rectangle_traits.hpp" +#include "rectangle_concept.hpp" + +//segment +#include "segment_data.hpp" +#include "segment_traits.hpp" +#include "segment_concept.hpp" + +//algorithms needed by polygon types +#include "detail/iterator_points_to_compact.hpp" +#include "detail/iterator_compact_to_points.hpp" + +//polygons +#include "polygon_45_data.hpp" +#include "polygon_data.hpp" +#include "polygon_90_data.hpp" +#include "polygon_90_with_holes_data.hpp" +#include "polygon_45_with_holes_data.hpp" +#include "polygon_with_holes_data.hpp" +#include "polygon_traits.hpp" + +//manhattan boolean algorithms +#include "detail/boolean_op.hpp" +#include "detail/polygon_formation.hpp" +#include "detail/rectangle_formation.hpp" +#include "detail/max_cover.hpp" +#include "detail/property_merge.hpp" +#include "detail/polygon_90_touch.hpp" +#include "detail/iterator_geometry_to_set.hpp" + +//45 boolean op algorithms +#include "detail/boolean_op_45.hpp" +#include "detail/polygon_45_formation.hpp" + +//polygon set data types +#include "polygon_90_set_data.hpp" +//polygon set trait types +#include "polygon_90_set_traits.hpp" +//polygon set concepts +#include "polygon_90_set_concept.hpp" +//boolean operator syntax +#include "detail/polygon_90_set_view.hpp" + +//45 boolean op algorithms +#include "detail/polygon_45_touch.hpp" +#include "detail/property_merge_45.hpp" +#include "polygon_45_set_data.hpp" +#include "polygon_45_set_traits.hpp" +#include "polygon_45_set_concept.hpp" +#include "detail/polygon_45_set_view.hpp" + +//arbitrary polygon algorithms +#include "detail/polygon_arbitrary_formation.hpp" +#include "polygon_set_data.hpp" + +//general scanline +#include "detail/scan_arbitrary.hpp" +#include "polygon_set_traits.hpp" +#include "detail/polygon_set_view.hpp" + +#include "polygon_set_concept.hpp" + +#include "segment_utils.hpp" + +#endif diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/polygon_45_data.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/polygon_45_data.hpp new file mode 100644 index 0000000..cdd5c24 --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/polygon_45_data.hpp @@ -0,0 +1,72 @@ +/* + Copyright 2008 Intel Corporation + + Use, modification and distribution are subject to the Boost Software License, + Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at + http://www.boost.org/LICENSE_1_0.txt). +*/ +#ifndef BOOST_POLYGON_POLYGON_45_DATA_HPP +#define BOOST_POLYGON_POLYGON_45_DATA_HPP +#include "isotropy.hpp" +namespace boost { namespace polygon{ +struct polygon_45_concept; +template class polygon_data; +template +class polygon_45_data { +public: + typedef polygon_45_concept geometry_type; + typedef T coordinate_type; + typedef typename std::vector >::const_iterator iterator_type; + typedef typename coordinate_traits::coordinate_distance area_type; + typedef point_data point_type; + + inline polygon_45_data() : coords_() {} //do nothing default constructor + + template + inline polygon_45_data(iT input_begin, iT input_end) : coords_(input_begin, input_end) {} + + template + inline polygon_45_data& set(iT input_begin, iT input_end) { + coords_.clear(); //just in case there was some old data there + coords_.insert(coords_.end(), input_begin, input_end); + return *this; + } + + // copy constructor (since we have dynamic memory) + inline polygon_45_data(const polygon_45_data& that) : coords_(that.coords_) {} + + // assignment operator (since we have dynamic memory do a deep copy) + inline polygon_45_data& operator=(const polygon_45_data& that) { + coords_ = that.coords_; + return *this; + } + + template + inline polygon_45_data& operator=(const T2& rvalue); + + inline bool operator==(const polygon_45_data& that) const { + if(coords_.size() != that.coords_.size()) return false; + for(std::size_t i = 0; i < coords_.size(); ++i) { + if(coords_[i] != that.coords_[i]) return false; + } + return true; + } + + inline bool operator!=(const polygon_45_data& that) const { return !((*this) == that); } + + // get begin iterator, returns a pointer to a const Unit + inline iterator_type begin() const { return coords_.begin(); } + + // get end iterator, returns a pointer to a const Unit + inline iterator_type end() const { return coords_.end(); } + + inline std::size_t size() const { return coords_.size(); } + +public: + std::vector > coords_; +}; + + +} +} +#endif diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/polygon_45_set_concept.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/polygon_45_set_concept.hpp new file mode 100644 index 0000000..623415f --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/polygon_45_set_concept.hpp @@ -0,0 +1,441 @@ +/* + Copyright 2008 Intel Corporation + + Use, modification and distribution are subject to the Boost Software License, + Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at + http://www.boost.org/LICENSE_1_0.txt). +*/ +#ifndef BOOST_POLYGON_POLYGON_45_SET_CONCEPT_HPP +#define BOOST_POLYGON_POLYGON_45_SET_CONCEPT_HPP +#include "polygon_45_set_data.hpp" +#include "polygon_45_set_traits.hpp" +#include "detail/polygon_45_touch.hpp" +namespace boost { namespace polygon{ + + template + struct is_either_polygon_45_set_type { + typedef typename gtl_or::type, typename is_polygon_45_set_type::type >::type type; + }; + + template + struct is_polygon_45_or_90_set_type { + typedef typename gtl_or::type, typename is_polygon_90_set_type::type >::type type; + }; + + template + typename enable_if< typename gtl_if::type>::type, + typename polygon_45_set_traits::iterator_type>::type + begin_45_set_data(const polygon_set_type& polygon_set) { + return polygon_45_set_traits::begin(polygon_set); + } + + template + typename enable_if< typename gtl_if::type>::type, + typename polygon_45_set_traits::iterator_type>::type + end_45_set_data(const polygon_set_type& polygon_set) { + return polygon_45_set_traits::end(polygon_set); + } + + template + typename enable_if< typename gtl_if::type>::type, + bool>::type + clean(const polygon_set_type& polygon_set) { + return polygon_45_set_traits::clean(polygon_set); + } + + //assign + template + typename enable_if< typename gtl_and< typename gtl_if::type>::type, + typename gtl_if::type>::type>::type, + polygon_set_type_1>::type & + assign(polygon_set_type_1& lvalue, const polygon_set_type_2& rvalue) { + polygon_45_set_mutable_traits::set(lvalue, begin_45_set_data(rvalue), end_45_set_data(rvalue)); + return lvalue; + } + + //get trapezoids + template + typename enable_if< typename gtl_if::type>::type, + void>::type + get_trapezoids(output_container_type& output, const polygon_set_type& polygon_set) { + clean(polygon_set); + polygon_45_set_data::coordinate_type> ps; + assign(ps, polygon_set); + ps.get_trapezoids(output); + } + + //get trapezoids + template + typename enable_if< typename gtl_if::type>::type, + void>::type + get_trapezoids(output_container_type& output, const polygon_set_type& polygon_set, orientation_2d slicing_orientation) { + clean(polygon_set); + polygon_45_set_data::coordinate_type> ps; + assign(ps, polygon_set); + ps.get_trapezoids(output, slicing_orientation); + } + + //equivalence + template + typename enable_if< typename gtl_and_3::type>::type, + typename gtl_if::type>::type, + typename gtl_if::type>::type>::type, + bool>::type + equivalence(const polygon_set_type_1& lvalue, + const polygon_set_type_2& rvalue) { + polygon_45_set_data::coordinate_type> ps1; + assign(ps1, lvalue); + polygon_45_set_data::coordinate_type> ps2; + assign(ps2, rvalue); + return ps1 == ps2; + } + + //clear + template + typename enable_if< typename gtl_if::type>::type, + void>::type + clear(polygon_set_type& polygon_set) { + polygon_45_set_data::coordinate_type> ps; + assign(polygon_set, ps); + } + + //empty + template + typename enable_if< typename gtl_if::type>::type, + bool>::type + empty(const polygon_set_type& polygon_set) { + if(clean(polygon_set)) return begin_45_set_data(polygon_set) == end_45_set_data(polygon_set); + polygon_45_set_data::coordinate_type> ps; + assign(ps, polygon_set); + ps.clean(); + return ps.empty(); + } + + //extents + template + typename enable_if< + typename gtl_and< typename gtl_if::type>::type, + typename is_mutable_rectangle_concept::type>::type>::type, + bool>::type + extents(rectangle_type& extents_rectangle, + const polygon_set_type& polygon_set) { + clean(polygon_set); + polygon_45_set_data::coordinate_type> ps; + assign(ps, polygon_set); + return ps.extents(extents_rectangle); + } + + //area + template + typename enable_if< typename is_mutable_polygon_45_set_type::type, + typename coordinate_traits::coordinate_type>::area_type>::type + area(const polygon_set_type& polygon_set) { + typedef typename polygon_45_set_traits::coordinate_type Unit; + typedef polygon_45_with_holes_data p_type; + typedef typename coordinate_traits::area_type area_type; + std::vector polys; + assign(polys, polygon_set); + area_type retval = (area_type)0; + for(std::size_t i = 0; i < polys.size(); ++i) { + retval += area(polys[i]); + } + return retval; + } + + //interact + template + typename enable_if < + typename gtl_and< typename gtl_if::type>::type, + typename gtl_if::type>::type >::type, + polygon_set_type_1>::type& + interact(polygon_set_type_1& polygon_set_1, const polygon_set_type_2& polygon_set_2) { + typedef typename polygon_45_set_traits::coordinate_type Unit; + std::vector > polys; + assign(polys, polygon_set_1); + std::vector > graph(polys.size()+1, std::set()); + connectivity_extraction_45 ce; + ce.insert(polygon_set_2); + for(std::size_t i = 0; i < polys.size(); ++i){ + ce.insert(polys[i]); + } + ce.extract(graph); + clear(polygon_set_1); + polygon_45_set_data ps; + for(std::set::iterator itr = graph[0].begin(); itr != graph[0].end(); ++itr){ + ps.insert(polys[(*itr)-1]); + } + assign(polygon_set_1, ps); + return polygon_set_1; + } + +// //self_intersect +// template +// typename enable_if< typename is_mutable_polygon_45_set_type::type>::type, +// polygon_set_type>::type & +// self_intersect(polygon_set_type& polygon_set) { +// typedef typename polygon_45_set_traits::coordinate_type Unit; +// //TODO +// } + + template + typename enable_if< typename is_mutable_polygon_45_set_type::type, + polygon_set_type>::type & + resize(polygon_set_type& polygon_set, coord_type resizing, + RoundingOption rounding = CLOSEST, CornerOption corner = INTERSECTION) { + typedef typename polygon_45_set_traits::coordinate_type Unit; + clean(polygon_set); + polygon_45_set_data ps; + assign(ps, polygon_set); + ps.resize(resizing, rounding, corner); + assign(polygon_set, ps); + return polygon_set; + } + + template + typename enable_if< typename is_mutable_polygon_45_set_type::type, + polygon_set_type>::type & + bloat(polygon_set_type& polygon_set, + typename coordinate_traits::coordinate_type>::unsigned_area_type bloating) { + return resize(polygon_set, static_cast::coordinate_type>(bloating)); + } + + template + typename enable_if< typename is_mutable_polygon_45_set_type::type, + polygon_set_type>::type & + shrink(polygon_set_type& polygon_set, + typename coordinate_traits::coordinate_type>::unsigned_area_type shrinking) { + return resize(polygon_set, -(typename polygon_45_set_traits::coordinate_type)shrinking); + } + + template + typename enable_if< typename is_mutable_polygon_45_set_type::type, + polygon_set_type>::type & + grow_and(polygon_set_type& polygon_set, + typename coordinate_traits::coordinate_type>::unsigned_area_type bloating) { + typedef typename polygon_45_set_traits::coordinate_type Unit; + std::vector > polys; + assign(polys, polygon_set); + clear(polygon_set); + polygon_45_set_data ps; + for(std::size_t i = 0; i < polys.size(); ++i) { + polygon_45_set_data tmpPs; + tmpPs.insert(polys[i]); + bloat(tmpPs, bloating); + tmpPs.clean(); //apply implicit OR on tmp polygon set + ps.insert(tmpPs); + } + ps.self_intersect(); + assign(polygon_set, ps); + return polygon_set; + } + + template + typename enable_if< typename is_mutable_polygon_45_set_type::type, + polygon_set_type>::type & + scale_up(polygon_set_type& polygon_set, + typename coordinate_traits::coordinate_type>::unsigned_area_type factor) { + typedef typename polygon_45_set_traits::coordinate_type Unit; + clean(polygon_set); + polygon_45_set_data ps; + assign(ps, polygon_set); + ps.scale_up(factor); + assign(polygon_set, ps); + return polygon_set; + } + + template + typename enable_if< typename is_mutable_polygon_45_set_type::type, + polygon_set_type>::type & + scale_down(polygon_set_type& polygon_set, + typename coordinate_traits::coordinate_type>::unsigned_area_type factor) { + typedef typename polygon_45_set_traits::coordinate_type Unit; + clean(polygon_set); + polygon_45_set_data ps; + assign(ps, polygon_set); + ps.scale_down(factor); + assign(polygon_set, ps); + return polygon_set; + } + + template + typename enable_if< typename is_mutable_polygon_45_set_type::type, + polygon_set_type>::type & + scale(polygon_set_type& polygon_set, double factor) { + typedef typename polygon_45_set_traits::coordinate_type Unit; + clean(polygon_set); + polygon_45_set_data ps; + assign(ps, polygon_set); + ps.scale(factor); + assign(polygon_set, ps); + return polygon_set; + } + + //self_intersect + template + typename enable_if< typename is_mutable_polygon_45_set_type::type, + polygon_set_type>::type & + self_intersect(polygon_set_type& polygon_set) { + typedef typename polygon_45_set_traits::coordinate_type Unit; + polygon_45_set_data ps; + assign(ps, polygon_set); + ps.self_intersect(); + assign(polygon_set, ps); + return polygon_set; + } + + //self_xor + template + typename enable_if< typename is_mutable_polygon_45_set_type::type, + polygon_set_type>::type & + self_xor(polygon_set_type& polygon_set) { + typedef typename polygon_45_set_traits::coordinate_type Unit; + polygon_45_set_data ps; + assign(ps, polygon_set); + ps.self_xor(); + assign(polygon_set, ps); + return polygon_set; + } + + //transform + template + typename enable_if< typename is_mutable_polygon_45_set_type::type, + polygon_set_type>::type & + transform(polygon_set_type& polygon_set, + const transformation_type& transformation) { + typedef typename polygon_45_set_traits::coordinate_type Unit; + clean(polygon_set); + polygon_45_set_data ps; + assign(ps, polygon_set); + ps.transform(transformation); + assign(polygon_set, ps); + return polygon_set; + } + + //keep + template + typename enable_if< typename is_mutable_polygon_45_set_type::type, + polygon_set_type>::type & + keep(polygon_set_type& polygon_set, + typename coordinate_traits::coordinate_type>::area_type min_area, + typename coordinate_traits::coordinate_type>::area_type max_area, + typename coordinate_traits::coordinate_type>::unsigned_area_type min_width, + typename coordinate_traits::coordinate_type>::unsigned_area_type max_width, + typename coordinate_traits::coordinate_type>::unsigned_area_type min_height, + typename coordinate_traits::coordinate_type>::unsigned_area_type max_height) { + typedef typename polygon_45_set_traits::coordinate_type Unit; + typedef typename coordinate_traits::unsigned_area_type uat; + std::list > polys; + assign(polys, polygon_set); + typename std::list >::iterator itr_nxt; + for(typename std::list >::iterator itr = polys.begin(); itr != polys.end(); itr = itr_nxt){ + itr_nxt = itr; + ++itr_nxt; + rectangle_data bbox; + extents(bbox, *itr); + uat pwidth = delta(bbox, HORIZONTAL); + if(pwidth > min_width && pwidth <= max_width){ + uat pheight = delta(bbox, VERTICAL); + if(pheight > min_height && pheight <= max_height){ + typename coordinate_traits::area_type parea = area(*itr); + if(parea <= max_area && parea >= min_area) { + continue; + } + } + } + polys.erase(itr); + } + assign(polygon_set, polys); + return polygon_set; + } + + template + struct view_of { + typedef typename get_coordinate_type::type >::type coordinate_type; + T* tp; + std::vector > polys; + view_of(T& obj) : tp(&obj), polys() { + std::vector > gpolys; + assign(gpolys, obj); + for(typename std::vector >::iterator itr = gpolys.begin(); + itr != gpolys.end(); ++itr) { + polys.push_back(polygon_90_with_holes_data()); + assign(polys.back(), view_as(*itr)); + } + } + view_of(const T& obj) : tp(), polys() { + std::vector > gpolys; + assign(gpolys, obj); + for(typename std::vector >::iterator itr = gpolys.begin(); + itr != gpolys.end(); ++itr) { + polys.push_back(polygon_90_with_holes_data()); + assign(polys.back(), view_as(*itr)); + } + } + + typedef typename std::vector >::const_iterator iterator_type; + typedef view_of operator_arg_type; + + inline iterator_type begin() const { + return polys.begin(); + } + + inline iterator_type end() const { + return polys.end(); + } + + inline orientation_2d orient() const { return HORIZONTAL; } + + inline bool clean() const { return false; } + + inline bool sorted() const { return false; } + + inline T& get() { return *tp; } + + }; + + template + struct polygon_90_set_traits > { + typedef typename view_of::coordinate_type coordinate_type; + typedef typename view_of::iterator_type iterator_type; + typedef view_of operator_arg_type; + + static inline iterator_type begin(const view_of& polygon_set) { + return polygon_set.begin(); + } + + static inline iterator_type end(const view_of& polygon_set) { + return polygon_set.end(); + } + + static inline orientation_2d orient(const view_of& polygon_set) { + return polygon_set.orient(); } + + static inline bool clean(const view_of& polygon_set) { + return polygon_set.clean(); } + + static inline bool sorted(const view_of& polygon_set) { + return polygon_set.sorted(); } + + }; + + template + struct geometry_concept > { + typedef polygon_90_set_concept type; + }; + + template + struct get_coordinate_type, polygon_90_set_concept> { + typedef typename view_of::coordinate_type type; + }; + template + struct get_iterator_type_2, polygon_90_set_concept> { + typedef typename view_of::iterator_type type; + static type begin(const view_of& t) { return t.begin(); } + static type end(const view_of& t) { return t.end(); } + }; + +} +} +#include "detail/polygon_45_set_view.hpp" +#endif diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/polygon_45_set_data.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/polygon_45_set_data.hpp new file mode 100644 index 0000000..97585f6 --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/polygon_45_set_data.hpp @@ -0,0 +1,1880 @@ +/* + Copyright 2008 Intel Corporation + + Use, modification and distribution are subject to the Boost Software License, + Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at + http://www.boost.org/LICENSE_1_0.txt). +*/ +#ifndef BOOST_POLYGON_POLYGON_45_SET_DATA_HPP +#define BOOST_POLYGON_POLYGON_45_SET_DATA_HPP +#include "polygon_90_set_data.hpp" +#include "detail/boolean_op_45.hpp" +#include "detail/polygon_45_formation.hpp" +#include "detail/polygon_45_touch.hpp" +#include "detail/property_merge_45.hpp" +namespace boost { namespace polygon{ + + enum RoundingOption { CLOSEST = 0, OVERSIZE = 1, UNDERSIZE = 2, SQRT2 = 3, SQRT1OVER2 = 4 }; + enum CornerOption { INTERSECTION = 0, ORTHOGONAL = 1, UNFILLED = 2 }; + + template + class polygon_45_set_view; + + struct polygon_45_set_concept {}; + + template + class polygon_45_set_data { + public: + typedef typename polygon_45_formation::Vertex45Compact Vertex45Compact; + typedef std::vector Polygon45VertexData; + + typedef Unit coordinate_type; + typedef Polygon45VertexData value_type; + typedef typename value_type::const_iterator iterator_type; + typedef polygon_45_set_data operator_arg_type; + + // default constructor + inline polygon_45_set_data() : error_data_(), data_(), dirty_(false), unsorted_(false), is_manhattan_(true) {} + + // constructor from a geometry object + template + inline polygon_45_set_data(const geometry_type& that) : error_data_(), data_(), dirty_(false), unsorted_(false), is_manhattan_(true) { + insert(that); + } + + // copy constructor + inline polygon_45_set_data(const polygon_45_set_data& that) : + error_data_(that.error_data_), data_(that.data_), dirty_(that.dirty_), + unsorted_(that.unsorted_), is_manhattan_(that.is_manhattan_) {} + + template + inline polygon_45_set_data(const polygon_45_set_view& that) : + error_data_(), data_(), dirty_(false), unsorted_(false), is_manhattan_(true) { + (*this) = that.value(); + } + + // destructor + inline ~polygon_45_set_data() {} + + // assignement operator + inline polygon_45_set_data& operator=(const polygon_45_set_data& that) { + if(this == &that) return *this; + error_data_ = that.error_data_; + data_ = that.data_; + dirty_ = that.dirty_; + unsorted_ = that.unsorted_; + is_manhattan_ = that.is_manhattan_; + return *this; + } + + template + inline polygon_45_set_data& operator=(const polygon_45_set_view& that) { + (*this) = that.value(); + return *this; + } + + template + inline polygon_45_set_data& operator=(const geometry_object& geometry) { + data_.clear(); + insert(geometry); + return *this; + } + + // insert iterator range + inline void insert(iterator_type input_begin, iterator_type input_end, bool is_hole = false) { + if(input_begin == input_end || (!data_.empty() && &(*input_begin) == &(*(data_.begin())))) return; + dirty_ = true; + unsorted_ = true; + while(input_begin != input_end) { + insert(*input_begin, is_hole); + ++input_begin; + } + } + + // insert iterator range + template + inline void insert(iT input_begin, iT input_end, bool is_hole = false) { + if(input_begin == input_end) return; + dirty_ = true; + unsorted_ = true; + while(input_begin != input_end) { + insert(*input_begin, is_hole); + ++input_begin; + } + } + + inline void insert(const polygon_45_set_data& polygon_set, bool is_hole = false); + template + inline void insert(const polygon_45_set_data& polygon_set, bool is_hole = false); + + template + inline void insert(const geometry_type& geometry_object, bool is_hole = false) { + insert_dispatch(geometry_object, is_hole, typename geometry_concept::type()); + } + + inline void insert_clean(const Vertex45Compact& vertex_45, bool is_hole = false) { + if(vertex_45.count.is_45()) is_manhattan_ = false; + data_.push_back(vertex_45); + if(is_hole) data_.back().count.invert(); + } + + inline void insert(const Vertex45Compact& vertex_45, bool is_hole = false) { + dirty_ = true; + unsorted_ = true; + insert_clean(vertex_45, is_hole); + } + + template + inline void insert(const polygon_90_set_data& polygon_set, bool is_hole = false) { + if(polygon_set.orient() == VERTICAL) { + for(typename polygon_90_set_data::iterator_type itr = polygon_set.begin(); + itr != polygon_set.end(); ++itr) { + Vertex45Compact vertex_45(point_data((*itr).first, (*itr).second.first), 2, (*itr).second.second); + vertex_45.count[1] = (*itr).second.second; + if(is_hole) vertex_45.count[1] *= - 1; + insert_clean(vertex_45, is_hole); + } + } else { + for(typename polygon_90_set_data::iterator_type itr = polygon_set.begin(); + itr != polygon_set.end(); ++itr) { + Vertex45Compact vertex_45(point_data((*itr).second.first, (*itr).first), 2, (*itr).second.second); + vertex_45.count[1] = (*itr).second.second; + if(is_hole) vertex_45.count[1] *= - 1; + insert_clean(vertex_45, is_hole); + } + } + dirty_ = true; + unsorted_ = true; + } + + template + inline void get(output_container& output) const { + get_dispatch(output, typename geometry_concept::type()); + } + + inline bool has_error_data() const { return !error_data_.empty(); } + inline std::size_t error_count() const { return error_data_.size() / 4; } + inline void get_error_data(polygon_45_set_data& p) const { + p.data_.insert(p.data_.end(), error_data_.begin(), error_data_.end()); + } + + // equivalence operator + inline bool operator==(const polygon_45_set_data& p) const { + clean(); + p.clean(); + return data_ == p.data_; + } + + // inequivalence operator + inline bool operator!=(const polygon_45_set_data& p) const { + return !((*this) == p); + } + + // get iterator to begin vertex data + inline iterator_type begin() const { + return data_.begin(); + } + + // get iterator to end vertex data + inline iterator_type end() const { + return data_.end(); + } + + const value_type& value() const { + return data_; + } + + // clear the contents of the polygon_45_set_data + inline void clear() { data_.clear(); error_data_.clear(); dirty_ = unsorted_ = false; is_manhattan_ = true; } + + // find out if Polygon set is empty + inline bool empty() const { return data_.empty(); } + + // get the Polygon set size in vertices + inline std::size_t size() const { clean(); return data_.size(); } + + // get the current Polygon set capacity in vertices + inline std::size_t capacity() const { return data_.capacity(); } + + // reserve size of polygon set in vertices + inline void reserve(std::size_t size) { return data_.reserve(size); } + + // find out if Polygon set is sorted + inline bool sorted() const { return !unsorted_; } + + // find out if Polygon set is clean + inline bool dirty() const { return dirty_; } + + // find out if Polygon set is clean + inline bool is_manhattan() const { return is_manhattan_; } + + bool clean() const; + + void sort() const{ + if(unsorted_) { + polygon_sort(data_.begin(), data_.end()); + unsorted_ = false; + } + } + + template + void set(input_iterator_type input_begin, input_iterator_type input_end) { + data_.clear(); + reserve(std::distance(input_begin, input_end)); + insert(input_begin, input_end); + dirty_ = true; + unsorted_ = true; + } + + void set_clean(const value_type& value) { + data_ = value; + dirty_ = false; + unsorted_ = false; + } + + void set(const value_type& value) { + data_ = value; + dirty_ = true; + unsorted_ = true; + } + + // append to the container cT with polygons (holes will be fractured vertically) + template + void get_polygons(cT& container) const { + get_dispatch(container, polygon_45_concept()); + } + + // append to the container cT with PolygonWithHoles objects + template + void get_polygons_with_holes(cT& container) const { + get_dispatch(container, polygon_45_with_holes_concept()); + } + + // append to the container cT with polygons of three or four verticies + // slicing orientation is vertical + template + void get_trapezoids(cT& container) const { + clean(); + typename polygon_45_formation::Polygon45Tiling pf; + //std::cout << "FORMING POLYGONS\n"; + pf.scan(container, data_.begin(), data_.end()); + //std::cout << "DONE FORMING POLYGONS\n"; + } + + // append to the container cT with polygons of three or four verticies + template + void get_trapezoids(cT& container, orientation_2d slicing_orientation) const { + if(slicing_orientation == VERTICAL) { + get_trapezoids(container); + } else { + polygon_45_set_data ps(*this); + ps.transform(axis_transformation(axis_transformation::SWAP_XY)); + cT result; + ps.get_trapezoids(result); + for(typename cT::iterator itr = result.begin(); itr != result.end(); ++itr) { + ::boost::polygon::transform(*itr, axis_transformation(axis_transformation::SWAP_XY)); + } + container.insert(container.end(), result.begin(), result.end()); + } + } + + // insert vertex sequence + template + void insert_vertex_sequence(iT begin_vertex, iT end_vertex, + direction_1d winding, bool is_hole = false); + + // get the external boundary rectangle + template + bool extents(rectangle_type& rect) const; + + // snap verticies of set to even,even or odd,odd coordinates + void snap() const; + + // |= &= += *= -= ^= binary operators + polygon_45_set_data& operator|=(const polygon_45_set_data& b); + polygon_45_set_data& operator&=(const polygon_45_set_data& b); + polygon_45_set_data& operator+=(const polygon_45_set_data& b); + polygon_45_set_data& operator*=(const polygon_45_set_data& b); + polygon_45_set_data& operator-=(const polygon_45_set_data& b); + polygon_45_set_data& operator^=(const polygon_45_set_data& b); + + // resizing operations + polygon_45_set_data& operator+=(Unit delta); + polygon_45_set_data& operator-=(Unit delta); + + // shrink the Polygon45Set by shrinking + polygon_45_set_data& resize(coordinate_type resizing, RoundingOption rounding = CLOSEST, + CornerOption corner = INTERSECTION); + + // transform set + template + polygon_45_set_data& transform(const transformation_type& tr); + + // scale set + polygon_45_set_data& scale_up(typename coordinate_traits::unsigned_area_type factor); + polygon_45_set_data& scale_down(typename coordinate_traits::unsigned_area_type factor); + polygon_45_set_data& scale(double scaling); + + // self_intersect + polygon_45_set_data& self_intersect() { + sort(); + applyAdaptiveUnary_<1>(); //1 = AND + dirty_ = false; + return *this; + } + + // self_xor + polygon_45_set_data& self_xor() { + sort(); + applyAdaptiveUnary_<3>(); //3 = XOR + dirty_ = false; + return *this; + } + + // accumulate the bloated polygon + template + polygon_45_set_data& insert_with_resize(const geometry_type& poly, + coordinate_type resizing, RoundingOption rounding = CLOSEST, + CornerOption corner = INTERSECTION, + bool hole = false) { + return insert_with_resize_dispatch(poly, resizing, rounding, corner, hole, typename geometry_concept::type()); + } + + private: + mutable value_type error_data_; + mutable value_type data_; + mutable bool dirty_; + mutable bool unsorted_; + mutable bool is_manhattan_; + + private: + //functions + template + void get_dispatch(output_container& output, polygon_45_concept tag) const { + get_fracture(output, true, tag); + } + template + void get_dispatch(output_container& output, polygon_45_with_holes_concept tag) const { + get_fracture(output, false, tag); + } + template + void get_dispatch(output_container& output, polygon_concept tag) const { + get_fracture(output, true, tag); + } + template + void get_dispatch(output_container& output, polygon_with_holes_concept tag) const { + get_fracture(output, false, tag); + } + template + void get_fracture(output_container& container, bool fracture_holes, concept_type ) const { + clean(); + typename polygon_45_formation::Polygon45Formation pf(fracture_holes); + //std::cout << "FORMING POLYGONS\n"; + pf.scan(container, data_.begin(), data_.end()); + } + + template + void insert_dispatch(const geometry_type& geometry_object, bool is_hole, undefined_concept) { + insert(geometry_object.begin(), geometry_object.end(), is_hole); + } + template + void insert_dispatch(const geometry_type& geometry_object, bool is_hole, rectangle_concept tag); + template + void insert_dispatch(const geometry_type& geometry_object, bool is_hole, polygon_90_concept ) { + insert_vertex_sequence(begin_points(geometry_object), end_points(geometry_object), winding(geometry_object), is_hole); + } + template + void insert_dispatch(const geometry_type& geometry_object, bool is_hole, polygon_90_with_holes_concept ) { + insert_vertex_sequence(begin_points(geometry_object), end_points(geometry_object), winding(geometry_object), is_hole); + for(typename polygon_with_holes_traits::iterator_holes_type itr = + begin_holes(geometry_object); itr != end_holes(geometry_object); + ++itr) { + insert_vertex_sequence(begin_points(*itr), end_points(*itr), winding(*itr), !is_hole); + } + } + template + void insert_dispatch(const geometry_type& geometry_object, bool is_hole, polygon_45_concept ) { + insert_vertex_sequence(begin_points(geometry_object), end_points(geometry_object), winding(geometry_object), is_hole); + } + template + void insert_dispatch(const geometry_type& geometry_object, bool is_hole, polygon_45_with_holes_concept ) { + insert_vertex_sequence(begin_points(geometry_object), end_points(geometry_object), winding(geometry_object), is_hole); + for(typename polygon_with_holes_traits::iterator_holes_type itr = + begin_holes(geometry_object); itr != end_holes(geometry_object); + ++itr) { + insert_vertex_sequence(begin_points(*itr), end_points(*itr), winding(*itr), !is_hole); + } + } + template + void insert_dispatch(const geometry_type& geometry_object, bool is_hole, polygon_45_set_concept ) { + polygon_45_set_data ps; + assign(ps, geometry_object); + insert(ps, is_hole); + } + template + void insert_dispatch(const geometry_type& geometry_object, bool is_hole, polygon_90_set_concept ) { + std::list > pl; + assign(pl, geometry_object); + insert(pl.begin(), pl.end(), is_hole); + } + + void insert_vertex_half_edge_45_pair(const point_data& pt1, point_data& pt2, + const point_data& pt3, direction_1d wdir); + + template + polygon_45_set_data& insert_with_resize_dispatch(const geometry_type& poly, + coordinate_type resizing, RoundingOption rounding, + CornerOption corner, bool hole, polygon_45_concept tag); + + // accumulate the bloated polygon with holes + template + polygon_45_set_data& insert_with_resize_dispatch(const geometry_type& poly, + coordinate_type resizing, RoundingOption rounding, + CornerOption corner, bool hole, polygon_45_with_holes_concept tag); + + static void snap_vertex_45(Vertex45Compact& vertex); + + public: + template + void applyAdaptiveBoolean_(const polygon_45_set_data& rvalue) const; + template + void applyAdaptiveBoolean_(polygon_45_set_data& result, const polygon_45_set_data& rvalue) const; + template + void applyAdaptiveUnary_() const; + }; + + template + struct geometry_concept > { + typedef polygon_45_set_concept type; + }; + + template + void scale_up_vertex_45_compact_range(iT beginr, iT endr, T factor) { + for( ; beginr != endr; ++beginr) { + scale_up((*beginr).pt, factor); + } + } + template + void scale_down_vertex_45_compact_range_blindly(iT beginr, iT endr, T factor) { + for( ; beginr != endr; ++beginr) { + scale_down((*beginr).pt, factor); + } + } + + template + inline std::pair characterizeEdge45(const point_data& pt1, const point_data& pt2) { + std::pair retval(0, 1); + if(pt1.x() == pt2.x()) { + retval.first = 3; + retval.second = -1; + return retval; + } + //retval.second = pt1.x() < pt2.x() ? -1 : 1; + retval.second = 1; + if(pt1.y() == pt2.y()) { + retval.first = 1; + } else if(pt1.x() < pt2.x()) { + if(pt1.y() < pt2.y()) { + retval.first = 2; + } else { + retval.first = 0; + } + } else { + if(pt1.y() < pt2.y()) { + retval.first = 0; + } else { + retval.first = 2; + } + } + return retval; + } + + template + bool insert_vertex_half_edge_45_pair_into_vector(cT& output, + const pT& pt1, pT& pt2, + const pT& pt3, + direction_1d wdir) { + int multiplier = wdir == LOW ? -1 : 1; + typename cT::value_type vertex(pt2, 0, 0); + //std::cout << pt1 << " " << pt2 << " " << pt3 << std::endl; + std::pair check; + check = characterizeEdge45(pt1, pt2); + //std::cout << "index " << check.first << " " << check.second * -multiplier << std::endl; + vertex.count[check.first] += check.second * -multiplier; + check = characterizeEdge45(pt2, pt3); + //std::cout << "index " << check.first << " " << check.second * multiplier << std::endl; + vertex.count[check.first] += check.second * multiplier; + output.push_back(vertex); + return vertex.count.is_45(); + } + + template + inline void polygon_45_set_data::insert_vertex_half_edge_45_pair(const point_data& pt1, point_data& pt2, + const point_data& pt3, + direction_1d wdir) { + if(insert_vertex_half_edge_45_pair_into_vector(data_, pt1, pt2, pt3, wdir)) is_manhattan_ = false; + } + + template + template + inline void polygon_45_set_data::insert_vertex_sequence(iT begin_vertex, iT end_vertex, + direction_1d winding, bool is_hole) { + if(begin_vertex == end_vertex) return; + if(is_hole) winding = winding.backward(); + iT itr = begin_vertex; + if(itr == end_vertex) return; + point_data firstPt = *itr; + ++itr; + point_data secondPt(firstPt); + //skip any duplicate points + do { + if(itr == end_vertex) return; + secondPt = *itr; + ++itr; + } while(secondPt == firstPt); + point_data prevPt = secondPt; + point_data prevPrevPt = firstPt; + while(itr != end_vertex) { + point_data pt = *itr; + //skip any duplicate points + if(pt == prevPt) { + ++itr; + continue; + } + //operate on the three points + insert_vertex_half_edge_45_pair(prevPrevPt, prevPt, pt, winding); + prevPrevPt = prevPt; + prevPt = pt; + ++itr; + } + if(prevPt != firstPt) { + insert_vertex_half_edge_45_pair(prevPrevPt, prevPt, firstPt, winding); + insert_vertex_half_edge_45_pair(prevPt, firstPt, secondPt, winding); + } else { + insert_vertex_half_edge_45_pair(prevPrevPt, firstPt, secondPt, winding); + } + dirty_ = true; + unsorted_ = true; + } + + // insert polygon set + template + inline void polygon_45_set_data::insert(const polygon_45_set_data& polygon_set, bool is_hole) { + std::size_t count = data_.size(); + data_.insert(data_.end(), polygon_set.data_.begin(), polygon_set.data_.end()); + error_data_.insert(error_data_.end(), polygon_set.error_data_.begin(), + polygon_set.error_data_.end()); + if(is_hole) { + for(std::size_t i = count; i < data_.size(); ++i) { + data_[i].count = data_[i].count.invert(); + } + } + dirty_ = true; + unsorted_ = true; + if(polygon_set.is_manhattan_ == false) is_manhattan_ = false; + return; + } + // insert polygon set + template + template + inline void polygon_45_set_data::insert(const polygon_45_set_data& polygon_set, bool is_hole) { + std::size_t count = data_.size(); + for(typename polygon_45_set_data::iterator_type itr = polygon_set.begin(); + itr != polygon_set.end(); ++itr) { + const typename polygon_45_set_data::Vertex45Compact& v = *itr; + typename polygon_45_set_data::Vertex45Compact v2; + v2.pt.x(static_cast(v.pt.x())); + v2.pt.y(static_cast(v.pt.y())); + v2.count = typename polygon_45_formation::Vertex45Count(v.count[0], v.count[1], v.count[2], v.count[3]); + data_.push_back(v2); + } + polygon_45_set_data tmp; + polygon_set.get_error_data(tmp); + for(typename polygon_45_set_data::iterator_type itr = tmp.begin(); + itr != tmp.end(); ++itr) { + const typename polygon_45_set_data::Vertex45Compact& v = *itr; + typename polygon_45_set_data::Vertex45Compact v2; + v2.pt.x(static_cast(v.pt.x())); + v2.pt.y(static_cast(v.pt.y())); + v2.count = typename polygon_45_formation::Vertex45Count(v.count[0], v.count[1], v.count[2], v.count[3]); + error_data_.push_back(v2); + } + if(is_hole) { + for(std::size_t i = count; i < data_.size(); ++i) { + data_[i].count = data_[i].count.invert(); + } + } + dirty_ = true; + unsorted_ = true; + if(polygon_set.is_manhattan() == false) is_manhattan_ = false; + return; + } + + template + void insert_rectangle_into_vector_45(cT& output, const rT& rect, bool is_hole) { + point_data::coordinate_type> + llpt = ll(rect), lrpt = lr(rect), ulpt = ul(rect), urpt = ur(rect); + direction_1d dir = COUNTERCLOCKWISE; + if(is_hole) dir = CLOCKWISE; + insert_vertex_half_edge_45_pair_into_vector(output, llpt, lrpt, urpt, dir); + insert_vertex_half_edge_45_pair_into_vector(output, lrpt, urpt, ulpt, dir); + insert_vertex_half_edge_45_pair_into_vector(output, urpt, ulpt, llpt, dir); + insert_vertex_half_edge_45_pair_into_vector(output, ulpt, llpt, lrpt, dir); + } + + template + template + inline void polygon_45_set_data::insert_dispatch(const geometry_type& geometry_object, + bool is_hole, rectangle_concept ) { + dirty_ = true; + unsorted_ = true; + insert_rectangle_into_vector_45(data_, geometry_object, is_hole); + } + + // get the external boundary rectangle + template + template + inline bool polygon_45_set_data::extents(rectangle_type& rect) const{ + clean(); + if(empty()) { + return false; + } + Unit low = (std::numeric_limits::max)(); + Unit high = (std::numeric_limits::min)(); + interval_data xivl(low, high); + interval_data yivl(low, high); + for(typename value_type::const_iterator itr = data_.begin(); + itr != data_.end(); ++ itr) { + if((*itr).pt.x() > xivl.get(HIGH)) + xivl.set(HIGH, (*itr).pt.x()); + if((*itr).pt.x() < xivl.get(LOW)) + xivl.set(LOW, (*itr).pt.x()); + if((*itr).pt.y() > yivl.get(HIGH)) + yivl.set(HIGH, (*itr).pt.y()); + if((*itr).pt.y() < yivl.get(LOW)) + yivl.set(LOW, (*itr).pt.y()); + } + rect = construct(xivl, yivl); + return true; + } + + //this function snaps the vertex and two half edges + //to be both even or both odd coordinate values if one of the edges is 45 + //and throws an excpetion if an edge is non-manhattan, non-45. + template + inline void polygon_45_set_data::snap_vertex_45(typename polygon_45_set_data::Vertex45Compact& vertex) { + bool plus45 = vertex.count[2] != 0; + bool minus45 = vertex.count[0] != 0; + if(plus45 || minus45) { + if(local_abs(vertex.pt.x()) % 2 != local_abs(vertex.pt.y()) % 2) { + if(vertex.count[1] != 0 || + (plus45 && minus45)) { + //move right + vertex.pt.x(vertex.pt.x() + 1); + } else { + //assert that vertex.count[3] != 0 + Unit modifier = plus45 ? -1 : 1; + vertex.pt.y(vertex.pt.y() + modifier); + } + } + } + } + + template + inline void polygon_45_set_data::snap() const { + for(typename value_type::iterator itr = data_.begin(); + itr != data_.end(); ++itr) { + snap_vertex_45(*itr); + } + } + + // |= &= += *= -= ^= binary operators + template + inline polygon_45_set_data& polygon_45_set_data::operator|=(const polygon_45_set_data& b) { + insert(b); + return *this; + } + template + inline polygon_45_set_data& polygon_45_set_data::operator&=(const polygon_45_set_data& b) { + //b.sort(); + //sort(); + applyAdaptiveBoolean_<1>(b); + dirty_ = false; + unsorted_ = false; + return *this; + } + template + inline polygon_45_set_data& polygon_45_set_data::operator+=(const polygon_45_set_data& b) { + return (*this) |= b; + } + template + inline polygon_45_set_data& polygon_45_set_data::operator*=(const polygon_45_set_data& b) { + return (*this) &= b; + } + template + inline polygon_45_set_data& polygon_45_set_data::operator-=(const polygon_45_set_data& b) { + //b.sort(); + //sort(); + applyAdaptiveBoolean_<2>(b); + dirty_ = false; + unsorted_ = false; + return *this; + } + template + inline polygon_45_set_data& polygon_45_set_data::operator^=(const polygon_45_set_data& b) { + //b.sort(); + //sort(); + applyAdaptiveBoolean_<3>(b); + dirty_ = false; + unsorted_ = false; + return *this; + } + + template + inline polygon_45_set_data& polygon_45_set_data::operator+=(Unit delta) { + return resize(delta); + } + template + inline polygon_45_set_data& polygon_45_set_data::operator-=(Unit delta) { + return (*this) += -delta; + } + + template + inline polygon_45_set_data& + polygon_45_set_data::resize(Unit resizing, RoundingOption rounding, CornerOption corner) { + if(resizing == 0) return *this; + std::list > pl; + get_polygons_with_holes(pl); + clear(); + for(typename std::list >::iterator itr = pl.begin(); itr != pl.end(); ++itr) { + insert_with_resize(*itr, resizing, rounding, corner); + } + clean(); + //perterb 45 edges to prevent non-integer intersection errors upon boolean op + //snap(); + return *this; + } + + //distance is assumed to be positive + inline int roundClosest(double distance) { + int f = (int)distance; + if(distance - (double)f < 0.5) return f; + return f+1; + } + + //distance is assumed to be positive + template + inline Unit roundWithOptions(double distance, RoundingOption rounding) { + if(rounding == CLOSEST) { + return roundClosest(distance); + } else if(rounding == OVERSIZE) { + return (Unit)distance + 1; + } else { //UNDERSIZE + return (Unit)distance; + } + } + + // 0 is east, 1 is northeast, 2 is north, 3 is northwest, 4 is west, 5 is southwest, 6 is south + // 7 is southwest + template + inline point_data bloatVertexInDirWithOptions(const point_data& point, unsigned int dir, + Unit bloating, RoundingOption rounding) { + const double sqrt2 = 1.4142135623730950488016887242097; + if(dir & 1) { + Unit unitDistance = (Unit)bloating; + if(rounding != SQRT2) { + //45 degree bloating + double distance = (double)bloating; + distance /= sqrt2; // multiply by 1/sqrt2 + unitDistance = roundWithOptions(distance, rounding); + } + int xMultiplier = 1; + int yMultiplier = 1; + if(dir == 3 || dir == 5) xMultiplier = -1; + if(dir == 5 || dir == 7) yMultiplier = -1; + return point_data(point.x()+xMultiplier*unitDistance, + point.y()+yMultiplier*unitDistance); + } else { + if(dir == 0) + return point_data(point.x()+bloating, point.y()); + if(dir == 2) + return point_data(point.x(), point.y()+bloating); + if(dir == 4) + return point_data(point.x()-bloating, point.y()); + if(dir == 6) + return point_data(point.x(), point.y()-bloating); + return point_data(); + } + } + + template + inline unsigned int getEdge45Direction(const point_data& pt1, const point_data& pt2) { + if(pt1.x() == pt2.x()) { + if(pt1.y() < pt2.y()) return 2; + return 6; + } + if(pt1.y() == pt2.y()) { + if(pt1.x() < pt2.x()) return 0; + return 4; + } + if(pt2.y() > pt1.y()) { + if(pt2.x() > pt1.x()) return 1; + return 3; + } + if(pt2.x() > pt1.x()) return 7; + return 5; + } + + inline unsigned int getEdge45NormalDirection(unsigned int dir, int multiplier) { + if(multiplier < 0) + return (dir + 2) % 8; + return (dir + 4 + 2) % 8; + } + + template + inline point_data getIntersectionPoint(const point_data& pt1, unsigned int slope1, + const point_data& pt2, unsigned int slope2) { + //the intention here is to use all integer arithmetic without causing overflow + //turncation error or divide by zero error + //I don't use floating point arithmetic because its precision may not be high enough + //at the extremes of the integer range + typedef typename coordinate_traits::area_type LongUnit; + const Unit rises[8] = {0, 1, 1, 1, 0, -1, -1, -1}; + const Unit runs[8] = {1, 1, 0, -1, -1, -1, 0, 1}; + LongUnit rise1 = rises[slope1]; + LongUnit rise2 = rises[slope2]; + LongUnit run1 = runs[slope1]; + LongUnit run2 = runs[slope2]; + LongUnit x1 = (LongUnit)pt1.x(); + LongUnit x2 = (LongUnit)pt2.x(); + LongUnit y1 = (LongUnit)pt1.y(); + LongUnit y2 = (LongUnit)pt2.y(); + Unit x = 0; + Unit y = 0; + if(run1 == 0) { + x = pt1.x(); + y = (Unit)(((x1 - x2) * rise2) / run2) + pt2.y(); + } else if(run2 == 0) { + x = pt2.x(); + y = (Unit)(((x2 - x1) * rise1) / run1) + pt1.y(); + } else { + // y - y1 = (rise1/run1)(x - x1) + // y - y2 = (rise2/run2)(x - x2) + // y = (rise1/run1)(x - x1) + y1 = (rise2/run2)(x - x2) + y2 + // (rise1/run1 - rise2/run2)x = y2 - y1 + rise1/run1 x1 - rise2/run2 x2 + // x = (y2 - y1 + rise1/run1 x1 - rise2/run2 x2)/(rise1/run1 - rise2/run2) + // x = (y2 - y1 + rise1/run1 x1 - rise2/run2 x2)(rise1 run2 - rise2 run1)/(run1 run2) + x = (Unit)((y2 - y1 + ((rise1 * x1) / run1) - ((rise2 * x2) / run2)) * + (run1 * run2) / (rise1 * run2 - rise2 * run1)); + if(rise1 == 0) { + y = pt1.y(); + } else if(rise2 == 0) { + y = pt2.y(); + } else { + // y - y1 = (rise1/run1)(x - x1) + // (run1/rise1)(y - y1) = x - x1 + // x = (run1/rise1)(y - y1) + x1 = (run2/rise2)(y - y2) + x2 + y = (Unit)((x2 - x1 + ((run1 * y1) / rise1) - ((run2 * y2) / rise2)) * + (rise1 * rise2) / (run1 * rise2 - run2 * rise1)); + } + } + return point_data(x, y); + } + + template + inline + void handleResizingEdge45_SQRT1OVER2(polygon_45_set_data& sizingSet, point_data first, + point_data second, Unit resizing, CornerOption corner) { + if(first.x() == second.x()) { + sizingSet.insert(rectangle_data(first.x() - resizing, first.y(), first.x() + resizing, second.y())); + return; + } + if(first.y() == second.y()) { + sizingSet.insert(rectangle_data(first.x(), first.y() - resizing, second.x(), first.y() + resizing)); + return; + } + std::vector > pts; + Unit bloating = resizing < 0 ? -resizing : resizing; + if(corner == UNFILLED) { + //we have to round up + bloating = bloating / 2 + bloating % 2 ; //round up + if(second.x() < first.x()) std::swap(first, second); + if(first.y() < second.y()) { //upward sloping + pts.push_back(point_data(first.x() + bloating, first.y() - bloating)); + pts.push_back(point_data(first.x() - bloating, first.y() + bloating)); + pts.push_back(point_data(second.x() - bloating, second.y() + bloating)); + pts.push_back(point_data(second.x() + bloating, second.y() - bloating)); + sizingSet.insert_vertex_sequence(pts.begin(), pts.end(), CLOCKWISE, false); + } else { //downward sloping + pts.push_back(point_data(first.x() + bloating, first.y() + bloating)); + pts.push_back(point_data(first.x() - bloating, first.y() - bloating)); + pts.push_back(point_data(second.x() - bloating, second.y() - bloating)); + pts.push_back(point_data(second.x() + bloating, second.y() + bloating)); + sizingSet.insert_vertex_sequence(pts.begin(), pts.end(), COUNTERCLOCKWISE, false); + } + return; + } + if(second.x() < first.x()) std::swap(first, second); + if(first.y() < second.y()) { //upward sloping + pts.push_back(point_data(first.x(), first.y() - bloating)); + pts.push_back(point_data(first.x() - bloating, first.y())); + pts.push_back(point_data(second.x(), second.y() + bloating)); + pts.push_back(point_data(second.x() + bloating, second.y())); + sizingSet.insert_vertex_sequence(pts.begin(), pts.end(), CLOCKWISE, false); + } else { //downward sloping + pts.push_back(point_data(first.x() - bloating, first.y())); + pts.push_back(point_data(first.x(), first.y() + bloating)); + pts.push_back(point_data(second.x() + bloating, second.y())); + pts.push_back(point_data(second.x(), second.y() - bloating)); + sizingSet.insert_vertex_sequence(pts.begin(), pts.end(), CLOCKWISE, false); + } + } + + + template + inline + void handleResizingEdge45(polygon_45_set_data& sizingSet, point_data first, + point_data second, Unit resizing, RoundingOption rounding) { + if(first.x() == second.x()) { + sizingSet.insert(rectangle_data(first.x() - resizing, first.y(), first.x() + resizing, second.y())); + return; + } + if(first.y() == second.y()) { + sizingSet.insert(rectangle_data(first.x(), first.y() - resizing, second.x(), first.y() + resizing)); + return; + } + //edge is 45 + std::vector > pts; + Unit bloating = resizing < 0 ? -resizing : resizing; + if(second.x() < first.x()) std::swap(first, second); + if(first.y() < second.y()) { + pts.push_back(bloatVertexInDirWithOptions(first, 3, bloating, rounding)); + pts.push_back(bloatVertexInDirWithOptions(first, 7, bloating, rounding)); + pts.push_back(bloatVertexInDirWithOptions(second, 7, bloating, rounding)); + pts.push_back(bloatVertexInDirWithOptions(second, 3, bloating, rounding)); + sizingSet.insert_vertex_sequence(pts.begin(), pts.end(), HIGH, false); + } else { + pts.push_back(bloatVertexInDirWithOptions(first, 1, bloating, rounding)); + pts.push_back(bloatVertexInDirWithOptions(first, 5, bloating, rounding)); + pts.push_back(bloatVertexInDirWithOptions(second, 5, bloating, rounding)); + pts.push_back(bloatVertexInDirWithOptions(second, 1, bloating, rounding)); + sizingSet.insert_vertex_sequence(pts.begin(), pts.end(), HIGH, false); + } + } + + template + inline point_data bloatVertexInDirWithSQRT1OVER2(int edge1, int normal1, const point_data& second, Unit bloating, + bool first) { + orientation_2d orient = first ? HORIZONTAL : VERTICAL; + orientation_2d orientp = orient.get_perpendicular(); + int multiplier = first ? 1 : -1; + point_data pt1(second); + if(edge1 == 1) { + if(normal1 == 3) { + move(pt1, orient, -multiplier * bloating); + } else { + move(pt1, orientp, -multiplier * bloating); + } + } else if(edge1 == 3) { + if(normal1 == 1) { + move(pt1, orient, multiplier * bloating); + } else { + move(pt1, orientp, -multiplier * bloating); + } + } else if(edge1 == 5) { + if(normal1 == 3) { + move(pt1, orientp, multiplier * bloating); + } else { + move(pt1, orient, multiplier * bloating); + } + } else { + if(normal1 == 5) { + move(pt1, orient, -multiplier * bloating); + } else { + move(pt1, orientp, multiplier * bloating); + } + } + return pt1; + } + + template + inline + void handleResizingVertex45(polygon_45_set_data& sizingSet, const point_data& first, + const point_data& second, const point_data& third, Unit resizing, + RoundingOption rounding, CornerOption corner, + int multiplier) { + unsigned int edge1 = getEdge45Direction(first, second); + unsigned int edge2 = getEdge45Direction(second, third); + unsigned int diffAngle; + if(multiplier < 0) + diffAngle = (edge2 + 8 - edge1) % 8; + else + diffAngle = (edge1 + 8 - edge2) % 8; + if(diffAngle < 4) { + if(resizing > 0) return; //accute interior corner + else multiplier *= -1; //make it appear to be an accute exterior angle + } + Unit bloating = local_abs(resizing); + if(rounding == SQRT1OVER2) { + if(edge1 % 2 && edge2 % 2) return; + if(corner == ORTHOGONAL && edge1 % 2 == 0 && edge2 % 2 == 0) { + rectangle_data insertion_rect; + set_points(insertion_rect, second, second); + bloat(insertion_rect, bloating); + sizingSet.insert(insertion_rect); + } else if(corner != ORTHOGONAL) { + point_data pt1(0, 0); + point_data pt2(0, 0); + unsigned int normal1 = getEdge45NormalDirection(edge1, multiplier); + unsigned int normal2 = getEdge45NormalDirection(edge2, multiplier); + if(edge1 % 2) { + pt1 = bloatVertexInDirWithSQRT1OVER2(edge1, normal1, second, bloating, true); + } else { + pt1 = bloatVertexInDirWithOptions(second, normal1, bloating, UNDERSIZE); + } + if(edge2 % 2) { + pt2 = bloatVertexInDirWithSQRT1OVER2(edge2, normal2, second, bloating, false); + } else { + pt2 = bloatVertexInDirWithOptions(second, normal2, bloating, UNDERSIZE); + } + std::vector > pts; + pts.push_back(pt1); + pts.push_back(second); + pts.push_back(pt2); + pts.push_back(getIntersectionPoint(pt1, edge1, pt2, edge2)); + polygon_45_data poly(pts.begin(), pts.end()); + sizingSet.insert(poly); + } else { + //ORTHOGONAL of a 45 degree corner + int normal = 0; + if(edge1 % 2) { + normal = getEdge45NormalDirection(edge2, multiplier); + } else { + normal = getEdge45NormalDirection(edge1, multiplier); + } + rectangle_data insertion_rect; + point_data edgePoint = bloatVertexInDirWithOptions(second, normal, bloating, UNDERSIZE); + set_points(insertion_rect, second, edgePoint); + if(normal == 0 || normal == 4) + bloat(insertion_rect, VERTICAL, bloating); + else + bloat(insertion_rect, HORIZONTAL, bloating); + sizingSet.insert(insertion_rect); + } + return; + } + unsigned int normal1 = getEdge45NormalDirection(edge1, multiplier); + unsigned int normal2 = getEdge45NormalDirection(edge2, multiplier); + point_data edgePoint1 = bloatVertexInDirWithOptions(second, normal1, bloating, rounding); + point_data edgePoint2 = bloatVertexInDirWithOptions(second, normal2, bloating, rounding); + //if the change in angle is 135 degrees it is an accute exterior corner + if((edge1+ multiplier * 3) % 8 == edge2) { + if(corner == ORTHOGONAL) { + rectangle_data insertion_rect; + set_points(insertion_rect, edgePoint1, edgePoint2); + sizingSet.insert(insertion_rect); + return; + } + } + std::vector > pts; + pts.push_back(edgePoint1); + pts.push_back(second); + pts.push_back(edgePoint2); + pts.push_back(getIntersectionPoint(edgePoint1, edge1, edgePoint2, edge2)); + polygon_45_data poly(pts.begin(), pts.end()); + sizingSet.insert(poly); + } + + template + template + inline polygon_45_set_data& + polygon_45_set_data::insert_with_resize_dispatch(const geometry_type& poly, + coordinate_type resizing, + RoundingOption rounding, + CornerOption corner, + bool hole, polygon_45_concept ) { + direction_1d wdir = winding(poly); + int multiplier = wdir == LOW ? -1 : 1; + if(hole) resizing *= -1; + typedef typename polygon_45_data::iterator_type piterator; + piterator first, second, third, end, real_end; + real_end = end_points(poly); + third = begin_points(poly); + first = third; + if(first == real_end) return *this; + ++third; + if(third == real_end) return *this; + second = end = third; + ++third; + if(third == real_end) return *this; + polygon_45_set_data sizingSet; + //insert minkofski shapes on edges and corners + do { + if(rounding != SQRT1OVER2) { + handleResizingEdge45(sizingSet, *first, *second, resizing, rounding); + } else { + handleResizingEdge45_SQRT1OVER2(sizingSet, *first, *second, resizing, corner); + } + if(corner != UNFILLED) + handleResizingVertex45(sizingSet, *first, *second, *third, resizing, rounding, corner, multiplier); + first = second; + second = third; + ++third; + if(third == real_end) { + third = begin_points(poly); + if(*second == *third) { + ++third; //skip first point if it is duplicate of last point + } + } + } while(second != end); + //sizingSet.snap(); + polygon_45_set_data tmp; + //insert original shape + tmp.insert_dispatch(poly, false, polygon_45_concept()); + if(resizing < 0) tmp -= sizingSet; + else tmp += sizingSet; + tmp.clean(); + insert(tmp, hole); + dirty_ = true; + unsorted_ = true; + return (*this); + } + + // accumulate the bloated polygon with holes + template + template + inline polygon_45_set_data& + polygon_45_set_data::insert_with_resize_dispatch(const geometry_type& poly, + coordinate_type resizing, + RoundingOption rounding, + CornerOption corner, + bool hole, polygon_45_with_holes_concept ) { + insert_with_resize_dispatch(poly, resizing, rounding, corner, hole, polygon_45_concept()); + for(typename polygon_with_holes_traits::iterator_holes_type itr = + begin_holes(poly); itr != end_holes(poly); + ++itr) { + insert_with_resize_dispatch(*itr, resizing, rounding, corner, !hole, polygon_45_concept()); + } + return *this; + } + + // transform set + template + template + inline polygon_45_set_data& polygon_45_set_data::transform(const transformation_type& tr){ + clean(); + std::vector > polys; + get(polys); + for(typename std::vector >::iterator itr = polys.begin(); + itr != polys.end(); ++itr) { + ::boost::polygon::transform(*itr, tr); + } + clear(); + insert(polys.begin(), polys.end()); + dirty_ = true; + unsorted_ = true; + return *this; + } + + template + inline polygon_45_set_data& polygon_45_set_data::scale_up(typename coordinate_traits::unsigned_area_type factor) { + scale_up_vertex_45_compact_range(data_.begin(), data_.end(), factor); + return *this; + } + + template + inline polygon_45_set_data& polygon_45_set_data::scale_down(typename coordinate_traits::unsigned_area_type factor) { + clean(); + std::vector > polys; + get_polygons_with_holes(polys); + for(typename std::vector >::iterator itr = polys.begin(); + itr != polys.end(); ++itr) { + ::boost::polygon::scale_down(*itr, factor); + } + clear(); + insert(polys.begin(), polys.end()); + dirty_ = true; + unsorted_ = true; + return *this; + } + + template + inline polygon_45_set_data& polygon_45_set_data::scale(double factor) { + clean(); + std::vector > polys; + get_polygons_with_holes(polys); + for(typename std::vector >::iterator itr = polys.begin(); + itr != polys.end(); ++itr) { + ::boost::polygon::scale(*itr, factor); + } + clear(); + insert(polys.begin(), polys.end()); + dirty_ = true; + unsorted_ = true; + return *this; + } + + template + inline bool polygon_45_set_data::clean() const { + if(unsorted_) sort(); + if(dirty_) { + applyAdaptiveUnary_<0>(); + dirty_ = false; + } + return true; + } + + template + template + inline void polygon_45_set_data::applyAdaptiveBoolean_(const polygon_45_set_data& rvalue) const { + polygon_45_set_data tmp; + applyAdaptiveBoolean_(tmp, rvalue); + data_.swap(tmp.data_); //swapping vectors should be constant time operation + error_data_.swap(tmp.error_data_); + is_manhattan_ = tmp.is_manhattan_; + unsorted_ = false; + dirty_ = false; + } + + template + bool applyBoolean45OpOnVectors(std::vector::Vertex45Compact>& result_data, + std::vector::Vertex45Compact>& lvalue_data, + std::vector::Vertex45Compact>& rvalue_data + ) { + bool result_is_manhattan_ = true; + typename boolean_op_45::template Scan45::Count2, + typename boolean_op_45::template boolean_op_45_output_functor > scan45; + std::vector::Vertex45> eventOut; + typedef std::pair::Point, + typename boolean_op_45::template Scan45CountT::Count2> > Scan45Vertex; + std::vector eventIn; + typedef std::vector::Vertex45Compact> value_type; + typename value_type::const_iterator iter1 = lvalue_data.begin(); + typename value_type::const_iterator iter2 = rvalue_data.begin(); + typename value_type::const_iterator end1 = lvalue_data.end(); + typename value_type::const_iterator end2 = rvalue_data.end(); + const Unit2 UnitMax = (std::numeric_limits::max)(); + Unit2 x = UnitMax; + while(iter1 != end1 || iter2 != end2) { + Unit2 currentX = UnitMax; + if(iter1 != end1) currentX = iter1->pt.x(); + if(iter2 != end2) currentX = (std::min)(currentX, iter2->pt.x()); + if(currentX != x) { + //std::cout << "SCAN " << currentX << "\n"; + //scan event + scan45.scan(eventOut, eventIn.begin(), eventIn.end()); + polygon_sort(eventOut.begin(), eventOut.end()); + std::size_t ptCount = 0; + for(std::size_t i = 0; i < eventOut.size(); ++i) { + if(!result_data.empty() && + result_data.back().pt == eventOut[i].pt) { + result_data.back().count += eventOut[i]; + ++ptCount; + } else { + if(!result_data.empty()) { + if(result_data.back().count.is_45()) { + result_is_manhattan_ = false; + } + if(ptCount == 2 && result_data.back().count == (typename polygon_45_formation::Vertex45Count(0, 0, 0, 0))) { + result_data.pop_back(); + } + } + result_data.push_back(eventOut[i]); + ptCount = 1; + } + } + if(ptCount == 2 && result_data.back().count == (typename polygon_45_formation::Vertex45Count(0, 0, 0, 0))) { + result_data.pop_back(); + } + eventOut.clear(); + eventIn.clear(); + x = currentX; + } + //std::cout << "get next\n"; + if(iter2 != end2 && (iter1 == end1 || iter2->pt.x() < iter1->pt.x() || + (iter2->pt.x() == iter1->pt.x() && + iter2->pt.y() < iter1->pt.y()) )) { + //std::cout << "case1 next\n"; + eventIn.push_back(Scan45Vertex + (iter2->pt, + typename polygon_45_formation:: + Scan45Count(typename polygon_45_formation::Count2(0, iter2->count[0]), + typename polygon_45_formation::Count2(0, iter2->count[1]), + typename polygon_45_formation::Count2(0, iter2->count[2]), + typename polygon_45_formation::Count2(0, iter2->count[3])))); + ++iter2; + } else if(iter1 != end1 && (iter2 == end2 || iter1->pt.x() < iter2->pt.x() || + (iter1->pt.x() == iter2->pt.x() && + iter1->pt.y() < iter2->pt.y()) )) { + //std::cout << "case2 next\n"; + eventIn.push_back(Scan45Vertex + (iter1->pt, + typename polygon_45_formation:: + Scan45Count( + typename polygon_45_formation::Count2(iter1->count[0], 0), + typename polygon_45_formation::Count2(iter1->count[1], 0), + typename polygon_45_formation::Count2(iter1->count[2], 0), + typename polygon_45_formation::Count2(iter1->count[3], 0)))); + ++iter1; + } else { + //std::cout << "case3 next\n"; + eventIn.push_back(Scan45Vertex + (iter2->pt, + typename polygon_45_formation:: + Scan45Count(typename polygon_45_formation::Count2(iter1->count[0], + iter2->count[0]), + typename polygon_45_formation::Count2(iter1->count[1], + iter2->count[1]), + typename polygon_45_formation::Count2(iter1->count[2], + iter2->count[2]), + typename polygon_45_formation::Count2(iter1->count[3], + iter2->count[3])))); + ++iter1; + ++iter2; + } + } + scan45.scan(eventOut, eventIn.begin(), eventIn.end()); + polygon_sort(eventOut.begin(), eventOut.end()); + + std::size_t ptCount = 0; + for(std::size_t i = 0; i < eventOut.size(); ++i) { + if(!result_data.empty() && + result_data.back().pt == eventOut[i].pt) { + result_data.back().count += eventOut[i]; + ++ptCount; + } else { + if(!result_data.empty()) { + if(result_data.back().count.is_45()) { + result_is_manhattan_ = false; + } + if(ptCount == 2 && result_data.back().count == (typename polygon_45_formation::Vertex45Count(0, 0, 0, 0))) { + result_data.pop_back(); + } + } + result_data.push_back(eventOut[i]); + ptCount = 1; + } + } + if(ptCount == 2 && result_data.back().count == (typename polygon_45_formation::Vertex45Count(0, 0, 0, 0))) { + result_data.pop_back(); + } + if(!result_data.empty() && + result_data.back().count.is_45()) { + result_is_manhattan_ = false; + } + return result_is_manhattan_; + } + + template + bool applyUnary45OpOnVectors(std::vector::Vertex45Compact>& result_data, + std::vector::Vertex45Compact>& lvalue_data ) { + bool result_is_manhattan_ = true; + typename boolean_op_45::template Scan45::Count1, + typename boolean_op_45::template unary_op_45_output_functor > scan45; + std::vector::Vertex45> eventOut; + typedef typename boolean_op_45::template Scan45CountT::Count1> Scan45Count; + typedef std::pair::Point, Scan45Count> Scan45Vertex; + std::vector eventIn; + typedef std::vector::Vertex45Compact> value_type; + typename value_type::const_iterator iter1 = lvalue_data.begin(); + typename value_type::const_iterator end1 = lvalue_data.end(); + const Unit2 UnitMax = (std::numeric_limits::max)(); + Unit2 x = UnitMax; + while(iter1 != end1) { + Unit2 currentX = iter1->pt.x(); + if(currentX != x) { + //std::cout << "SCAN " << currentX << "\n"; + //scan event + scan45.scan(eventOut, eventIn.begin(), eventIn.end()); + polygon_sort(eventOut.begin(), eventOut.end()); + std::size_t ptCount = 0; + for(std::size_t i = 0; i < eventOut.size(); ++i) { + if(!result_data.empty() && + result_data.back().pt == eventOut[i].pt) { + result_data.back().count += eventOut[i]; + ++ptCount; + } else { + if(!result_data.empty()) { + if(result_data.back().count.is_45()) { + result_is_manhattan_ = false; + } + if(ptCount == 2 && result_data.back().count == (typename polygon_45_formation::Vertex45Count(0, 0, 0, 0))) { + result_data.pop_back(); + } + } + result_data.push_back(eventOut[i]); + ptCount = 1; + } + } + if(ptCount == 2 && result_data.back().count == (typename polygon_45_formation::Vertex45Count(0, 0, 0, 0))) { + result_data.pop_back(); + } + eventOut.clear(); + eventIn.clear(); + x = currentX; + } + //std::cout << "get next\n"; + eventIn.push_back(Scan45Vertex + (iter1->pt, + Scan45Count( typename boolean_op_45::Count1(iter1->count[0]), + typename boolean_op_45::Count1(iter1->count[1]), + typename boolean_op_45::Count1(iter1->count[2]), + typename boolean_op_45::Count1(iter1->count[3])))); + ++iter1; + } + scan45.scan(eventOut, eventIn.begin(), eventIn.end()); + polygon_sort(eventOut.begin(), eventOut.end()); + + std::size_t ptCount = 0; + for(std::size_t i = 0; i < eventOut.size(); ++i) { + if(!result_data.empty() && + result_data.back().pt == eventOut[i].pt) { + result_data.back().count += eventOut[i]; + ++ptCount; + } else { + if(!result_data.empty()) { + if(result_data.back().count.is_45()) { + result_is_manhattan_ = false; + } + if(ptCount == 2 && result_data.back().count == (typename polygon_45_formation::Vertex45Count(0, 0, 0, 0))) { + result_data.pop_back(); + } + } + result_data.push_back(eventOut[i]); + ptCount = 1; + } + } + if(ptCount == 2 && result_data.back().count == (typename polygon_45_formation::Vertex45Count(0, 0, 0, 0))) { + result_data.pop_back(); + } + if(!result_data.empty() && + result_data.back().count.is_45()) { + result_is_manhattan_ = false; + } + return result_is_manhattan_; + } + + template + void get_error_rects_shell(cT& posE, cT& negE, iT beginr, iT endr) { + typedef typename std::iterator_traits::value_type Point; + typedef typename point_traits::coordinate_type Unit; + typedef typename coordinate_traits::area_type area_type; + Point pt1, pt2, pt3; + bool i1 = true; + bool i2 = true; + bool not_done = beginr != endr; + bool next_to_last = false; + bool last = false; + Point first, second; + while(not_done) { + if(last) { + last = false; + not_done = false; + pt3 = second; + } else if(next_to_last) { + next_to_last = false; + last = true; + pt3 = first; + } else if(i1) { + const Point& pt = *beginr; + first = pt1 = pt; + i1 = false; + i2 = true; + ++beginr; + if(beginr == endr) return; //too few points + continue; + } else if (i2) { + const Point& pt = *beginr; + second = pt2 = pt; + i2 = false; + ++beginr; + if(beginr == endr) return; //too few points + continue; + } else { + const Point& pt = *beginr; + pt3 = pt; + ++beginr; + if(beginr == endr) { + next_to_last = true; + //skip last point equal to first + continue; + } + } + if(local_abs(x(pt2)) % 2) { //y % 2 should also be odd + //is corner concave or convex? + Point pts[] = {pt1, pt2, pt3}; + area_type ar = point_sequence_area(pts, pts+3); + direction_1d dir = ar < 0 ? COUNTERCLOCKWISE : CLOCKWISE; + //std::cout << pt1 << " " << pt2 << " " << pt3 << " " << ar << std::endl; + if(dir == CLOCKWISE) { + posE.push_back(rectangle_data + (x(pt2) - 1, y(pt2) - 1, x(pt2) + 1, y(pt2) + 1)); + + } else { + negE.push_back(rectangle_data + (x(pt2) - 1, y(pt2) - 1, x(pt2) + 1, y(pt2) + 1)); + } + } + pt1 = pt2; + pt2 = pt3; + } + } + + template + void get_error_rects(cT& posE, cT& negE, const pT& p) { + get_error_rects_shell(posE, negE, p.begin(), p.end()); + for(typename pT::iterator_holes_type iHb = p.begin_holes(); + iHb != p.end_holes(); ++iHb) { + get_error_rects_shell(posE, negE, iHb->begin(), iHb->end()); + } + } + + template + template + inline void polygon_45_set_data::applyAdaptiveBoolean_(polygon_45_set_data& result, + const polygon_45_set_data& rvalue) const { + result.clear(); + result.error_data_ = error_data_; + result.error_data_.insert(result.error_data_.end(), rvalue.error_data_.begin(), + rvalue.error_data_.end()); + if(is_manhattan() && rvalue.is_manhattan()) { + //convert each into polygon_90_set data and call boolean operations + polygon_90_set_data l90sd(VERTICAL), r90sd(VERTICAL), output(VERTICAL); + for(typename value_type::const_iterator itr = data_.begin(); itr != data_.end(); ++itr) { + if((*itr).count[3] == 0) continue; //skip all non vertical edges + l90sd.insert(std::make_pair((*itr).pt.x(), std::make_pair((*itr).pt.y(), (*itr).count[3])), false, VERTICAL); + } + for(typename value_type::const_iterator itr = rvalue.data_.begin(); itr != rvalue.data_.end(); ++itr) { + if((*itr).count[3] == 0) continue; //skip all non vertical edges + r90sd.insert(std::make_pair((*itr).pt.x(), std::make_pair((*itr).pt.y(), (*itr).count[3])), false, VERTICAL); + } + l90sd.sort(); + r90sd.sort(); +#ifdef BOOST_POLYGON_MSVC +#pragma warning (push) +#pragma warning (disable: 4127) +#endif + if(op == 0) { + output.applyBooleanBinaryOp(l90sd.begin(), l90sd.end(), + r90sd.begin(), r90sd.end(), boolean_op::BinaryCount()); + } else if (op == 1) { + output.applyBooleanBinaryOp(l90sd.begin(), l90sd.end(), + r90sd.begin(), r90sd.end(), boolean_op::BinaryCount()); + } else if (op == 2) { + output.applyBooleanBinaryOp(l90sd.begin(), l90sd.end(), + r90sd.begin(), r90sd.end(), boolean_op::BinaryCount()); + } else if (op == 3) { + output.applyBooleanBinaryOp(l90sd.begin(), l90sd.end(), + r90sd.begin(), r90sd.end(), boolean_op::BinaryCount()); + } +#ifdef BOOST_POLYGON_MSVC +#pragma warning (pop) +#endif + result.data_.clear(); + result.insert(output); + result.is_manhattan_ = true; + result.dirty_ = false; + result.unsorted_ = false; + } else { + sort(); + rvalue.sort(); + try { + result.is_manhattan_ = applyBoolean45OpOnVectors(result.data_, data_, rvalue.data_); + } catch (std::string str) { + std::string msg = "GTL 45 Boolean error, precision insufficient to represent edge intersection coordinate value."; + if(str == msg) { + result.clear(); + typedef typename coordinate_traits::manhattan_area_type Unit2; + typedef typename polygon_45_formation::Vertex45Compact Vertex45Compact2; + typedef std::vector Data2; + Data2 rvalue_data, lvalue_data, result_data; + rvalue_data.reserve(rvalue.data_.size()); + lvalue_data.reserve(data_.size()); + for(std::size_t i = 0 ; i < data_.size(); ++i) { + const Vertex45Compact& vi = data_[i]; + Vertex45Compact2 ci; + ci.pt = point_data(x(vi.pt), y(vi.pt)); + ci.count = typename polygon_45_formation::Vertex45Count + ( vi.count[0], vi.count[1], vi.count[2], vi.count[3]); + lvalue_data.push_back(ci); + } + for(std::size_t i = 0 ; i < rvalue.data_.size(); ++i) { + const Vertex45Compact& vi = rvalue.data_[i]; + Vertex45Compact2 ci; + ci.pt = (point_data(x(vi.pt), y(vi.pt))); + ci.count = typename polygon_45_formation::Vertex45Count + ( vi.count[0], vi.count[1], vi.count[2], vi.count[3]); + rvalue_data.push_back(ci); + } + scale_up_vertex_45_compact_range(lvalue_data.begin(), lvalue_data.end(), 2); + scale_up_vertex_45_compact_range(rvalue_data.begin(), rvalue_data.end(), 2); + bool result_is_manhattan = applyBoolean45OpOnVectors(result_data, + lvalue_data, + rvalue_data ); + if(!result_is_manhattan) { + typename polygon_45_formation::Polygon45Formation pf(false); + //std::cout << "FORMING POLYGONS\n"; + std::vector > container; + pf.scan(container, result_data.begin(), result_data.end()); + Data2 error_data_out; + std::vector > pos_error_rects; + std::vector > neg_error_rects; + for(std::size_t i = 0; i < container.size(); ++i) { + get_error_rects(pos_error_rects, neg_error_rects, container[i]); + } + for(std::size_t i = 0; i < pos_error_rects.size(); ++i) { + insert_rectangle_into_vector_45(result_data, pos_error_rects[i], false); + insert_rectangle_into_vector_45(error_data_out, pos_error_rects[i], false); + } + for(std::size_t i = 0; i < neg_error_rects.size(); ++i) { + insert_rectangle_into_vector_45(result_data, neg_error_rects[i], true); + insert_rectangle_into_vector_45(error_data_out, neg_error_rects[i], false); + } + scale_down_vertex_45_compact_range_blindly(error_data_out.begin(), error_data_out.end(), 2); + for(std::size_t i = 0 ; i < error_data_out.size(); ++i) { + const Vertex45Compact2& vi = error_data_out[i]; + Vertex45Compact ci; + ci.pt.x(static_cast(x(vi.pt))); + ci.pt.y(static_cast(y(vi.pt))); + ci.count = typename polygon_45_formation::Vertex45Count + ( vi.count[0], vi.count[1], vi.count[2], vi.count[3]); + result.error_data_.push_back(ci); + } + Data2 new_result_data; + polygon_sort(result_data.begin(), result_data.end()); + applyUnary45OpOnVectors(new_result_data, result_data); //OR operation + result_data.swap(new_result_data); + } + scale_down_vertex_45_compact_range_blindly(result_data.begin(), result_data.end(), 2); + //result.data_.reserve(result_data.size()); + for(std::size_t i = 0 ; i < result_data.size(); ++i) { + const Vertex45Compact2& vi = result_data[i]; + Vertex45Compact ci; + ci.pt.x(static_cast(x(vi.pt))); + ci.pt.y(static_cast(y(vi.pt))); + ci.count = typename polygon_45_formation::Vertex45Count + ( vi.count[0], vi.count[1], vi.count[2], vi.count[3]); + result.data_.push_back(ci); + } + result.is_manhattan_ = result_is_manhattan; + result.dirty_ = false; + result.unsorted_ = false; + } else { throw str; } + } + //std::cout << "DONE SCANNING\n"; + } + } + + template + template + inline void polygon_45_set_data::applyAdaptiveUnary_() const { + polygon_45_set_data result; + result.error_data_ = error_data_; + if(is_manhattan()) { + //convert each into polygon_90_set data and call boolean operations + polygon_90_set_data l90sd(VERTICAL); + for(typename value_type::const_iterator itr = data_.begin(); itr != data_.end(); ++itr) { + if((*itr).count[3] == 0) continue; //skip all non vertical edges + l90sd.insert(std::make_pair((*itr).pt.x(), std::make_pair((*itr).pt.y(), (*itr).count[3])), false, VERTICAL); + } + l90sd.sort(); +#ifdef BOOST_POLYGON_MSVC +#pragma warning (push) +#pragma warning (disable: 4127) +#endif + if(op == 0) { + l90sd.clean(); + } else if (op == 1) { + l90sd.self_intersect(); + } else if (op == 3) { + l90sd.self_xor(); + } +#ifdef BOOST_POLYGON_MSVC +#pragma warning (pop) +#endif + result.data_.clear(); + result.insert(l90sd); + result.is_manhattan_ = true; + result.dirty_ = false; + result.unsorted_ = false; + } else { + sort(); + try { + result.is_manhattan_ = applyUnary45OpOnVectors(result.data_, data_); + } catch (std::string str) { + std::string msg = "GTL 45 Boolean error, precision insufficient to represent edge intersection coordinate value."; + if(str == msg) { + result.clear(); + typedef typename coordinate_traits::manhattan_area_type Unit2; + typedef typename polygon_45_formation::Vertex45Compact Vertex45Compact2; + typedef std::vector Data2; + Data2 lvalue_data, result_data; + lvalue_data.reserve(data_.size()); + for(std::size_t i = 0 ; i < data_.size(); ++i) { + const Vertex45Compact& vi = data_[i]; + Vertex45Compact2 ci; + ci.pt.x(static_cast(x(vi.pt))); + ci.pt.y(static_cast(y(vi.pt))); + ci.count = typename polygon_45_formation::Vertex45Count + ( vi.count[0], vi.count[1], vi.count[2], vi.count[3]); + lvalue_data.push_back(ci); + } + scale_up_vertex_45_compact_range(lvalue_data.begin(), lvalue_data.end(), 2); + bool result_is_manhattan = applyUnary45OpOnVectors(result_data, + lvalue_data ); + if(!result_is_manhattan) { + typename polygon_45_formation::Polygon45Formation pf(false); + //std::cout << "FORMING POLYGONS\n"; + std::vector > container; + pf.scan(container, result_data.begin(), result_data.end()); + Data2 error_data_out; + std::vector > pos_error_rects; + std::vector > neg_error_rects; + for(std::size_t i = 0; i < container.size(); ++i) { + get_error_rects(pos_error_rects, neg_error_rects, container[i]); + } + for(std::size_t i = 0; i < pos_error_rects.size(); ++i) { + insert_rectangle_into_vector_45(result_data, pos_error_rects[i], false); + insert_rectangle_into_vector_45(error_data_out, pos_error_rects[i], false); + } + for(std::size_t i = 0; i < neg_error_rects.size(); ++i) { + insert_rectangle_into_vector_45(result_data, neg_error_rects[i], true); + insert_rectangle_into_vector_45(error_data_out, neg_error_rects[i], false); + } + scale_down_vertex_45_compact_range_blindly(error_data_out.begin(), error_data_out.end(), 2); + for(std::size_t i = 0 ; i < error_data_out.size(); ++i) { + const Vertex45Compact2& vi = error_data_out[i]; + Vertex45Compact ci; + ci.pt.x(static_cast(x(vi.pt))); + ci.pt.y(static_cast(y(vi.pt))); + ci.count = typename polygon_45_formation::Vertex45Count + ( vi.count[0], vi.count[1], vi.count[2], vi.count[3]); + result.error_data_.push_back(ci); + } + Data2 new_result_data; + polygon_sort(result_data.begin(), result_data.end()); + applyUnary45OpOnVectors(new_result_data, result_data); //OR operation + result_data.swap(new_result_data); + } + scale_down_vertex_45_compact_range_blindly(result_data.begin(), result_data.end(), 2); + //result.data_.reserve(result_data.size()); + for(std::size_t i = 0 ; i < result_data.size(); ++i) { + const Vertex45Compact2& vi = result_data[i]; + Vertex45Compact ci; + ci.pt.x(static_cast(x(vi.pt))); + ci.pt.y(static_cast(y(vi.pt))); + ci.count = typename polygon_45_formation::Vertex45Count + ( vi.count[0], vi.count[1], vi.count[2], vi.count[3]); + result.data_.push_back(ci); + } + result.is_manhattan_ = result_is_manhattan; + result.dirty_ = false; + result.unsorted_ = false; + } else { throw str; } + } + //std::cout << "DONE SCANNING\n"; + } + data_.swap(result.data_); + error_data_.swap(result.error_data_); + dirty_ = result.dirty_; + unsorted_ = result.unsorted_; + is_manhattan_ = result.is_manhattan_; + } + + template + class property_merge_45 { + private: + typedef typename coordinate_traits::manhattan_area_type big_coord; + typedef typename polygon_45_property_merge::MergeSetData tsd; + tsd tsd_; + public: + inline property_merge_45() : tsd_() {} + inline property_merge_45(const property_merge_45& that) : tsd_(that.tsd_) {} + inline property_merge_45& operator=(const property_merge_45& that) { + tsd_ = that.tsd_; + return *this; + } + + inline void insert(const polygon_45_set_data& ps, property_type property) { + ps.clean(); + polygon_45_property_merge::populateMergeSetData(tsd_, ps.begin(), ps.end(), property); + } + template + inline void insert(const GeoObjT& geoObj, property_type property) { + polygon_45_set_data ps; + ps.insert(geoObj); + insert(ps, property); + } + + //merge properties of input geometries and store the resulting geometries of regions + //with unique sets of merged properties to polygons sets in a map keyed by sets of properties + // T = std::map, polygon_45_set_data > or + // T = std::map, polygon_45_set_data > + template + inline void merge(result_type& result) { + typedef typename result_type::key_type keytype; + typedef std::map > bigtype; + bigtype result_big; + polygon_45_property_merge::performMerge(result_big, tsd_); + std::vector > polys; + std::vector > pos_error_rects; + std::vector > neg_error_rects; + for(typename std::map >::iterator itr = result_big.begin(); + itr != result_big.end(); ++itr) { + polys.clear(); + (*itr).second.get(polys); + for(std::size_t i = 0; i < polys.size(); ++i) { + get_error_rects(pos_error_rects, neg_error_rects, polys[i]); + } + (*itr).second += pos_error_rects; + (*itr).second -= neg_error_rects; + (*itr).second.scale_down(2); + result[(*itr).first].insert((*itr).second); + } + } + }; + + //ConnectivityExtraction computes the graph of connectivity between rectangle, polygon and + //polygon set graph nodes where an edge is created whenever the geometry in two nodes overlap + template + class connectivity_extraction_45 { + private: + typedef typename coordinate_traits::manhattan_area_type big_coord; + typedef typename polygon_45_touch::TouchSetData tsd; + tsd tsd_; + unsigned int nodeCount_; + public: + inline connectivity_extraction_45() : tsd_(), nodeCount_(0) {} + inline connectivity_extraction_45(const connectivity_extraction_45& that) : tsd_(that.tsd_), + nodeCount_(that.nodeCount_) {} + inline connectivity_extraction_45& operator=(const connectivity_extraction_45& that) { + tsd_ = that.tsd_; + nodeCount_ = that.nodeCount_; {} + return *this; + } + + //insert a polygon set graph node, the value returned is the id of the graph node + inline unsigned int insert(const polygon_45_set_data& ps) { + ps.clean(); + polygon_45_touch::populateTouchSetData(tsd_, ps.begin(), ps.end(), nodeCount_); + return nodeCount_++; + } + template + inline unsigned int insert(const GeoObjT& geoObj) { + polygon_45_set_data ps; + ps.insert(geoObj); + return insert(ps); + } + + //extract connectivity and store the edges in the graph + //graph must be indexable by graph node id and the indexed value must be a std::set of + //graph node id + template + inline void extract(GraphT& graph) { + polygon_45_touch::performTouch(graph, tsd_); + } + }; +} +} +#endif + diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/polygon_45_set_traits.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/polygon_45_set_traits.hpp new file mode 100644 index 0000000..f52f57f --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/polygon_45_set_traits.hpp @@ -0,0 +1,149 @@ +/* + Copyright 2008 Intel Corporation + + Use, modification and distribution are subject to the Boost Software License, + Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at + http://www.boost.org/LICENSE_1_0.txt). +*/ +#ifndef BOOST_POLYGON_POLYGON_45_SET_TRAITS_HPP +#define BOOST_POLYGON_POLYGON_45_SET_TRAITS_HPP +namespace boost { namespace polygon{ + + //default definition of polygon 45 set traits works for any model of polygon 45, polygon 45 with holes or any vector or list thereof + template + struct polygon_45_set_traits { + typedef typename get_coordinate_type::type >::type coordinate_type; + typedef typename get_iterator_type::type iterator_type; + typedef T operator_arg_type; + + static inline iterator_type begin(const T& polygon_set) { + return get_iterator_type::begin(polygon_set); + } + + static inline iterator_type end(const T& polygon_set) { + return get_iterator_type::end(polygon_set); + } + + static inline bool clean(const T& ) { return false; } + + static inline bool sorted(const T& ) { return false; } + }; + + template + struct is_45_polygonal_concept { typedef gtl_no type; }; + template <> + struct is_45_polygonal_concept { typedef gtl_yes type; }; + template <> + struct is_45_polygonal_concept { typedef gtl_yes type; }; + template <> + struct is_45_polygonal_concept { typedef gtl_yes type; }; + + template + struct is_polygon_45_set_type { + typedef typename is_45_polygonal_concept::type>::type type; + }; + template + struct is_polygon_45_set_type > { + typedef typename gtl_or< + typename is_45_polygonal_concept >::type>::type, + typename is_45_polygonal_concept::value_type>::type>::type>::type type; + }; + template + struct is_polygon_45_set_type > { + typedef typename gtl_or< + typename is_45_polygonal_concept >::type>::type, + typename is_45_polygonal_concept::value_type>::type>::type>::type type; + }; + + template + struct is_mutable_polygon_45_set_type { + typedef typename gtl_same_type::type>::type type; + }; + template + struct is_mutable_polygon_45_set_type > { + typedef typename gtl_or< + typename gtl_same_type >::type>::type, + typename is_45_polygonal_concept::value_type>::type>::type>::type type; + }; + template + struct is_mutable_polygon_45_set_type > { + typedef typename gtl_or< + typename gtl_same_type >::type>::type, + typename is_45_polygonal_concept::value_type>::type>::type>::type type; + }; + + template + bool fracture_holes_45_by_concept() { return false; } + template <> + inline bool fracture_holes_45_by_concept() { return true; } + + template + void get_45_polygons_T(T& t, iT begin, iT end) { + typedef typename polygon_45_set_traits::coordinate_type Unit; + typedef typename geometry_concept::type CType; + typename polygon_45_formation::Polygon45Formation pf(fracture_holes_45_by_concept()); + //std::cout << "FORMING POLYGONS\n"; + pf.scan(t, begin, end); + } + + template + struct polygon_45_set_mutable_traits {}; + template + struct polygon_45_set_mutable_traits > { + template + static inline void set(std::list& polygon_set, input_iterator_type input_begin, input_iterator_type input_end) { + polygon_set.clear(); + polygon_45_set_data >::coordinate_type> ps; + ps.reserve(std::distance(input_begin, input_end)); + ps.insert(input_begin, input_end); + ps.sort(); + ps.clean(); + get_45_polygons_T(polygon_set, ps.begin(), ps.end()); + } + }; + template + struct polygon_45_set_mutable_traits > { + template + static inline void set(std::vector& polygon_set, input_iterator_type input_begin, input_iterator_type input_end) { + polygon_set.clear(); + size_t num_ele = std::distance(input_begin, input_end); + polygon_set.reserve(num_ele); + polygon_45_set_data >::coordinate_type> ps; + ps.reserve(num_ele); + ps.insert(input_begin, input_end); + ps.sort(); + ps.clean(); + get_45_polygons_T(polygon_set, ps.begin(), ps.end()); + } + }; + + template + struct polygon_45_set_mutable_traits > { + template + static inline void set(polygon_45_set_data& polygon_set, + input_iterator_type input_begin, input_iterator_type input_end) { + polygon_set.set(input_begin, input_end); + } + }; + template + struct polygon_45_set_traits > { + typedef typename polygon_45_set_data::coordinate_type coordinate_type; + typedef typename polygon_45_set_data::iterator_type iterator_type; + typedef typename polygon_45_set_data::operator_arg_type operator_arg_type; + + static inline iterator_type begin(const polygon_45_set_data& polygon_set) { + return polygon_set.begin(); + } + + static inline iterator_type end(const polygon_45_set_data& polygon_set) { + return polygon_set.end(); + } + + static inline bool clean(const polygon_45_set_data& polygon_set) { polygon_set.clean(); return true; } + + static inline bool sorted(const polygon_45_set_data& polygon_set) { polygon_set.sort(); return true; } + + }; +} +} +#endif diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/polygon_45_with_holes_data.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/polygon_45_with_holes_data.hpp new file mode 100644 index 0000000..0601bdc --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/polygon_45_with_holes_data.hpp @@ -0,0 +1,107 @@ +/* + Copyright 2008 Intel Corporation + + Use, modification and distribution are subject to the Boost Software License, + Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at + http://www.boost.org/LICENSE_1_0.txt). +*/ +#ifndef BOOST_POLYGON_POLYGON_45_WITH_HOLES_DATA_HPP +#define BOOST_POLYGON_POLYGON_45_WITH_HOLES_DATA_HPP +#include "isotropy.hpp" +#include "polygon_45_data.hpp" +namespace boost { namespace polygon{ +struct polygon_45_with_holes_concept; +template +class polygon_45_with_holes_data { +public: + typedef polygon_45_with_holes_concept geometry_type; + typedef T coordinate_type; + typedef typename polygon_45_data::iterator_type iterator_type; + typedef typename std::list >::const_iterator iterator_holes_type; + typedef polygon_45_data hole_type; + typedef typename coordinate_traits::coordinate_distance area_type; + typedef point_data point_type; + + // default constructor of point does not initialize x and y + inline polygon_45_with_holes_data() : self_(), holes_() {} //do nothing default constructor + + template + inline polygon_45_with_holes_data(iT input_begin, iT input_end) : self_(), holes_() { + set(input_begin, input_end); + } + + template + inline polygon_45_with_holes_data(iT input_begin, iT input_end, hiT holes_begin, hiT holes_end) : self_(), holes_() { + set(input_begin, input_end); + set_holes(holes_begin, holes_end); + } + + template + inline polygon_45_with_holes_data& set(iT input_begin, iT input_end) { + self_.set(input_begin, input_end); + return *this; + } + + // initialize a polygon from x,y values, it is assumed that the first is an x + // and that the input is a well behaved polygon + template + inline polygon_45_with_holes_data& set_holes(iT input_begin, iT input_end) { + holes_.clear(); //just in case there was some old data there + for( ; input_begin != input_end; ++ input_begin) { + holes_.push_back(hole_type()); + holes_.back().set((*input_begin).begin(), (*input_begin).end()); + } + return *this; + } + + // copy constructor (since we have dynamic memory) + inline polygon_45_with_holes_data(const polygon_45_with_holes_data& that) : self_(that.self_), + holes_(that.holes_) {} + + // assignment operator (since we have dynamic memory do a deep copy) + inline polygon_45_with_holes_data& operator=(const polygon_45_with_holes_data& that) { + self_ = that.self_; + holes_ = that.holes_; + return *this; + } + + template + inline polygon_45_with_holes_data& operator=(const T2& rvalue); + + // get begin iterator, returns a pointer to a const coordinate_type + inline const iterator_type begin() const { + return self_.begin(); + } + + // get end iterator, returns a pointer to a const coordinate_type + inline const iterator_type end() const { + return self_.end(); + } + + inline std::size_t size() const { + return self_.size(); + } + + // get begin iterator, returns a pointer to a const polygon + inline const iterator_holes_type begin_holes() const { + return holes_.begin(); + } + + // get end iterator, returns a pointer to a const polygon + inline const iterator_holes_type end_holes() const { + return holes_.end(); + } + + inline std::size_t size_holes() const { + return holes_.size(); + } + +public: + polygon_45_data self_; + std::list holes_; +}; + + +} +} +#endif diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/polygon_90_data.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/polygon_90_data.hpp new file mode 100644 index 0000000..1f14ed7 --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/polygon_90_data.hpp @@ -0,0 +1,79 @@ +/* + Copyright 2008 Intel Corporation + + Use, modification and distribution are subject to the Boost Software License, + Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at + http://www.boost.org/LICENSE_1_0.txt). +*/ +#ifndef BOOST_POLYGON_POLYGON_90_DATA_HPP +#define BOOST_POLYGON_POLYGON_90_DATA_HPP +namespace boost { namespace polygon{ +struct polygon_90_concept; +template +class polygon_90_data { +public: + typedef polygon_90_concept geometry_type; + typedef T coordinate_type; + typedef typename std::vector::const_iterator compact_iterator_type; + typedef iterator_compact_to_points > iterator_type; + typedef typename coordinate_traits::area_type area_type; + + inline polygon_90_data() : coords_() {} //do nothing default constructor + + // initialize a polygon from x,y values, it is assumed that the first is an x + // and that the input is a well behaved polygon + template + inline polygon_90_data& set(iT begin_point, iT end_point) { + return set_compact(iterator_points_to_compact::value_type>(begin_point, end_point), + iterator_points_to_compact::value_type>(end_point, end_point)); + } + + template + inline polygon_90_data& set_compact(iT input_begin, iT input_end) { + coords_.clear(); //just in case there was some old data there + while(input_begin != input_end) { + coords_.insert(coords_.end(), *input_begin); + ++input_begin; + } + return *this; + } + + // copy constructor (since we have dynamic memory) + inline polygon_90_data(const polygon_90_data& that) : coords_(that.coords_) {} + + // assignment operator (since we have dynamic memory do a deep copy) + inline polygon_90_data& operator=(const polygon_90_data& that) { + coords_ = that.coords_; + return *this; + } + + template + inline polygon_90_data& operator=(const T2& rvalue); + + // assignment operator (since we have dynamic memory do a deep copy) + inline bool operator==(const polygon_90_data& that) const { + return coords_ == that.coords_; + } + + // get begin iterator, returns a pointer to a const Unit + inline iterator_type begin() const { return iterator_type(coords_.begin(), coords_.end()); } + + // get end iterator, returns a pointer to a const Unit + inline iterator_type end() const { return iterator_type(coords_.end(), coords_.end()); } + + // get begin iterator, returns a pointer to a const Unit + inline compact_iterator_type begin_compact() const { return coords_.begin(); } + + // get end iterator, returns a pointer to a const Unit + inline compact_iterator_type end_compact() const { return coords_.end(); } + + inline std::size_t size() const { return coords_.size(); } + +private: + std::vector coords_; +}; + + +} +} +#endif diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/polygon_90_set_concept.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/polygon_90_set_concept.hpp new file mode 100644 index 0000000..5259a07 --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/polygon_90_set_concept.hpp @@ -0,0 +1,550 @@ +/* + Copyright 2008 Intel Corporation + + Use, modification and distribution are subject to the Boost Software License, + Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at + http://www.boost.org/LICENSE_1_0.txt). +*/ +#ifndef BOOST_POLYGON_POLYGON_90_SET_CONCEPT_HPP +#define BOOST_POLYGON_POLYGON_90_SET_CONCEPT_HPP +#include "polygon_90_set_data.hpp" +#include "polygon_90_set_traits.hpp" +namespace boost { namespace polygon{ + + template + typename enable_if< typename is_polygon_90_set_type::type, + typename polygon_90_set_traits::iterator_type>::type + begin_90_set_data(const polygon_set_type& polygon_set) { + return polygon_90_set_traits::begin(polygon_set); + } + + template + typename enable_if< typename is_polygon_90_set_type::type, + typename polygon_90_set_traits::iterator_type>::type + end_90_set_data(const polygon_set_type& polygon_set) { + return polygon_90_set_traits::end(polygon_set); + } + + template + typename enable_if< typename is_polygon_90_set_type::type, + orientation_2d>::type + scanline_orientation(const polygon_set_type& polygon_set) { + return polygon_90_set_traits::orient(polygon_set); + } + + template + typename enable_if< typename is_polygon_90_set_type::type, + bool>::type + clean(const polygon_set_type& polygon_set) { + return polygon_90_set_traits::clean(polygon_set); + } + + //assign + template + typename enable_if < + typename gtl_and< + typename is_mutable_polygon_90_set_type::type, + typename is_polygon_90_set_type::type>::type, + polygon_set_type_1>::type & + assign(polygon_set_type_1& lvalue, const polygon_set_type_2& rvalue) { + polygon_90_set_mutable_traits::set(lvalue, begin_90_set_data(rvalue), end_90_set_data(rvalue), + scanline_orientation(rvalue)); + return lvalue; + } + + template + struct are_not_both_rectangle_concept { typedef gtl_yes type; }; + template <> + struct are_not_both_rectangle_concept { typedef gtl_no type; }; + + //equivalence + template + typename enable_if< typename gtl_and_3< + typename is_polygon_90_set_type::type, + typename is_polygon_90_set_type::type, + typename are_not_both_rectangle_concept::type, + typename geometry_concept::type>::type>::type, + bool>::type + equivalence(const polygon_set_type_1& lvalue, + const polygon_set_type_2& rvalue) { + polygon_90_set_data::coordinate_type> ps1; + assign(ps1, lvalue); + polygon_90_set_data::coordinate_type> ps2; + assign(ps2, rvalue); + return ps1 == ps2; + } + + + //get rectangle tiles (slicing orientation is vertical) + template + typename enable_if< typename gtl_if::type>::type, + void>::type + get_rectangles(output_container_type& output, const polygon_set_type& polygon_set) { + clean(polygon_set); + polygon_90_set_data::coordinate_type> ps(VERTICAL); + assign(ps, polygon_set); + ps.get_rectangles(output); + } + + //get rectangle tiles + template + typename enable_if< typename gtl_if::type>::type, + void>::type + get_rectangles(output_container_type& output, const polygon_set_type& polygon_set, orientation_2d slicing_orientation) { + clean(polygon_set); + polygon_90_set_data::coordinate_type> ps; + assign(ps, polygon_set); + ps.get_rectangles(output, slicing_orientation); + } + + //get: min_rectangles max_rectangles + template + typename enable_if ::type, + typename gtl_same_type::value_type>::type>::type>::type, + void>::type + get_max_rectangles(output_container_type& output, const polygon_set_type& polygon_set) { + std::vector::coordinate_type> > rects; + assign(rects, polygon_set); + MaxCover::coordinate_type>::getMaxCover(output, rects, scanline_orientation(polygon_set)); + } + + //clear + template + typename enable_if< typename is_mutable_polygon_90_set_type::type, + void>::type + clear(polygon_set_type& polygon_set) { + polygon_90_set_data::coordinate_type> ps(scanline_orientation(polygon_set)); + assign(polygon_set, ps); + } + + //empty + template + typename enable_if< typename is_mutable_polygon_90_set_type::type, + bool>::type + empty(const polygon_set_type& polygon_set) { + if(clean(polygon_set)) return begin_90_set_data(polygon_set) == end_90_set_data(polygon_set); + polygon_90_set_data::coordinate_type> ps; + assign(ps, polygon_set); + ps.clean(); + return ps.empty(); + } + + //extents + template + typename enable_if ::type, + typename is_mutable_rectangle_concept::type>::type>::type, + bool>::type + extents(rectangle_type& extents_rectangle, + const polygon_set_type& polygon_set) { + typedef typename polygon_90_set_traits::coordinate_type Unit; + polygon_90_set_data ps; + assign(ps, polygon_set); + return ps.extents(extents_rectangle); + } + + //area + template + typename enable_if< typename is_mutable_polygon_90_set_type::type, + typename coordinate_traits::coordinate_type>::manhattan_area_type>::type + area(const polygon_set_type& polygon_set) { + typedef rectangle_data::coordinate_type> rectangle_type; + typedef typename coordinate_traits::coordinate_type>::manhattan_area_type area_type; + std::vector rects; + assign(rects, polygon_set); + area_type retval = (area_type)0; + for(std::size_t i = 0; i < rects.size(); ++i) { + retval += (area_type)area(rects[i]); + } + return retval; + } + + //interact + template + typename enable_if ::type, + typename is_mutable_polygon_90_set_type::type>::type, + polygon_set_type_1>::type& + interact(polygon_set_type_1& polygon_set_1, const polygon_set_type_2& polygon_set_2) { + typedef typename polygon_90_set_traits::coordinate_type Unit; + polygon_90_set_data ps(scanline_orientation(polygon_set_2)); + polygon_90_set_data ps2(ps); + ps.insert(polygon_set_1); + ps2.insert(polygon_set_2); + ps.interact(ps2); + assign(polygon_set_1, ps); + return polygon_set_1; + } + + //self_intersect + template + typename enable_if< typename is_mutable_polygon_90_set_type::type, + polygon_set_type>::type & + self_intersect(polygon_set_type& polygon_set) { + typedef typename polygon_90_set_traits::coordinate_type Unit; + polygon_90_set_data ps; + assign(ps, polygon_set); + ps.self_intersect(); + assign(polygon_set, ps); + return polygon_set; + } + + //self_xor + template + typename enable_if< typename is_mutable_polygon_90_set_type::type, + polygon_set_type>::type & + self_xor(polygon_set_type& polygon_set) { + typedef typename polygon_90_set_traits::coordinate_type Unit; + polygon_90_set_data ps; + assign(ps, polygon_set); + ps.self_xor(); + assign(polygon_set, ps); + return polygon_set; + } + + template + typename enable_if< typename is_mutable_polygon_90_set_type::type, + polygon_set_type>::type & + bloat(polygon_set_type& polygon_set, + typename coordinate_traits::coordinate_type>::unsigned_area_type bloating) { + return bloat(polygon_set, bloating, bloating, bloating, bloating); + } + + template + typename enable_if< typename is_mutable_polygon_90_set_type::type, + polygon_set_type>::type & + bloat(polygon_set_type& polygon_set, orientation_2d orient, + typename coordinate_traits::coordinate_type>::unsigned_area_type bloating) { + if(orient == orientation_2d(HORIZONTAL)) + return bloat(polygon_set, bloating, bloating, 0, 0); + return bloat(polygon_set, 0, 0, bloating, bloating); + } + + template + typename enable_if< typename is_mutable_polygon_90_set_type::type, + polygon_set_type>::type & + bloat(polygon_set_type& polygon_set, orientation_2d orient, + typename coordinate_traits::coordinate_type>::unsigned_area_type low_bloating, + typename coordinate_traits::coordinate_type>::unsigned_area_type high_bloating) { + if(orient == orientation_2d(HORIZONTAL)) + return bloat(polygon_set, low_bloating, high_bloating, 0, 0); + return bloat(polygon_set, 0, 0, low_bloating, high_bloating); + } + + template + typename enable_if< typename is_mutable_polygon_90_set_type::type, + polygon_set_type>::type & + bloat(polygon_set_type& polygon_set, direction_2d dir, + typename coordinate_traits::coordinate_type>::unsigned_area_type bloating) { + if(dir == direction_2d(EAST)) + return bloat(polygon_set, 0, bloating, 0, 0); + if(dir == direction_2d(WEST)) + return bloat(polygon_set, bloating, 0, 0, 0); + if(dir == direction_2d(SOUTH)) + return bloat(polygon_set, 0, 0, bloating, 0); + return bloat(polygon_set, 0, 0, 0, bloating); + } + + template + typename enable_if< typename is_mutable_polygon_90_set_type::type, + polygon_set_type>::type & + bloat(polygon_set_type& polygon_set, + typename coordinate_traits::coordinate_type>::unsigned_area_type west_bloating, + typename coordinate_traits::coordinate_type>::unsigned_area_type east_bloating, + typename coordinate_traits::coordinate_type>::unsigned_area_type south_bloating, + typename coordinate_traits::coordinate_type>::unsigned_area_type north_bloating) { + typedef typename polygon_90_set_traits::coordinate_type Unit; + polygon_90_set_data ps; + assign(ps, polygon_set); + ps.bloat(west_bloating, east_bloating, south_bloating, north_bloating); + ps.clean(); + assign(polygon_set, ps); + return polygon_set; + } + + template + typename enable_if< typename is_mutable_polygon_90_set_type::type, + polygon_set_type>::type & + shrink(polygon_set_type& polygon_set, + typename coordinate_traits::coordinate_type>::unsigned_area_type shrinking) { + return shrink(polygon_set, shrinking, shrinking, shrinking, shrinking); + } + + template + typename enable_if< typename is_mutable_polygon_90_set_type::type, + polygon_set_type>::type & + shrink(polygon_set_type& polygon_set, orientation_2d orient, + typename coordinate_traits::coordinate_type>::unsigned_area_type shrinking) { + if(orient == orientation_2d(HORIZONTAL)) + return shrink(polygon_set, shrinking, shrinking, 0, 0); + return shrink(polygon_set, 0, 0, shrinking, shrinking); + } + + template + typename enable_if< typename is_mutable_polygon_90_set_type::type, + polygon_set_type>::type & + shrink(polygon_set_type& polygon_set, orientation_2d orient, + typename coordinate_traits::coordinate_type>::unsigned_area_type low_shrinking, + typename coordinate_traits::coordinate_type>::unsigned_area_type high_shrinking) { + if(orient == orientation_2d(HORIZONTAL)) + return shrink(polygon_set, low_shrinking, high_shrinking, 0, 0); + return shrink(polygon_set, 0, 0, low_shrinking, high_shrinking); + } + + template + typename enable_if< typename is_mutable_polygon_90_set_type::type, + polygon_set_type>::type & + shrink(polygon_set_type& polygon_set, direction_2d dir, + typename coordinate_traits::coordinate_type>::unsigned_area_type shrinking) { + if(dir == direction_2d(EAST)) + return shrink(polygon_set, 0, shrinking, 0, 0); + if(dir == direction_2d(WEST)) + return shrink(polygon_set, shrinking, 0, 0, 0); + if(dir == direction_2d(SOUTH)) + return shrink(polygon_set, 0, 0, shrinking, 0); + return shrink(polygon_set, 0, 0, 0, shrinking); + } + + template + typename enable_if< typename is_mutable_polygon_90_set_type::type, + polygon_set_type>::type & + shrink(polygon_set_type& polygon_set, + typename coordinate_traits::coordinate_type>::unsigned_area_type west_shrinking, + typename coordinate_traits::coordinate_type>::unsigned_area_type east_shrinking, + typename coordinate_traits::coordinate_type>::unsigned_area_type south_shrinking, + typename coordinate_traits::coordinate_type>::unsigned_area_type north_shrinking) { + typedef typename polygon_90_set_traits::coordinate_type Unit; + polygon_90_set_data ps; + assign(ps, polygon_set); + ps.shrink(west_shrinking, east_shrinking, south_shrinking, north_shrinking); + ps.clean(); + assign(polygon_set, ps); + return polygon_set; + } + + template + typename enable_if< typename is_mutable_polygon_90_set_type::type, + polygon_set_type>::type & + resize(polygon_set_type& polygon_set, coord_type resizing) { + if(resizing > 0) { + return bloat(polygon_set, resizing); + } + if(resizing < 0) { + return shrink(polygon_set, -resizing); + } + return polygon_set; + } + + //positive or negative values allow for any and all directions of sizing + template + typename enable_if< typename is_mutable_polygon_90_set_type::type, + polygon_set_type>::type & + resize(polygon_set_type& polygon_set, coord_type west, coord_type east, coord_type south, coord_type north) { + typedef typename polygon_90_set_traits::coordinate_type Unit; + polygon_90_set_data ps; + assign(ps, polygon_set); + ps.resize(west, east, south, north); + assign(polygon_set, ps); + return polygon_set; + } + + template + typename enable_if< typename is_mutable_polygon_90_set_type::type, + polygon_set_type>::type & + grow_and(polygon_set_type& polygon_set, + typename coordinate_traits::coordinate_type>::unsigned_area_type bloating) { + return grow_and(polygon_set, bloating, bloating, bloating, bloating); + } + + template + typename enable_if< typename is_mutable_polygon_90_set_type::type, + polygon_set_type>::type & + grow_and(polygon_set_type& polygon_set, orientation_2d orient, + typename coordinate_traits::coordinate_type>::unsigned_area_type bloating) { + if(orient == orientation_2d(HORIZONTAL)) + return grow_and(polygon_set, bloating, bloating, 0, 0); + return grow_and(polygon_set, 0, 0, bloating, bloating); + } + + template + typename enable_if< typename is_mutable_polygon_90_set_type::type, + polygon_set_type>::type & + grow_and(polygon_set_type& polygon_set, orientation_2d orient, + typename coordinate_traits::coordinate_type>::unsigned_area_type low_bloating, + typename coordinate_traits::coordinate_type>::unsigned_area_type high_bloating) { + if(orient == orientation_2d(HORIZONTAL)) + return grow_and(polygon_set, low_bloating, high_bloating, 0, 0); + return grow_and(polygon_set, 0, 0, low_bloating, high_bloating); + } + + template + typename enable_if< typename is_mutable_polygon_90_set_type::type, + polygon_set_type>::type & + grow_and(polygon_set_type& polygon_set, direction_2d dir, + typename coordinate_traits::coordinate_type>::unsigned_area_type bloating) { + if(dir == direction_2d(EAST)) + return grow_and(polygon_set, 0, bloating, 0, 0); + if(dir == direction_2d(WEST)) + return grow_and(polygon_set, bloating, 0, 0, 0); + if(dir == direction_2d(SOUTH)) + return grow_and(polygon_set, 0, 0, bloating, 0); + return grow_and(polygon_set, 0, 0, 0, bloating); + } + + template + typename enable_if< typename gtl_if::type>::type, + polygon_set_type>::type & + grow_and(polygon_set_type& polygon_set, + typename coordinate_traits::coordinate_type>::unsigned_area_type west_bloating, + typename coordinate_traits::coordinate_type>::unsigned_area_type east_bloating, + typename coordinate_traits::coordinate_type>::unsigned_area_type south_bloating, + typename coordinate_traits::coordinate_type>::unsigned_area_type north_bloating) { + typedef typename polygon_90_set_traits::coordinate_type Unit; + std::vector > polys; + assign(polys, polygon_set); + clear(polygon_set); + polygon_90_set_data ps(scanline_orientation(polygon_set)); + for(std::size_t i = 0; i < polys.size(); ++i) { + polygon_90_set_data tmpPs(scanline_orientation(polygon_set)); + tmpPs.insert(polys[i]); + bloat(tmpPs, west_bloating, east_bloating, south_bloating, north_bloating); + tmpPs.clean(); //apply implicit OR on tmp polygon set + ps.insert(tmpPs); + } + self_intersect(ps); + assign(polygon_set, ps); + return polygon_set; + } + + template + typename enable_if< typename is_mutable_polygon_90_set_type::type, + polygon_set_type>::type & + scale_up(polygon_set_type& polygon_set, + typename coordinate_traits::coordinate_type> + ::unsigned_area_type factor) { + typedef typename polygon_90_set_traits::coordinate_type Unit; + polygon_90_set_data ps; + assign(ps, polygon_set); + ps.scale_up(factor); + assign(polygon_set, ps); + return polygon_set; + } + + template + typename enable_if< typename is_mutable_polygon_90_set_type::type, + polygon_set_type>::type & + scale_down(polygon_set_type& polygon_set, + typename coordinate_traits::coordinate_type> + ::unsigned_area_type factor) { + typedef typename polygon_90_set_traits::coordinate_type Unit; + polygon_90_set_data ps; + assign(ps, polygon_set); + ps.scale_down(factor); + assign(polygon_set, ps); + return polygon_set; + } + + template + typename enable_if< typename is_mutable_polygon_90_set_type::type, + polygon_set_type>::type & + scale(polygon_set_type& polygon_set, + const scaling_type& scaling) { + typedef typename polygon_90_set_traits::coordinate_type Unit; + polygon_90_set_data ps; + assign(ps, polygon_set); + ps.scale(scaling); + assign(polygon_set, ps); + return polygon_set; + } + + struct y_p_s_move : gtl_yes {}; + + //move + template + typename enable_if< typename gtl_and::type>::type>::type, + polygon_set_type>::type & + move(polygon_set_type& polygon_set, + orientation_2d orient, typename polygon_90_set_traits::coordinate_type displacement) { + if(orient == HORIZONTAL) + return move(polygon_set, displacement, 0); + else + return move(polygon_set, 0, displacement); + } + + struct y_p_s_move2 : gtl_yes {}; + + template + typename enable_if< typename gtl_and::type>::type>::type, + polygon_set_type>::type & + move(polygon_set_type& polygon_set, typename polygon_90_set_traits::coordinate_type x_displacement, + typename polygon_90_set_traits::coordinate_type y_displacement) { + typedef typename polygon_90_set_traits::coordinate_type Unit; + polygon_90_set_data ps; + assign(ps, polygon_set); + ps.move(x_displacement, y_displacement); + ps.clean(); + assign(polygon_set, ps); + return polygon_set; + } + + //transform + template + typename enable_if< typename is_mutable_polygon_90_set_type::type, + polygon_set_type>::type & + transform(polygon_set_type& polygon_set, + const transformation_type& transformation) { + typedef typename polygon_90_set_traits::coordinate_type Unit; + polygon_90_set_data ps; + assign(ps, polygon_set); + ps.transform(transformation); + ps.clean(); + assign(polygon_set, ps); + return polygon_set; + typedef typename polygon_90_set_traits::coordinate_type Unit; + } + + //keep + template + typename enable_if< typename is_mutable_polygon_90_set_type::type, + polygon_set_type>::type & + keep(polygon_set_type& polygon_set, + typename coordinate_traits::coordinate_type>::unsigned_area_type min_area, + typename coordinate_traits::coordinate_type>::unsigned_area_type max_area, + typename coordinate_traits::coordinate_type>::unsigned_area_type min_width, + typename coordinate_traits::coordinate_type>::unsigned_area_type max_width, + typename coordinate_traits::coordinate_type>::unsigned_area_type min_height, + typename coordinate_traits::coordinate_type>::unsigned_area_type max_height) { + typedef typename polygon_90_set_traits::coordinate_type Unit; + typedef typename coordinate_traits::unsigned_area_type uat; + std::list > polys; + assign(polys, polygon_set); + clear(polygon_set); + typename std::list >::iterator itr_nxt; + for(typename std::list >::iterator itr = polys.begin(); itr != polys.end(); itr = itr_nxt){ + itr_nxt = itr; + ++itr_nxt; + rectangle_data bbox; + extents(bbox, *itr); + uat pwidth = delta(bbox, HORIZONTAL); + if(pwidth > min_width && pwidth <= max_width){ + uat pheight = delta(bbox, VERTICAL); + if(pheight > min_height && pheight <= max_height){ + uat parea = area(*itr); + if(parea <= max_area && parea >= min_area) { + continue; + } + } + } + polys.erase(itr); + } + assign(polygon_set, polys); + return polygon_set; + } + + +} +} +#include "detail/polygon_90_set_view.hpp" +#endif diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/polygon_90_set_data.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/polygon_90_set_data.hpp new file mode 100644 index 0000000..2c640bf --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/polygon_90_set_data.hpp @@ -0,0 +1,989 @@ +/* + Copyright 2008 Intel Corporation + + Use, modification and distribution are subject to the Boost Software License, + Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at + http://www.boost.org/LICENSE_1_0.txt). +*/ +#ifndef BOOST_POLYGON_POLYGON_90_SET_DATA_HPP +#define BOOST_POLYGON_POLYGON_90_SET_DATA_HPP +#include "isotropy.hpp" +#include "point_concept.hpp" +#include "transform.hpp" +#include "interval_concept.hpp" +#include "rectangle_concept.hpp" +#include "segment_concept.hpp" +#include "detail/iterator_points_to_compact.hpp" +#include "detail/iterator_compact_to_points.hpp" +#include "polygon_traits.hpp" + +//manhattan boolean algorithms +#include "detail/boolean_op.hpp" +#include "detail/polygon_formation.hpp" +#include "detail/rectangle_formation.hpp" +#include "detail/max_cover.hpp" +#include "detail/property_merge.hpp" +#include "detail/polygon_90_touch.hpp" +#include "detail/iterator_geometry_to_set.hpp" + +namespace boost { namespace polygon{ + template + class polygon_90_set_view; + + template + class polygon_90_set_data { + public: + typedef T coordinate_type; + typedef std::vector > > value_type; + typedef typename std::vector > >::const_iterator iterator_type; + typedef polygon_90_set_data operator_arg_type; + + // default constructor + inline polygon_90_set_data() : orient_(HORIZONTAL), data_(), dirty_(false), unsorted_(false) {} + + // constructor + inline polygon_90_set_data(orientation_2d orient) : orient_(orient), data_(), dirty_(false), unsorted_(false) {} + + // constructor from an iterator pair over vertex data + template + inline polygon_90_set_data(orientation_2d, iT input_begin, iT input_end) : + orient_(HORIZONTAL), data_(), dirty_(false), unsorted_(false) { + dirty_ = true; + unsorted_ = true; + for( ; input_begin != input_end; ++input_begin) { insert(*input_begin); } + } + + // copy constructor + inline polygon_90_set_data(const polygon_90_set_data& that) : + orient_(that.orient_), data_(that.data_), dirty_(that.dirty_), unsorted_(that.unsorted_) {} + + template + inline polygon_90_set_data(const polygon_90_set_view& that); + + // copy with orientation change constructor + inline polygon_90_set_data(orientation_2d orient, const polygon_90_set_data& that) : + orient_(orient), data_(), dirty_(false), unsorted_(false) { + insert(that, false, that.orient_); + } + + // destructor + inline ~polygon_90_set_data() {} + + // assignement operator + inline polygon_90_set_data& operator=(const polygon_90_set_data& that) { + if(this == &that) return *this; + orient_ = that.orient_; + data_ = that.data_; + dirty_ = that.dirty_; + unsorted_ = that.unsorted_; + return *this; + } + + template + inline polygon_90_set_data& operator=(const polygon_90_set_view& that); + + template + inline polygon_90_set_data& operator=(const geometry_object& geometry) { + data_.clear(); + insert(geometry); + return *this; + } + + // insert iterator range + inline void insert(iterator_type input_begin, iterator_type input_end, orientation_2d orient = HORIZONTAL) { + if(input_begin == input_end || (!data_.empty() && &(*input_begin) == &(*(data_.begin())))) return; + dirty_ = true; + unsorted_ = true; + if(orient == orient_) + data_.insert(data_.end(), input_begin, input_end); + else { + for( ; input_begin != input_end; ++input_begin) { + insert(*input_begin, false, orient); + } + } + } + + // insert iterator range + template + inline void insert(iT input_begin, iT input_end, orientation_2d orient = HORIZONTAL) { + if(input_begin == input_end) return; + dirty_ = true; + unsorted_ = true; + for( ; input_begin != input_end; ++input_begin) { + insert(*input_begin, false, orient); + } + } + + inline void insert(const polygon_90_set_data& polygon_set) { + insert(polygon_set.begin(), polygon_set.end(), polygon_set.orient()); + } + + inline void insert(const std::pair, point_data >, int>& edge, bool is_hole = false, + orientation_2d = HORIZONTAL) { + std::pair > vertex; + vertex.first = edge.first.first.x(); + vertex.second.first = edge.first.first.y(); + vertex.second.second = edge.second * (is_hole ? -1 : 1); + insert(vertex, false, VERTICAL); + vertex.first = edge.first.second.x(); + vertex.second.first = edge.first.second.y(); + vertex.second.second *= -1; + insert(vertex, false, VERTICAL); + } + + template + inline void insert(const geometry_type& geometry_object, bool is_hole = false, orientation_2d = HORIZONTAL) { + iterator_geometry_to_set::type, geometry_type> + begin_input(geometry_object, LOW, orient_, is_hole), end_input(geometry_object, HIGH, orient_, is_hole); + insert(begin_input, end_input, orient_); + } + + inline void insert(const std::pair >& vertex, bool is_hole = false, + orientation_2d orient = HORIZONTAL) { + data_.push_back(vertex); + if(orient != orient_) std::swap(data_.back().first, data_.back().second.first); + if(is_hole) data_.back().second.second *= -1; + dirty_ = true; + unsorted_ = true; + } + + inline void insert(coordinate_type major_coordinate, const std::pair, int>& edge) { + std::pair > vertex; + vertex.first = major_coordinate; + vertex.second.first = edge.first.get(LOW); + vertex.second.second = edge.second; + insert(vertex, false, orient_); + vertex.second.first = edge.first.get(HIGH); + vertex.second.second *= -1; + insert(vertex, false, orient_); + } + + template + inline void get(output_container& output) const { + get_dispatch(output, typename geometry_concept::type()); + } + + template + inline void get(output_container& output, size_t vthreshold) const { + get_dispatch(output, typename geometry_concept::type(), vthreshold); + } + + + template + inline void get_polygons(output_container& output) const { + get_dispatch(output, polygon_90_concept()); + } + + template + inline void get_rectangles(output_container& output) const { + clean(); + form_rectangles(output, data_.begin(), data_.end(), orient_, rectangle_concept()); + } + + template + inline void get_rectangles(output_container& output, orientation_2d slicing_orientation) const { + if(slicing_orientation == orient_) { + get_rectangles(output); + } else { + polygon_90_set_data ps(*this); + ps.transform(axis_transformation(axis_transformation::SWAP_XY)); + output_container result; + ps.get_rectangles(result); + for(typename output_container::iterator itr = result.begin(); itr != result.end(); ++itr) { + ::boost::polygon::transform(*itr, axis_transformation(axis_transformation::SWAP_XY)); + } + output.insert(output.end(), result.begin(), result.end()); + } + } + + // equivalence operator + inline bool operator==(const polygon_90_set_data& p) const { + if(orient_ == p.orient()) { + clean(); + p.clean(); + return data_ == p.data_; + } else { + return false; + } + } + + // inequivalence operator + inline bool operator!=(const polygon_90_set_data& p) const { + return !((*this) == p); + } + + // get iterator to begin vertex data + inline iterator_type begin() const { + return data_.begin(); + } + + // get iterator to end vertex data + inline iterator_type end() const { + return data_.end(); + } + + const value_type& value() const { + return data_; + } + + // clear the contents of the polygon_90_set_data + inline void clear() { data_.clear(); dirty_ = unsorted_ = false; } + + // find out if Polygon set is empty + inline bool empty() const { clean(); return data_.empty(); } + + // get the Polygon set size in vertices + inline std::size_t size() const { clean(); return data_.size(); } + + // get the current Polygon set capacity in vertices + inline std::size_t capacity() const { return data_.capacity(); } + + // reserve size of polygon set in vertices + inline void reserve(std::size_t size) { return data_.reserve(size); } + + // find out if Polygon set is sorted + inline bool sorted() const { return !unsorted_; } + + // find out if Polygon set is clean + inline bool dirty() const { return dirty_; } + + // get the scanline orientation of the polygon set + inline orientation_2d orient() const { return orient_; } + + // Start BM + // The problem: If we have two polygon sets with two different scanline orientations: + // I tried changing the orientation of one to coincide with other (If not, resulting boolean operation + // produces spurious results). + // First I tried copying polygon data from one of the sets into another set with corrected orientation + // using one of the copy constructor that takes in orientation (see somewhere above in this file) --> copy constructor throws error + // Then I tried another approach:(see below). This approach also fails to produce the desired results when test case is run. + // Here is the part that beats me: If I comment out the whole section, I can do all the operations (^=, -=, &= )these commented out + // operations perform. So then why do we need them?. Hence, I commented out this whole section. + // End BM + // polygon_90_set_data& operator-=(const polygon_90_set_data& that) { + // sort(); + // that.sort(); + // value_type data; + // std::swap(data, data_); + // applyBooleanBinaryOp(data.begin(), data.end(), + // that.begin(), that.end(), boolean_op::BinaryCount()); + // return *this; + // } + // polygon_90_set_data& operator^=(const polygon_90_set_data& that) { + // sort(); + // that.sort(); + // value_type data; + // std::swap(data, data_); + // applyBooleanBinaryOp(data.begin(), data.end(), + // that.begin(), that.end(), boolean_op::BinaryCount()); + // return *this; + // } + // polygon_90_set_data& operator&=(const polygon_90_set_data& that) { + // sort(); + // that.sort(); + // value_type data; + // std::swap(data, data_); + // applyBooleanBinaryOp(data.begin(), data.end(), + // that.begin(), that.end(), boolean_op::BinaryCount()); + // return *this; + // } + // polygon_90_set_data& operator|=(const polygon_90_set_data& that) { + // insert(that); + // return *this; + // } + + void clean() const { + sort(); + if(dirty_) { + boolean_op::default_arg_workaround::applyBooleanOr(data_); + dirty_ = false; + } + } + + void sort() const{ + if(unsorted_) { + polygon_sort(data_.begin(), data_.end()); + unsorted_ = false; + } + } + + template + void set(input_iterator_type input_begin, input_iterator_type input_end, orientation_2d orient) { + data_.clear(); + reserve(std::distance(input_begin, input_end)); + data_.insert(data_.end(), input_begin, input_end); + orient_ = orient; + dirty_ = true; + unsorted_ = true; + } + + void set(const value_type& value, orientation_2d orient) { + data_ = value; + orient_ = orient; + dirty_ = true; + unsorted_ = true; + } + + //extents + template + bool + extents(rectangle_type& extents_rectangle) const { + clean(); + if(data_.empty()) return false; + if(orient_ == HORIZONTAL) + set_points(extents_rectangle, point_data(data_[0].second.first, data_[0].first), + point_data(data_[data_.size() - 1].second.first, data_[data_.size() - 1].first)); + else + set_points(extents_rectangle, point_data(data_[0].first, data_[0].second.first), + point_data(data_[data_.size() - 1].first, data_[data_.size() - 1].second.first)); + for(std::size_t i = 1; i < data_.size() - 1; ++i) { + if(orient_ == HORIZONTAL) + encompass(extents_rectangle, point_data(data_[i].second.first, data_[i].first)); + else + encompass(extents_rectangle, point_data(data_[i].first, data_[i].second.first)); + } + return true; + } + + polygon_90_set_data& + bloat2(typename coordinate_traits::unsigned_area_type west_bloating, + typename coordinate_traits::unsigned_area_type east_bloating, + typename coordinate_traits::unsigned_area_type south_bloating, + typename coordinate_traits::unsigned_area_type north_bloating) { + std::vector > rects; + clean(); + rects.reserve(data_.size() / 2); + get(rects); + rectangle_data convolutionRectangle(interval_data(-((coordinate_type)west_bloating), + (coordinate_type)east_bloating), + interval_data(-((coordinate_type)south_bloating), + (coordinate_type)north_bloating)); + for(typename std::vector >::iterator itr = rects.begin(); + itr != rects.end(); ++itr) { + convolve(*itr, convolutionRectangle); + } + clear(); + insert(rects.begin(), rects.end()); + return *this; + } + + static void modify_pt(point_data& pt, const point_data& prev_pt, + const point_data& current_pt, const point_data& next_pt, + coordinate_type west_bloating, + coordinate_type east_bloating, + coordinate_type south_bloating, + coordinate_type north_bloating) { + bool pxl = prev_pt.x() < current_pt.x(); + bool pyl = prev_pt.y() < current_pt.y(); + bool nxl = next_pt.x() < current_pt.x(); + bool nyl = next_pt.y() < current_pt.y(); + bool pxg = prev_pt.x() > current_pt.x(); + bool pyg = prev_pt.y() > current_pt.y(); + bool nxg = next_pt.x() > current_pt.x(); + bool nyg = next_pt.y() > current_pt.y(); + //two of the four if statements will execute + if(pxl) + pt.y(current_pt.y() - south_bloating); + if(pxg) + pt.y(current_pt.y() + north_bloating); + if(nxl) + pt.y(current_pt.y() + north_bloating); + if(nxg) + pt.y(current_pt.y() - south_bloating); + if(pyl) + pt.x(current_pt.x() + east_bloating); + if(pyg) + pt.x(current_pt.x() - west_bloating); + if(nyl) + pt.x(current_pt.x() - west_bloating); + if(nyg) + pt.x(current_pt.x() + east_bloating); + } + static void resize_poly_up(std::vector >& poly, + coordinate_type west_bloating, + coordinate_type east_bloating, + coordinate_type south_bloating, + coordinate_type north_bloating) { + point_data first_pt = poly[0]; + point_data second_pt = poly[1]; + point_data prev_pt = poly[0]; + point_data current_pt = poly[1]; + for(std::size_t i = 2; i < poly.size(); ++i) { + point_data next_pt = poly[i]; + modify_pt(poly[i-1], prev_pt, current_pt, next_pt, west_bloating, east_bloating, south_bloating, north_bloating); + prev_pt = current_pt; + current_pt = next_pt; + } + point_data next_pt = first_pt; + modify_pt(poly.back(), prev_pt, current_pt, next_pt, west_bloating, east_bloating, south_bloating, north_bloating); + prev_pt = current_pt; + current_pt = next_pt; + next_pt = second_pt; + modify_pt(poly[0], prev_pt, current_pt, next_pt, west_bloating, east_bloating, south_bloating, north_bloating); + remove_colinear_pts(poly); + } + static bool resize_poly_down(std::vector >& poly, + coordinate_type west_shrinking, + coordinate_type east_shrinking, + coordinate_type south_shrinking, + coordinate_type north_shrinking) { + rectangle_data extents_rectangle; + set_points(extents_rectangle, poly[0], poly[0]); + point_data first_pt = poly[0]; + point_data second_pt = poly[1]; + point_data prev_pt = poly[0]; + point_data current_pt = poly[1]; + encompass(extents_rectangle, current_pt); + for(std::size_t i = 2; i < poly.size(); ++i) { + point_data next_pt = poly[i]; + encompass(extents_rectangle, next_pt); + modify_pt(poly[i-1], prev_pt, current_pt, next_pt, west_shrinking, east_shrinking, south_shrinking, north_shrinking); + prev_pt = current_pt; + current_pt = next_pt; + } + if(delta(extents_rectangle, HORIZONTAL) < std::abs(west_shrinking + east_shrinking)) + return false; + if(delta(extents_rectangle, VERTICAL) < std::abs(north_shrinking + south_shrinking)) + return false; + point_data next_pt = first_pt; + modify_pt(poly.back(), prev_pt, current_pt, next_pt, west_shrinking, east_shrinking, south_shrinking, north_shrinking); + prev_pt = current_pt; + current_pt = next_pt; + next_pt = second_pt; + modify_pt(poly[0], prev_pt, current_pt, next_pt, west_shrinking, east_shrinking, south_shrinking, north_shrinking); + return remove_colinear_pts(poly); + } + + static bool remove_colinear_pts(std::vector >& poly) { + bool found_colinear = true; + while(found_colinear && poly.size() >= 4) { + found_colinear = false; + typename std::vector >::iterator itr = poly.begin(); + itr += poly.size() - 1; //get last element position + typename std::vector >::iterator itr2 = poly.begin(); + typename std::vector >::iterator itr3 = itr2; + ++itr3; + std::size_t count = 0; + for( ; itr3 < poly.end(); ++itr3) { + if(((*itr).x() == (*itr2).x() && (*itr).x() == (*itr3).x()) || + ((*itr).y() == (*itr2).y() && (*itr).y() == (*itr3).y()) ) { + ++count; + found_colinear = true; + } else { + itr = itr2; + ++itr2; + } + *itr2 = *itr3; + } + itr3 = poly.begin(); + if(((*itr).x() == (*itr2).x() && (*itr).x() == (*itr3).x()) || + ((*itr).y() == (*itr2).y() && (*itr).y() == (*itr3).y()) ) { + ++count; + found_colinear = true; + } + poly.erase(poly.end() - count, poly.end()); + } + return poly.size() >= 4; + } + + polygon_90_set_data& + bloat(typename coordinate_traits::unsigned_area_type west_bloating, + typename coordinate_traits::unsigned_area_type east_bloating, + typename coordinate_traits::unsigned_area_type south_bloating, + typename coordinate_traits::unsigned_area_type north_bloating) { + std::list > polys; + get(polys); + clear(); + for(typename std::list >::iterator itr = polys.begin(); + itr != polys.end(); ++itr) { + //polygon_90_set_data psref; + //psref.insert(view_as((*itr).self_)); + //rectangle_data prerect; + //psref.extents(prerect); + resize_poly_up((*itr).self_.coords_, (coordinate_type)west_bloating, (coordinate_type)east_bloating, + (coordinate_type)south_bloating, (coordinate_type)north_bloating); + iterator_geometry_to_set > > + begin_input(view_as((*itr).self_), LOW, orient_, false, true, COUNTERCLOCKWISE), + end_input(view_as((*itr).self_), HIGH, orient_, false, true, COUNTERCLOCKWISE); + insert(begin_input, end_input, orient_); + //polygon_90_set_data pstest; + //pstest.insert(view_as((*itr).self_)); + //psref.bloat2(west_bloating, east_bloating, south_bloating, north_bloating); + //if(!equivalence(psref, pstest)) { + // std::cout << "test failed\n"; + //} + for(typename std::list >::iterator itrh = (*itr).holes_.begin(); + itrh != (*itr).holes_.end(); ++itrh) { + //rectangle_data rect; + //psref.extents(rect); + //polygon_90_set_data psrefhole; + //psrefhole.insert(prerect); + //psrefhole.insert(view_as(*itrh), true); + //polygon_45_data testpoly(*itrh); + if(resize_poly_down((*itrh).coords_,(coordinate_type)west_bloating, (coordinate_type)east_bloating, + (coordinate_type)south_bloating, (coordinate_type)north_bloating)) { + iterator_geometry_to_set > > + begin_input2(view_as(*itrh), LOW, orient_, true, true), + end_input2(view_as(*itrh), HIGH, orient_, true, true); + insert(begin_input2, end_input2, orient_); + //polygon_90_set_data pstesthole; + //pstesthole.insert(rect); + //iterator_geometry_to_set > > + // begin_input2(view_as(*itrh), LOW, orient_, true, true); + //pstesthole.insert(begin_input2, end_input, orient_); + //psrefhole.bloat2(west_bloating, east_bloating, south_bloating, north_bloating); + //if(!equivalence(psrefhole, pstesthole)) { + // std::cout << (winding(testpoly) == CLOCKWISE) << std::endl; + // std::cout << (winding(*itrh) == CLOCKWISE) << std::endl; + // polygon_90_set_data c(psrefhole); + // c.clean(); + // polygon_90_set_data a(pstesthole); + // polygon_90_set_data b(pstesthole); + // a.sort(); + // b.clean(); + // std::cout << "test hole failed\n"; + // //std::cout << testpoly << std::endl; + //} + } + } + } + return *this; + } + + polygon_90_set_data& + shrink(typename coordinate_traits::unsigned_area_type west_shrinking, + typename coordinate_traits::unsigned_area_type east_shrinking, + typename coordinate_traits::unsigned_area_type south_shrinking, + typename coordinate_traits::unsigned_area_type north_shrinking) { + std::list > polys; + get(polys); + clear(); + for(typename std::list >::iterator itr = polys.begin(); + itr != polys.end(); ++itr) { + //polygon_90_set_data psref; + //psref.insert(view_as((*itr).self_)); + //rectangle_data prerect; + //psref.extents(prerect); + //polygon_45_data testpoly((*itr).self_); + if(resize_poly_down((*itr).self_.coords_, -(coordinate_type)west_shrinking, -(coordinate_type)east_shrinking, + -(coordinate_type)south_shrinking, -(coordinate_type)north_shrinking)) { + iterator_geometry_to_set > > + begin_input(view_as((*itr).self_), LOW, orient_, false, true, COUNTERCLOCKWISE), + end_input(view_as((*itr).self_), HIGH, orient_, false, true, COUNTERCLOCKWISE); + insert(begin_input, end_input, orient_); + //iterator_geometry_to_set > > + // begin_input2(view_as((*itr).self_), LOW, orient_, false, true, COUNTERCLOCKWISE); + //polygon_90_set_data pstest; + //pstest.insert(begin_input2, end_input, orient_); + //psref.shrink2(west_shrinking, east_shrinking, south_shrinking, north_shrinking); + //if(!equivalence(psref, pstest)) { + // std::cout << "test failed\n"; + //} + for(typename std::list >::iterator itrh = (*itr).holes_.begin(); + itrh != (*itr).holes_.end(); ++itrh) { + //rectangle_data rect; + //psref.extents(rect); + //polygon_90_set_data psrefhole; + //psrefhole.insert(prerect); + //psrefhole.insert(view_as(*itrh), true); + //polygon_45_data testpoly(*itrh); + resize_poly_up((*itrh).coords_, -(coordinate_type)west_shrinking, -(coordinate_type)east_shrinking, + -(coordinate_type)south_shrinking, -(coordinate_type)north_shrinking); + iterator_geometry_to_set > > + begin_input2(view_as(*itrh), LOW, orient_, true, true), + end_input2(view_as(*itrh), HIGH, orient_, true, true); + insert(begin_input2, end_input2, orient_); + //polygon_90_set_data pstesthole; + //pstesthole.insert(rect); + //iterator_geometry_to_set > > + // begin_input2(view_as(*itrh), LOW, orient_, true, true); + //pstesthole.insert(begin_input2, end_input, orient_); + //psrefhole.shrink2(west_shrinking, east_shrinking, south_shrinking, north_shrinking); + //if(!equivalence(psrefhole, pstesthole)) { + // std::cout << (winding(testpoly) == CLOCKWISE) << std::endl; + // std::cout << (winding(*itrh) == CLOCKWISE) << std::endl; + // polygon_90_set_data c(psrefhole); + // c.clean(); + // polygon_90_set_data a(pstesthole); + // polygon_90_set_data b(pstesthole); + // a.sort(); + // b.clean(); + // std::cout << "test hole failed\n"; + // //std::cout << testpoly << std::endl; + //} + } + } + } + return *this; + } + + polygon_90_set_data& + shrink2(typename coordinate_traits::unsigned_area_type west_shrinking, + typename coordinate_traits::unsigned_area_type east_shrinking, + typename coordinate_traits::unsigned_area_type south_shrinking, + typename coordinate_traits::unsigned_area_type north_shrinking) { + rectangle_data externalBoundary; + if(!extents(externalBoundary)) return *this; + ::boost::polygon::bloat(externalBoundary, 10); //bloat by diferential ammount + //insert a hole that encompasses the data + insert(externalBoundary, true); //note that the set is in a dirty state now + sort(); //does not apply implicit OR operation + std::vector > rects; + rects.reserve(data_.size() / 2); + //begin does not apply implicit or operation, this is a dirty range + form_rectangles(rects, data_.begin(), data_.end(), orient_, rectangle_concept()); + clear(); + rectangle_data convolutionRectangle(interval_data(-((coordinate_type)east_shrinking), + (coordinate_type)west_shrinking), + interval_data(-((coordinate_type)north_shrinking), + (coordinate_type)south_shrinking)); + for(typename std::vector >::iterator itr = rects.begin(); + itr != rects.end(); ++itr) { + rectangle_data& rect = *itr; + convolve(rect, convolutionRectangle); + //insert rectangle as a hole + insert(rect, true); + } + convolve(externalBoundary, convolutionRectangle); + //insert duplicate of external boundary as solid to cancel out the external hole boundaries + insert(externalBoundary); + clean(); //we have negative values in the set, so we need to apply an OR operation to make it valid input to a boolean + return *this; + } + + polygon_90_set_data& + shrink(direction_2d dir, typename coordinate_traits::unsigned_area_type shrinking) { + if(dir == WEST) + return shrink(shrinking, 0, 0, 0); + if(dir == EAST) + return shrink(0, shrinking, 0, 0); + if(dir == SOUTH) + return shrink(0, 0, shrinking, 0); + return shrink(0, 0, 0, shrinking); + } + + polygon_90_set_data& + bloat(direction_2d dir, typename coordinate_traits::unsigned_area_type shrinking) { + if(dir == WEST) + return bloat(shrinking, 0, 0, 0); + if(dir == EAST) + return bloat(0, shrinking, 0, 0); + if(dir == SOUTH) + return bloat(0, 0, shrinking, 0); + return bloat(0, 0, 0, shrinking); + } + + polygon_90_set_data& + resize(coordinate_type west, coordinate_type east, coordinate_type south, coordinate_type north); + + polygon_90_set_data& move(coordinate_type x_delta, coordinate_type y_delta) { + for(typename std::vector > >::iterator + itr = data_.begin(); itr != data_.end(); ++itr) { + if(orient_ == orientation_2d(VERTICAL)) { + (*itr).first += x_delta; + (*itr).second.first += y_delta; + } else { + (*itr).second.first += x_delta; + (*itr).first += y_delta; + } + } + return *this; + } + + // transform set + template + polygon_90_set_data& transform(const transformation_type& transformation) { + direction_2d dir1, dir2; + transformation.get_directions(dir1, dir2); + int sign = dir1.get_sign() * dir2.get_sign(); + for(typename std::vector > >::iterator + itr = data_.begin(); itr != data_.end(); ++itr) { + if(orient_ == orientation_2d(VERTICAL)) { + transformation.transform((*itr).first, (*itr).second.first); + } else { + transformation.transform((*itr).second.first, (*itr).first); + } + (*itr).second.second *= sign; + } + if(dir1 != EAST || dir2 != NORTH) + unsorted_ = true; //some mirroring or rotation must have happened + return *this; + } + + // scale set + polygon_90_set_data& scale_up(typename coordinate_traits::unsigned_area_type factor) { + for(typename std::vector > >::iterator + itr = data_.begin(); itr != data_.end(); ++itr) { + (*itr).first *= (coordinate_type)factor; + (*itr).second.first *= (coordinate_type)factor; + } + return *this; + } + polygon_90_set_data& scale_down(typename coordinate_traits::unsigned_area_type factor) { + typedef typename coordinate_traits::coordinate_distance dt; + for(typename std::vector > >::iterator + itr = data_.begin(); itr != data_.end(); ++itr) { + (*itr).first = scaling_policy::round((dt)((*itr).first) / (dt)factor); + (*itr).second.first = scaling_policy::round((dt)((*itr).second.first) / (dt)factor); + } + unsorted_ = true; //scaling down can make coordinates equal that were not previously equal + return *this; + } + template + polygon_90_set_data& scale(const anisotropic_scale_factor& scaling) { + for(typename std::vector > >::iterator + itr = data_.begin(); itr != data_.end(); ++itr) { + if(orient_ == orientation_2d(VERTICAL)) { + scaling.scale((*itr).first, (*itr).second.first); + } else { + scaling.scale((*itr).second.first, (*itr).first); + } + } + unsorted_ = true; + return *this; + } + template + polygon_90_set_data& scale_with(const scaling_type& scaling) { + for(typename std::vector > >::iterator + itr = data_.begin(); itr != data_.end(); ++itr) { + if(orient_ == orientation_2d(VERTICAL)) { + scaling.scale((*itr).first, (*itr).second.first); + } else { + scaling.scale((*itr).second.first, (*itr).first); + } + } + unsorted_ = true; + return *this; + } + polygon_90_set_data& scale(double factor) { + typedef typename coordinate_traits::coordinate_distance dt; + for(typename std::vector > >::iterator + itr = data_.begin(); itr != data_.end(); ++itr) { + (*itr).first = scaling_policy::round((dt)((*itr).first) * (dt)factor); + (*itr).second.first = scaling_policy::round((dt)((*itr).second.first) * (dt)factor); + } + unsorted_ = true; //scaling make coordinates equal that were not previously equal + return *this; + } + + polygon_90_set_data& self_xor() { + sort(); + if(dirty_) { //if it is clean it is a no-op + boolean_op::default_arg_workaround::applyBooleanOr(data_); + dirty_ = false; + } + return *this; + } + + polygon_90_set_data& self_intersect() { + sort(); + if(dirty_) { //if it is clean it is a no-op + interval_data ivl((std::numeric_limits::min)(), (std::numeric_limits::max)()); + rectangle_data rect(ivl, ivl); + insert(rect, true); + clean(); + } + return *this; + } + + inline polygon_90_set_data& interact(const polygon_90_set_data& that) { + typedef coordinate_type Unit; + if(that.dirty_) that.clean(); + typename touch_90_operation::TouchSetData tsd; + touch_90_operation::populateTouchSetData(tsd, that.data_, 0); + std::vector > polys; + get(polys); + std::vector > graph(polys.size()+1, std::set()); + for(std::size_t i = 0; i < polys.size(); ++i){ + polygon_90_set_data psTmp(that.orient_); + psTmp.insert(polys[i]); + psTmp.clean(); + touch_90_operation::populateTouchSetData(tsd, psTmp.data_, i+1); + } + touch_90_operation::performTouch(graph, tsd); + clear(); + for(std::set::iterator itr = graph[0].begin(); itr != graph[0].end(); ++itr){ + insert(polys[(*itr)-1]); + } + dirty_ = false; + return *this; + } + + + template + void applyBooleanBinaryOp(iterator_type_1 itr1, iterator_type_1 itr1_end, + iterator_type_2 itr2, iterator_type_2 itr2_end, + T2 defaultCount) { + data_.clear(); + boolean_op::applyBooleanBinaryOp(data_, itr1, itr1_end, itr2, itr2_end, defaultCount); + } + + private: + orientation_2d orient_; + mutable value_type data_; + mutable bool dirty_; + mutable bool unsorted_; + + private: + //functions + template + void get_dispatch(output_container& output, rectangle_concept ) const { + clean(); + form_rectangles(output, data_.begin(), data_.end(), orient_, rectangle_concept()); + } + template + void get_dispatch(output_container& output, polygon_90_concept tag) const { + get_fracture(output, true, tag); + } + + template + void get_dispatch(output_container& output, polygon_90_concept tag, + size_t vthreshold) const { + get_fracture(output, true, tag, vthreshold); + } + + template + void get_dispatch(output_container& output, polygon_90_with_holes_concept tag) const { + get_fracture(output, false, tag); + } + + template + void get_dispatch(output_container& output, polygon_90_with_holes_concept tag, + size_t vthreshold) const { + get_fracture(output, false, tag, vthreshold); + } + + + template + void get_dispatch(output_container& output, polygon_45_concept tag) const { + get_fracture(output, true, tag); + } + template + void get_dispatch(output_container& output, polygon_45_with_holes_concept tag) const { + get_fracture(output, false, tag); + } + template + void get_dispatch(output_container& output, polygon_concept tag) const { + get_fracture(output, true, tag); + } + template + void get_dispatch(output_container& output, polygon_with_holes_concept tag) const { + get_fracture(output, false, tag); + } + template + void get_fracture(output_container& container, bool fracture_holes, concept_type tag) const { + clean(); + ::boost::polygon::get_polygons(container, data_.begin(), data_.end(), orient_, fracture_holes, tag); + } + + template + void get_fracture(output_container& container, bool fracture_holes, concept_type tag, + size_t vthreshold) const { + clean(); + ::boost::polygon::get_polygons(container, data_.begin(), data_.end(), orient_, fracture_holes, tag, vthreshold); + } + }; + + template + polygon_90_set_data& + polygon_90_set_data::resize(coordinate_type west, + coordinate_type east, + coordinate_type south, + coordinate_type north) { + move(-west, -south); + coordinate_type e_total = west + east; + coordinate_type n_total = south + north; + if((e_total < 0) ^ (n_total < 0)) { + //different signs + if(e_total < 0) { + shrink(0, -e_total, 0, 0); + if(n_total != 0) + return bloat(0, 0, 0, n_total); + else + return (*this); + } else { + shrink(0, 0, 0, -n_total); //shrink first + if(e_total != 0) + return bloat(0, e_total, 0, 0); + else + return (*this); + } + } else { + if(e_total < 0) { + return shrink(0, -e_total, 0, -n_total); + } + return bloat(0, e_total, 0, n_total); + } + } + + template + class property_merge_90 { + private: + std::vector, std::pair > > pmd_; + public: + inline property_merge_90() : pmd_() {} + inline property_merge_90(const property_merge_90& that) : pmd_(that.pmd_) {} + inline property_merge_90& operator=(const property_merge_90& that) { pmd_ = that.pmd_; return *this; } + inline void insert(const polygon_90_set_data& ps, const property_type& property) { + merge_scanline >:: + populate_property_merge_data(pmd_, ps.begin(), ps.end(), property, ps.orient()); + } + template + inline void insert(const GeoObjT& geoObj, const property_type& property) { + polygon_90_set_data ps; + ps.insert(geoObj); + insert(ps, property); + } + //merge properties of input geometries and store the resulting geometries of regions + //with unique sets of merged properties to polygons sets in a map keyed by sets of properties + // T = std::map, polygon_90_set_data > or + // T = std::map, polygon_90_set_data > + template + inline void merge(ResultType& result) { + merge_scanline, typename ResultType::key_type> ms; + ms.perform_merge(result, pmd_); + } + }; + + //ConnectivityExtraction computes the graph of connectivity between rectangle, polygon and + //polygon set graph nodes where an edge is created whenever the geometry in two nodes overlap + template + class connectivity_extraction_90 { + private: + typedef typename touch_90_operation::TouchSetData tsd; + tsd tsd_; + unsigned int nodeCount_; + public: + inline connectivity_extraction_90() : tsd_(), nodeCount_(0) {} + inline connectivity_extraction_90(const connectivity_extraction_90& that) : tsd_(that.tsd_), + nodeCount_(that.nodeCount_) {} + inline connectivity_extraction_90& operator=(const connectivity_extraction_90& that) { + tsd_ = that.tsd_; + nodeCount_ = that.nodeCount_; {} + return *this; + } + + //insert a polygon set graph node, the value returned is the id of the graph node + inline unsigned int insert(const polygon_90_set_data& ps) { + ps.clean(); + touch_90_operation::populateTouchSetData(tsd_, ps.begin(), ps.end(), nodeCount_); + return nodeCount_++; + } + template + inline unsigned int insert(const GeoObjT& geoObj) { + polygon_90_set_data ps; + ps.insert(geoObj); + return insert(ps); + } + + //extract connectivity and store the edges in the graph + //graph must be indexable by graph node id and the indexed value must be a std::set of + //graph node id + template + inline void extract(GraphT& graph) { + touch_90_operation::performTouch(graph, tsd_); + } + }; +} +} +#endif diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/polygon_90_set_traits.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/polygon_90_set_traits.hpp new file mode 100644 index 0000000..c1312e8 --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/polygon_90_set_traits.hpp @@ -0,0 +1,366 @@ +/* + Copyright 2008 Intel Corporation + + Use, modification and distribution are subject to the Boost Software License, + Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at + http://www.boost.org/LICENSE_1_0.txt). +*/ +#ifndef BOOST_POLYGON_POLYGON_90_SET_TRAITS_HPP +#define BOOST_POLYGON_POLYGON_90_SET_TRAITS_HPP +namespace boost { namespace polygon{ + + struct polygon_90_set_concept {}; + + template + struct traits_by_concept {}; + template + struct traits_by_concept { typedef coordinate_traits type; }; + template + struct traits_by_concept { typedef interval_traits type; }; + template + struct traits_by_concept { typedef point_traits type; }; + template + struct traits_by_concept { typedef rectangle_traits type; }; + template + struct traits_by_concept { typedef segment_traits type; }; + template + struct traits_by_concept { typedef polygon_traits type; }; + template + struct traits_by_concept { typedef polygon_traits type; }; + template + struct traits_by_concept { typedef polygon_traits type; }; + template + struct traits_by_concept { typedef polygon_traits type; }; + template + struct traits_by_concept { typedef polygon_traits type; }; + template + struct traits_by_concept { typedef polygon_traits type; }; + + struct polygon_45_set_concept; + struct polygon_set_concept; + template + struct polygon_90_set_traits; + template + struct polygon_45_set_traits; + template + struct polygon_set_traits; + template + struct traits_by_concept { typedef polygon_90_set_traits type; }; + template + struct traits_by_concept { typedef polygon_45_set_traits type; }; + template + struct traits_by_concept { typedef polygon_set_traits type; }; + + template + struct get_coordinate_type { + typedef typename traits_by_concept::type traits_type; + typedef typename traits_type::coordinate_type type; + }; + //want to prevent recursive template definition syntax errors, so duplicate get_coordinate_type + template + struct get_coordinate_type_2 { + typedef typename traits_by_concept::type traits_type; + typedef typename traits_type::coordinate_type type; + }; + template + struct get_coordinate_type { + typedef typename get_coordinate_type_2::value_type, + typename geometry_concept::value_type>::type>::type type; }; + + template + struct get_iterator_type_2 { + typedef const T* type; + static type begin(const T& t) { return &t; } + static type end(const T& t) { const T* tp = &t; ++tp; return tp; } + }; + template + struct get_iterator_type { + typedef get_iterator_type_2::type> indirect_type; + typedef typename indirect_type::type type; + static type begin(const T& t) { return indirect_type::begin(t); } + static type end(const T& t) { return indirect_type::end(t); } + }; + template + struct get_iterator_type_2 { + typedef typename T::const_iterator type; + static type begin(const T& t) { return t.begin(); } + static type end(const T& t) { return t.end(); } + }; + +// //helpers for allowing polygon 45 and containers of polygon 45 to behave interchangably in polygon_45_set_traits +// template +// struct get_coordinate_type_45 {}; +// template +// struct get_coordinate_type_2_45 {}; +// template +// struct get_coordinate_type_45 { +// typedef typename get_coordinate_type_2_45< typename T::value_type, typename geometry_concept::type >::type type; }; +// template +// struct get_coordinate_type_45 { typedef typename polygon_traits::coordinate_type type; }; +// template +// struct get_coordinate_type_45 { typedef typename polygon_traits::coordinate_type type; }; +// template +// struct get_coordinate_type_2_45 { typedef typename polygon_traits::coordinate_type type; }; +// template +// struct get_coordinate_type_2_45 { typedef typename polygon_traits::coordinate_type type; }; +// template +// struct get_iterator_type_45 {}; +// template +// struct get_iterator_type_45 { +// typedef typename T::const_iterator type; +// static type begin(const T& t) { return t.begin(); } +// static type end(const T& t) { return t.end(); } +// }; +// template +// struct get_iterator_type_45 { +// typedef const T* type; +// static type begin(const T& t) { return &t; } +// static type end(const T& t) { const T* tp = &t; ++tp; return tp; } +// }; +// template +// struct get_iterator_type_45 { +// typedef const T* type; +// static type begin(const T& t) { return &t; } +// static type end(const T& t) { const T* tp = &t; ++tp; return tp; } +// }; +// template +// struct get_iterator_type_45 { +// typedef const T* type; +// static type begin(const T& t) { return &t; } +// static type end(const T& t) { const T* tp = &t; ++tp; return tp; } +// }; + + template + struct polygon_90_set_traits { + typedef typename get_coordinate_type::type >::type coordinate_type; + typedef get_iterator_type indirection_type; + typedef typename get_iterator_type::type iterator_type; + typedef T operator_arg_type; + + static inline iterator_type begin(const T& polygon_set) { + return indirection_type::begin(polygon_set); + } + + static inline iterator_type end(const T& polygon_set) { + return indirection_type::end(polygon_set); + } + + static inline orientation_2d orient(const T&) { return HORIZONTAL; } + + static inline bool clean(const T&) { return false; } + + static inline bool sorted(const T&) { return false; } + }; + + template + struct is_manhattan_polygonal_concept { typedef gtl_no type; }; + template <> + struct is_manhattan_polygonal_concept { typedef gtl_yes type; }; + template <> + struct is_manhattan_polygonal_concept { typedef gtl_yes type; }; + template <> + struct is_manhattan_polygonal_concept { typedef gtl_yes type; }; + template <> + struct is_manhattan_polygonal_concept { typedef gtl_yes type; }; + + template + struct is_polygon_90_set_type { + typedef typename is_manhattan_polygonal_concept::type>::type type; + }; + template + struct is_polygon_90_set_type > { + typedef typename gtl_or< + typename is_manhattan_polygonal_concept >::type>::type, + typename is_manhattan_polygonal_concept::value_type>::type>::type>::type type; + }; + template + struct is_polygon_90_set_type > { + typedef typename gtl_or< + typename is_manhattan_polygonal_concept >::type>::type, + typename is_manhattan_polygonal_concept::value_type>::type>::type>::type type; + }; + + template + struct is_mutable_polygon_90_set_type { + typedef typename gtl_same_type::type>::type type; + }; + template + struct is_mutable_polygon_90_set_type > { + typedef typename gtl_or< + typename gtl_same_type >::type>::type, + typename is_manhattan_polygonal_concept::value_type>::type>::type>::type type; + }; + template + struct is_mutable_polygon_90_set_type > { + typedef typename gtl_or< + typename gtl_same_type >::type>::type, + typename is_manhattan_polygonal_concept::value_type>::type>::type>::type type; + }; + +// //specialization for rectangle, polygon_90 and polygon_90_with_holes types +// template +// struct polygon_90_set_traits +// typedef typename geometry_concept::type concept_type; +// typedef typename get_coordinate_type::type coordinate_type; +// typedef iterator_geometry_to_set iterator_type; +// typedef T operator_arg_type; + +// static inline iterator_type begin(const T& polygon_set) { +// return iterator_geometry_to_set(polygon_set, LOW, HORIZONTAL); +// } + +// static inline iterator_type end(const T& polygon_set) { +// return iterator_geometry_to_set(polygon_set, HIGH, HORIZONTAL); +// } + +// static inline orientation_2d orient(const T& polygon_set) { return HORIZONTAL; } + +// static inline bool clean(const T& polygon_set) { return false; } + +// static inline bool sorted(const T& polygon_set) { return false; } + +// }; + +// //specialization for containers of recangle, polygon_90, polygon_90_with_holes +// template +// struct polygon_90_set_traits::value_type>::type> { +// typedef typename std::iterator_traits::value_type geometry_type; +// typedef typename geometry_concept::type concept_type; +// typedef typename get_coordinate_type::type coordinate_type; +// typedef iterator_geometry_range_to_set iterator_type; +// typedef T operator_arg_type; + +// static inline iterator_type begin(const T& polygon_set) { +// return iterator_type(polygon_set.begin(), HORIZONTAL); +// } + +// static inline iterator_type end(const T& polygon_set) { +// return iterator_type(polygon_set.end(), HORIZONTAL); +// } + +// static inline orientation_2d orient(const T& polygon_set) { return HORIZONTAL; } + +// static inline bool clean(const T& polygon_set) { return false; } + +// static inline bool sorted(const T& polygon_set) { return false; } + +// }; + + //get dispatch functions + template + void get_90_dispatch(output_container_type& output, const pst& ps, + orientation_2d orient, rectangle_concept ) { + form_rectangles(output, ps.begin(), ps.end(), orient, rectangle_concept()); + } + + template + void get_90_dispatch(output_container_type& output, const pst& ps, + orientation_2d orient, polygon_90_concept tag) { + get_polygons(output, ps.begin(), ps.end(), orient, true, tag); + } + + template + void get_90_dispatch(output_container_type& output, const pst& ps, + orientation_2d orient, polygon_90_with_holes_concept tag) { + get_polygons(output, ps.begin(), ps.end(), orient, false, tag); + } + + //by default works with containers of rectangle, polygon or polygon with holes + //must be specialized to work with anything else + template + struct polygon_90_set_mutable_traits {}; + template + struct polygon_90_set_mutable_traits > { + typedef typename geometry_concept::type concept_type; + template + static inline void set(std::list& polygon_set, input_iterator_type input_begin, input_iterator_type input_end, orientation_2d orient) { + polygon_set.clear(); + polygon_90_set_data >::coordinate_type> ps(orient); + ps.reserve(std::distance(input_begin, input_end)); + ps.insert(input_begin, input_end, orient); + ps.clean(); + get_90_dispatch(polygon_set, ps, orient, concept_type()); + } + }; + template + struct polygon_90_set_mutable_traits > { + typedef typename geometry_concept::type concept_type; + template + static inline void set(std::vector& polygon_set, input_iterator_type input_begin, input_iterator_type input_end, orientation_2d orient) { + polygon_set.clear(); + size_t num_ele = std::distance(input_begin, input_end); + polygon_set.reserve(num_ele); + polygon_90_set_data >::coordinate_type> ps(orient); + ps.reserve(num_ele); + ps.insert(input_begin, input_end, orient); + ps.clean(); + get_90_dispatch(polygon_set, ps, orient, concept_type()); + } + }; + + template + struct polygon_90_set_mutable_traits > { + + template + static inline void set(polygon_90_set_data& polygon_set, + input_iterator_type input_begin, input_iterator_type input_end, + orientation_2d orient) { + polygon_set.clear(); + polygon_set.reserve(std::distance(input_begin, input_end)); + polygon_set.insert(input_begin, input_end, orient); + } + + }; + + template + struct polygon_90_set_traits > { + typedef typename polygon_90_set_data::coordinate_type coordinate_type; + typedef typename polygon_90_set_data::iterator_type iterator_type; + typedef typename polygon_90_set_data::operator_arg_type operator_arg_type; + + static inline iterator_type begin(const polygon_90_set_data& polygon_set) { + return polygon_set.begin(); + } + + static inline iterator_type end(const polygon_90_set_data& polygon_set) { + return polygon_set.end(); + } + + static inline orientation_2d orient(const polygon_90_set_data& polygon_set) { return polygon_set.orient(); } + + static inline bool clean(const polygon_90_set_data& polygon_set) { polygon_set.clean(); return true; } + + static inline bool sorted(const polygon_90_set_data& polygon_set) { polygon_set.sort(); return true; } + + }; + + template + struct is_polygon_90_set_concept { }; + template <> + struct is_polygon_90_set_concept { typedef gtl_yes type; }; + template <> + struct is_polygon_90_set_concept { typedef gtl_yes type; }; + template <> + struct is_polygon_90_set_concept { typedef gtl_yes type; }; + template <> + struct is_polygon_90_set_concept { typedef gtl_yes type; }; + + template + struct is_mutable_polygon_90_set_concept { typedef gtl_no type; }; + template <> + struct is_mutable_polygon_90_set_concept { typedef gtl_yes type; }; + + template + struct geometry_concept > { typedef polygon_90_set_concept type; }; + + //template + //typename enable_if::type, void>::type + //print_is_polygon_90_set_concept(const T& t) { std::cout << "is polygon 90 set concept\n"; } + //template + //typename enable_if::type, void>::type + //print_is_mutable_polygon_90_set_concept(const T& t) { std::cout << "is mutable polygon 90 set concept\n"; } +} +} +#endif diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/polygon_90_with_holes_data.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/polygon_90_with_holes_data.hpp new file mode 100644 index 0000000..be43b65 --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/polygon_90_with_holes_data.hpp @@ -0,0 +1,115 @@ +/* + Copyright 2008 Intel Corporation + + Use, modification and distribution are subject to the Boost Software License, + Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at + http://www.boost.org/LICENSE_1_0.txt). +*/ +#ifndef BOOST_POLYGON_POLYGON_90_WITH_HOLES_DATA_HPP +#define BOOST_POLYGON_POLYGON_90_WITH_HOLES_DATA_HPP +namespace boost { namespace polygon{ +#include "isotropy.hpp" +#include "polygon_90_data.hpp" +struct polygon_90_with_holes_concept; +template +class polygon_90_with_holes_data { +public: + typedef polygon_90_with_holes_concept geometry_type; + typedef T coordinate_type; + typedef typename polygon_90_data::iterator_type iterator_type; + typedef typename polygon_90_data::compact_iterator_type compact_iterator_type; + typedef typename std::list >::const_iterator iterator_holes_type; + typedef polygon_90_data hole_type; + typedef typename coordinate_traits::area_type area_type; + typedef point_data point_type; + + // default constructor of point does not initialize x and y + inline polygon_90_with_holes_data() : self_(), holes_() {} //do nothing default constructor + + // initialize a polygon from x,y values, it is assumed that the first is an x + // and that the input is a well behaved polygon + template + inline polygon_90_with_holes_data& set(iT input_begin, iT input_end) { + self_.set(input_begin, input_end); + return *this; + } + + // initialize a polygon from x,y values, it is assumed that the first is an x + // and that the input is a well behaved polygon + template + inline polygon_90_with_holes_data& set_compact(iT input_begin, iT input_end) { + self_.set_compact(input_begin, input_end); + return *this; + } + + // initialize a polygon from x,y values, it is assumed that the first is an x + // and that the input is a well behaved polygon + template + inline polygon_90_with_holes_data& set_holes(iT input_begin, iT input_end) { + holes_.clear(); //just in case there was some old data there + for( ; input_begin != input_end; ++ input_begin) { + holes_.push_back(hole_type()); + holes_.back().set_compact((*input_begin).begin_compact(), (*input_begin).end_compact()); + } + return *this; + } + + // copy constructor (since we have dynamic memory) + inline polygon_90_with_holes_data(const polygon_90_with_holes_data& that) : self_(that.self_), + holes_(that.holes_) {} + + // assignment operator (since we have dynamic memory do a deep copy) + inline polygon_90_with_holes_data& operator=(const polygon_90_with_holes_data& that) { + self_ = that.self_; + holes_ = that.holes_; + return *this; + } + + template + inline polygon_90_with_holes_data& operator=(const T2& rvalue); + + // get begin iterator, returns a pointer to a const coordinate_type + inline const iterator_type begin() const { + return self_.begin(); + } + + // get end iterator, returns a pointer to a const coordinate_type + inline const iterator_type end() const { + return self_.end(); + } + + // get begin iterator, returns a pointer to a const coordinate_type + inline const compact_iterator_type begin_compact() const { + return self_.begin_compact(); + } + + // get end iterator, returns a pointer to a const coordinate_type + inline const compact_iterator_type end_compact() const { + return self_.end_compact(); + } + + inline std::size_t size() const { + return self_.size(); + } + + // get begin iterator, returns a pointer to a const polygon + inline const iterator_holes_type begin_holes() const { + return holes_.begin(); + } + + // get end iterator, returns a pointer to a const polygon + inline const iterator_holes_type end_holes() const { + return holes_.end(); + } + + inline std::size_t size_holes() const { + return holes_.size(); + } + +private: + polygon_90_data self_; + std::list holes_; +}; +} +} +#endif diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/polygon_data.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/polygon_data.hpp new file mode 100644 index 0000000..9784466 --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/polygon_data.hpp @@ -0,0 +1,69 @@ +/* + Copyright 2008 Intel Corporation + + Use, modification and distribution are subject to the Boost Software License, + Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at + http://www.boost.org/LICENSE_1_0.txt). +*/ +#ifndef BOOST_POLYGON_POLYGON_DATA_HPP +#define BOOST_POLYGON_POLYGON_DATA_HPP +namespace boost { namespace polygon{ +struct polygon_concept; +template +class polygon_data { +public: + typedef polygon_concept geometry_type; + typedef T coordinate_type; + typedef typename std::vector >::const_iterator iterator_type; + typedef typename coordinate_traits::coordinate_distance area_type; + typedef point_data point_type; + + inline polygon_data() : coords_() {} //do nothing default constructor + + template + inline polygon_data(iT input_begin, iT input_end) : coords_(input_begin, input_end) {} + + template + inline polygon_data& set(iT input_begin, iT input_end) { + coords_.clear(); //just in case there was some old data there + coords_.insert(coords_.end(), input_begin, input_end); + return *this; + } + + // copy constructor (since we have dynamic memory) + inline polygon_data(const polygon_data& that) : coords_(that.coords_) {} + + // assignment operator (since we have dynamic memory do a deep copy) + inline polygon_data& operator=(const polygon_data& that) { + coords_ = that.coords_; + return *this; + } + + template + inline polygon_data& operator=(const T2& rvalue); + + inline bool operator==(const polygon_data& that) const { + if(coords_.size() != that.coords_.size()) return false; + for(std::size_t i = 0; i < coords_.size(); ++i) { + if(coords_[i] != that.coords_[i]) return false; + } + return true; + } + + inline bool operator!=(const polygon_data& that) const { return !((*this) == that); } + + // get begin iterator, returns a pointer to a const Unit + inline iterator_type begin() const { return coords_.begin(); } + + // get end iterator, returns a pointer to a const Unit + inline iterator_type end() const { return coords_.end(); } + + inline std::size_t size() const { return coords_.size(); } + +public: + std::vector > coords_; +}; + +} +} +#endif diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/polygon_set_concept.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/polygon_set_concept.hpp new file mode 100644 index 0000000..e3d37b8 --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/polygon_set_concept.hpp @@ -0,0 +1,581 @@ +/* + Copyright 2008 Intel Corporation + + Use, modification and distribution are subject to the Boost Software License, + Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at + http://www.boost.org/LICENSE_1_0.txt). +*/ +#ifndef BOOST_POLYGON_POLYGON_SET_CONCEPT_HPP +#define BOOST_POLYGON_POLYGON_SET_CONCEPT_HPP +#include "polygon_set_data.hpp" +#include "detail/polygon_simplify.hpp" +namespace boost { namespace polygon{ + + template + struct is_either_polygon_set_type { + typedef typename gtl_or::type, typename is_polygon_set_type::type >::type type; + }; + + template + struct is_any_polygon_set_type { + typedef typename gtl_or::type, typename is_polygon_set_type::type >::type type; + }; + + template + typename enable_if< typename is_any_polygon_set_type::type, + typename polygon_set_traits::iterator_type>::type + begin_polygon_set_data(const polygon_set_type& polygon_set) { + return polygon_set_traits::begin(polygon_set); + } + + template + typename enable_if< typename is_any_polygon_set_type::type, + typename polygon_set_traits::iterator_type>::type + end_polygon_set_data(const polygon_set_type& polygon_set) { + return polygon_set_traits::end(polygon_set); + } + + template + typename enable_if< typename is_polygon_set_type::type, + bool>::type + clean(const polygon_set_type& polygon_set) { + return polygon_set_traits::clean(polygon_set); + } + + //assign + template + typename enable_if< typename gtl_and< + typename is_mutable_polygon_set_type::type, + typename is_any_polygon_set_type::type>::type, + polygon_set_type_1>::type & + assign(polygon_set_type_1& lvalue, const polygon_set_type_2& rvalue) { + if(clean(rvalue)) + polygon_set_mutable_traits::set(lvalue, begin_polygon_set_data(rvalue), end_polygon_set_data(rvalue)); + else { + polygon_set_data::coordinate_type> ps; + ps.insert(begin_polygon_set_data(rvalue), end_polygon_set_data(rvalue)); + ps.clean(); + polygon_set_mutable_traits::set(lvalue, ps.begin(), ps.end()); + } + return lvalue; + } + + //get trapezoids + template + typename enable_if< typename is_mutable_polygon_set_type::type, + void>::type + get_trapezoids(output_container_type& output, const polygon_set_type& polygon_set) { + polygon_set_data::coordinate_type> ps; + assign(ps, polygon_set); + ps.get_trapezoids(output); + } + + //get trapezoids + template + typename enable_if< typename is_mutable_polygon_set_type::type, + void>::type + get_trapezoids(output_container_type& output, const polygon_set_type& polygon_set, + orientation_2d orient) { + polygon_set_data::coordinate_type> ps; + assign(ps, polygon_set); + ps.get_trapezoids(output, orient); + } + + //equivalence + template + typename enable_if< typename gtl_and_3 < + typename is_any_polygon_set_type::type, + typename is_any_polygon_set_type::type, + typename is_either_polygon_set_type::type>::type, + bool>::type + equivalence(const polygon_set_type_1& lvalue, + const polygon_set_type_2& rvalue) { + polygon_set_data::coordinate_type> ps1; + assign(ps1, lvalue); + polygon_set_data::coordinate_type> ps2; + assign(ps2, rvalue); + return ps1 == ps2; + } + + //clear + template + typename enable_if< typename is_mutable_polygon_set_type::type, + void>::type + clear(polygon_set_type& polygon_set) { + polygon_set_data::coordinate_type> ps; + assign(polygon_set, ps); + } + + //empty + template + typename enable_if< typename is_mutable_polygon_set_type::type, + bool>::type + empty(const polygon_set_type& polygon_set) { + if(clean(polygon_set)) return begin_polygon_set_data(polygon_set) == end_polygon_set_data(polygon_set); + polygon_set_data::coordinate_type> ps; + assign(ps, polygon_set); + ps.clean(); + return ps.empty(); + } + + //extents + template + typename enable_if< typename gtl_and< + typename is_mutable_polygon_set_type::type, + typename is_mutable_rectangle_concept::type>::type>::type, + bool>::type + extents(rectangle_type& extents_rectangle, + const polygon_set_type& polygon_set) { + clean(polygon_set); + polygon_set_data::coordinate_type> ps; + assign(ps, polygon_set); + return ps.extents(extents_rectangle); + } + + //area + template + typename enable_if< typename is_mutable_polygon_set_type::type, + typename coordinate_traits::coordinate_type>::area_type>::type + area(const polygon_set_type& polygon_set) { + typedef typename polygon_set_traits::coordinate_type Unit; + typedef polygon_with_holes_data p_type; + typedef typename coordinate_traits::area_type area_type; + std::vector polys; + assign(polys, polygon_set); + area_type retval = (area_type)0; + for(std::size_t i = 0; i < polys.size(); ++i) { + retval += area(polys[i]); + } + return retval; + } + + template + typename enable_if< typename is_mutable_polygon_set_type::type, + std::size_t>::type + simplify(polygon_set_type& polygon_set, typename coordinate_traits< + typename polygon_set_traits::coordinate_type + >::coordinate_distance threshold) { + typedef typename polygon_set_traits::coordinate_type Unit; + typedef polygon_with_holes_data p_type; + std::vector polys; + assign(polys, polygon_set); + std::size_t retval = 0; + for(std::size_t i = 0; i < polys.size(); ++i) { + retval += detail::simplify_detail::simplify(polys[i].self_.coords_, + polys[i].self_.coords_, threshold); + for(typename std::list >::iterator itrh = + polys[i].holes_.begin(); itrh != (polys[i].holes_.end()); ++itrh) { + retval += detail::simplify_detail::simplify((*itrh).coords_, + (*itrh).coords_, threshold); + } + } + assign(polygon_set, polys); + return retval; + } + + template + typename enable_if< typename is_mutable_polygon_set_type::type, + polygon_set_type>::type & + resize(polygon_set_type& polygon_set, coord_type resizing, bool corner_fill_arcs = false, int num_circle_segments = 0) { + typedef typename polygon_set_traits::coordinate_type Unit; + clean(polygon_set); + polygon_set_data ps; + assign(ps, polygon_set); + ps.resize(resizing, corner_fill_arcs,num_circle_segments); + assign(polygon_set, ps); + return polygon_set; + } + + template + typename enable_if< typename is_mutable_polygon_set_type::type, + polygon_set_type>::type & + bloat(polygon_set_type& polygon_set, + typename coordinate_traits::coordinate_type>::unsigned_area_type bloating) { + return resize(polygon_set, bloating); + } + + template + typename enable_if< typename is_mutable_polygon_set_type::type, + polygon_set_type>::type & + shrink(polygon_set_type& polygon_set, + typename coordinate_traits::coordinate_type>::unsigned_area_type shrinking) { + return resize(polygon_set, -(typename polygon_set_traits::coordinate_type)shrinking); + } + + //interact + template + typename enable_if< typename gtl_and_3 < + typename is_any_polygon_set_type::type, + typename is_any_polygon_set_type::type, + typename is_either_polygon_set_type::type>::type, + polygon_set_type_1>::type& + interact(polygon_set_type_1& polygon_set_1, const polygon_set_type_2& polygon_set_2) { + polygon_set_data::coordinate_type> ps1; + assign(ps1, polygon_set_1); + polygon_set_data::coordinate_type> ps2; + assign(ps2, polygon_set_2); + ps1.interact(ps2); + assign(polygon_set_1, ps1); + return polygon_set_1; + } + + template + typename enable_if< typename is_mutable_polygon_set_type::type, + polygon_set_type>::type & + scale_up(polygon_set_type& polygon_set, + typename coordinate_traits::coordinate_type>::unsigned_area_type factor) { + typedef typename polygon_set_traits::coordinate_type Unit; + clean(polygon_set); + polygon_set_data ps; + assign(ps, polygon_set); + ps.scale_up(factor); + assign(polygon_set, ps); + return polygon_set; + } + + template + typename enable_if< typename is_mutable_polygon_set_type::type, + polygon_set_type>::type & + scale_down(polygon_set_type& polygon_set, + typename coordinate_traits::coordinate_type>::unsigned_area_type factor) { + typedef typename polygon_set_traits::coordinate_type Unit; + clean(polygon_set); + polygon_set_data ps; + assign(ps, polygon_set); + ps.scale_down(factor); + assign(polygon_set, ps); + return polygon_set; + } + + //transform + template + typename enable_if< typename is_mutable_polygon_set_type::type, + polygon_set_type>::type & + transform(polygon_set_type& polygon_set, + const transformation_type& transformation) { + typedef typename polygon_set_traits::coordinate_type Unit; + clean(polygon_set); + polygon_set_data ps; + assign(ps, polygon_set); + ps.transform(transformation); + assign(polygon_set, ps); + return polygon_set; + } + + //keep + template + typename enable_if< typename is_mutable_polygon_set_type::type, + polygon_set_type>::type & + keep(polygon_set_type& polygon_set, + typename coordinate_traits::coordinate_type>::area_type min_area, + typename coordinate_traits::coordinate_type>::area_type max_area, + typename coordinate_traits::coordinate_type>::unsigned_area_type min_width, + typename coordinate_traits::coordinate_type>::unsigned_area_type max_width, + typename coordinate_traits::coordinate_type>::unsigned_area_type min_height, + typename coordinate_traits::coordinate_type>::unsigned_area_type max_height) { + typedef typename polygon_set_traits::coordinate_type Unit; + typedef typename coordinate_traits::unsigned_area_type uat; + std::list > polys; + assign(polys, polygon_set); + typename std::list >::iterator itr_nxt; + for(typename std::list >::iterator itr = polys.begin(); itr != polys.end(); itr = itr_nxt){ + itr_nxt = itr; + ++itr_nxt; + rectangle_data bbox; + extents(bbox, *itr); + uat pwidth = delta(bbox, HORIZONTAL); + if(pwidth > min_width && pwidth <= max_width){ + uat pheight = delta(bbox, VERTICAL); + if(pheight > min_height && pheight <= max_height){ + typename coordinate_traits::area_type parea = area(*itr); + if(parea <= max_area && parea >= min_area) { + continue; + } + } + } + polys.erase(itr); + } + assign(polygon_set, polys); + return polygon_set; + } + + namespace operators { + + struct yes_ps_ob : gtl_yes {}; + + template + typename enable_if< typename gtl_and_4 < yes_ps_ob, typename is_any_polygon_set_type::type, + typename is_any_polygon_set_type::type, + typename is_either_polygon_set_type::type>::type, + polygon_set_view >::type + operator|(const geometry_type_1& lvalue, const geometry_type_2& rvalue) { + return polygon_set_view + (lvalue, rvalue); + } + + struct yes_ps_op : gtl_yes {}; + + template + typename enable_if< typename gtl_and_4 < yes_ps_op, + typename gtl_if::type>::type, + typename gtl_if::type>::type, + typename gtl_if::type>::type> + ::type, polygon_set_view >::type + operator+(const geometry_type_1& lvalue, const geometry_type_2& rvalue) { + return polygon_set_view + (lvalue, rvalue); + } + + struct yes_ps_os : gtl_yes {}; + + template + typename enable_if< typename gtl_and_4 < yes_ps_os, + typename is_any_polygon_set_type::type, + typename is_any_polygon_set_type::type, + typename is_either_polygon_set_type::type>::type, + polygon_set_view >::type + operator*(const geometry_type_1& lvalue, const geometry_type_2& rvalue) { + return polygon_set_view + (lvalue, rvalue); + } + + struct yes_ps_oa : gtl_yes {}; + + template + typename enable_if< typename gtl_and_4 < yes_ps_oa, + typename is_any_polygon_set_type::type, + typename is_any_polygon_set_type::type, + typename is_either_polygon_set_type::type>::type, + polygon_set_view >::type + operator&(const geometry_type_1& lvalue, const geometry_type_2& rvalue) { + return polygon_set_view + (lvalue, rvalue); + } + + struct yes_ps_ox : gtl_yes {}; + + template + typename enable_if< typename gtl_and_4 < yes_ps_ox, + typename is_any_polygon_set_type::type, + typename is_any_polygon_set_type::type, + typename is_either_polygon_set_type::type>::type, + polygon_set_view >::type + operator^(const geometry_type_1& lvalue, const geometry_type_2& rvalue) { + return polygon_set_view + (lvalue, rvalue); + } + + struct yes_ps_om : gtl_yes {}; + + template + typename enable_if< typename gtl_and_4 < yes_ps_om, + typename gtl_if::type>::type, + typename gtl_if::type>::type, + typename gtl_if::type>::type> + ::type, polygon_set_view >::type + operator-(const geometry_type_1& lvalue, const geometry_type_2& rvalue) { + return polygon_set_view + (lvalue, rvalue); + } + + struct yes_ps_ope : gtl_yes {}; + + template + typename enable_if< typename gtl_and_4< yes_ps_ope, gtl_yes, typename is_mutable_polygon_set_type::type, + typename is_any_polygon_set_type::type>::type, + geometry_type_1>::type & + operator+=(geometry_type_1& lvalue, const geometry_type_2& rvalue) { + return self_assignment_boolean_op(lvalue, rvalue); + } + + struct yes_ps_obe : gtl_yes {}; + + template + typename enable_if< typename gtl_and_3< yes_ps_obe, typename is_mutable_polygon_set_type::type, + typename is_any_polygon_set_type::type>::type, + geometry_type_1>::type & + operator|=(geometry_type_1& lvalue, const geometry_type_2& rvalue) { + return self_assignment_boolean_op(lvalue, rvalue); + } + + struct yes_ps_ose : gtl_yes {}; + + template + typename enable_if< typename gtl_and_3< yes_ps_ose, typename is_mutable_polygon_set_type::type, + typename is_any_polygon_set_type::type>::type, + geometry_type_1>::type & + operator*=(geometry_type_1& lvalue, const geometry_type_2& rvalue) { + return self_assignment_boolean_op(lvalue, rvalue); + } + + struct yes_ps_oae : gtl_yes {}; + + template + typename enable_if< + typename gtl_and_3< yes_ps_oae, typename is_mutable_polygon_set_type::type, + typename is_any_polygon_set_type::type>::type, + geometry_type_1>::type & + operator&=(geometry_type_1& lvalue, const geometry_type_2& rvalue) { + return self_assignment_boolean_op(lvalue, rvalue); + } + + struct yes_ps_oxe : gtl_yes {}; + + template + typename enable_if< typename gtl_and_3< yes_ps_oxe, typename is_mutable_polygon_set_type::type, + typename is_any_polygon_set_type::type>::type, + geometry_type_1>::type & + operator^=(geometry_type_1& lvalue, const geometry_type_2& rvalue) { + return self_assignment_boolean_op(lvalue, rvalue); + } + + struct yes_ps_ome : gtl_yes {}; + + template + typename enable_if< + typename gtl_and_3< yes_ps_ome, typename is_mutable_polygon_set_type::type, + typename is_any_polygon_set_type::type>::type, + geometry_type_1>::type & + operator-=(geometry_type_1& lvalue, const geometry_type_2& rvalue) { + return self_assignment_boolean_op(lvalue, rvalue); + } + + // TODO: Dafna, test these four resizing operators + struct y_ps_rpe : gtl_yes {}; + + template + typename enable_if< typename gtl_and_3< y_ps_rpe, typename is_mutable_polygon_set_type::type, + typename gtl_same_type::type, + coordinate_concept>::type>::type, + geometry_type_1>::type & + operator+=(geometry_type_1& lvalue, coordinate_type_1 rvalue) { + return resize(lvalue, rvalue); + } + + struct y_ps_rme : gtl_yes {}; + + template + typename enable_if< typename gtl_and_3::type>::type, + typename gtl_same_type::type, + coordinate_concept>::type>::type, + geometry_type_1>::type & + operator-=(geometry_type_1& lvalue, coordinate_type_1 rvalue) { + return resize(lvalue, -rvalue); + } + + struct y_ps_rp : gtl_yes {}; + + template + typename enable_if< typename gtl_and_3::type>::type, + typename gtl_same_type::type, + coordinate_concept>::type> + ::type, geometry_type_1>::type + operator+(const geometry_type_1& lvalue, coordinate_type_1 rvalue) { + geometry_type_1 retval(lvalue); + retval += rvalue; + return retval; + } + + struct y_ps_rm : gtl_yes {}; + + template + typename enable_if< typename gtl_and_3::type>::type, + typename gtl_same_type::type, + coordinate_concept>::type> + ::type, geometry_type_1>::type + operator-(const geometry_type_1& lvalue, coordinate_type_1 rvalue) { + geometry_type_1 retval(lvalue); + retval -= rvalue; + return retval; + } + + + } //end operators namespace + + template + struct view_of { + typedef typename get_coordinate_type::type >::type coordinate_type; + T* tp; + std::vector > polys; + view_of(const T& obj) : tp(), polys() { + std::vector > gpolys; + assign(gpolys, obj); + for(typename std::vector >::iterator itr = gpolys.begin(); + itr != gpolys.end(); ++itr) { + polys.push_back(polygon_45_with_holes_data()); + assign(polys.back(), view_as(*itr)); + } + } + view_of(T& obj) : tp(&obj), polys() { + std::vector > gpolys; + assign(gpolys, obj); + for(typename std::vector >::iterator itr = gpolys.begin(); + itr != gpolys.end(); ++itr) { + polys.push_back(polygon_45_with_holes_data()); + assign(polys.back(), view_as(*itr)); + } + } + + typedef typename std::vector >::const_iterator iterator_type; + typedef view_of operator_arg_type; + + inline iterator_type begin() const { + return polys.begin(); + } + + inline iterator_type end() const { + return polys.end(); + } + + inline orientation_2d orient() const { return HORIZONTAL; } + + inline bool clean() const { return false; } + + inline bool sorted() const { return false; } + + inline T& get() { return *tp; } + }; + + template + struct polygon_45_set_traits > { + typedef typename view_of::coordinate_type coordinate_type; + typedef typename view_of::iterator_type iterator_type; + typedef view_of operator_arg_type; + + static inline iterator_type begin(const view_of& polygon_set) { + return polygon_set.begin(); + } + + static inline iterator_type end(const view_of& polygon_set) { + return polygon_set.end(); + } + + static inline orientation_2d orient(const view_of& polygon_set) { + return polygon_set.orient(); } + + static inline bool clean(const view_of& polygon_set) { + return polygon_set.clean(); } + + static inline bool sorted(const view_of& polygon_set) { + return polygon_set.sorted(); } + + }; + + template + struct geometry_concept > { + typedef polygon_45_set_concept type; + }; + + template + struct get_coordinate_type, polygon_45_set_concept> { + typedef typename view_of::coordinate_type type; + }; + template + struct get_iterator_type_2, polygon_45_set_concept> { + typedef typename view_of::iterator_type type; + static type begin(const view_of& t) { return t.begin(); } + static type end(const view_of& t) { return t.end(); } + }; +} +} +#endif diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/polygon_set_data.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/polygon_set_data.hpp new file mode 100644 index 0000000..32dd800 --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/polygon_set_data.hpp @@ -0,0 +1,1006 @@ +/* + Copyright 2008 Intel Corporation + + Use, modification and distribution are subject to the Boost Software License, + Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at + http://www.boost.org/LICENSE_1_0.txt). +*/ +#ifndef BOOST_POLYGON_POLYGON_SET_DATA_HPP +#define BOOST_POLYGON_POLYGON_SET_DATA_HPP +#include "polygon_45_set_data.hpp" +#include "polygon_45_set_concept.hpp" +#include "polygon_traits.hpp" +#include "detail/polygon_arbitrary_formation.hpp" + +namespace boost { namespace polygon { + + + // utility function to round coordinate types down + // rounds down for both negative and positive numbers + // intended really for integer type T (does not make sense for float) + template + static inline T round_down(double val) { + T rounded_val = (T)(val); + if(val < (double)rounded_val) + --rounded_val; + return rounded_val; + } + template + static inline point_data round_down(point_data v) { + return point_data(round_down(v.x()),round_down(v.y())); + } + + + + //foward declare view + template class polygon_set_view; + + template + class polygon_set_data { + public: + typedef T coordinate_type; + typedef point_data point_type; + typedef std::pair edge_type; + typedef std::pair element_type; + typedef std::vector value_type; + typedef typename value_type::const_iterator iterator_type; + typedef polygon_set_data operator_arg_type; + + // default constructor + inline polygon_set_data() : data_(), dirty_(false), unsorted_(false), is_45_(true) {} + + // constructor from an iterator pair over edge data + template + inline polygon_set_data(iT input_begin, iT input_end) : data_(), dirty_(false), unsorted_(false), is_45_(true) { + for( ; input_begin != input_end; ++input_begin) { insert(*input_begin); } + } + + // copy constructor + inline polygon_set_data(const polygon_set_data& that) : + data_(that.data_), dirty_(that.dirty_), unsorted_(that.unsorted_), is_45_(that.is_45_) {} + + // copy constructor + template + inline polygon_set_data(const polygon_set_view& that); + + // destructor + inline ~polygon_set_data() {} + + // assignement operator + inline polygon_set_data& operator=(const polygon_set_data& that) { + if(this == &that) return *this; + data_ = that.data_; + dirty_ = that.dirty_; + unsorted_ = that.unsorted_; + is_45_ = that.is_45_; + return *this; + } + + template + inline polygon_set_data& operator=(const polygon_set_view& geometry) { + (*this) = geometry.value(); + dirty_ = false; + unsorted_ = false; + return *this; + } + + template + inline polygon_set_data& operator=(const geometry_object& geometry) { + data_.clear(); + insert(geometry); + return *this; + } + + + // insert iterator range + inline void insert(iterator_type input_begin, iterator_type input_end, bool is_hole = false) { + if(input_begin == input_end || (!data_.empty() && &(*input_begin) == &(*(data_.begin())))) return; + dirty_ = true; + unsorted_ = true; + while(input_begin != input_end) { + insert(*input_begin, is_hole); + ++input_begin; + } + } + + // insert iterator range + template + inline void insert(iT input_begin, iT input_end, bool is_hole = false) { + if(input_begin == input_end) return; + for(; input_begin != input_end; ++input_begin) { + insert(*input_begin, is_hole); + } + } + + template + inline void insert(const geometry_type& geometry_object, bool is_hole = false) { + insert(geometry_object, is_hole, typename geometry_concept::type()); + } + + template + inline void insert(const polygon_type& polygon_object, bool is_hole, polygon_concept ) { + insert_vertex_sequence(begin_points(polygon_object), end_points(polygon_object), winding(polygon_object), is_hole); + } + + inline void insert(const polygon_set_data& ps, bool is_hole = false) { + insert(ps.data_.begin(), ps.data_.end(), is_hole); + } + + template + inline void insert(const polygon_45_set_type& ps, bool is_hole, polygon_45_set_concept) { + std::vector::coordinate_type> > polys; + assign(polys, ps); + insert(polys.begin(), polys.end(), is_hole); + } + + template + inline void insert(const polygon_90_set_type& ps, bool is_hole, polygon_90_set_concept) { + std::vector::coordinate_type> > polys; + assign(polys, ps); + insert(polys.begin(), polys.end(), is_hole); + } + + template + inline void insert(const polygon_type& polygon_object, bool is_hole, polygon_45_concept ) { + insert(polygon_object, is_hole, polygon_concept()); } + + template + inline void insert(const polygon_type& polygon_object, bool is_hole, polygon_90_concept ) { + insert(polygon_object, is_hole, polygon_concept()); } + + template + inline void insert(const polygon_with_holes_type& polygon_with_holes_object, bool is_hole, + polygon_with_holes_concept ) { + insert(polygon_with_holes_object, is_hole, polygon_concept()); + for(typename polygon_with_holes_traits::iterator_holes_type itr = + begin_holes(polygon_with_holes_object); + itr != end_holes(polygon_with_holes_object); ++itr) { + insert(*itr, !is_hole, polygon_concept()); + } + } + + template + inline void insert(const polygon_with_holes_type& polygon_with_holes_object, bool is_hole, + polygon_45_with_holes_concept ) { + insert(polygon_with_holes_object, is_hole, polygon_with_holes_concept()); } + + template + inline void insert(const polygon_with_holes_type& polygon_with_holes_object, bool is_hole, + polygon_90_with_holes_concept ) { + insert(polygon_with_holes_object, is_hole, polygon_with_holes_concept()); } + + template + inline void insert(const rectangle_type& rectangle_object, bool is_hole, rectangle_concept ) { + polygon_90_data poly; + assign(poly, rectangle_object); + insert(poly, is_hole, polygon_concept()); + } + + inline void insert_clean(const element_type& edge, bool is_hole = false) { + if( ! scanline_base::is_45_degree(edge.first) && + ! scanline_base::is_horizontal(edge.first) && + ! scanline_base::is_vertical(edge.first) ) is_45_ = false; + data_.push_back(edge); + if(data_.back().first.second < data_.back().first.first) { + std::swap(data_.back().first.second, data_.back().first.first); + data_.back().second *= -1; + } + if(is_hole) + data_.back().second *= -1; + } + + inline void insert(const element_type& edge, bool is_hole = false) { + insert_clean(edge, is_hole); + dirty_ = true; + unsorted_ = true; + } + + template + inline void insert_vertex_sequence(iT begin_vertex, iT end_vertex, direction_1d winding, bool is_hole) { + if (begin_vertex == end_vertex) { + // No edges to insert. + return; + } + // Current edge endpoints. + iT vertex0 = begin_vertex; + iT vertex1 = begin_vertex; + if (++vertex1 == end_vertex) { + // No edges to insert. + return; + } + int wmultiplier = (winding == COUNTERCLOCKWISE) ? 1 : -1; + if (is_hole) { + wmultiplier = -wmultiplier; + } + dirty_ = true; + unsorted_ = true; + while (vertex0 != end_vertex) { + point_type p0, p1; + assign(p0, *vertex0); + assign(p1, *vertex1); + if (p0 != p1) { + int hmultiplier = (p0.get(HORIZONTAL) == p1.get(HORIZONTAL)) ? -1 : 1; + element_type elem(edge_type(p0, p1), hmultiplier * wmultiplier); + insert_clean(elem); + } + ++vertex0; + ++vertex1; + if (vertex1 == end_vertex) { + vertex1 = begin_vertex; + } + } + } + + template + inline void get(output_container& output) const { + get_dispatch(output, typename geometry_concept::type()); + } + + // append to the container cT with polygons of three or four verticies + // slicing orientation is vertical + template + void get_trapezoids(cT& container) const { + clean(); + trapezoid_arbitrary_formation pf; + typedef typename polygon_arbitrary_formation::vertex_half_edge vertex_half_edge; + std::vector data; + for(iterator_type itr = data_.begin(); itr != data_.end(); ++itr){ + data.push_back(vertex_half_edge((*itr).first.first, (*itr).first.second, (*itr).second)); + data.push_back(vertex_half_edge((*itr).first.second, (*itr).first.first, -1 * (*itr).second)); + } + polygon_sort(data.begin(), data.end()); + pf.scan(container, data.begin(), data.end()); + //std::cout << "DONE FORMING POLYGONS\n"; + } + + // append to the container cT with polygons of three or four verticies + template + void get_trapezoids(cT& container, orientation_2d slicing_orientation) const { + if(slicing_orientation == VERTICAL) { + get_trapezoids(container); + } else { + polygon_set_data ps(*this); + ps.transform(axis_transformation(axis_transformation::SWAP_XY)); + cT result; + ps.get_trapezoids(result); + for(typename cT::iterator itr = result.begin(); itr != result.end(); ++itr) { + ::boost::polygon::transform(*itr, axis_transformation(axis_transformation::SWAP_XY)); + } + container.insert(container.end(), result.begin(), result.end()); + } + } + + // equivalence operator + inline bool operator==(const polygon_set_data& p) const; + + // inequivalence operator + inline bool operator!=(const polygon_set_data& p) const { + return !((*this) == p); + } + + // get iterator to begin vertex data + inline iterator_type begin() const { + return data_.begin(); + } + + // get iterator to end vertex data + inline iterator_type end() const { + return data_.end(); + } + + const value_type& value() const { + return data_; + } + + // clear the contents of the polygon_set_data + inline void clear() { data_.clear(); dirty_ = unsorted_ = false; } + + // find out if Polygon set is empty + inline bool empty() const { return data_.empty(); } + + // get the Polygon set size in vertices + inline std::size_t size() const { clean(); return data_.size(); } + + // get the current Polygon set capacity in vertices + inline std::size_t capacity() const { return data_.capacity(); } + + // reserve size of polygon set in vertices + inline void reserve(std::size_t size) { return data_.reserve(size); } + + // find out if Polygon set is sorted + inline bool sorted() const { return !unsorted_; } + + // find out if Polygon set is clean + inline bool dirty() const { return dirty_; } + + void clean() const; + + void sort() const{ + if(unsorted_) { + polygon_sort(data_.begin(), data_.end()); + unsorted_ = false; + } + } + + template + void set(input_iterator_type input_begin, input_iterator_type input_end) { + clear(); + reserve(std::distance(input_begin,input_end)); + insert(input_begin, input_end); + dirty_ = true; + unsorted_ = true; + } + + void set(const value_type& value) { + data_ = value; + dirty_ = true; + unsorted_ = true; + } + + template + bool extents(rectangle_type& rect) { + clean(); + if(empty()) return false; + bool first_iteration = true; + for(iterator_type itr = begin(); + itr != end(); ++itr) { + rectangle_type edge_box; + set_points(edge_box, (*itr).first.first, (*itr).first.second); + if(first_iteration) + rect = edge_box; + else + encompass(rect, edge_box); + first_iteration = false; + } + return true; + } + + inline polygon_set_data& + resize(coordinate_type resizing, bool corner_fill_arc = false, unsigned int num_circle_segments=0); + + template + inline polygon_set_data& + transform(const transform_type& tr) { + std::vector > polys; + get(polys); + clear(); + for(std::size_t i = 0 ; i < polys.size(); ++i) { + ::boost::polygon::transform(polys[i], tr); + insert(polys[i]); + } + unsorted_ = true; + dirty_ = true; + return *this; + } + + inline polygon_set_data& + scale_up(typename coordinate_traits::unsigned_area_type factor) { + for(typename value_type::iterator itr = data_.begin(); itr != data_.end(); ++itr) { + ::boost::polygon::scale_up((*itr).first.first, factor); + ::boost::polygon::scale_up((*itr).first.second, factor); + } + return *this; + } + + inline polygon_set_data& + scale_down(typename coordinate_traits::unsigned_area_type factor) { + for(typename value_type::iterator itr = data_.begin(); itr != data_.end(); ++itr) { + bool vb = (*itr).first.first.x() == (*itr).first.second.x(); + ::boost::polygon::scale_down((*itr).first.first, factor); + ::boost::polygon::scale_down((*itr).first.second, factor); + bool va = (*itr).first.first.x() == (*itr).first.second.x(); + if(!vb && va) { + (*itr).second *= -1; + } + } + unsorted_ = true; + dirty_ = true; + return *this; + } + + template + inline polygon_set_data& scale(polygon_set_data&, + const scaling_type& scaling) { + for(typename value_type::iterator itr = begin(); itr != end(); ++itr) { + bool vb = (*itr).first.first.x() == (*itr).first.second.x(); + ::boost::polygon::scale((*itr).first.first, scaling); + ::boost::polygon::scale((*itr).first.second, scaling); + bool va = (*itr).first.first.x() == (*itr).first.second.x(); + if(!vb && va) { + (*itr).second *= -1; + } + } + unsorted_ = true; + dirty_ = true; + return *this; + } + + static inline void compute_offset_edge(point_data& pt1, point_data& pt2, + const point_data& prev_pt, + const point_data& current_pt, + long double distance, int multiplier) { + long double dx = current_pt.x() - prev_pt.x(); + long double dy = current_pt.y() - prev_pt.y(); + long double edge_length = std::sqrt(dx*dx + dy*dy); + long double dnx = dy; + long double dny = -dx; + dnx = dnx * (long double)distance / edge_length; + dny = dny * (long double)distance / edge_length; + pt1.x(prev_pt.x() + (long double)dnx * (long double)multiplier); + pt2.x(current_pt.x() + (long double)dnx * (long double)multiplier); + pt1.y(prev_pt.y() + (long double)dny * (long double)multiplier); + pt2.y(current_pt.y() + (long double)dny * (long double)multiplier); + } + + static inline void modify_pt(point_data& pt, const point_data& prev_pt, + const point_data& current_pt, const point_data& next_pt, + coordinate_type distance, coordinate_type multiplier) { + std::pair, point_data > he1, he2; + he1.first.x((long double)(prev_pt.x())); + he1.first.y((long double)(prev_pt.y())); + he1.second.x((long double)(current_pt.x())); + he1.second.y((long double)(current_pt.y())); + he2.first.x((long double)(current_pt.x())); + he2.first.y((long double)(current_pt.y())); + he2.second.x((long double)(next_pt.x())); + he2.second.y((long double)(next_pt.y())); + compute_offset_edge(he1.first, he1.second, prev_pt, current_pt, distance, multiplier); + compute_offset_edge(he2.first, he2.second, current_pt, next_pt, distance, multiplier); + typedef scanline_base::compute_intersection_pack pack; + point_data rpt; + point_data bisectorpt((he1.second.x()+he2.first.x())/2, + (he1.second.y()+he2.first.y())/2); + point_data orig_pt((long double)pt.x(), (long double)pt.y()); + if(euclidean_distance(bisectorpt, orig_pt) < distance/2) { + if(!pack::compute_lazy_intersection(rpt, he1, he2, true, false)) { + rpt = he1.second; //colinear offset edges use shared point + } + } else { + if(!pack::compute_lazy_intersection(rpt, he1, std::pair, point_data >(orig_pt, bisectorpt), true, false)) { + rpt = he1.second; //colinear offset edges use shared point + } + } + pt.x((coordinate_type)(std::floor(rpt.x()+0.5))); + pt.y((coordinate_type)(std::floor(rpt.y()+0.5))); + } + + static void resize_poly_up(std::vector >& poly, coordinate_type distance, coordinate_type multiplier) { + point_data first_pt = poly[0]; + point_data second_pt = poly[1]; + point_data prev_pt = poly[0]; + point_data current_pt = poly[1]; + for(std::size_t i = 2; i < poly.size()-1; ++i) { + point_data next_pt = poly[i]; + modify_pt(poly[i-1], prev_pt, current_pt, next_pt, distance, multiplier); + prev_pt = current_pt; + current_pt = next_pt; + } + point_data next_pt = first_pt; + modify_pt(poly[poly.size()-2], prev_pt, current_pt, next_pt, distance, multiplier); + prev_pt = current_pt; + current_pt = next_pt; + next_pt = second_pt; + modify_pt(poly[0], prev_pt, current_pt, next_pt, distance, multiplier); + poly.back() = poly.front(); + } + static bool resize_poly_down(std::vector >& poly, coordinate_type distance, coordinate_type multiplier) { + std::vector > orig_poly(poly); + rectangle_data extents_rectangle; + set_points(extents_rectangle, poly[0], poly[0]); + point_data first_pt = poly[0]; + point_data second_pt = poly[1]; + point_data prev_pt = poly[0]; + point_data current_pt = poly[1]; + encompass(extents_rectangle, current_pt); + for(std::size_t i = 2; i < poly.size()-1; ++i) { + point_data next_pt = poly[i]; + encompass(extents_rectangle, next_pt); + modify_pt(poly[i-1], prev_pt, current_pt, next_pt, distance, multiplier); + prev_pt = current_pt; + current_pt = next_pt; + } + if(delta(extents_rectangle, HORIZONTAL) <= std::abs(2*distance)) + return false; + if(delta(extents_rectangle, VERTICAL) <= std::abs(2*distance)) + return false; + point_data next_pt = first_pt; + modify_pt(poly[poly.size()-2], prev_pt, current_pt, next_pt, distance, multiplier); + prev_pt = current_pt; + current_pt = next_pt; + next_pt = second_pt; + modify_pt(poly[0], prev_pt, current_pt, next_pt, distance, multiplier); + poly.back() = poly.front(); + //if the line segments formed between orignial and new points cross for an edge that edge inverts + //if all edges invert the polygon should be discarded + //if even one edge does not invert return true because the polygon is valid + bool non_inverting_edge = false; + for(std::size_t i = 1; i < poly.size(); ++i) { + std::pair, point_data > + he1(poly[i], orig_poly[i]), + he2(poly[i-1], orig_poly[i-1]); + if(!scanline_base::intersects(he1, he2)) { + non_inverting_edge = true; + break; + } + } + return non_inverting_edge; + } + + polygon_set_data& + bloat(typename coordinate_traits::unsigned_area_type distance) { + std::list > polys; + get(polys); + clear(); + for(typename std::list >::iterator itr = polys.begin(); + itr != polys.end(); ++itr) { + resize_poly_up((*itr).self_.coords_, (coordinate_type)distance, (coordinate_type)1); + insert_vertex_sequence((*itr).self_.begin(), (*itr).self_.end(), COUNTERCLOCKWISE, false); //inserts without holes + for(typename std::list >::iterator itrh = (*itr).holes_.begin(); + itrh != (*itr).holes_.end(); ++itrh) { + if(resize_poly_down((*itrh).coords_, (coordinate_type)distance, (coordinate_type)1)) { + insert_vertex_sequence((*itrh).coords_.begin(), (*itrh).coords_.end(), CLOCKWISE, true); + } + } + } + return *this; + } + + polygon_set_data& + shrink(typename coordinate_traits::unsigned_area_type distance) { + std::list > polys; + get(polys); + clear(); + for(typename std::list >::iterator itr = polys.begin(); + itr != polys.end(); ++itr) { + if(resize_poly_down((*itr).self_.coords_, (coordinate_type)distance, (coordinate_type)-1)) { + insert_vertex_sequence((*itr).self_.begin(), (*itr).self_.end(), COUNTERCLOCKWISE, false); //inserts without holes + for(typename std::list >::iterator itrh = (*itr).holes_.begin(); + itrh != (*itr).holes_.end(); ++itrh) { + resize_poly_up((*itrh).coords_, (coordinate_type)distance, (coordinate_type)-1); + insert_vertex_sequence((*itrh).coords_.begin(), (*itrh).coords_.end(), CLOCKWISE, true); + } + } + } + return *this; + } + + // TODO:: should be private + template + inline polygon_set_data& + insert_with_resize(const geometry_type& poly, coordinate_type resizing, bool corner_fill_arc=false, unsigned int num_circle_segments=0, bool hole = false) { + return insert_with_resize_dispatch(poly, resizing, corner_fill_arc, num_circle_segments, hole, typename geometry_concept::type()); + } + + template + inline polygon_set_data& + insert_with_resize_dispatch(const geometry_type& poly, coordinate_type resizing, bool corner_fill_arc, unsigned int num_circle_segments, bool hole, + polygon_with_holes_concept) { + insert_with_resize_dispatch(poly, resizing, corner_fill_arc, num_circle_segments, hole, polygon_concept()); + for(typename polygon_with_holes_traits::iterator_holes_type itr = + begin_holes(poly); itr != end_holes(poly); + ++itr) { + insert_with_resize_dispatch(*itr, resizing, corner_fill_arc, num_circle_segments, !hole, polygon_concept()); + } + return *this; + } + + template + inline polygon_set_data& + insert_with_resize_dispatch(const geometry_type& poly, coordinate_type resizing, bool corner_fill_arc, unsigned int num_circle_segments, bool hole, + polygon_concept) { + + if (resizing==0) + return *this; + + + // one dimensional used to store CCW/CW flag + //direction_1d wdir = winding(poly); + // LOW==CLOCKWISE just faster to type + // so > 0 is CCW + //int multiplier = wdir == LOW ? -1 : 1; + //std::cout<<" multiplier : "<0?COUNTERCLOCKWISE:CLOCKWISE; + + typedef typename polygon_data::iterator_type piterator; + piterator first, second, third, end, real_end; + real_end = end_points(poly); + third = begin_points(poly); + first = third; + if(first == real_end) return *this; + ++third; + if(third == real_end) return *this; + second = end = third; + ++third; + if(third == real_end) return *this; + + // for 1st corner + std::vector > first_pts; + std::vector > all_pts; + direction_1d first_wdir = CLOCKWISE; + + // for all corners + polygon_set_data sizingSet; + bool sizing_sign = resizing<0; + bool prev_concave = true; + point_data prev_point; + //int iCtr=0; + + + //insert minkofski shapes on edges and corners + do { // REAL WORK IS HERE + + + //first, second and third point to points in correct CCW order + // check if convex or concave case + point_data normal1( second->y()-first->y(), first->x()-second->x()); + point_data normal2( third->y()-second->y(), second->x()-third->x()); + double direction = normal1.x()*normal2.y()- normal2.x()*normal1.y(); + bool convex = direction>0; + + bool treat_as_concave = !convex; + if(sizing_sign) + treat_as_concave = convex; + point_data v; + assign(v, normal1); + double s2 = (v.x()*v.x()+v.y()*v.y()); + double s = std::sqrt(s2)/resizing; + v = point_data(v.x()/s,v.y()/s); + point_data curr_prev; + if (prev_concave) + //TODO missing round_down() + curr_prev = point_data(first->x()+v.x(),first->y()+v.y()); + else + curr_prev = prev_point; + + // around concave corners - insert rectangle + // if previous corner is concave it's point info may be ignored + if ( treat_as_concave) { + std::vector > pts; + + pts.push_back(point_data(second->x()+v.x(),second->y()+v.y())); + pts.push_back(*second); + pts.push_back(*first); + pts.push_back(point_data(curr_prev)); + if (first_pts.size()){ + sizingSet.insert_vertex_sequence(pts.begin(),pts.end(), resize_wdir,false); + }else { + first_pts=pts; + first_wdir = resize_wdir; + } + } else { + + // add either intersection_quad or pie_shape, based on corner_fill_arc option + // for convex corner (convexity depends on sign of resizing, whether we shrink or grow) + std::vector< std::vector > > pts; + direction_1d winding; + winding = convex?COUNTERCLOCKWISE:CLOCKWISE; + if (make_resizing_vertex_list(pts, curr_prev, prev_concave, *first, *second, *third, resizing + , num_circle_segments, corner_fill_arc)) + { + if (first_pts.size()) { + for (int i=0; i tmp; + + //insert original shape + tmp.insert(poly, false, polygon_concept()); + if((resizing < 0) ^ hole) tmp -= sizingSet; + else tmp += sizingSet; + //tmp.clean(); + insert(tmp, hole); + return (*this); + } + + + inline polygon_set_data& + interact(const polygon_set_data& that); + + inline bool downcast(polygon_45_set_data& result) const { + if(!is_45_) return false; + for(iterator_type itr = begin(); itr != end(); ++itr) { + const element_type& elem = *itr; + int count = elem.second; + int rise = 1; //up sloping 45 + if(scanline_base::is_horizontal(elem.first)) rise = 0; + else if(scanline_base::is_vertical(elem.first)) rise = 2; + else { + if(!scanline_base::is_45_degree(elem.first)) { + is_45_ = false; + return false; //consider throwing because is_45_ has be be wrong + } + if(elem.first.first.y() > elem.first.second.y()) rise = -1; //down sloping 45 + } + typename polygon_45_set_data::Vertex45Compact vertex(elem.first.first, rise, count); + result.insert(vertex); + typename polygon_45_set_data::Vertex45Compact vertex2(elem.first.second, rise, -count); + result.insert(vertex2); + } + return true; + } + + inline GEOMETRY_CONCEPT_ID concept_downcast() const { + typedef typename coordinate_traits::coordinate_difference delta_type; + bool is_45 = false; + for(iterator_type itr = begin(); itr != end(); ++itr) { + const element_type& elem = *itr; + delta_type h_delta = euclidean_distance(elem.first.first, elem.first.second, HORIZONTAL); + delta_type v_delta = euclidean_distance(elem.first.first, elem.first.second, VERTICAL); + if(h_delta != 0 || v_delta != 0) { + //neither delta is zero and the edge is not MANHATTAN + if(v_delta != h_delta && v_delta != -h_delta) return POLYGON_SET_CONCEPT; + else is_45 = true; + } + } + if(is_45) return POLYGON_45_SET_CONCEPT; + return POLYGON_90_SET_CONCEPT; + } + + private: + mutable value_type data_; + mutable bool dirty_; + mutable bool unsorted_; + mutable bool is_45_; + + private: + //functions + + template + void get_dispatch(output_container& output, polygon_concept tag) const { + get_fracture(output, true, tag); + } + template + void get_dispatch(output_container& output, polygon_with_holes_concept tag) const { + get_fracture(output, false, tag); + } + template + void get_fracture(output_container& container, bool fracture_holes, concept_type ) const { + clean(); + polygon_arbitrary_formation pf(fracture_holes); + typedef typename polygon_arbitrary_formation::vertex_half_edge vertex_half_edge; + std::vector data; + for(iterator_type itr = data_.begin(); itr != data_.end(); ++itr){ + data.push_back(vertex_half_edge((*itr).first.first, (*itr).first.second, (*itr).second)); + data.push_back(vertex_half_edge((*itr).first.second, (*itr).first.first, -1 * (*itr).second)); + } + polygon_sort(data.begin(), data.end()); + pf.scan(container, data.begin(), data.end()); + } + }; + + struct polygon_set_concept; + template + struct geometry_concept > { + typedef polygon_set_concept type; + }; + +// template +// inline double compute_area(point_data& a, point_data& b, point_data& c) { + +// return (double)(b.x()-a.x())*(double)(c.y()-a.y())- (double)(c.x()-a.x())*(double)(b.y()-a.y()); + + +// } + + template + inline int make_resizing_vertex_list(std::vector > >& return_points, + point_data& curr_prev, bool ignore_prev_point, + point_data< T> start, point_data middle, point_data< T> end, + double sizing_distance, unsigned int num_circle_segments, bool corner_fill_arc) { + + // handle the case of adding an intersection point + point_data dn1( middle.y()-start.y(), start.x()-middle.x()); + double size = sizing_distance/std::sqrt( dn1.x()*dn1.x()+dn1.y()*dn1.y()); + dn1 = point_data( dn1.x()*size, dn1.y()* size); + point_data dn2( end.y()-middle.y(), middle.x()-end.x()); + size = sizing_distance/std::sqrt( dn2.x()*dn2.x()+dn2.y()*dn2.y()); + dn2 = point_data( dn2.x()*size, dn2.y()* size); + point_data start_offset((start.x()+dn1.x()),(start.y()+dn1.y())); + point_data mid1_offset((middle.x()+dn1.x()),(middle.y()+dn1.y())); + point_data end_offset((end.x()+dn2.x()),(end.y()+dn2.y())); + point_data mid2_offset((middle.x()+dn2.x()),(middle.y()+dn2.y())); + if (ignore_prev_point) + curr_prev = round_down(start_offset); + + + if (corner_fill_arc) { + std::vector > return_points1; + return_points.push_back(return_points1); + std::vector >& return_points_back = return_points[return_points.size()-1]; + return_points_back.push_back(round_down(mid1_offset)); + return_points_back.push_back(middle); + return_points_back.push_back(start); + return_points_back.push_back(curr_prev); + point_data dmid(middle.x(),middle.y()); + return_points.push_back(return_points1); + int num = make_arc(return_points[return_points.size()-1],mid1_offset,mid2_offset,dmid,sizing_distance,num_circle_segments); + curr_prev = round_down(mid2_offset); + return num; + + } + + std::pair,point_data > he1(start_offset,mid1_offset); + std::pair,point_data > he2(mid2_offset ,end_offset); + //typedef typename high_precision_type::type high_precision; + + point_data intersect; + typename scanline_base::compute_intersection_pack pack; + bool res = pack.compute_intersection(intersect,he1,he2,true); + if( res ) { + std::vector > return_points1; + return_points.push_back(return_points1); + std::vector >& return_points_back = return_points[return_points.size()-1]; + return_points_back.push_back(intersect); + return_points_back.push_back(middle); + return_points_back.push_back(start); + return_points_back.push_back(curr_prev); + + //double d1= compute_area(intersect,middle,start); + //double d2= compute_area(start,curr_prev,intersect); + + curr_prev = intersect; + + + return return_points.size(); + } + return 0; + + } + + // this routine should take in start and end point s.t. end point is CCW from start + // it sould make a pie slice polygon that is an intersection of that arc + // with an ngon segments approximation of the circle centered at center with radius r + // point start is gauaranteed to be on the segmentation + // returnPoints will start with the first point after start + // returnPoints vector may be empty + template + inline int make_arc(std::vector >& return_points, + point_data< double> start, point_data< double> end, + point_data< double> center, double r, unsigned int num_circle_segments) { + const double our_pi=3.1415926535897932384626433832795028841971; + + // derive start and end angles + double ps = atan2(start.y()-center.y(), start.x()-center.x()); + double pe = atan2(end.y()-center.y(), end.x()-center.x()); + if (ps < 0.0) + ps += 2.0 * our_pi; + if (pe <= 0.0) + pe += 2.0 * our_pi; + if (ps >= 2.0 * our_pi) + ps -= 2.0 * our_pi; + while (pe <= ps) + pe += 2.0 * our_pi; + double delta_angle = (2.0 * our_pi) / (double)num_circle_segments; + if ( start==end) // full circle? + { + ps = delta_angle*0.5; + pe = ps + our_pi * 2.0; + double x,y; + x = center.x() + r * cos(ps); + y = center.y() + r * sin(ps); + start = point_data(x,y); + end = start; + } + return_points.push_back(round_down(center)); + return_points.push_back(round_down(start)); + unsigned int i=0; + double curr_angle = ps+delta_angle; + while( curr_angle < pe - 0.01 && i < 2 * num_circle_segments) { + i++; + double x = center.x() + r * cos( curr_angle); + double y = center.y() + r * sin( curr_angle); + return_points.push_back( round_down((point_data(x,y)))); + curr_angle+=delta_angle; + } + return_points.push_back(round_down(end)); + return return_points.size(); + } + +}// close namespace +}// close name space + +#include "detail/scan_arbitrary.hpp" + +namespace boost { namespace polygon { + //ConnectivityExtraction computes the graph of connectivity between rectangle, polygon and + //polygon set graph nodes where an edge is created whenever the geometry in two nodes overlap + template + class connectivity_extraction{ + private: + typedef arbitrary_connectivity_extraction ce; + ce ce_; + unsigned int nodeCount_; + public: + inline connectivity_extraction() : ce_(), nodeCount_(0) {} + inline connectivity_extraction(const connectivity_extraction& that) : ce_(that.ce_), + nodeCount_(that.nodeCount_) {} + inline connectivity_extraction& operator=(const connectivity_extraction& that) { + ce_ = that.ce_; + nodeCount_ = that.nodeCount_; {} + return *this; + } + + //insert a polygon set graph node, the value returned is the id of the graph node + inline unsigned int insert(const polygon_set_data& ps) { + ps.clean(); + ce_.populateTouchSetData(ps.begin(), ps.end(), nodeCount_); + return nodeCount_++; + } + template + inline unsigned int insert(const GeoObjT& geoObj) { + polygon_set_data ps; + ps.insert(geoObj); + return insert(ps); + } + + //extract connectivity and store the edges in the graph + //graph must be indexable by graph node id and the indexed value must be a std::set of + //graph node id + template + inline void extract(GraphT& graph) { + ce_.execute(graph); + } + }; + + template + polygon_set_data& + polygon_set_data::interact(const polygon_set_data& that) { + connectivity_extraction ce; + std::vector > polys; + get(polys); + clear(); + for(std::size_t i = 0; i < polys.size(); ++i) { + ce.insert(polys[i]); + } + int id = ce.insert(that); + std::vector > graph(id+1); + ce.extract(graph); + for(std::set::iterator itr = graph[id].begin(); + itr != graph[id].end(); ++itr) { + insert(polys[*itr]); + } + return *this; + } +} +} + +#include "polygon_set_traits.hpp" +#include "detail/polygon_set_view.hpp" + +#include "polygon_set_concept.hpp" +#include "detail/minkowski.hpp" +#endif diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/polygon_set_traits.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/polygon_set_traits.hpp new file mode 100644 index 0000000..b68bbc1 --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/polygon_set_traits.hpp @@ -0,0 +1,133 @@ +/* + Copyright 2008 Intel Corporation + + Use, modification and distribution are subject to the Boost Software License, + Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at + http://www.boost.org/LICENSE_1_0.txt). +*/ +#ifndef BOOST_POLYGON_POLYGON_SET_TRAITS_HPP +#define BOOST_POLYGON_POLYGON_SET_TRAITS_HPP +namespace boost { namespace polygon{ + + struct polygon_set_concept {}; + + //default definition of polygon set traits works for any model of polygon , polygon with holes or any vector or list thereof + template + struct polygon_set_traits { + typedef typename get_coordinate_type::type >::type coordinate_type; + typedef typename get_iterator_type::type iterator_type; + typedef T operator_arg_type; + + static inline iterator_type begin(const T& polygon_set) { + return get_iterator_type::begin(polygon_set); + } + + static inline iterator_type end(const T& polygon_set) { + return get_iterator_type::end(polygon_set); + } + + static inline bool clean(const T& ) { return false; } + + static inline bool sorted(const T& ) { return false; } + }; + + template + struct is_polygonal_concept { typedef gtl_no type; }; + template <> + struct is_polygonal_concept { typedef gtl_yes type; }; + template <> + struct is_polygonal_concept { typedef gtl_yes type; }; + template <> + struct is_polygonal_concept { typedef gtl_yes type; }; + + template + struct is_polygon_set_type { + typedef typename is_polygonal_concept::type>::type type; + }; + template + struct is_polygon_set_type > { + typedef typename gtl_or< + typename is_polygonal_concept >::type>::type, + typename is_polygonal_concept::value_type>::type>::type>::type type; + }; + template + struct is_polygon_set_type > { + typedef typename gtl_or< + typename is_polygonal_concept >::type>::type, + typename is_polygonal_concept::value_type>::type>::type>::type type; + }; + + template + struct is_mutable_polygon_set_type { + typedef typename gtl_same_type::type>::type type; + }; + template + struct is_mutable_polygon_set_type > { + typedef typename gtl_or< + typename gtl_same_type >::type>::type, + typename is_polygonal_concept::value_type>::type>::type>::type type; + }; + template + struct is_mutable_polygon_set_type > { + typedef typename gtl_or< + typename gtl_same_type >::type>::type, + typename is_polygonal_concept::value_type>::type>::type>::type type; + }; + + template + struct polygon_set_mutable_traits {}; + template + struct polygon_set_mutable_traits > { + template + static inline void set(std::list& polygon_set, input_iterator_type input_begin, input_iterator_type input_end) { + polygon_set.clear(); + polygon_set_data >::coordinate_type> ps; + ps.reserve(std::distance(input_begin, input_end)); + ps.insert(input_begin, input_end); + ps.get(polygon_set); + } + }; + template + struct polygon_set_mutable_traits > { + template + static inline void set(std::vector& polygon_set, input_iterator_type input_begin, input_iterator_type input_end) { + polygon_set.clear(); + size_t num_ele = std::distance(input_begin, input_end); + polygon_set.reserve(num_ele); + polygon_set_data >::coordinate_type> ps; + ps.reserve(num_ele); + ps.insert(input_begin, input_end); + ps.get(polygon_set); + } + }; + + template + struct polygon_set_mutable_traits > { + template + static inline void set(polygon_set_data& polygon_set, + input_iterator_type input_begin, input_iterator_type input_end) { + polygon_set.set(input_begin, input_end); + } + }; + template + struct polygon_set_traits > { + typedef typename polygon_set_data::coordinate_type coordinate_type; + typedef typename polygon_set_data::iterator_type iterator_type; + typedef typename polygon_set_data::operator_arg_type operator_arg_type; + + static inline iterator_type begin(const polygon_set_data& polygon_set) { + return polygon_set.begin(); + } + + static inline iterator_type end(const polygon_set_data& polygon_set) { + return polygon_set.end(); + } + + static inline bool clean(const polygon_set_data& polygon_set) { polygon_set.clean(); return true; } + + static inline bool sorted(const polygon_set_data& polygon_set) { polygon_set.sort(); return true; } + + }; +} +} +#endif diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/polygon_traits.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/polygon_traits.hpp new file mode 100644 index 0000000..e3d1859 --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/polygon_traits.hpp @@ -0,0 +1,1861 @@ +/* + Copyright 2008 Intel Corporation + + Use, modification and distribution are subject to the Boost Software License, + Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at + http://www.boost.org/LICENSE_1_0.txt). +*/ +#ifndef BOOST_POLYGON_POLYGON_TRAITS_HPP +#define BOOST_POLYGON_POLYGON_TRAITS_HPP +namespace boost { namespace polygon{ + + template + struct polygon_90_traits { + typedef typename T::coordinate_type coordinate_type; + typedef typename T::compact_iterator_type compact_iterator_type; + + // Get the begin iterator + static inline compact_iterator_type begin_compact(const T& t) { + return t.begin_compact(); + } + + // Get the end iterator + static inline compact_iterator_type end_compact(const T& t) { + return t.end_compact(); + } + + // Get the number of sides of the polygon + static inline std::size_t size(const T& t) { + return t.size(); + } + + // Get the winding direction of the polygon + static inline winding_direction winding(const T&) { + return unknown_winding; + } + }; + + template + struct polygon_traits_general { + typedef typename T::coordinate_type coordinate_type; + typedef typename T::iterator_type iterator_type; + typedef typename T::point_type point_type; + + // Get the begin iterator + static inline iterator_type begin_points(const T& t) { + return t.begin(); + } + + // Get the end iterator + static inline iterator_type end_points(const T& t) { + return t.end(); + } + + // Get the number of sides of the polygon + static inline std::size_t size(const T& t) { + return t.size(); + } + + // Get the winding direction of the polygon + static inline winding_direction winding(const T&) { + return unknown_winding; + } + }; + + template + struct polygon_traits_90 { + typedef typename polygon_90_traits::coordinate_type coordinate_type; + typedef iterator_compact_to_points::compact_iterator_type, point_data > iterator_type; + typedef point_data point_type; + + // Get the begin iterator + static inline iterator_type begin_points(const T& t) { + return iterator_type(polygon_90_traits::begin_compact(t), + polygon_90_traits::end_compact(t)); + } + + // Get the end iterator + static inline iterator_type end_points(const T& t) { + return iterator_type(polygon_90_traits::end_compact(t), + polygon_90_traits::end_compact(t)); + } + + // Get the number of sides of the polygon + static inline std::size_t size(const T& t) { + return polygon_90_traits::size(t); + } + + // Get the winding direction of the polygon + static inline winding_direction winding(const T& t) { + return polygon_90_traits::winding(t); + } + }; + +#ifndef BOOST_VERY_LITTLE_SFINAE + + template + struct polygon_traits {}; + + template + struct polygon_traits::type, polygon_concept>::type, + typename gtl_same_type::type, polygon_45_concept>::type, + typename gtl_same_type::type, polygon_with_holes_concept>::type, + typename gtl_same_type::type, polygon_45_with_holes_concept>::type + >::type> : public polygon_traits_general {}; + + template + struct polygon_traits< T, + typename gtl_or< + typename gtl_same_type::type, polygon_90_concept>::type, + typename gtl_same_type::type, polygon_90_with_holes_concept>::type + >::type > : public polygon_traits_90 {}; + +#else + + template + struct gtl_ifelse {}; + template + struct gtl_ifelse { + typedef T_ELSE type; + }; + template + struct gtl_ifelse { + typedef T_IF type; + }; + + template + struct polygon_traits {}; + + template + struct polygon_traits::type, polygon_concept>::type, + typename gtl_same_type::type, polygon_45_concept>::type, + typename gtl_same_type::type, polygon_with_holes_concept>::type, + typename gtl_same_type::type, polygon_45_with_holes_concept>::type + >::type, typename gtl_or< + typename gtl_same_type::type, polygon_90_concept>::type, + typename gtl_same_type::type, polygon_90_with_holes_concept>::type + >::type>::type > : public gtl_ifelse::type, polygon_90_concept>::type, + typename gtl_same_type::type, polygon_90_with_holes_concept>::type >::type, + polygon_traits_90, + polygon_traits_general >::type { + }; + +#endif + + template + struct polygon_with_holes_traits { + typedef typename T::iterator_holes_type iterator_holes_type; + typedef typename T::hole_type hole_type; + + // Get the begin iterator + static inline iterator_holes_type begin_holes(const T& t) { + return t.begin_holes(); + } + + // Get the end iterator + static inline iterator_holes_type end_holes(const T& t) { + return t.end_holes(); + } + + // Get the number of holes + static inline std::size_t size_holes(const T& t) { + return t.size_holes(); + } + }; + + template + struct polygon_90_mutable_traits { + + // Set the data of a polygon with the unique coordinates in an iterator, starting with an x + template + static inline T& set_compact(T& t, iT input_begin, iT input_end) { + t.set_compact(input_begin, input_end); + return t; + } + + }; + + template + struct polygon_mutable_traits { + + // Set the data of a polygon with the unique coordinates in an iterator, starting with an x + template + static inline T& set_points(T& t, iT input_begin, iT input_end) { + t.set(input_begin, input_end); + return t; + } + + }; + + template + struct polygon_with_holes_mutable_traits { + + // Set the data of a polygon with the unique coordinates in an iterator, starting with an x + template + static inline T& set_holes(T& t, iT inputBegin, iT inputEnd) { + t.set_holes(inputBegin, inputEnd); + return t; + } + + }; +} +} +#include "isotropy.hpp" + +//point +#include "point_data.hpp" +#include "point_traits.hpp" +#include "point_concept.hpp" + +//interval +#include "interval_data.hpp" +#include "interval_traits.hpp" +#include "interval_concept.hpp" + +//rectangle +#include "rectangle_data.hpp" +#include "rectangle_traits.hpp" +#include "rectangle_concept.hpp" + +//algorithms needed by polygon types +#include "detail/iterator_points_to_compact.hpp" +#include "detail/iterator_compact_to_points.hpp" + +//polygons +#include "polygon_45_data.hpp" +#include "polygon_data.hpp" +#include "polygon_90_data.hpp" +#include "polygon_90_with_holes_data.hpp" +#include "polygon_45_with_holes_data.hpp" +#include "polygon_with_holes_data.hpp" + +namespace boost { namespace polygon{ + struct polygon_concept {}; + struct polygon_with_holes_concept {}; + struct polygon_45_concept {}; + struct polygon_45_with_holes_concept {}; + struct polygon_90_concept {}; + struct polygon_90_with_holes_concept {}; + + + template + struct is_polygon_90_type { + typedef typename geometry_concept::type GC; + typedef typename gtl_same_type::type type; + }; + + template + struct is_polygon_45_type { + typedef typename geometry_concept::type GC; + typedef typename gtl_or::type, + typename gtl_same_type::type>::type type; + }; + + template + struct is_polygon_type { + typedef typename geometry_concept::type GC; + typedef typename gtl_or::type, + typename gtl_same_type::type>::type type; + }; + + template + struct is_polygon_90_with_holes_type { + typedef typename geometry_concept::type GC; + typedef typename gtl_or::type, + typename gtl_same_type::type>::type type; + }; + + template + struct is_polygon_45_with_holes_type { + typedef typename geometry_concept::type GC; + typedef typename gtl_or_3::type, + typename is_polygon_45_type::type, + typename gtl_same_type::type>::type type; + }; + + template + struct is_polygon_with_holes_type { + typedef typename geometry_concept::type GC; + typedef typename gtl_or_3::type, + typename is_polygon_type::type, + typename gtl_same_type::type>::type type; + }; + + template + struct is_mutable_polygon_90_type { + typedef typename geometry_concept::type GC; + typedef typename gtl_same_type::type type; + }; + + template + struct is_mutable_polygon_45_type { + typedef typename geometry_concept::type GC; + typedef typename gtl_same_type::type type; + }; + + template + struct is_mutable_polygon_type { + typedef typename geometry_concept::type GC; + typedef typename gtl_same_type::type type; + }; + + template + struct is_mutable_polygon_90_with_holes_type { + typedef typename geometry_concept::type GC; + typedef typename gtl_same_type::type type; + }; + + template + struct is_mutable_polygon_45_with_holes_type { + typedef typename geometry_concept::type GC; + typedef typename gtl_same_type::type type; + }; + + template + struct is_mutable_polygon_with_holes_type { + typedef typename geometry_concept::type GC; + typedef typename gtl_same_type::type type; + }; + + template + struct is_any_mutable_polygon_with_holes_type { + typedef typename gtl_or_3::type, + typename is_mutable_polygon_45_with_holes_type::type, + typename is_mutable_polygon_with_holes_type::type>::type type; + }; + template + struct is_any_mutable_polygon_without_holes_type { + typedef typename gtl_or_3< + typename is_mutable_polygon_90_type::type, + typename is_mutable_polygon_45_type::type, + typename is_mutable_polygon_type::type>::type type; }; + + template + struct is_any_mutable_polygon_type { + typedef typename gtl_or::type, + typename is_any_mutable_polygon_without_holes_type::type>::type type; + }; + + template + struct polygon_from_polygon_with_holes_type {}; + template <> + struct polygon_from_polygon_with_holes_type { typedef polygon_concept type; }; + template <> + struct polygon_from_polygon_with_holes_type { typedef polygon_45_concept type; }; + template <> + struct polygon_from_polygon_with_holes_type { typedef polygon_90_concept type; }; + + template <> + struct geometry_domain { typedef forty_five_domain type; }; + template <> + struct geometry_domain { typedef forty_five_domain type; }; + template <> + struct geometry_domain { typedef manhattan_domain type; }; + template <> + struct geometry_domain { typedef manhattan_domain type; }; + + template + struct distance_type_by_domain { typedef typename coordinate_traits::coordinate_distance type; }; + template + struct distance_type_by_domain { + typedef typename coordinate_traits::coordinate_difference type; }; + + // \brief Sets the boundary of the polygon to the points in the iterator range + // \tparam T A type that models polygon_concept + // \tparam iT Iterator type over objects that model point_concept + // \param t The polygon to set + // \param begin_points The start of the range of points + // \param end_points The end of the range of points + + /// \relatesalso polygon_concept + template + typename enable_if ::type, T>::type & + set_points(T& t, iT begin_points, iT end_points) { + polygon_mutable_traits::set_points(t, begin_points, end_points); + return t; + } + + // \brief Sets the boundary of the polygon to the non-redundant coordinates in the iterator range + // \tparam T A type that models polygon_90_concept + // \tparam iT Iterator type over objects that model coordinate_concept + // \param t The polygon to set + // \param begin_compact_coordinates The start of the range of coordinates + // \param end_compact_coordinates The end of the range of coordinates + +/// \relatesalso polygon_90_concept + template + typename enable_if ::type, + typename is_mutable_polygon_90_with_holes_type::type>::type, T>::type & + set_compact(T& t, iT begin_compact_coordinates, iT end_compact_coordinates) { + polygon_90_mutable_traits::set_compact(t, begin_compact_coordinates, end_compact_coordinates); + return t; + } + +/// \relatesalso polygon_with_holes_concept + template + typename enable_if< typename gtl_and < + typename is_any_mutable_polygon_with_holes_type::type, + typename gtl_different_type::type>::type, + manhattan_domain>::type>::type, + T>::type & + set_compact(T& t, iT begin_compact_coordinates, iT end_compact_coordinates) { + iterator_compact_to_points::coordinate_type> > + itrb(begin_compact_coordinates, end_compact_coordinates), + itre(end_compact_coordinates, end_compact_coordinates); + return set_points(t, itrb, itre); + } + +/// \relatesalso polygon_with_holes_concept + template + typename enable_if ::type, T>::type & + set_holes(T& t, iT begin_holes, iT end_holes) { + polygon_with_holes_mutable_traits::set_holes(t, begin_holes, end_holes); + return t; + } + +/// \relatesalso polygon_90_concept + template + typename polygon_90_traits::compact_iterator_type + begin_compact(const T& polygon, + typename enable_if< + typename gtl_and ::type, + typename gtl_same_type::type>::type, + manhattan_domain>::type>::type>::type * = 0 + ) { + return polygon_90_traits::begin_compact(polygon); + } + +/// \relatesalso polygon_90_concept + template + typename polygon_90_traits::compact_iterator_type + end_compact(const T& polygon, + typename enable_if< + typename gtl_and ::type, + typename gtl_same_type::type>::type, + manhattan_domain>::type>::type>::type * = 0 + ) { + return polygon_90_traits::end_compact(polygon); + } + + /// \relatesalso polygon_concept + template + typename enable_if < typename gtl_if< + typename is_polygon_with_holes_type::type>::type, + typename polygon_traits::iterator_type>::type + begin_points(const T& polygon) { + return polygon_traits::begin_points(polygon); + } + + /// \relatesalso polygon_concept + template + typename enable_if < typename gtl_if< + typename is_polygon_with_holes_type::type>::type, + typename polygon_traits::iterator_type>::type + end_points(const T& polygon) { + return polygon_traits::end_points(polygon); + } + + /// \relatesalso polygon_concept + template + typename enable_if ::type, + std::size_t>::type + size(const T& polygon) { + return polygon_traits::size(polygon); + } + +/// \relatesalso polygon_with_holes_concept + template + typename enable_if < typename gtl_if< + typename is_polygon_with_holes_type::type>::type, + typename polygon_with_holes_traits::iterator_holes_type>::type + begin_holes(const T& polygon) { + return polygon_with_holes_traits::begin_holes(polygon); + } + +/// \relatesalso polygon_with_holes_concept + template + typename enable_if < typename gtl_if< + typename is_polygon_with_holes_type::type>::type, + typename polygon_with_holes_traits::iterator_holes_type>::type + end_holes(const T& polygon) { + return polygon_with_holes_traits::end_holes(polygon); + } + +/// \relatesalso polygon_with_holes_concept + template + typename enable_if ::type, + std::size_t>::type + size_holes(const T& polygon) { + return polygon_with_holes_traits::size_holes(polygon); + } + + // \relatesalso polygon_concept + template + typename enable_if< + typename gtl_and< typename is_mutable_polygon_type::type, + typename is_polygon_type::type>::type, T1>::type & + assign(T1& lvalue, const T2& rvalue) { + polygon_mutable_traits::set_points(lvalue, polygon_traits::begin_points(rvalue), + polygon_traits::end_points(rvalue)); + return lvalue; + } + +// \relatesalso polygon_with_holes_concept + template + typename enable_if< + typename gtl_and< typename is_mutable_polygon_with_holes_type::type, + typename is_polygon_with_holes_type::type>::type, T1>::type & + assign(T1& lvalue, const T2& rvalue) { + polygon_mutable_traits::set_points(lvalue, polygon_traits::begin_points(rvalue), + polygon_traits::end_points(rvalue)); + polygon_with_holes_mutable_traits::set_holes(lvalue, polygon_with_holes_traits::begin_holes(rvalue), + polygon_with_holes_traits::end_holes(rvalue)); + return lvalue; + } + + // \relatesalso polygon_45_concept + template + typename enable_if< typename gtl_and< typename is_mutable_polygon_45_type::type, typename is_polygon_45_type::type>::type, T1>::type & + assign(T1& lvalue, const T2& rvalue) { + polygon_mutable_traits::set_points(lvalue, polygon_traits::begin_points(rvalue), + polygon_traits::end_points(rvalue)); + return lvalue; + } + +// \relatesalso polygon_45_with_holes_concept + template + typename enable_if< + typename gtl_and< typename is_mutable_polygon_45_with_holes_type::type, + typename is_polygon_45_with_holes_type::type>::type, T1>::type & + assign(T1& lvalue, const T2& rvalue) { + polygon_mutable_traits::set_points(lvalue, polygon_traits::begin_points(rvalue), + polygon_traits::end_points(rvalue)); + polygon_with_holes_mutable_traits::set_holes(lvalue, polygon_with_holes_traits::begin_holes(rvalue), + polygon_with_holes_traits::end_holes(rvalue)); + return lvalue; + } + + // \relatesalso polygon_90_concept + template + typename enable_if< + typename gtl_and< typename is_mutable_polygon_90_type::type, + typename is_polygon_90_type::type>::type, T1>::type & + assign(T1& lvalue, const T2& rvalue) { + polygon_90_mutable_traits::set_compact(lvalue, polygon_90_traits::begin_compact(rvalue), + polygon_90_traits::end_compact(rvalue)); + return lvalue; + } + +// \relatesalso polygon_90_with_holes_concept + template + typename enable_if< + typename gtl_and< typename is_mutable_polygon_90_with_holes_type::type, + typename is_polygon_90_with_holes_type::type>::type, T1>::type & + assign(T1& lvalue, const T2& rvalue) { + polygon_90_mutable_traits::set_compact(lvalue, polygon_90_traits::begin_compact(rvalue), + polygon_90_traits::end_compact(rvalue)); + polygon_with_holes_mutable_traits::set_holes(lvalue, polygon_with_holes_traits::begin_holes(rvalue), + polygon_with_holes_traits::end_holes(rvalue)); + return lvalue; + } + + // \relatesalso polygon_90_concept + template + typename enable_if< + typename gtl_and< typename is_any_mutable_polygon_type::type, + typename is_rectangle_concept::type>::type>::type, T1>::type & + assign(T1& polygon, const T2& rect) { + typedef point_data::coordinate_type> PT; + PT points[4] = {PT(xl(rect), yl(rect)), PT(xh(rect), yl(rect)), PT(xh(rect), yh(rect)), PT(xl(rect), yh(rect))}; + set_points(polygon, points, points+4); + return polygon; + } + +/// \relatesalso polygon_90_concept + template + typename enable_if< typename gtl_and< typename is_mutable_polygon_90_type::type, + typename is_point_concept::type>::type>::type, + polygon_type>::type & + convolve(polygon_type& polygon, const point_type& point) { + std::vector::coordinate_type> coords; + coords.reserve(::boost::polygon::size(polygon)); + bool pingpong = true; + for(typename polygon_90_traits::compact_iterator_type iter = begin_compact(polygon); + iter != end_compact(polygon); ++iter) { + coords.push_back((*iter) + (pingpong ? x(point) : y(point))); + pingpong = !pingpong; + } + polygon_90_mutable_traits::set_compact(polygon, coords.begin(), coords.end()); + return polygon; + } + +/// \relatesalso polygon_concept + template + typename enable_if< typename gtl_and< typename gtl_or< + typename is_mutable_polygon_45_type::type, + typename is_mutable_polygon_type::type>::type, + typename is_point_concept::type>::type>::type, + polygon_type>::type & + convolve(polygon_type& polygon, const point_type& point) { + std::vector::iterator_type>::value_type> points; + points.reserve(::boost::polygon::size(polygon)); + for(typename polygon_traits::iterator_type iter = begin_points(polygon); + iter != end_points(polygon); ++iter) { + points.push_back(*iter); + convolve(points.back(), point); + } + polygon_mutable_traits::set_points(polygon, points.begin(), points.end()); + return polygon; + } + +/// \relatesalso polygon_with_holes_concept + template + typename enable_if< + typename gtl_and< typename is_any_mutable_polygon_with_holes_type::type, + typename is_point_concept::type>::type>::type, + polygon_type>::type & + convolve(polygon_type& polygon, const point_type& point) { + typedef typename polygon_with_holes_traits::hole_type hole_type; + hole_type h; + set_points(h, begin_points(polygon), end_points(polygon)); + convolve(h, point); + std::vector holes; + holes.reserve(size_holes(polygon)); + for(typename polygon_with_holes_traits::iterator_holes_type itr = begin_holes(polygon); + itr != end_holes(polygon); ++itr) { + holes.push_back(*itr); + convolve(holes.back(), point); + } + assign(polygon, h); + set_holes(polygon, holes.begin(), holes.end()); + return polygon; + } + +/// \relatesalso polygon_concept + template + typename enable_if< typename is_any_mutable_polygon_type::type, T>::type & + move(T& polygon, orientation_2d orient, typename polygon_traits::coordinate_type displacement) { + typedef typename polygon_traits::coordinate_type Unit; + if(orient == HORIZONTAL) return convolve(polygon, point_data(displacement, Unit(0))); + return convolve(polygon, point_data(Unit(0), displacement)); + } + +/// \relatesalso polygon_concept +/// \brief Applies a transformation to the polygon. +/// \tparam polygon_type A type that models polygon_concept +/// \tparam transform_type A type that may be either axis_transformation or transformation or that overloads point_concept::transform +/// \param polygon The polygon to transform +/// \param tr The transformation to apply + template + typename enable_if< typename is_any_mutable_polygon_without_holes_type::type, polygon_type>::type & + transform(polygon_type& polygon, const transform_type& tr) { + std::vector::iterator_type>::value_type> points; + points.reserve(::boost::polygon::size(polygon)); + for(typename polygon_traits::iterator_type iter = begin_points(polygon); + iter != end_points(polygon); ++iter) { + points.push_back(*iter); + transform(points.back(), tr); + } + polygon_mutable_traits::set_points(polygon, points.begin(), points.end()); + return polygon; + } + +/// \relatesalso polygon_with_holes_concept + template + typename enable_if< typename is_any_mutable_polygon_with_holes_type::type, T>::type & + transform(T& polygon, const transform_type& tr) { + typedef typename polygon_with_holes_traits::hole_type hole_type; + hole_type h; + set_points(h, begin_points(polygon), end_points(polygon)); + transform(h, tr); + std::vector holes; + holes.reserve(size_holes(polygon)); + for(typename polygon_with_holes_traits::iterator_holes_type itr = begin_holes(polygon); + itr != end_holes(polygon); ++itr) { + holes.push_back(*itr); + transform(holes.back(), tr); + } + assign(polygon, h); + set_holes(polygon, holes.begin(), holes.end()); + return polygon; + } + + template + typename enable_if< typename is_any_mutable_polygon_without_holes_type::type, polygon_type>::type & + scale_up(polygon_type& polygon, typename coordinate_traits::coordinate_type>::unsigned_area_type factor) { + std::vector::iterator_type>::value_type> points; + points.reserve(::boost::polygon::size(polygon)); + for(typename polygon_traits::iterator_type iter = begin_points(polygon); + iter != end_points(polygon); ++iter) { + points.push_back(*iter); + scale_up(points.back(), factor); + } + polygon_mutable_traits::set_points(polygon, points.begin(), points.end()); + return polygon; + } + + template + typename enable_if< typename is_any_mutable_polygon_with_holes_type::type, T>::type & + scale_up(T& polygon, typename coordinate_traits::coordinate_type>::unsigned_area_type factor) { + typedef typename polygon_with_holes_traits::hole_type hole_type; + hole_type h; + set_points(h, begin_points(polygon), end_points(polygon)); + scale_up(h, factor); + std::vector holes; + holes.reserve(size_holes(polygon)); + for(typename polygon_with_holes_traits::iterator_holes_type itr = begin_holes(polygon); + itr != end_holes(polygon); ++itr) { + holes.push_back(*itr); + scale_up(holes.back(), factor); + } + assign(polygon, h); + set_holes(polygon, holes.begin(), holes.end()); + return polygon; + } + + //scale non-45 down + template + typename enable_if< + typename gtl_and< typename is_any_mutable_polygon_without_holes_type::type, + typename gtl_not::type>::type>::type>::type>::type, + polygon_type>::type & + scale_down(polygon_type& polygon, typename coordinate_traits::coordinate_type>::unsigned_area_type factor) { + std::vector::iterator_type>::value_type> points; + points.reserve(::boost::polygon::size(polygon)); + for(typename polygon_traits::iterator_type iter = begin_points(polygon); + iter != end_points(polygon); ++iter) { + points.push_back(*iter); + scale_down(points.back(), factor); + } + polygon_mutable_traits::set_points(polygon, points.begin(), points.end()); + return polygon; + } + + template + Unit local_abs(Unit value) { return value < 0 ? (Unit)-value : value; } + + template + void snap_point_vector_to_45(std::vector >& pts) { + typedef point_data Point; + if(pts.size() < 3) { pts.clear(); return; } + typename std::vector >::iterator endLocation = std::unique(pts.begin(), pts.end()); + if(endLocation != pts.end()){ + pts.resize(endLocation - pts.begin()); + } + if(pts.back() == pts[0]) pts.pop_back(); + //iterate over point triplets + int numPts = pts.size(); + bool wrap_around = false; + for(int i = 0; i < numPts; ++i) { + Point& pt1 = pts[i]; + Point& pt2 = pts[(i + 1) % numPts]; + Point& pt3 = pts[(i + 2) % numPts]; + //check if non-45 edge + Unit deltax = x(pt2) - x(pt1); + Unit deltay = y(pt2) - y(pt1); + if(deltax && deltay && + local_abs(deltax) != local_abs(deltay)) { + //adjust the middle point + Unit ndx = x(pt3) - x(pt2); + Unit ndy = y(pt3) - y(pt2); + if(ndx && ndy) { + Unit diff = local_abs(local_abs(deltax) - local_abs(deltay)); + Unit halfdiff = diff/2; + if((deltax > 0 && deltay > 0) || + (deltax < 0 && deltay < 0)) { + //previous edge is rising slope + if(local_abs(deltax + halfdiff + (diff % 2)) == + local_abs(deltay - halfdiff)) { + x(pt2, x(pt2) + halfdiff + (diff % 2)); + y(pt2, y(pt2) - halfdiff); + } else if(local_abs(deltax - halfdiff - (diff % 2)) == + local_abs(deltay + halfdiff)) { + x(pt2, x(pt2) - halfdiff - (diff % 2)); + y(pt2, y(pt2) + halfdiff); + } else{ + //std::cout << "fail1\n"; + } + } else { + //previous edge is falling slope + if(local_abs(deltax + halfdiff + (diff % 2)) == + local_abs(deltay + halfdiff)) { + x(pt2, x(pt2) + halfdiff + (diff % 2)); + y(pt2, y(pt2) + halfdiff); + } else if(local_abs(deltax - halfdiff - (diff % 2)) == + local_abs(deltay - halfdiff)) { + x(pt2, x(pt2) - halfdiff - (diff % 2)); + y(pt2, y(pt2) - halfdiff); + } else { + //std::cout << "fail2\n"; + } + } + if(i == numPts - 1 && (diff % 2)) { + //we have a wrap around effect + if(!wrap_around) { + wrap_around = true; + i = -1; + } + } + } else if(ndx) { + //next edge is horizontal + //find the x value for pt1 that would make the abs(deltax) == abs(deltay) + Unit newDeltaX = local_abs(deltay); + if(deltax < 0) newDeltaX *= -1; + x(pt2, x(pt1) + newDeltaX); + } else { //ndy + //next edge is vertical + //find the y value for pt1 that would make the abs(deltax) == abs(deltay) + Unit newDeltaY = local_abs(deltax); + if(deltay < 0) newDeltaY *= -1; + y(pt2, y(pt1) + newDeltaY); + } + } + } + } + + template + typename enable_if< typename is_any_mutable_polygon_without_holes_type::type, polygon_type>::type & + snap_to_45(polygon_type& polygon) { + std::vector::iterator_type>::value_type> points; + points.reserve(::boost::polygon::size(polygon)); + for(typename polygon_traits::iterator_type iter = begin_points(polygon); + iter != end_points(polygon); ++iter) { + points.push_back(*iter); + } + snap_point_vector_to_45(points); + polygon_mutable_traits::set_points(polygon, points.begin(), points.end()); + return polygon; + } + + template + typename enable_if< typename is_any_mutable_polygon_with_holes_type::type, polygon_type>::type & + snap_to_45(polygon_type& polygon) { + typedef typename polygon_with_holes_traits::hole_type hole_type; + hole_type h; + set_points(h, begin_points(polygon), end_points(polygon)); + snap_to_45(h); + std::vector holes; + holes.reserve(size_holes(polygon)); + for(typename polygon_with_holes_traits::iterator_holes_type itr = begin_holes(polygon); + itr != end_holes(polygon); ++itr) { + holes.push_back(*itr); + snap_to_45(holes.back()); + } + assign(polygon, h); + set_holes(polygon, holes.begin(), holes.end()); + return polygon; + } + + //scale specifically 45 down + template + typename enable_if< + typename gtl_and< typename is_any_mutable_polygon_without_holes_type::type, + typename gtl_same_type + < forty_five_domain, + typename geometry_domain::type>::type>::type>::type, + polygon_type>::type & + scale_down(polygon_type& polygon, typename coordinate_traits::coordinate_type>::unsigned_area_type factor) { + std::vector::iterator_type>::value_type> points; + points.reserve(::boost::polygon::size(polygon)); + for(typename polygon_traits::iterator_type iter = begin_points(polygon); + iter != end_points(polygon); ++iter) { + points.push_back(*iter); + scale_down(points.back(), factor); + } + snap_point_vector_to_45(points); + polygon_mutable_traits::set_points(polygon, points.begin(), points.end()); + return polygon; + } + + template + typename enable_if< typename is_any_mutable_polygon_with_holes_type::type, T>::type & + scale_down(T& polygon, typename coordinate_traits::coordinate_type>::unsigned_area_type factor) { + typedef typename polygon_with_holes_traits::hole_type hole_type; + hole_type h; + set_points(h, begin_points(polygon), end_points(polygon)); + scale_down(h, factor); + std::vector holes; + holes.reserve(size_holes(polygon)); + for(typename polygon_with_holes_traits::iterator_holes_type itr = begin_holes(polygon); + itr != end_holes(polygon); ++itr) { + holes.push_back(*itr); + scale_down(holes.back(), factor); + } + assign(polygon, h); + set_holes(polygon, holes.begin(), holes.end()); + return polygon; + } + + //scale non-45 + template + typename enable_if< + typename gtl_and< typename is_any_mutable_polygon_without_holes_type::type, + typename gtl_not::type>::type>::type>::type>::type, + polygon_type>::type & + scale(polygon_type& polygon, double factor) { + std::vector::iterator_type>::value_type> points; + points.reserve(::boost::polygon::size(polygon)); + for(typename polygon_traits::iterator_type iter = begin_points(polygon); + iter != end_points(polygon); ++iter) { + points.push_back(*iter); + scale(points.back(), anisotropic_scale_factor(factor, factor)); + } + polygon_mutable_traits::set_points(polygon, points.begin(), points.end()); + return polygon; + } + + //scale specifically 45 + template + polygon_type& + scale(polygon_type& polygon, double factor, + typename enable_if< + typename gtl_and< typename is_any_mutable_polygon_without_holes_type::type, + typename gtl_same_type + < forty_five_domain, + typename geometry_domain::type>::type>::type>::type>::type * = 0 + ) { + std::vector::iterator_type>::value_type> points; + points.reserve(::boost::polygon::size(polygon)); + for(typename polygon_traits::iterator_type iter = begin_points(polygon); + iter != end_points(polygon); ++iter) { + points.push_back(*iter); + scale(points.back(), anisotropic_scale_factor(factor, factor)); + } + snap_point_vector_to_45(points); + polygon_mutable_traits::set_points(polygon, points.begin(), points.end()); + return polygon; + } + + template + T& + scale(T& polygon, double factor, + typename enable_if< typename is_any_mutable_polygon_with_holes_type::type>::type * = 0 + ) { + typedef typename polygon_with_holes_traits::hole_type hole_type; + hole_type h; + set_points(h, begin_points(polygon), end_points(polygon)); + scale(h, factor); + std::vector holes; + holes.reserve(size_holes(polygon)); + for(typename polygon_with_holes_traits::iterator_holes_type itr = begin_holes(polygon); + itr != end_holes(polygon); ++itr) { + holes.push_back(*itr); + scale(holes.back(), factor); + } + assign(polygon, h); + set_holes(polygon, holes.begin(), holes.end()); + return polygon; + } + + template + static area_type + point_sequence_area(iterator_type begin_range, iterator_type end_range) { + typedef typename std::iterator_traits::value_type point_type; + if(begin_range == end_range) return area_type(0); + point_type first = *begin_range; + point_type previous = first; + ++begin_range; + // Initialize trapezoid base line + area_type y_base = (area_type)y(first); + // Initialize area accumulator + + area_type area(0); + while (begin_range != end_range) { + area_type x1 = (area_type)x(previous); + area_type x2 = (area_type)x(*begin_range); +#ifdef BOOST_POLYGON_ICC +#pragma warning (push) +#pragma warning (disable:1572) +#endif + if(x1 != x2) { +#ifdef BOOST_POLYGON_ICC +#pragma warning (pop) +#endif + // do trapezoid area accumulation + area += (x2 - x1) * (((area_type)y(*begin_range) - y_base) + + ((area_type)y(previous) - y_base)) / 2; + } + previous = *begin_range; + // go to next point + ++begin_range; + } + //wrap around to evaluate the edge between first and last if not closed + if(!equivalence(first, previous)) { + area_type x1 = (area_type)x(previous); + area_type x2 = (area_type)x(first); + area += (x2 - x1) * (((area_type)y(first) - y_base) + + ((area_type)y(previous) - y_base)) / 2; + } + return area; + } + + template + typename enable_if< + typename is_polygon_with_holes_type::type, + typename area_type_by_domain< typename geometry_domain::type>::type, + typename polygon_traits::coordinate_type>::type>::type + area(const T& polygon) { + typedef typename area_type_by_domain< typename geometry_domain::type>::type, + typename polygon_traits::coordinate_type>::type area_type; + area_type retval = point_sequence_area::iterator_type, area_type> + (begin_points(polygon), end_points(polygon)); + if(retval < 0) retval *= -1; + for(typename polygon_with_holes_traits::iterator_holes_type itr = + polygon_with_holes_traits::begin_holes(polygon); + itr != polygon_with_holes_traits::end_holes(polygon); ++itr) { + area_type tmp_area = point_sequence_area + ::hole_type>::iterator_type, area_type> + (begin_points(*itr), end_points(*itr)); + if(tmp_area < 0) tmp_area *= -1; + retval -= tmp_area; + } + return retval; + } + + template + bool point_sequence_is_45(iT itr, iT itr_end) { + typedef typename std::iterator_traits::value_type Point; + typedef typename point_traits::coordinate_type Unit; + if(itr == itr_end) return true; + Point firstPt = *itr; + Point prevPt = firstPt; + ++itr; + while(itr != itr_end) { + Point pt = *itr; + Unit deltax = x(pt) - x(prevPt); + Unit deltay = y(pt) - y(prevPt); + if(deltax && deltay && + local_abs(deltax) != local_abs(deltay)) + return false; + prevPt = pt; + ++itr; + } + Unit deltax = x(firstPt) - x(prevPt); + Unit deltay = y(firstPt) - y(prevPt); + if(deltax && deltay && + local_abs(deltax) != local_abs(deltay)) + return false; + return true; + } + + template + typename enable_if< typename is_polygon_with_holes_type::type, bool>::type + is_45(const polygon_type& polygon) { + typename polygon_traits::iterator_type itr = begin_points(polygon), itr_end = end_points(polygon); + if(!point_sequence_is_45(itr, itr_end)) return false; + typename polygon_with_holes_traits::iterator_holes_type itrh = begin_holes(polygon), itrh_end = end_holes(polygon); + typedef typename polygon_with_holes_traits::hole_type hole_type; + for(; itrh != itrh_end; ++ itrh) { + typename polygon_traits::iterator_type itr1 = begin_points(polygon), itr1_end = end_points(polygon); + if(!point_sequence_is_45(itr1, itr1_end)) return false; + } + return true; + } + + template + distance_type point_sequence_distance(iterator_type itr, iterator_type itr_end) { + typedef distance_type Unit; + typedef iterator_type iterator; + typedef typename std::iterator_traits::value_type point_type; + Unit return_value = Unit(0); + point_type previous_point, first_point; + if(itr == itr_end) return return_value; + previous_point = first_point = *itr; + ++itr; + for( ; itr != itr_end; ++itr) { + point_type current_point = *itr; + return_value += (Unit)euclidean_distance(current_point, previous_point); + previous_point = current_point; + } + return_value += (Unit)euclidean_distance(previous_point, first_point); + return return_value; + } + + template + typename distance_type_by_domain + ::type>::type, typename polygon_traits::coordinate_type>::type + perimeter(const T& polygon, + typename enable_if< + typename is_polygon_with_holes_type::type>::type * = 0 + ) { + typedef typename distance_type_by_domain + ::type>::type, typename polygon_traits::coordinate_type>::type Unit; + typedef typename polygon_traits::iterator_type iterator; + iterator itr = begin_points(polygon); + iterator itr_end = end_points(polygon); + Unit return_value = point_sequence_distance(itr, itr_end); + for(typename polygon_with_holes_traits::iterator_holes_type itr_holes = begin_holes(polygon); + itr_holes != end_holes(polygon); ++itr_holes) { + typedef typename polygon_traits::hole_type>::iterator_type hitertype; + return_value += point_sequence_distance(begin_points(*itr_holes), end_points(*itr_holes)); + } + return return_value; + } + + template + typename enable_if ::type, + direction_1d>::type + winding(const T& polygon) { + winding_direction wd = polygon_traits::winding(polygon); + if(wd != unknown_winding) { + return wd == clockwise_winding ? CLOCKWISE: COUNTERCLOCKWISE; + } + typedef typename area_type_by_domain< typename geometry_domain::type>::type, + typename polygon_traits::coordinate_type>::type area_type; + return point_sequence_area::iterator_type, area_type>(begin_points(polygon), end_points(polygon)) < 0 ? + COUNTERCLOCKWISE : CLOCKWISE; + } + + template + typename enable_if< + typename gtl_and< + typename is_polygon_90_type::type, + typename gtl_same_type< + typename geometry_concept::type, + point_concept + >::type + >::type, + bool + >::type contains( + const T& polygon, + const input_point_type& point, + bool consider_touch = true) { + typedef T polygon_type; + typedef typename polygon_traits::coordinate_type coordinate_type; + typedef typename polygon_traits::iterator_type iterator; + typedef typename std::iterator_traits::value_type point_type; + coordinate_type point_x = x(point); + coordinate_type point_y = y(point); + // Check how many intersections has the ray extended from the given + // point in the x-axis negative direction with the polygon edges. + // If the number is odd the point is within the polygon, otherwise not. + // We can safely ignore horizontal edges, however intersections with + // end points of the vertical edges require special handling. We should + // add one intersection in case horizontal edges that extend vertical edge + // point in the same direction. + int num_full_intersections = 0; + int num_half_intersections = 0; + for (iterator iter = begin_points(polygon); iter != end_points(polygon);) { + point_type curr_point = *iter; + ++iter; + point_type next_point = (iter == end_points(polygon)) ? *begin_points(polygon) : *iter; + if (x(curr_point) == x(next_point)) { + if (x(curr_point) > point_x) { + continue; + } + coordinate_type min_y = (std::min)(y(curr_point), y(next_point)); + coordinate_type max_y = (std::max)(y(curr_point), y(next_point)); + if (point_y > min_y && point_y < max_y) { + if (x(curr_point) == point_x) { + return consider_touch; + } + ++num_full_intersections; + } + if (point_y == min_y || point_y == max_y) { + num_half_intersections += (y(curr_point) < y(next_point) ? 1 : -1); + } + } else { + coordinate_type min_x = (std::min)(x(curr_point), x(next_point)); + coordinate_type max_x = (std::max)(x(curr_point), x(next_point)); + if (point_x >= min_x && point_x <= max_x) { + if (y(curr_point) == point_y) { + return consider_touch; + } + } + } + } + int total_intersections = num_full_intersections + (num_half_intersections >> 1); + return total_intersections & 1; + } + + //TODO: refactor to expose as user APIs + template + struct edge_utils { + typedef point_data Point; + typedef std::pair half_edge; + + class less_point { + public: + typedef Point first_argument_type; + typedef Point second_argument_type; + typedef bool result_type; + inline less_point() {} + inline bool operator () (const Point& pt1, const Point& pt2) const { + if(pt1.get(HORIZONTAL) < pt2.get(HORIZONTAL)) return true; + if(pt1.get(HORIZONTAL) == pt2.get(HORIZONTAL)) { + if(pt1.get(VERTICAL) < pt2.get(VERTICAL)) return true; + } + return false; + } + }; + + static inline bool between(Point pt, Point pt1, Point pt2) { + less_point lp; + if(lp(pt1, pt2)) + return lp(pt, pt2) && lp(pt1, pt); + return lp(pt, pt1) && lp(pt2, pt); + } + + template + static inline bool equal_slope(area_type dx1, area_type dy1, area_type dx2, area_type dy2) { + typedef typename coordinate_traits::unsigned_area_type unsigned_product_type; + unsigned_product_type cross_1 = (unsigned_product_type)(dx2 < 0 ? -dx2 :dx2) * (unsigned_product_type)(dy1 < 0 ? -dy1 : dy1); + unsigned_product_type cross_2 = (unsigned_product_type)(dx1 < 0 ? -dx1 :dx1) * (unsigned_product_type)(dy2 < 0 ? -dy2 : dy2); + int dx1_sign = dx1 < 0 ? -1 : 1; + int dx2_sign = dx2 < 0 ? -1 : 1; + int dy1_sign = dy1 < 0 ? -1 : 1; + int dy2_sign = dy2 < 0 ? -1 : 1; + int cross_1_sign = dx2_sign * dy1_sign; + int cross_2_sign = dx1_sign * dy2_sign; + return cross_1 == cross_2 && (cross_1_sign == cross_2_sign || cross_1 == 0); + } + + static inline bool equal_slope(const Unit& x, const Unit& y, + const Point& pt1, const Point& pt2) { + const Point* pts[2] = {&pt1, &pt2}; + typedef typename coordinate_traits::manhattan_area_type at; + at dy2 = (at)pts[1]->get(VERTICAL) - (at)y; + at dy1 = (at)pts[0]->get(VERTICAL) - (at)y; + at dx2 = (at)pts[1]->get(HORIZONTAL) - (at)x; + at dx1 = (at)pts[0]->get(HORIZONTAL) - (at)x; + return equal_slope(dx1, dy1, dx2, dy2); + } + + template + static inline bool less_slope(area_type dx1, area_type dy1, area_type dx2, area_type dy2) { + //reflext x and y slopes to right hand side half plane + if(dx1 < 0) { + dy1 *= -1; + dx1 *= -1; + } else if(dx1 == 0) { + //if the first slope is vertical the first cannot be less + return false; + } + if(dx2 < 0) { + dy2 *= -1; + dx2 *= -1; + } else if(dx2 == 0) { + //if the second slope is vertical the first is always less unless it is also vertical, in which case they are equal + return dx1 != 0; + } + typedef typename coordinate_traits::unsigned_area_type unsigned_product_type; + unsigned_product_type cross_1 = (unsigned_product_type)(dx2 < 0 ? -dx2 :dx2) * (unsigned_product_type)(dy1 < 0 ? -dy1 : dy1); + unsigned_product_type cross_2 = (unsigned_product_type)(dx1 < 0 ? -dx1 :dx1) * (unsigned_product_type)(dy2 < 0 ? -dy2 : dy2); + int dx1_sign = dx1 < 0 ? -1 : 1; + int dx2_sign = dx2 < 0 ? -1 : 1; + int dy1_sign = dy1 < 0 ? -1 : 1; + int dy2_sign = dy2 < 0 ? -1 : 1; + int cross_1_sign = dx2_sign * dy1_sign; + int cross_2_sign = dx1_sign * dy2_sign; + if(cross_1_sign < cross_2_sign) return true; + if(cross_2_sign < cross_1_sign) return false; + if(cross_1_sign == -1) return cross_2 < cross_1; + return cross_1 < cross_2; + } + + static inline bool less_slope(const Unit& x, const Unit& y, + const Point& pt1, const Point& pt2) { + const Point* pts[2] = {&pt1, &pt2}; + //compute y value on edge from pt_ to pts[1] at the x value of pts[0] + typedef typename coordinate_traits::manhattan_area_type at; + at dy2 = (at)pts[1]->get(VERTICAL) - (at)y; + at dy1 = (at)pts[0]->get(VERTICAL) - (at)y; + at dx2 = (at)pts[1]->get(HORIZONTAL) - (at)x; + at dx1 = (at)pts[0]->get(HORIZONTAL) - (at)x; + return less_slope(dx1, dy1, dx2, dy2); + } + + //return -1 below, 0 on and 1 above line + //assumes point is on x interval of segment + static inline int on_above_or_below(Point pt, const half_edge& he) { + if(pt == he.first || pt == he.second) return 0; + if(equal_slope(pt.get(HORIZONTAL), pt.get(VERTICAL), he.first, he.second)) return 0; + bool less_result = less_slope(pt.get(HORIZONTAL), pt.get(VERTICAL), he.first, he.second); + int retval = less_result ? -1 : 1; + less_point lp; + if(lp(he.second, he.first)) retval *= -1; + if(!between(pt, he.first, he.second)) retval *= -1; + return retval; + } + }; + + template + typename enable_if< + typename gtl_and< typename is_any_mutable_polygon_with_holes_type::type, + typename gtl_same_type::type, point_concept>::type>::type, + bool>::type + contains(const T& polygon, const input_point_type& point, bool consider_touch = true) { + typedef typename polygon_with_holes_traits::iterator_holes_type holes_iterator; + bool isInside = contains( view_as< typename polygon_from_polygon_with_holes_type< + typename geometry_concept::type>::type>( polygon ), point, consider_touch ); + if(!isInside) return false; //no need to check holes + holes_iterator itH = begin_holes( polygon ); + while( itH != end_holes( polygon ) ) { + if( contains( *itH, point, !consider_touch ) ) { + isInside = false; + break; + } + ++itH; + } + return isInside; + } + + template + typename enable_if< + typename gtl_and_3< + typename is_polygon_type::type, + typename gtl_different_type::type>::type, manhattan_domain>::type, + typename gtl_same_type::type, point_concept>::type>::type, + bool>::type + contains(const T& polygon, const input_point_type& point, bool consider_touch = true) { + typedef typename point_traits::coordinate_type Unit; + typedef point_data Point; + typedef std::pair half_edge; + typedef typename polygon_traits::iterator_type iterator; + iterator itr = begin_points(polygon); + iterator itrEnd = end_points(polygon); + half_edge he; + if(itr == itrEnd) return false; + assign(he.first, *itr); + Point firstPt; + assign(firstPt, *itr); + ++itr; + if(itr == itrEnd) return false; + bool done = false; + int above = 0; + while(!done) { + Point currentPt; + if(itr == itrEnd) { + done = true; + currentPt = firstPt; + } else { + assign(currentPt, *itr); + ++itr; + } + if(currentPt == he.first) { + continue; + } else { + he.second = currentPt; + if(equivalence(point, currentPt)) return consider_touch; + Unit xmin = (std::min)(x(he.first), x(he.second)); + Unit xmax = (std::max)(x(he.first), x(he.second)); + if(x(point) >= xmin && x(point) < xmax) { //double counts if <= xmax + Point tmppt; + assign(tmppt, point); + int oabedge = edge_utils::on_above_or_below(tmppt, he); + if(oabedge == 0) return consider_touch; + if(oabedge == 1) ++above; + } else if(x(point) == xmax) { + if(x(point) == xmin) { + Unit ymin = (std::min)(y(he.first), y(he.second)); + Unit ymax = (std::max)(y(he.first), y(he.second)); + Unit ypt = y(point); + if(ypt <= ymax && ypt >= ymin) + return consider_touch; + } else { + Point tmppt; + assign(tmppt, point); + if( edge_utils::on_above_or_below(tmppt, he) == 0 ) { + return consider_touch; + } + } + } + } + he.first = he.second; + } + return above % 2 != 0; //if the point is above an odd number of edges is must be inside polygon + } + + /* + template + typename enable_if< + typename gtl_and_3< + typename is_polygon_with_holes_type::type, + typename gtl_different_type::type>::type, manhattan_domain>::type, + typename gtl_same_type::type, point_concept>::type>::type, + bool>::type + contains(const T& polygon, const input_point_type& point, bool consider_touch = true) { + typedef typename point_traits::coordinate_type Unit; + typedef point_data Point; + typedef std::pair half_edge; + typedef typename polygon_traits::iterator_type iterator; + iterator itr = begin_points(polygon); + iterator itrEnd = end_points(polygon); + half_edge he; + if(itr == itrEnd) return false; + assign(he.first, *itr); + Point firstPt; + assign(firstPt, *itr); + ++itr; + if(itr == itrEnd) return false; + bool done = false; + int above = 0; + while(!done) { + Point currentPt; + if(itr == itrEnd) { + done = true; + currentPt = firstPt; + } else { + assign(currentPt, *itr); + ++itr; + } + if(currentPt == he.first) { + continue; + } else { + he.second = currentPt; + if(equivalence(point, currentPt)) return consider_touch; + Unit xmin = (std::min)(x(he.first), x(he.second)); + Unit xmax = (std::max)(x(he.first), x(he.second)); + if(x(point) >= xmin && x(point) < xmax) { //double counts if <= xmax + Point tmppt; + assign(tmppt, point); + int oabedge = edge_utils::on_above_or_below(tmppt, he); + if(oabedge == 0) return consider_touch; + if(oabedge == 1) ++above; + } + } + he.first = he.second; + } + return above % 2 != 0; //if the point is above an odd number of edges is must be inside polygon + } + */ + + template + typename enable_if< + typename gtl_and< typename is_mutable_rectangle_concept::type>::type, + typename is_polygon_with_holes_type::type>::type, + bool>::type + extents(T1& bounding_box, const T2& polygon) { + typedef typename polygon_traits::iterator_type iterator; + bool first_iteration = true; + iterator itr_end = end_points(polygon); + for(iterator itr = begin_points(polygon); itr != itr_end; ++itr) { + if(first_iteration) { + set_points(bounding_box, *itr, *itr); + first_iteration = false; + } else { + encompass(bounding_box, *itr); + } + } + if(first_iteration) return false; + return true; + } + + template + typename enable_if< + typename gtl_and< typename is_mutable_point_concept::type>::type, + typename is_polygon_with_holes_type::type>::type, + bool>::type + center(T1& center_point, const T2& polygon) { + typedef typename polygon_traits::coordinate_type coordinate_type; + rectangle_data bbox; + extents(bbox, polygon); + return center(center_point, bbox); + } + + template + template + polygon_90_data& polygon_90_data::operator=(const T2& rvalue) { + assign(*this, rvalue); + return *this; + } + + template + template + polygon_45_data& polygon_45_data::operator=(const T2& rvalue) { + assign(*this, rvalue); + return *this; + } + + template + template + polygon_data& polygon_data::operator=(const T2& rvalue) { + assign(*this, rvalue); + return *this; + } + + template + template + polygon_90_with_holes_data& polygon_90_with_holes_data::operator=(const T2& rvalue) { + assign(*this, rvalue); + return *this; + } + + template + template + polygon_45_with_holes_data& polygon_45_with_holes_data::operator=(const T2& rvalue) { + assign(*this, rvalue); + return *this; + } + + template + template + polygon_with_holes_data& polygon_with_holes_data::operator=(const T2& rvalue) { + assign(*this, rvalue); + return *this; + } + + template + struct geometry_concept > { + typedef polygon_concept type; + }; + template + struct geometry_concept > { + typedef polygon_45_concept type; + }; + template + struct geometry_concept > { + typedef polygon_90_concept type; + }; + template + struct geometry_concept > { + typedef polygon_with_holes_concept type; + }; + template + struct geometry_concept > { + typedef polygon_45_with_holes_concept type; + }; + template + struct geometry_concept > { + typedef polygon_90_with_holes_concept type; + }; + +// template struct polygon_with_holes_traits > { +// typedef polygon_90_data hole_type; +// typedef const hole_type* iterator_holes_type; +// static inline iterator_holes_type begin_holes(const hole_type& t) { return &t; } +// static inline iterator_holes_type end_holes(const hole_type& t) { return &t; } +// static inline std::size_t size_holes(const hole_type& t) { return 0; } +// }; +// template struct polygon_with_holes_traits > { +// typedef polygon_45_data hole_type; +// typedef const hole_type* iterator_holes_type; +// static inline iterator_holes_type begin_holes(const hole_type& t) { return &t; } +// static inline iterator_holes_type end_holes(const hole_type& t) { return &t; } +// static inline std::size_t size_holes(const hole_type& t) { return 0; } +// }; +// template struct polygon_with_holes_traits > { +// typedef polygon_data hole_type; +// typedef const hole_type* iterator_holes_type; +// static inline iterator_holes_type begin_holes(const hole_type& t) { return &t; } +// static inline iterator_holes_type end_holes(const hole_type& t) { return &t; } +// static inline std::size_t size_holes(const hole_type& t) { return 0; } +// }; + template struct get_void {}; + template <> struct get_void { typedef void type; }; + + template struct polygon_with_holes_traits< + T, typename get_void::type>::type > { + typedef T hole_type; + typedef const hole_type* iterator_holes_type; + static inline iterator_holes_type begin_holes(const hole_type& t) { return &t; } + static inline iterator_holes_type end_holes(const hole_type& t) { return &t; } + }; + + template + struct view_of { + typedef typename polygon_traits::coordinate_type coordinate_type; + typedef interval_data interval_type; + rectangle_data rect; + view_of(const T& obj) : rect() { + point_data pts[2]; + typename polygon_traits::iterator_type itr = + begin_points(obj), itre = end_points(obj); + if(itr == itre) return; + assign(pts[0], *itr); + ++itr; + if(itr == itre) return; + ++itr; + if(itr == itre) return; + assign(pts[1], *itr); + set_points(rect, pts[0], pts[1]); + } + inline interval_type get(orientation_2d orient) const { + return rect.get(orient); } + }; + + template + struct geometry_concept > { + typedef rectangle_concept type; + }; + + template + struct view_of { + const T* t; + view_of(const T& obj) : t(&obj) {} + typedef typename polygon_traits::coordinate_type coordinate_type; + typedef typename polygon_traits::iterator_type iterator_type; + typedef typename polygon_traits::point_type point_type; + + /// Get the begin iterator + inline iterator_type begin() const { + return polygon_traits::begin_points(*t); + } + + /// Get the end iterator + inline iterator_type end() const { + return polygon_traits::end_points(*t); + } + + /// Get the number of sides of the polygon + inline std::size_t size() const { + return polygon_traits::size(*t); + } + + /// Get the winding direction of the polygon + inline winding_direction winding() const { + return polygon_traits::winding(*t); + } + }; + + template + struct geometry_concept > { + typedef polygon_45_concept type; + }; + + template + struct view_of { + const T* t; + view_of(const T& obj) : t(&obj) {} + typedef typename polygon_traits::coordinate_type coordinate_type; + typedef typename polygon_traits::iterator_type iterator_type; + typedef typename polygon_traits::point_type point_type; + typedef iterator_points_to_compact compact_iterator_type; + + /// Get the begin iterator + inline compact_iterator_type begin_compact() const { + return compact_iterator_type(polygon_traits::begin_points(*t), + polygon_traits::end_points(*t)); + } + + /// Get the end iterator + inline compact_iterator_type end_compact() const { + return compact_iterator_type(polygon_traits::end_points(*t), + polygon_traits::end_points(*t)); + } + + /// Get the number of sides of the polygon + inline std::size_t size() const { + return polygon_traits::size(*t); + } + + /// Get the winding direction of the polygon + inline winding_direction winding() const { + return polygon_traits::winding(*t); + } + }; + + template + struct geometry_concept > { + typedef polygon_90_concept type; + }; + + template + struct view_of { + const T* t; + view_of(const T& obj) : t(&obj) {} + typedef typename polygon_traits::coordinate_type coordinate_type; + typedef typename polygon_traits::iterator_type iterator_type; + typedef typename polygon_traits::point_type point_type; + typedef view_of::hole_type> hole_type; + struct iterator_holes_type { + typedef std::forward_iterator_tag iterator_category; + typedef hole_type value_type; + typedef std::ptrdiff_t difference_type; + typedef const hole_type* pointer; //immutable + typedef const hole_type& reference; //immutable + typedef typename polygon_with_holes_traits::iterator_holes_type iht; + iht internal_itr; + iterator_holes_type() : internal_itr() {} + iterator_holes_type(iht iht_in) : internal_itr(iht_in) {} + inline iterator_holes_type& operator++() { + ++internal_itr; + return *this; + } + inline const iterator_holes_type operator++(int) { + iterator_holes_type tmp(*this); + ++(*this); + return tmp; + } + inline bool operator==(const iterator_holes_type& that) const { + return (internal_itr == that.internal_itr); + } + inline bool operator!=(const iterator_holes_type& that) const { + return (internal_itr != that.internal_itr); + } + inline value_type operator*() const { + return view_as(*internal_itr); + } + }; + + /// Get the begin iterator + inline iterator_type begin() const { + return polygon_traits::begin_points(*t); + } + + /// Get the end iterator + inline iterator_type end() const { + return polygon_traits::end_points(*t); + } + + /// Get the number of sides of the polygon + inline std::size_t size() const { + return polygon_traits::size(*t); + } + + /// Get the winding direction of the polygon + inline winding_direction winding() const { + return polygon_traits::winding(*t); + } + + /// Get the begin iterator + inline iterator_holes_type begin_holes() const { + return polygon_with_holes_traits::begin_holes(*t); + } + + /// Get the end iterator + inline iterator_holes_type end_holes() const { + return polygon_with_holes_traits::end_holes(*t); + } + + /// Get the number of sides of the polygon + inline std::size_t size_holes() const { + return polygon_with_holes_traits::size_holes(*t); + } + + }; + + template + struct geometry_concept > { + typedef polygon_45_with_holes_concept type; + }; + + template + struct view_of { + const T* t; + view_of(const T& obj) : t(&obj) {} + typedef typename polygon_traits::coordinate_type coordinate_type; + typedef typename polygon_traits::iterator_type iterator_type; + typedef typename polygon_traits::point_type point_type; + typedef iterator_points_to_compact compact_iterator_type; + typedef view_of::hole_type> hole_type; + struct iterator_holes_type { + typedef std::forward_iterator_tag iterator_category; + typedef hole_type value_type; + typedef std::ptrdiff_t difference_type; + typedef const hole_type* pointer; //immutable + typedef const hole_type& reference; //immutable + typedef typename polygon_with_holes_traits::iterator_holes_type iht; + iht internal_itr; + iterator_holes_type() : internal_itr() {} + iterator_holes_type(iht iht_in) : internal_itr(iht_in) {} + inline iterator_holes_type& operator++() { + ++internal_itr; + return *this; + } + inline const iterator_holes_type operator++(int) { + iterator_holes_type tmp(*this); + ++(*this); + return tmp; + } + inline bool operator==(const iterator_holes_type& that) const { + return (internal_itr == that.internal_itr); + } + inline bool operator!=(const iterator_holes_type& that) const { + return (internal_itr != that.internal_itr); + } + inline value_type operator*() const { + return view_as(*internal_itr); + } + }; + + /// Get the begin iterator + inline compact_iterator_type begin_compact() const { + return compact_iterator_type(polygon_traits::begin_points(*t), + polygon_traits::end_points(*t)); + } + + /// Get the end iterator + inline compact_iterator_type end_compact() const { + return compact_iterator_type(polygon_traits::end_points(*t), + polygon_traits::end_points(*t)); + } + + /// Get the number of sides of the polygon + inline std::size_t size() const { + return polygon_traits::size(*t); + } + + /// Get the winding direction of the polygon + inline winding_direction winding() const { + return polygon_traits::winding(*t); + } + + /// Get the begin iterator + inline iterator_holes_type begin_holes() const { + return polygon_with_holes_traits::begin_holes(*t); + } + + /// Get the end iterator + inline iterator_holes_type end_holes() const { + return polygon_with_holes_traits::end_holes(*t); + } + + /// Get the number of sides of the polygon + inline std::size_t size_holes() const { + return polygon_with_holes_traits::size_holes(*t); + } + + }; + + template + struct geometry_concept > { + typedef polygon_90_with_holes_concept type; + }; + + template + struct view_of { + const T* t; + view_of(const T& obj) : t(&obj) {} + typedef typename polygon_traits::coordinate_type coordinate_type; + typedef typename polygon_traits::iterator_type iterator_type; + typedef typename polygon_traits::point_type point_type; + + /// Get the begin iterator + inline iterator_type begin() const { + return polygon_traits::begin_points(*t); + } + + /// Get the end iterator + inline iterator_type end() const { + return polygon_traits::end_points(*t); + } + + /// Get the number of sides of the polygon + inline std::size_t size() const { + return polygon_traits::size(*t); + } + + /// Get the winding direction of the polygon + inline winding_direction winding() const { + return polygon_traits::winding(*t); + } + }; + + template + struct geometry_concept > { + typedef polygon_concept type; + }; +} +} + +#endif diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/polygon_with_holes_data.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/polygon_with_holes_data.hpp new file mode 100644 index 0000000..a1a0e1d --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/polygon_with_holes_data.hpp @@ -0,0 +1,107 @@ +/* + Copyright 2008 Intel Corporation + + Use, modification and distribution are subject to the Boost Software License, + Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at + http://www.boost.org/LICENSE_1_0.txt). +*/ +#ifndef BOOST_POLYGON_POLYGON_WITH_HOLES_DATA_HPP +#define BOOST_POLYGON_POLYGON_WITH_HOLES_DATA_HPP +#include "isotropy.hpp" +#include "polygon_data.hpp" +namespace boost { namespace polygon{ + struct polygon_with_holes_concept; + template + class polygon_with_holes_data { +public: + typedef polygon_with_holes_concept geometry_type; + typedef T coordinate_type; + typedef typename polygon_data::iterator_type iterator_type; + typedef typename std::list >::const_iterator iterator_holes_type; + typedef polygon_data hole_type; + typedef typename coordinate_traits::coordinate_distance area_type; + typedef point_data point_type; + + // default constructor of point does not initialize x and y + inline polygon_with_holes_data() : self_(), holes_() {} //do nothing default constructor + + template + inline polygon_with_holes_data(iT input_begin, iT input_end) : self_(), holes_() { + set(input_begin, input_end); + } + + template + inline polygon_with_holes_data(iT input_begin, iT input_end, hiT holes_begin, hiT holes_end) : self_(), holes_() { + set(input_begin, input_end); + set_holes(holes_begin, holes_end); + } + + template + inline polygon_with_holes_data& set(iT input_begin, iT input_end) { + self_.set(input_begin, input_end); + return *this; + } + + // initialize a polygon from x,y values, it is assumed that the first is an x + // and that the input is a well behaved polygon + template + inline polygon_with_holes_data& set_holes(iT input_begin, iT input_end) { + holes_.clear(); //just in case there was some old data there + for( ; input_begin != input_end; ++ input_begin) { + holes_.push_back(hole_type()); + holes_.back().set((*input_begin).begin(), (*input_begin).end()); + } + return *this; + } + + // copy constructor (since we have dynamic memory) + inline polygon_with_holes_data(const polygon_with_holes_data& that) : self_(that.self_), + holes_(that.holes_) {} + + // assignment operator (since we have dynamic memory do a deep copy) + inline polygon_with_holes_data& operator=(const polygon_with_holes_data& that) { + self_ = that.self_; + holes_ = that.holes_; + return *this; + } + + template + inline polygon_with_holes_data& operator=(const T2& rvalue); + + // get begin iterator, returns a pointer to a const coordinate_type + inline const iterator_type begin() const { + return self_.begin(); + } + + // get end iterator, returns a pointer to a const coordinate_type + inline const iterator_type end() const { + return self_.end(); + } + + inline std::size_t size() const { + return self_.size(); + } + + // get begin iterator, returns a pointer to a const polygon + inline const iterator_holes_type begin_holes() const { + return holes_.begin(); + } + + // get end iterator, returns a pointer to a const polygon + inline const iterator_holes_type end_holes() const { + return holes_.end(); + } + + inline std::size_t size_holes() const { + return holes_.size(); + } + +public: + polygon_data self_; + std::list holes_; + }; + + +} +} +#endif diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/rectangle_concept.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/rectangle_concept.hpp new file mode 100644 index 0000000..e824319 --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/rectangle_concept.hpp @@ -0,0 +1,1082 @@ +/* + Copyright 2008 Intel Corporation + + Use, modification and distribution are subject to the Boost Software License, + Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at + http://www.boost.org/LICENSE_1_0.txt). +*/ +#ifndef BOOST_POLYGON_RECTANGLE_CONCEPT_HPP +#define BOOST_POLYGON_RECTANGLE_CONCEPT_HPP + +#include "isotropy.hpp" + +//point +#include "point_data.hpp" +#include "point_traits.hpp" +#include "point_concept.hpp" + +//interval +#include "interval_data.hpp" +#include "interval_traits.hpp" +#include "interval_concept.hpp" + +#include "rectangle_data.hpp" +#include "rectangle_traits.hpp" + +namespace boost { namespace polygon{ + struct rectangle_concept {}; + + template + struct is_rectangle_concept { typedef gtl_no type; }; + template <> + struct is_rectangle_concept { typedef gtl_yes type; }; + + template + struct is_mutable_rectangle_concept { typedef gtl_no type; }; + template <> + struct is_mutable_rectangle_concept { typedef gtl_yes type; }; + + template <> + struct geometry_domain { typedef manhattan_domain type; }; + + template + struct rectangle_interval_type_by_concept { typedef void type; }; + template + struct rectangle_interval_type_by_concept { typedef typename rectangle_traits::interval_type type; }; + + template + struct rectangle_interval_type { + typedef typename rectangle_interval_type_by_concept::type>::type>::type type; + }; + + template + struct rectangle_coordinate_type_by_concept { typedef void type; }; + template + struct rectangle_coordinate_type_by_concept { typedef typename rectangle_traits::coordinate_type type; }; + + template + struct rectangle_coordinate_type { + typedef typename rectangle_coordinate_type_by_concept::type>::type>::type type; + }; + + template + struct rectangle_difference_type_by_concept { typedef void type; }; + template + struct rectangle_difference_type_by_concept { + typedef typename coordinate_traits::coordinate_type>::coordinate_difference type; }; + + template + struct rectangle_difference_type { + typedef typename rectangle_difference_type_by_concept< + T, typename is_rectangle_concept::type>::type>::type type; + }; + + template + struct rectangle_distance_type_by_concept { typedef void type; }; + template + struct rectangle_distance_type_by_concept { + typedef typename coordinate_traits::type>::coordinate_distance type; }; + + template + struct rectangle_distance_type { + typedef typename rectangle_distance_type_by_concept< + T, typename is_rectangle_concept::type>::type>::type type; + }; + + struct y_r_get_interval : gtl_yes {}; + + template + typename enable_if< typename gtl_and::type>::type>::type, + typename rectangle_interval_type::type>::type + get(const T& rectangle, orientation_2d orient) { + return rectangle_traits::get(rectangle, orient); + } + + struct y_r_h : gtl_yes {}; + + template + typename enable_if< typename gtl_and::type>::type>::type, + typename rectangle_interval_type::type>::type + horizontal(const T& rectangle) { + return rectangle_traits::get(rectangle, HORIZONTAL); + } + + struct y_r_v : gtl_yes {}; + + template + typename enable_if< typename gtl_and::type>::type>::type, + typename rectangle_interval_type::type>::type + vertical(const T& rectangle) { + return rectangle_traits::get(rectangle, VERTICAL); + } + + struct y_r_set : gtl_yes {}; + + template + typename enable_if< typename gtl_and_3::type>::type, + typename is_interval_concept::type>::type>::type, + void>::type + set(T& rectangle, const T2& interval) { + rectangle_mutable_traits::set(rectangle, orient, interval); + } + + struct y_r_set2 : gtl_yes {}; + + template + typename enable_if< typename gtl_and_3::type>::type, + typename is_interval_concept::type>::type>::type, + void>::type + set(T& rectangle, orientation_2d orient, const T2& interval) { + rectangle_mutable_traits::set(rectangle, orient, interval); + } + + struct y_r_h2 : gtl_yes {}; + + template + typename enable_if< typename gtl_and_3::type>::type, + typename is_interval_concept::type>::type>::type, + void>::type + horizontal(T& rectangle, const T2& interval) { + rectangle_mutable_traits::set(rectangle, HORIZONTAL, interval); + } + + struct y_r_v2 : gtl_yes {}; + + template + typename enable_if< + typename gtl_and_3::type>::type, + typename is_interval_concept::type>::type>::type, void>::type + vertical(T& rectangle, const T2& interval) { + rectangle_mutable_traits::set(rectangle, VERTICAL, interval); + } + + struct y_r_construct : gtl_yes {}; + + template + typename enable_if< typename gtl_and::type>::type>::type, + T>::type + construct(const T2& interval_horizontal, + const T3& interval_vertical) { + return rectangle_mutable_traits::construct(interval_horizontal, interval_vertical); } + + struct y_r_construct2 : gtl_yes {}; + + template + typename enable_if< typename gtl_and::type>::type>::type, + T>::type + construct(coord_type xl, coord_type yl, coord_type xh, coord_type yh) { + return rectangle_mutable_traits::construct(interval_data(xl, xh), + interval_data(yl, yh)); + } + + struct y_r_cconstruct : gtl_yes {}; + + template + typename enable_if< + typename gtl_and_3::type>::type, + typename is_rectangle_concept::type>::type>::type, + T>::type + copy_construct(const T2& rectangle) { + return construct (get(rectangle, HORIZONTAL), get(rectangle, VERTICAL)); + } + + struct y_r_assign : gtl_yes {}; + + template + typename enable_if< + typename gtl_and_3< y_r_assign, + typename is_mutable_rectangle_concept::type>::type, + typename is_rectangle_concept::type>::type>::type, + rectangle_type_1>::type & + assign(rectangle_type_1& lvalue, const rectangle_type_2& rvalue) { + set(lvalue, HORIZONTAL, get(rvalue, HORIZONTAL)); + set(lvalue, VERTICAL, get(rvalue, VERTICAL)); + return lvalue; + } + + struct y_r_equiv : gtl_yes {}; + + template + typename enable_if< + typename gtl_and_3< y_r_equiv, + typename is_rectangle_concept::type>::type, + typename is_rectangle_concept::type>::type>::type, + bool>::type + equivalence(const T& rect1, const T2& rect2) { + return equivalence(get(rect1, HORIZONTAL), get(rect2, HORIZONTAL)) && + equivalence(get(rect1, VERTICAL), get(rect2, VERTICAL)); + } + + struct y_r_get : gtl_yes {}; + + template + typename enable_if< typename gtl_and::type>::type>::type, + typename rectangle_coordinate_type::type>::type + get(const rectangle_type& rectangle, orientation_2d orient, direction_1d dir) { + return get(rectangle_traits::get(rectangle, orient), dir); + } + + struct y_r_set3 : gtl_yes {}; + + template + typename enable_if::type>::type>::type, void>::type + set(rectangle_type& rectangle, orientation_2d orient, direction_1d dir, + typename rectangle_coordinate_type::type value) { + typename rectangle_interval_type::type ivl = get(rectangle, orient); + set(ivl, dir, value); + set(rectangle, orient, ivl); + } + + struct y_r_xl : gtl_yes {}; + + template + typename enable_if< typename gtl_and::type>::type>::type, + typename rectangle_coordinate_type::type>::type + xl(const rectangle_type& rectangle) { + return get(rectangle, HORIZONTAL, LOW); + } + + struct y_r_xl2 : gtl_yes {}; + + template + typename enable_if::type>::type>::type, void>::type + xl(rectangle_type& rectangle, typename rectangle_coordinate_type::type value) { + return set(rectangle, HORIZONTAL, LOW, value); + } + + struct y_r_xh : gtl_yes {}; + + template + typename enable_if< typename gtl_and::type>::type>::type, + typename rectangle_coordinate_type::type>::type + xh(const rectangle_type& rectangle) { + return get(rectangle, HORIZONTAL, HIGH); + } + + struct y_r_xh2 : gtl_yes {}; + + template + typename enable_if::type>::type>::type, void>::type + xh(rectangle_type& rectangle, typename rectangle_coordinate_type::type value) { + return set(rectangle, HORIZONTAL, HIGH, value); + } + + struct y_r_yl : gtl_yes {}; + + template + typename enable_if< typename gtl_and::type>::type>::type, + typename rectangle_coordinate_type::type>::type + yl(const rectangle_type& rectangle) { + return get(rectangle, VERTICAL, LOW); + } + + struct y_r_yl2 : gtl_yes {}; + + template + typename enable_if::type>::type>::type, void>::type + yl(rectangle_type& rectangle, typename rectangle_coordinate_type::type value) { + return set(rectangle, VERTICAL, LOW, value); + } + + struct y_r_yh : gtl_yes {}; + + template + typename enable_if< typename gtl_and::type>::type>::type, + typename rectangle_coordinate_type::type>::type + yh(const rectangle_type& rectangle) { + return get(rectangle, VERTICAL, HIGH); + } + + struct y_r_yh2 : gtl_yes {}; + + template + typename enable_if::type>::type>::type, void>::type + yh(rectangle_type& rectangle, typename rectangle_coordinate_type::type value) { + return set(rectangle, VERTICAL, HIGH, value); + } + + struct y_r_ll : gtl_yes {}; + + template + typename enable_if::type>::type>::type, + point_data::type> >::type + ll(const rectangle_type& rectangle) { + return point_data::type> (xl(rectangle), yl(rectangle)); + } + + struct y_r_lr : gtl_yes {}; + + template + typename enable_if::type>::type>::type, + point_data::type> >::type + lr(const rectangle_type& rectangle) { + return point_data::type> (xh(rectangle), yl(rectangle)); + } + + struct y_r_ul : gtl_yes {}; + + template + typename enable_if::type>::type>::type, + point_data::type> >::type + ul(const rectangle_type& rectangle) { + return point_data::type> (xl(rectangle), yh(rectangle)); + } + + struct y_r_ur : gtl_yes {}; + + template + typename enable_if::type>::type>::type, + point_data::type> >::type + ur(const rectangle_type& rectangle) { + return point_data::type> (xh(rectangle), yh(rectangle)); + } + + struct y_r_contains : gtl_yes {}; + + template + typename enable_if< typename gtl_and_3::type>::type, + typename is_rectangle_concept::type>::type>::type, + bool>::type + contains(const rectangle_type& rectangle, const rectangle_type_2 rectangle_contained, + bool consider_touch = true) { + return contains(horizontal(rectangle), horizontal(rectangle_contained), consider_touch) && + contains(vertical(rectangle), vertical(rectangle_contained), consider_touch); + } + + struct y_r_contains2 : gtl_yes {}; + + template + typename enable_if< typename gtl_and_3::type>::type, + typename is_point_concept::type>::type>::type, bool>::type + contains(const rectangle_type& rectangle, const point_type point_contained, + bool consider_touch = true) { + return contains(horizontal(rectangle), x(point_contained), consider_touch) && + contains(vertical(rectangle), y(point_contained), consider_touch); + } + + struct y_r_set_points : gtl_yes {}; + + // set all four coordinates based upon two points + template + typename enable_if< typename gtl_and_4< y_r_set_points, + typename is_mutable_rectangle_concept::type>::type, + typename is_point_concept::type>::type, + typename is_point_concept::type>::type>::type, + rectangle_type>::type & + set_points(rectangle_type& rectangle, const point_type_1& p1, + const point_type_2& p2) { + typedef typename rectangle_coordinate_type::type Unit; + Unit x1(x(p1)); + Unit x2(x(p2)); + Unit y1(y(p1)); + Unit y2(y(p2)); + horizontal(rectangle, construct::type>(x1, x2)); + vertical(rectangle, construct::type>(y1, y2)); + return rectangle; + } + + struct y_r_move : gtl_yes {}; + + // move rectangle by delta in orient + template + typename enable_if< typename gtl_and::type>::type>::type, + rectangle_type>::type & + move(rectangle_type& rectangle, orientation_2d orient, + typename coordinate_traits::type>::coordinate_difference delta) { + typename rectangle_interval_type::type ivl = get(rectangle, orient); + move(ivl, delta); + set(rectangle, orient, ivl); + return rectangle; + } + + struct y_r_convolve : gtl_yes {}; + + // convolve this with b + template + typename enable_if< + typename gtl_and_3< y_r_convolve, + typename is_mutable_rectangle_concept::type>::type, + typename is_rectangle_concept::type>::type>::type, + rectangle_type_1>::type & + convolve(rectangle_type_1& rectangle, + const rectangle_type_2& convolution_rectangle) { + typename rectangle_interval_type::type ivl = horizontal(rectangle); + horizontal(rectangle, convolve(ivl, horizontal(convolution_rectangle))); + ivl = vertical(rectangle); + vertical(rectangle, convolve(ivl, vertical(convolution_rectangle))); + return rectangle; + } + + struct y_r_deconvolve : gtl_yes {}; + + // deconvolve this with b + template + typename enable_if< typename gtl_and_3< y_r_deconvolve, + typename is_mutable_rectangle_concept::type>::type, + typename is_rectangle_concept::type>::type>::type, + rectangle_type_1>::type & + deconvolve(rectangle_type_1& rectangle, const rectangle_type_2& convolution_rectangle) { + typename rectangle_interval_type::type ivl = horizontal(rectangle); + horizontal(rectangle, deconvolve(ivl, horizontal(convolution_rectangle))); + ivl = vertical(rectangle); + vertical(rectangle, deconvolve(ivl, vertical(convolution_rectangle))); + return rectangle; + } + + struct y_r_reconvolve : gtl_yes {}; + + // reflectedConvolve this with b + template + typename enable_if< + typename gtl_and_3::type>::type, + typename is_rectangle_concept::type>::type>::type, + rectangle_type_1>::type & + reflected_convolve(rectangle_type_1& rectangle, const rectangle_type_2& convolution_rectangle) { + typename rectangle_interval_type::type ivl = horizontal(rectangle); + horizontal(rectangle, reflected_convolve(ivl, horizontal(convolution_rectangle))); + ivl = vertical(rectangle); + vertical(rectangle, reflected_convolve(ivl, vertical(convolution_rectangle))); + return rectangle; + } + + struct y_r_redeconvolve : gtl_yes {}; + + // reflectedDeconvolve this with b + // deconvolve this with b + template + typename enable_if< + typename gtl_and_3::type>::type, + typename is_rectangle_concept::type>::type>::type, + rectangle_type_1>::type & + reflected_deconvolve(rectangle_type_1& rectangle, const rectangle_type_2& convolution_rectangle) { + typename rectangle_interval_type::type ivl = horizontal(rectangle); + horizontal(rectangle, reflected_deconvolve(ivl, horizontal(convolution_rectangle))); + ivl = vertical(rectangle); + vertical(rectangle, reflected_deconvolve(ivl, vertical(convolution_rectangle))); + return rectangle; + } + + struct y_r_convolve2 : gtl_yes {}; + + // convolve with point + template + typename enable_if< typename gtl_and_3::type>::type, + typename is_point_concept::type>::type>::type, + rectangle_type>::type & + convolve(rectangle_type& rectangle, const point_type& convolution_point) { + typename rectangle_interval_type::type ivl = horizontal(rectangle); + horizontal(rectangle, convolve(ivl, x(convolution_point))); + ivl = vertical(rectangle); + vertical(rectangle, convolve(ivl, y(convolution_point))); + return rectangle; + } + + struct y_r_deconvolve2 : gtl_yes {}; + + // deconvolve with point + template + typename enable_if< + typename gtl_and_3::type>::type, + typename is_point_concept::type>::type>::type, rectangle_type>::type & + deconvolve(rectangle_type& rectangle, const point_type& convolution_point) { + typename rectangle_interval_type::type ivl = horizontal(rectangle); + horizontal(rectangle, deconvolve(ivl, x(convolution_point))); + ivl = vertical(rectangle); + vertical(rectangle, deconvolve(ivl, y(convolution_point))); + return rectangle; + } + + struct y_r_delta : gtl_yes {}; + + // get the magnitude of the interval range depending on orient + template + typename enable_if< typename gtl_and::type>::type>::type, + typename rectangle_difference_type::type>::type + delta(const rectangle_type& rectangle, orientation_2d orient) { + return delta(get(rectangle, orient)); + } + + struct y_r_area : gtl_yes {}; + + // get the area of the rectangle + template + typename enable_if< typename gtl_and::type>::type>::type, + typename coordinate_traits::type>::manhattan_area_type>::type + area(const rectangle_type& rectangle) { + typedef typename coordinate_traits::type>::manhattan_area_type area_type; + return (area_type)delta(rectangle, HORIZONTAL) * (area_type)delta(rectangle, VERTICAL); + } + + struct y_r_go : gtl_yes {}; + + // returns the orientation of the longest side + template + typename enable_if::type>::type>::type, + orientation_2d>::type + guess_orientation(const rectangle_type& rectangle) { + return delta(rectangle, HORIZONTAL) >= delta(rectangle, VERTICAL) ? + HORIZONTAL : VERTICAL; + } + + struct y_r_half_p : gtl_yes {}; + + // get the half perimeter of the rectangle + template + typename enable_if< typename gtl_and::type>::type>::type, + typename rectangle_difference_type::type>::type + half_perimeter(const rectangle_type& rectangle) { + return delta(rectangle, HORIZONTAL) + delta(rectangle, VERTICAL); + } + + struct y_r_perimeter : gtl_yes {}; + + // get the perimeter of the rectangle + template + typename enable_if< typename gtl_and::type>::type>::type, + typename rectangle_difference_type::type>::type + perimeter(const rectangle_type& rectangle) { + return 2 * half_perimeter(rectangle); + } + + struct y_r_intersects : gtl_yes {}; + + // check if Rectangle b intersects `this` Rectangle + // [in] b Rectangle that will be checked + // [in] considerTouch If true, return true even if b touches the boundary + // [ret] . true if `t` intersects b + template + typename enable_if< + typename gtl_and_3::type>::type, + typename is_rectangle_concept::type>::type>::type, + bool>::type + intersects(const rectangle_type_1& rectangle, const rectangle_type_2& b, bool consider_touch = true) { + return intersects(horizontal(rectangle), horizontal(b), consider_touch) && + intersects(vertical(rectangle), vertical(b), consider_touch); + } + + struct y_r_b_intersect : gtl_yes {}; + + // Check if boundaries of Rectangle b and `this` Rectangle intersect + // [in] b Rectangle that will be checked + // [in] considerTouch If true, return true even if p is on the foundary + // [ret] . true if `t` contains p + template + typename enable_if< + typename gtl_and_3::type>::type, + typename is_rectangle_concept::type>::type>::type, + bool>::type + boundaries_intersect(const rectangle_type_1& rectangle, const rectangle_type_2& b, + bool consider_touch = true) { + return (intersects(rectangle, b, consider_touch) && + !(contains(rectangle, b, !consider_touch)) && + !(contains(b, rectangle, !consider_touch))); + } + + struct y_r_b_abuts : gtl_yes {}; + + // check if b is touching 'this' on the end specified by dir + template + typename enable_if< typename gtl_and_3::type>::type, + typename is_rectangle_concept::type>::type>::type, + bool>::type + abuts(const rectangle_type_1& rectangle, const rectangle_type_2& b, + direction_2d dir) { + return + abuts(get(rectangle, orientation_2d(dir)), + get(b, orientation_2d(dir)), + direction_1d(dir)) && + intersects(get(rectangle, orientation_2d(dir).get_perpendicular()), + get(b, orientation_2d(dir).get_perpendicular()), true); + } + + struct y_r_b_abuts2 : gtl_yes {}; + + // check if they are touching in the given orientation + template + typename enable_if< typename gtl_and_3::type>::type, + typename is_rectangle_concept::type>::type>::type, + bool>::type + abuts(const rectangle_type_1& rectangle, const rectangle_type_2& b, + orientation_2d orient) { + return + abuts(get(rectangle, orient), get(b, orient)) && + intersects(get(rectangle, orient.get_perpendicular()), + get(b, orient.get_perpendicular()), true); + } + + struct y_r_b_abuts3 : gtl_yes {}; + + // check if they are touching but not overlapping + template + typename enable_if< typename gtl_and_3::type>::type, + typename is_rectangle_concept::type>::type>::type, + bool>::type + abuts(const rectangle_type_1& rectangle, const rectangle_type_2& b) { + return abuts(rectangle, b, HORIZONTAL) || abuts(rectangle, b, VERTICAL); + } + + struct y_r_b_intersect2 : gtl_yes {}; + + // intersect rectangle with interval on orient + template + typename enable_if< + typename gtl_and_3::type>::type, + typename is_interval_concept::type>::type>::type, + bool>::type + intersect(rectangle_type& rectangle, const interval_type& b, + orientation_2d orient, bool consider_touch = true) { + typename rectangle_interval_type::type ivl = get(rectangle, orient); + if(intersect(ivl, b, consider_touch)) { + set(rectangle, orient, ivl); + return true; + } + return false; + } + + struct y_r_b_intersect3 : gtl_yes {}; + + // clip rectangle to b + template + typename enable_if< typename gtl_and_3::type>::type, + typename is_rectangle_concept::type>::type>::type, + bool>::type + intersect(rectangle_type_1& rectangle, const rectangle_type_2& b, bool consider_touch = true) { + if(intersects(rectangle, b)) { + intersect(rectangle, horizontal(b), HORIZONTAL, consider_touch); + intersect(rectangle, vertical(b), VERTICAL, consider_touch); + return true; + } + return false; + } + + struct y_r_g_intersect : gtl_yes {}; + + // Sets this to the generalized intersection of this and the given rectangle + template + typename enable_if< typename gtl_and_3::type>::type, + typename is_rectangle_concept::type>::type>::type, + rectangle_type_1>::type & + generalized_intersect(rectangle_type_1& rectangle, const rectangle_type_2& b) { + typename rectangle_interval_type::type ivl = get(rectangle, HORIZONTAL); + generalized_intersect(ivl, horizontal(b)); + horizontal(rectangle, ivl); + ivl = vertical(rectangle); + generalized_intersect(ivl, vertical(b)); + vertical(rectangle, ivl); + return rectangle; + } + + struct y_r_bloat : gtl_yes {}; + + // bloat the interval specified by orient by bloating + template + typename enable_if::type>::type>::type, + rectangle_type>::type & + bloat(rectangle_type& rectangle, orientation_2d orient, + typename rectangle_coordinate_type::type bloating) { + typename rectangle_interval_type::type ivl = get(rectangle, orient); + bloat(ivl, bloating); + set(rectangle, orient, ivl); + return rectangle; + } + + struct y_r_bloat2 : gtl_yes {}; + + // bloat the Rectangle by bloating + template + typename enable_if::type>::type>::type, + rectangle_type>::type & + bloat(rectangle_type& rectangle, + typename rectangle_coordinate_type::type bloating) { + bloat(rectangle, HORIZONTAL, bloating); + return bloat(rectangle, VERTICAL, bloating); + } + + struct y_r_bloat3 : gtl_yes {}; + + // bloat the interval cooresponding to orient by bloating in dir direction + template + typename enable_if::type>::type>::type, + rectangle_type>::type & + bloat(rectangle_type& rectangle, direction_2d dir, + typename rectangle_coordinate_type::type bloating) { + typename rectangle_interval_type::type ivl = get(rectangle, orientation_2d(dir)); + bloat(ivl, direction_1d(dir), bloating); + set(rectangle, orientation_2d(dir), ivl); + return rectangle; + } + + struct y_r_shrink : gtl_yes {}; + + // shrink the interval specified by orient by bloating + template + typename enable_if::type>::type>::type, + rectangle_type>::type & + shrink(rectangle_type& rectangle, orientation_2d orient, + typename rectangle_coordinate_type::type shrinking) { + return bloat(rectangle, orient, -shrinking); + } + + struct y_r_shrink2 : gtl_yes {}; + + // shrink the Rectangle by bloating + template + typename enable_if::type>::type>::type, + rectangle_type>::type & + shrink(rectangle_type& rectangle, + typename rectangle_coordinate_type::type shrinking) { + return bloat(rectangle, -shrinking); + } + + struct y_r_shrink3 : gtl_yes {}; + + // shrink the interval cooresponding to orient by bloating in dir direction + template + typename enable_if::type>::type>::type, + rectangle_type>::type & + shrink(rectangle_type& rectangle, direction_2d dir, + typename rectangle_coordinate_type::type shrinking) { + return bloat(rectangle, dir, -shrinking); + } + + struct y_r_encompass : gtl_yes {}; + + // encompass interval on orient + template + typename enable_if::type>::type, + typename is_interval_concept::type>::type>::type, + bool>::type + encompass(rectangle_type& rectangle, const interval_type& b, orientation_2d orient) { + typename rectangle_interval_type::type ivl = get(rectangle, orient); + if(encompass(ivl, b)) { + set(rectangle, orient, ivl); + return true; + } + return false; + } + + struct y_r_encompass2 : gtl_yes {}; + + // enlarge rectangle to encompass the Rectangle b + template + typename enable_if< typename gtl_and_3< + y_r_encompass2, + typename is_mutable_rectangle_concept::type>::type, + typename is_rectangle_concept::type>::type >::type, + bool>::type + encompass(rectangle_type_1& rectangle, const rectangle_type_2& b) { + //note that operator | is intentional because both should be called regardless + return encompass(rectangle, horizontal(b), HORIZONTAL) | + encompass(rectangle, vertical(b), VERTICAL); + } + + struct y_r_encompass3 : gtl_yes {}; + + // enlarge rectangle to encompass the point b + template + typename enable_if::type>::type, + typename is_point_concept::type>::type>::type, + bool>::type + encompass(rectangle_type_1& rectangle, const point_type& b) { + typename rectangle_interval_type::type hivl, vivl; + hivl = horizontal(rectangle); + vivl = vertical(rectangle); + //note that operator | is intentional because both should be called regardless + bool retval = encompass(hivl, x(b)) | encompass(vivl, y(b)); + if(retval) { + horizontal(rectangle, hivl); + vertical(rectangle, vivl); + } + return retval; + } + + struct y_r_center : gtl_yes {}; + + // returns the center of the rectangle + template + typename enable_if< + typename gtl_and_3::type>::type, + typename is_rectangle_concept::type>::type>::type, + bool>::type + center(point_type& center_point, const rectangle_type& rectangle) { + center_point = construct(center(horizontal(rectangle)), + center(vertical(rectangle))); + return true; + } + + struct y_r_get_corner : gtl_yes {}; + + template + typename enable_if< + typename gtl_and_3::type>::type, + typename is_rectangle_concept::type>::type>::type, + bool>::type + get_corner(point_type& corner_point, const rectangle_type& rectangle, direction_2d direction_facing, direction_1d direction_turning) { + typedef typename rectangle_coordinate_type::type Unit; + Unit u1 = get(rectangle, direction_facing); + Unit u2 = get(rectangle, direction_facing.turn(direction_turning)); + if(orientation_2d(direction_facing).to_int()) std::swap(u1, u2); + corner_point = construct(u1, u2); + return true; + } + + struct y_r_get_half : gtl_yes {}; + + template + typename enable_if::type>::type>::type, + rectangle_type>::type + get_half(const rectangle_type& rectangle, direction_2d dir) { + rectangle_type retval(rectangle); + set(retval, orientation_2d(dir), get_half(get(rectangle, orientation_2d(dir)), direction_1d(dir))); + return retval; + } + + struct y_r_join_with : gtl_yes {}; + + template + typename enable_if< typename gtl_and_3::type>::type, + typename is_rectangle_concept::type>::type>::type, + bool>::type + join_with(rectangle_type_1& rectangle, const rectangle_type_2& b) { + typedef typename rectangle_interval_type::type Interval1; + typedef typename rectangle_interval_type::type Interval2; + Interval1 hi1 = get(rectangle, HORIZONTAL); + Interval1 vi1 = get(rectangle, VERTICAL); + Interval2 hi2 = get(b, HORIZONTAL), vi2 = get(b, VERTICAL); + Interval1 temp; + if (equivalence(hi1, hi2) && join_with(vi1, vi2)) { + vertical(rectangle, vi1); + return true; + } + if (equivalence(vi1, vi2) && join_with(hi1, hi2)) { + horizontal(rectangle, hi1); + return true; + } + return false; + } + + struct y_r_eda2 : gtl_yes {}; + + template + typename enable_if< typename gtl_and_3::type>::type, + typename is_point_concept::type>::type>::type, + typename rectangle_difference_type::type>::type + euclidean_distance(const rectangle_type& lvalue, const point_type& rvalue, orientation_2d orient) { + return euclidean_distance(get(lvalue, orient), get(rvalue, orient)); + } + + struct y_r_eda : gtl_yes {}; + + template + typename enable_if< + typename gtl_and_3::type>::type, + typename is_rectangle_concept::type>::type>::type, + typename rectangle_difference_type::type>::type + euclidean_distance(const rectangle_type& lvalue, const rectangle_type_2& rvalue, orientation_2d orient) { + return euclidean_distance(get(lvalue, orient), get(rvalue, orient)); + } + + struct y_r_sed : gtl_yes {}; + + template + typename enable_if< typename gtl_and_3::type>::type, + typename is_point_concept::type>::type>::type, + typename rectangle_difference_type::type>::type + square_euclidean_distance(rectangle_type& lvalue, const point_type& rvalue) { + typename coordinate_traits::type>::coordinate_difference xdist, ydist; + xdist = euclidean_distance(lvalue, rvalue, HORIZONTAL); + ydist = euclidean_distance(lvalue, rvalue, VERTICAL); + return (xdist * xdist) + (ydist * ydist); + } + + struct y_r_sed2 : gtl_yes {}; + + template + typename enable_if< + typename gtl_and_3::type>::type, + typename is_rectangle_concept< typename geometry_concept::type>::type>::type, + typename rectangle_difference_type::type>::type + square_euclidean_distance(const rectangle_type& lvalue, const rectangle_type_2& rvalue) { + typename coordinate_traits::type>::coordinate_difference xdist, ydist; + xdist = euclidean_distance(lvalue, rvalue, HORIZONTAL); + ydist = euclidean_distance(lvalue, rvalue, VERTICAL); + return (xdist * xdist) + (ydist * ydist); + } + + struct y_r_edist : gtl_yes {}; + + template + typename enable_if< typename gtl_and_3::type>::type, + typename is_point_concept::type>::type>::type, + typename rectangle_distance_type::type>::type + euclidean_distance(rectangle_type& lvalue, const point_type& rvalue) { + return std::sqrt((double)(square_euclidean_distance(lvalue, rvalue))); + } + + struct y_r_edist2 : gtl_yes {}; + + template + typename enable_if< typename gtl_and_3::type>::type, + typename is_rectangle_concept::type>::type>::type, + typename rectangle_distance_type::type>::type + euclidean_distance(const rectangle_type& lvalue, const rectangle_type_2& rvalue) { + double val = (int)square_euclidean_distance(lvalue, rvalue); + return std::sqrt(val); + } + + struct y_r_mdist : gtl_yes {}; + + template + typename enable_if< + typename gtl_and_3::type>::type, + typename is_point_concept::type>::type>::type, + typename rectangle_difference_type::type>::type + manhattan_distance(rectangle_type& lvalue, const point_type& rvalue) { + typename coordinate_traits::type>::coordinate_difference xdist, ydist; + xdist = euclidean_distance(lvalue, rvalue, HORIZONTAL); + ydist = euclidean_distance(lvalue, rvalue, VERTICAL); + return xdist + ydist; + } + + struct y_r_mdist2 : gtl_yes {}; + + template + typename enable_if< + typename gtl_and_3::type>::type, + typename is_rectangle_concept::type>::type>::type, + typename rectangle_difference_type::type>::type + manhattan_distance(const rectangle_type& lvalue, const rectangle_type_2& rvalue) { + typename coordinate_traits::type>::coordinate_difference xdist, ydist; + xdist = euclidean_distance(lvalue, rvalue, HORIZONTAL); + ydist = euclidean_distance(lvalue, rvalue, VERTICAL); + return xdist + ydist; + } + + struct y_r_scale_up : gtl_yes {}; + + template + typename enable_if::type>::type>::type, + rectangle_type>::type & + scale_up(rectangle_type& rectangle, + typename coordinate_traits::type>::unsigned_area_type factor) { + typename rectangle_interval_type::type h = horizontal(rectangle); + horizontal(rectangle, scale_up(h, factor)); + typename rectangle_interval_type::type v = vertical(rectangle); + vertical(rectangle, scale_up(v, factor)); + return rectangle; + } + + struct y_r_scale_down : gtl_yes {}; + + template + typename enable_if::type>::type>::type, + rectangle_type>::type & + scale_down(rectangle_type& rectangle, + typename coordinate_traits::type>::unsigned_area_type factor) { + typename rectangle_interval_type::type h = horizontal(rectangle); + horizontal(rectangle, scale_down(h, factor)); + typename rectangle_interval_type::type v = vertical(rectangle); + vertical(rectangle, scale_down(v, factor)); + return rectangle; + } + + struct y_r_scale : gtl_yes {}; + + template + typename enable_if::type>::type>::type, + rectangle_type>::type & + scale(rectangle_type& rectangle, const scaling_type& scaling) { + point_data::type> llp(xl(rectangle), yl(rectangle)); + point_data::type> urp(xl(rectangle), yl(rectangle)); + scale(llp, scaling); + scale(urp, scaling); + set_points(rectangle, llp, urp); + return rectangle; + } + + struct y_r_transform : gtl_yes {}; + + template + typename enable_if::type>::type>::type, + rectangle_type>::type & + transform(rectangle_type& rectangle, const transformation_type& transformation) { + point_data::type> llp(xl(rectangle), yl(rectangle)); + point_data::type> urp(xh(rectangle), yh(rectangle)); + transform(llp, transformation); + transform(urp, transformation); + set_points(rectangle, llp, urp); + return rectangle; + } + + template + class less_rectangle_concept { + private: + orientation_2d orient_; + public: + inline less_rectangle_concept(orientation_2d orient = VERTICAL) : orient_(orient) {} + typename enable_if< + typename gtl_and< typename is_rectangle_concept::type>::type, + typename is_rectangle_concept::type>::type>::type, + bool>::type + operator () (const rectangle_type_1& a, + const rectangle_type_2& b) const { + typedef typename rectangle_coordinate_type::type Unit; + Unit vl1 = get(get(a, orient_), LOW); + Unit vl2 = get(get(b, orient_), LOW); + if(vl1 > vl2) return false; + if(vl1 == vl2) { + orientation_2d perp = orient_.get_perpendicular(); + Unit hl1 = get(get(a, perp), LOW); + Unit hl2 = get(get(b, perp), LOW); + if(hl1 > hl2) return false; + if(hl1 == hl2) { + Unit vh1 = get(get(a, orient_), HIGH); + Unit vh2 = get(get(b, orient_), HIGH); + if(vh1 > vh2) return false; + if(vh1 == vh2) { + Unit hh1 = get(get(a, perp), HIGH); + Unit hh2 = get(get(b, perp), HIGH); + return hh1 < hh2; + } + } + } + return true; + } + + }; + + template + template + inline void rectangle_data::set(orientation_2d orient, const interval_type_1& interval) { + assign(ranges_[orient.to_int()], interval); + } + + template + template + rectangle_data& rectangle_data::operator=(const T2& rvalue) { + assign(*this, rvalue); + return *this; + } + + template + template + bool rectangle_data::operator==(const T2& rvalue) const { + return equivalence(*this, rvalue); + } + + template + struct geometry_concept > { + typedef rectangle_concept type; + }; +} +} +#endif diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/rectangle_data.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/rectangle_data.hpp new file mode 100644 index 0000000..5a1f99e --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/rectangle_data.hpp @@ -0,0 +1,63 @@ +/* + Copyright 2008 Intel Corporation + + Use, modification and distribution are subject to the Boost Software License, + Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at + http://www.boost.org/LICENSE_1_0.txt). +*/ +#ifndef BOOST_POLYGON_RECTANGLE_DATA_HPP +#define BOOST_POLYGON_RECTANGLE_DATA_HPP + +#include "isotropy.hpp" +//interval +#include "interval_data.hpp" + +namespace boost { namespace polygon{ + +template +class rectangle_data { +public: + typedef T coordinate_type; + typedef interval_data interval_type; + inline rectangle_data():ranges_() {} + inline rectangle_data(T xl, T yl, T xh, T yh):ranges_() { + if(xl > xh) std::swap(xl, xh); + if(yl > yh) std::swap(yl, yh); + ranges_[HORIZONTAL] = interval_data(xl, xh); + ranges_[VERTICAL] = interval_data(yl, yh); + } + template + inline rectangle_data(const interval_type_1& hrange, + const interval_type_2& vrange):ranges_() { + set(HORIZONTAL, hrange); set(VERTICAL, vrange); } + + inline rectangle_data(const rectangle_data& that):ranges_() { (*this) = that; } + inline rectangle_data& operator=(const rectangle_data& that) { + ranges_[0] = that.ranges_[0]; ranges_[1] = that.ranges_[1]; return *this; + } + template + inline rectangle_data& operator=(const T2& rvalue); + + template + inline bool operator==(const T2& rvalue) const; + template + inline bool operator!=(const T2& rvalue) const { return !((*this) == rvalue); } + + inline interval_data get(orientation_2d orient) const { + return ranges_[orient.to_int()]; } + inline coordinate_type get(direction_2d dir) const { + return ranges_[orientation_2d(dir).to_int()].get(direction_1d(dir)); + } + inline void set(direction_2d dir, coordinate_type value) { + return ranges_[orientation_2d(dir).to_int()].set(direction_1d(dir), value); + } + template + inline void set(orientation_2d orient, const interval_type_1& interval); +private: + interval_data ranges_[2]; +}; + + +} +} +#endif diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/rectangle_traits.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/rectangle_traits.hpp new file mode 100644 index 0000000..bd49474 --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/rectangle_traits.hpp @@ -0,0 +1,40 @@ +/* + Copyright 2008 Intel Corporation + + Use, modification and distribution are subject to the Boost Software License, + Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at + http://www.boost.org/LICENSE_1_0.txt). +*/ +#ifndef BOOST_POLYGON_RECTANGLE_TRAITS_HPP +#define BOOST_POLYGON_RECTANGLE_TRAITS_HPP + +#include "isotropy.hpp" + +namespace boost { namespace polygon{ + + template + struct rectangle_traits {}; + template + struct rectangle_traits {}; + + template + struct rectangle_traits::type> { + typedef typename T::coordinate_type coordinate_type; + typedef typename T::interval_type interval_type; + static inline interval_type get(const T& rectangle, orientation_2d orient) { + return rectangle.get(orient); } + }; + + template + struct rectangle_mutable_traits { + template + static inline void set(T& rectangle, orientation_2d orient, const T2& interval) { + rectangle.set(orient, interval); } + template + static inline T construct(const T2& interval_horizontal, + const T3& interval_vertical) { + return T(interval_horizontal, interval_vertical); } + }; +} +} +#endif diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/segment_concept.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/segment_concept.hpp new file mode 100644 index 0000000..2f41c1b --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/segment_concept.hpp @@ -0,0 +1,696 @@ +// Boost.Polygon library segment_concept.hpp header file + +// Copyright (c) Intel Corporation 2008. +// Copyright (c) 2008-2012 Simonson Lucanus. +// Copyright (c) 2012-2012 Andrii Sydorchuk. + +// See http://www.boost.org for updates, documentation, and revision history. +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_POLYGON_SEGMENT_CONCEPT_HPP +#define BOOST_POLYGON_SEGMENT_CONCEPT_HPP + +#include "isotropy.hpp" +#include "segment_traits.hpp" +#include "rectangle_concept.hpp" + +namespace boost { +namespace polygon { + +struct segment_concept {}; + +template +struct is_segment_concept { + typedef gtl_no type; +}; + +template <> +struct is_segment_concept { + typedef gtl_yes type; +}; + +template +struct is_mutable_segment_concept { + typedef gtl_no type; +}; + +template <> +struct is_mutable_segment_concept { + typedef gtl_yes type; +}; + +template +struct segment_distance_type_by_concept { + typedef void type; +}; + +template +struct segment_distance_type_by_concept { + typedef typename coordinate_traits< + typename segment_traits::coordinate_type + >::coordinate_distance type; +}; + +template +struct segment_distance_type { + typedef typename segment_distance_type_by_concept< + GeometryType, + typename is_segment_concept< + typename geometry_concept::type + >::type + >::type type; +}; + +template +struct segment_point_type_by_concept { + typedef void type; +}; + +template +struct segment_point_type_by_concept { + typedef typename segment_traits::point_type type; +}; + +template +struct segment_point_type { + typedef typename segment_point_type_by_concept< + GeometryType, + typename is_segment_concept< + typename geometry_concept::type + >::type + >::type type; +}; + +template +struct segment_coordinate_type_by_concept { + typedef void type; +}; + +template +struct segment_coordinate_type_by_concept { + typedef typename segment_traits::coordinate_type type; +}; + +template +struct segment_coordinate_type { + typedef typename segment_coordinate_type_by_concept< + GeometryType, + typename is_segment_concept< + typename geometry_concept::type + >::type + >::type type; +}; + +struct y_s_get : gtl_yes {}; + +template +typename enable_if< + typename gtl_and< + y_s_get, + typename is_segment_concept< + typename geometry_concept::type + >::type + >::type, +typename segment_point_type::type>::type +get(const Segment& segment, direction_1d dir) { + return segment_traits::get(segment, dir); +} + +struct y_s_set : gtl_yes {}; + +template +typename enable_if< + typename gtl_and_3< + y_s_set, + typename is_mutable_segment_concept< + typename geometry_concept::type + >::type, + typename is_point_concept< + typename geometry_concept::type + >::type + >::type, +void>::type set(Segment& segment, direction_1d dir, const Point& point) { + segment_mutable_traits::set(segment, dir, point); +} + +struct y_s_construct : gtl_yes {}; + +template +typename enable_if< + typename gtl_and_4< + y_s_construct, + typename is_mutable_segment_concept< + typename geometry_concept::type + >::type, + typename is_point_concept< + typename geometry_concept::type + >::type, + typename is_point_concept< + typename geometry_concept::type + >::type + >::type, +Segment>::type construct(const Point1& low, const Point2& high) { + return segment_mutable_traits::construct(low, high); +} + +struct y_s_copy_construct : gtl_yes {}; + +template +typename enable_if< + typename gtl_and_3< + y_s_copy_construct, + typename is_mutable_segment_concept< + typename geometry_concept::type + >::type, + typename is_segment_concept< + typename geometry_concept::type + >::type + >::type, +Segment1>::type copy_construct(const Segment2& segment) { + return construct(get(segment, LOW), get(segment, HIGH)); +} + +struct y_s_assign : gtl_yes {}; + +template +typename enable_if< + typename gtl_and_3< + y_s_assign, + typename is_mutable_segment_concept< + typename geometry_concept::type + >::type, + typename is_segment_concept< + typename geometry_concept::type + >::type + >::type, +Segment1>::type& assign(Segment1& segment1, const Segment2& segment2) { + return segment1 = copy_construct(segment2); +} + +struct y_s_equivalence : gtl_yes {}; + +template +typename enable_if< + typename gtl_and_3< + y_s_equivalence, + typename is_segment_concept< + typename geometry_concept::type + >::type, + typename is_segment_concept< + typename geometry_concept::type + >::type + >::type, +bool>::type equivalence(const Segment1& segment1, const Segment2& segment2) { + return get(segment1, LOW) == get(segment2, LOW) && + get(segment1, HIGH) == get(segment2, HIGH); +} + +struct y_s_low : gtl_yes {}; + +template +typename enable_if< + typename gtl_and< + y_s_low, + typename is_segment_concept< + typename geometry_concept::type + >::type + >::type, +typename segment_point_type::type>::type low(const Segment& segment) { + return get(segment, LOW); +} + +struct y_s_high : gtl_yes {}; + +template +typename enable_if< + typename gtl_and< + y_s_high, + typename is_segment_concept< + typename geometry_concept::type + >::type + >::type, +typename segment_point_type::type>::type high(const Segment& segment) { + return get(segment, HIGH); +} + +struct y_s_center : gtl_yes {}; + +template +typename enable_if< + typename gtl_and< + y_s_center, + typename is_segment_concept< + typename geometry_concept::type + >::type + >::type, +typename segment_point_type::type>::type +center(const Segment& segment) { + return construct::type>( + (x(high(segment)) + x(low(segment)))/2, + (y(high(segment)) + y(low(segment)))/2); +} + +struct y_s_low2 : gtl_yes {}; + +template +typename enable_if< + typename gtl_and_3< + y_s_low2, + typename is_mutable_segment_concept< + typename geometry_concept::type + >::type, + typename is_point_concept< + typename geometry_concept::type + >::type + >::type, +void>::type low(Segment& segment, const Point& point) { + set(segment, LOW, point); +} + +struct y_s_high2 : gtl_yes {}; + +template +typename enable_if< + typename gtl_and_3< + y_s_high2, + typename is_mutable_segment_concept< + typename geometry_concept::type + >::type, + typename is_point_concept< + typename geometry_concept::type + >::type + >::type, +void>::type high(Segment& segment, const Point& point) { + set(segment, HIGH, point); +} + +struct y_s_orientation1 : gtl_yes {}; + +// -1 for CW, 0 for collinear and 1 for CCW. +template +typename enable_if< + typename gtl_and_3< + y_s_orientation1, + typename is_segment_concept< + typename geometry_concept::type + >::type, + typename is_segment_concept< + typename geometry_concept::type + >::type + >::type, +int>::type orientation(const Segment1& segment1, const Segment2& segment2) { + typedef typename coordinate_traits< + typename segment_traits::coordinate_type + >::manhattan_area_type int_x2; + typedef typename coordinate_traits< + typename segment_traits::coordinate_type + >::unsigned_area_type uint_x2; + int_x2 a1 = (int_x2)x(high(segment1)) - (int_x2)x(low(segment1)); + int_x2 b1 = (int_x2)y(high(segment1)) - (int_x2)y(low(segment1)); + int_x2 a2 = (int_x2)x(high(segment2)) - (int_x2)x(low(segment2)); + int_x2 b2 = (int_x2)y(high(segment2)) - (int_x2)y(low(segment2)); + + int sign1 = 0; + int sign2 = 0; + if (a1 && b2) + sign1 = ((a1 > 0) ^ (b2 > 0)) ? -1 : 1; + if (a2 && b1) + sign2 = ((a2 > 0) ^ (b1 > 0)) ? -1 : 1; + + if (sign1 != sign2) + return (sign1 < sign2) ? -1 : 1; + uint_x2 a3 = (uint_x2)(a1 < 0 ? -a1 : a1) * (uint_x2)(b2 < 0 ? -b2 : b2); + uint_x2 b3 = (uint_x2)(b1 < 0 ? -b1 : b1) * (uint_x2)(a2 < 0 ? -a2 : a2); + if (a3 == b3) + return 0; + return ((a3 < b3) ^ (sign1 == 1)) ? 1 : -1; +} + +struct y_s_orientation2 : gtl_yes {}; + +// -1 for right, 0 for collinear and 1 for left. +template +typename enable_if< + typename gtl_and_3< + y_s_orientation2, + typename is_segment_concept< + typename geometry_concept::type + >::type, + typename is_point_concept< + typename geometry_concept::type + >::type + >::type, +int>::type orientation(const Segment& segment, const Point& point) { + Segment segment2 = construct(high(segment), point); + return orientation(segment, segment2); +} + +struct y_s_contains : gtl_yes {}; + +template +typename enable_if< + typename gtl_and_3< + y_s_contains, + typename is_segment_concept< + typename geometry_concept::type + >::type, + typename is_point_concept< + typename geometry_concept::type + >::type + >::type, +bool>::type contains(const Segment& segment, + const Point& point, bool consider_touch = true ) { + if (orientation(segment, point)) + return false; + rectangle_data::type> rect; + set_points(rect, low(segment), high(segment)); + if (!contains(rect, point, true)) + return false; + if (!consider_touch && + (equivalence(low(segment), point) || + equivalence(high(segment), point))) + return false; + return true; +} + +struct y_s_contains2 : gtl_yes {}; + +template +typename enable_if< + typename gtl_and_3< + y_s_contains2, + typename is_segment_concept< + typename geometry_concept::type + >::type, + typename is_segment_concept< + typename geometry_concept::type + >::type + >::type, +bool>::type contains(const Segment1& segment1, + const Segment2& segment2, bool consider_touch = true) { + return contains(segment1, get(segment2, LOW), consider_touch) && + contains(segment1, get(segment2, HIGH), consider_touch); +} + +struct y_s_length : gtl_yes {}; + +template +typename enable_if< + typename gtl_and< + y_s_length, + typename is_segment_concept< + typename geometry_concept::type + >::type + >::type, +typename segment_distance_type::type>::type +length(const Segment& segment) { + return euclidean_distance(low(segment), high(segment)); +} + +struct y_s_scale_up : gtl_yes {}; + +template +typename enable_if< + typename gtl_and< + y_s_scale_up, + typename is_mutable_segment_concept< + typename geometry_concept::type + >::type + >::type, +Segment>::type& scale_up(Segment& segment, + typename coordinate_traits< + typename segment_coordinate_type::type + >::unsigned_area_type factor) { + typename segment_point_type::type l = low(segment); + typename segment_point_type::type h = high(segment); + low(segment, scale_up(l, factor)); + high(segment, scale_up(h, factor)); + return segment; +} + +struct y_s_scale_down : gtl_yes {}; + +template +typename enable_if< + typename gtl_and< + y_s_scale_down, + typename is_mutable_segment_concept< + typename geometry_concept::type + >::type + >::type, +Segment>::type& scale_down(Segment& segment, + typename coordinate_traits< + typename segment_coordinate_type::type + >::unsigned_area_type factor) { + typename segment_point_type::type l = low(segment); + typename segment_point_type::type h = high(segment); + low(segment, scale_down(l, factor)); + high(segment, scale_down(h, factor)); + return segment; +} + +struct y_s_scale : gtl_yes {}; + +template +typename enable_if< + typename gtl_and< + y_s_scale, + typename is_mutable_segment_concept< + typename geometry_concept::type + >::type + >::type, +Segment>::type& scale(Segment& segment, const Scale& sc) { + typename segment_point_type::type l = low(segment); + typename segment_point_type::type h = high(segment); + low(segment, scale(l, sc)); + high(segment, scale(h, sc)); + return segment; +} + +struct y_s_transform : gtl_yes {}; + +template +typename enable_if< + typename gtl_and< + y_s_transform, + typename is_mutable_segment_concept< + typename geometry_concept::type + >::type + >::type, +Segment>::type& transform(Segment& segment, const Transform& tr) { + typename segment_point_type::type l = low(segment); + typename segment_point_type::type h = high(segment); + low(segment, transform(l, tr)); + high(segment, transform(h, tr)); + return segment; +} + +struct y_s_move : gtl_yes {}; + +template +typename enable_if< + typename gtl_and< + y_s_move, + typename is_mutable_segment_concept< + typename geometry_concept::type + >::type + >::type, +Segment>::type& move(Segment& segment, orientation_2d orient, + typename segment_coordinate_type::type displacement) { + typename segment_point_type::type l = low(segment); + typename segment_point_type::type h = high(segment); + low(segment, move(l, orient, displacement)); + high(segment, move(h, orient, displacement)); + return segment; +} + +struct y_s_convolve : gtl_yes {}; + +template +typename enable_if< + typename gtl_and_3< + y_s_convolve, + typename is_mutable_segment_concept< + typename geometry_concept::type + >::type, + typename is_point_concept< + typename geometry_concept::type + >::type + >::type, +Segment>::type& convolve(Segment& segment, const Point& point) { + typename segment_point_type::type l = low(segment); + typename segment_point_type::type h = high(segment); + low(segment, convolve(l, point)); + high(segment, convolve(h, point)); + return segment; +} + +struct y_s_deconvolve : gtl_yes {}; + +template +typename enable_if< + typename gtl_and_3< + y_s_deconvolve, + typename is_mutable_segment_concept< + typename geometry_concept::type + >::type, + typename is_point_concept< + typename geometry_concept::type + >::type + >::type, +Segment>::type& deconvolve(Segment& segment, const Point& point) { + typename segment_point_type::type l = low(segment); + typename segment_point_type::type h = high(segment); + low(segment, deconvolve(l, point)); + high(segment, deconvolve(h, point)); + return segment; +} + +struct y_s_abuts1 : gtl_yes {}; + +template +typename enable_if< + typename gtl_and_3< + y_s_abuts1, + typename is_segment_concept< + typename geometry_concept::type + >::type, + typename is_segment_concept< + typename geometry_concept::type + >::type + >::type, +bool>::type abuts(const Segment1& segment1, + const Segment2& segment2, direction_1d dir) { + return dir.to_int() ? equivalence(low(segment2) , high(segment1)) : + equivalence(low(segment1) , high(segment2)); +} + +struct y_s_abuts2 : gtl_yes {}; + +template +typename enable_if< + typename gtl_and_3< + y_s_abuts2, + typename is_segment_concept< + typename geometry_concept::type + >::type, + typename is_segment_concept< + typename geometry_concept::type + >::type + >::type, +bool>::type abuts(const Segment1& segment1, const Segment2& segment2) { + return abuts(segment1, segment2, HIGH) || abuts(segment1, segment2, LOW); +} + +struct y_s_e_intersects : gtl_yes {}; + +template +typename enable_if< + typename gtl_and_3< + y_s_e_intersects, + typename is_segment_concept< + typename geometry_concept::type + >::type, + typename is_segment_concept< + typename geometry_concept::type + >::type + >::type, +bool +>::type intersects(const Segment1& segment1, const Segment2& segment2, + bool consider_touch = true) { + rectangle_data::type> rect1, rect2; + set_points(rect1, low(segment1), high(segment1)); + set_points(rect2, low(segment2), high(segment2)); + // Check if axis-parallel rectangles containing segments intersect. + if (!intersects(rect1, rect2, true)) + return false; + int or1_1 = orientation(segment1, low(segment2)); + int or1_2 = orientation(segment1, high(segment2)); + if (or1_1 * or1_2 > 0) + return false; + int or2_1 = orientation(segment2, low(segment1)); + int or2_2 = orientation(segment2, high(segment1)); + if (or2_1 * or2_2 > 0) + return false; + if (consider_touch || (or1_1 && or1_2) || (or2_1 && or2_2)) + return true; + if (or1_1 || or1_2) + return false; + return intersects(vertical(rect1), vertical(rect2), false) || + intersects(horizontal(rect1), horizontal(rect2), false); +} + +struct y_s_e_dist : gtl_yes {}; + +template +typename enable_if< + typename gtl_and_3< + y_s_e_dist, + typename is_segment_concept< + typename geometry_concept::type + >::type, + typename is_point_concept< + typename geometry_concept::type + >::type + >::type, +typename segment_distance_type::type>::type +euclidean_distance(const Segment& segment, const Point& point) { + typedef typename segment_distance_type::type Unit; + Unit x1 = x(low(segment)); + Unit y1 = y(low(segment)); + Unit x2 = x(high(segment)); + Unit y2 = y(high(segment)); + Unit X = x(point); + Unit Y = y(point); + Unit A = X - x1; + Unit B = Y - y1; + Unit C = x2 - x1; + Unit D = y2 - y1; + Unit param = (A * C + B * D); + Unit length_sq = C * C + D * D; + if (param > length_sq) { + return euclidean_distance(high(segment), point); + } else if (param < 0.0) { + return euclidean_distance(low(segment), point); + } + if (length_sq == 0.0) + return 0.0; + Unit denom = std::sqrt(length_sq); + Unit result = (A * D - C * B) / denom; + return (result < 0.0) ? -result : result; +} + +struct y_s_e_dist2 : gtl_yes {}; + +template +typename enable_if< + typename gtl_and_3< + y_s_e_dist2, + typename is_segment_concept< + typename geometry_concept::type + >::type, + typename is_segment_concept< + typename geometry_concept::type + >::type + >::type, +typename segment_distance_type::type>::type +euclidean_distance(const Segment1& segment1, const Segment2& segment2) { + if (intersects(segment1, segment2)) + return 0.0; + typename segment_distance_type::type + result1 = euclidean_distance(segment1, low(segment2)), + result2 = euclidean_distance(segment1, high(segment2)), + result3 = euclidean_distance(segment2, low(segment1)), + result4 = euclidean_distance(segment2, high(segment1)); + if (result2 < result1) + result1 = result2; + if (result4 < result3) + result3 = result4; + return (result1 < result3) ? result1 : result3; +} +} // polygon +} // boost + +#endif // BOOST_POLYGON_SEGMENT_CONCEPT_HPP diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/segment_data.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/segment_data.hpp new file mode 100644 index 0000000..2bcfe11 --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/segment_data.hpp @@ -0,0 +1,121 @@ +// Boost.Polygon library segment_data.hpp header file + +// Copyright (c) Intel Corporation 2008. +// Copyright (c) 2008-2012 Simonson Lucanus. +// Copyright (c) 2012-2012 Andrii Sydorchuk. + +// See http://www.boost.org for updates, documentation, and revision history. +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_POLYGON_SEGMENT_DATA_HPP +#define BOOST_POLYGON_SEGMENT_DATA_HPP + +#include "isotropy.hpp" +#include "segment_concept.hpp" + +namespace boost { +namespace polygon { + +template +class segment_data { + public: + typedef T coordinate_type; + typedef point_data point_type; + + segment_data() +#ifndef BOOST_POLYGON_MSVC + : points_() +#endif + {} + + segment_data(const point_type& low, const point_type& high) { + points_[LOW] = low; + points_[HIGH] = high; + } + + segment_data(const segment_data& that) { + points_[0] = that.points_[0]; + points_[1] = that.points_[1]; + } + + segment_data& operator=(const segment_data& that) { + points_[0] = that.points_[0]; + points_[1] = that.points_[1]; + return *this; + } + + template + segment_data& operator=(const SegmentType& that) { + assign(*this, that); + return *this; + } + + point_type get(direction_1d dir) const { + return points_[dir.to_int()]; + } + + void set(direction_1d dir, const point_type& point) { + points_[dir.to_int()] = point; + } + + point_type low() const { + return points_[LOW]; + } + + segment_data& low(const point_type& point) { + points_[LOW] = point; + return *this; + } + + point_type high() const { + return points_[HIGH]; + } + + segment_data& high(const point_type& point) { + points_[HIGH] = point; + return *this; + } + + bool operator==(const segment_data& that) const { + return (points_[0] == that.points_[0]) && + (points_[1] == that.points_[1]); + } + + bool operator!=(const segment_data& that) const { + return (points_[0] != that.points_[0]) || + (points_[1] != that.points_[1]); + } + + bool operator<(const segment_data& that) const { + if (points_[0] != that.points_[0]) { + return points_[0] < that.points_[0]; + } + return points_[1] < that.points_[1]; + } + + bool operator<=(const segment_data& that) const { + return !(that < *this); + } + + bool operator>(const segment_data& that) const { + return that < *this; + } + + bool operator>=(const segment_data& that) const { + return !((*this) < that); + } + + private: + point_type points_[2]; +}; + +template +struct geometry_concept > { + typedef segment_concept type; +}; +} // polygon +} // boost + +#endif // BOOST_POLYGON_SEGMENT_DATA_HPP diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/segment_traits.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/segment_traits.hpp new file mode 100644 index 0000000..cb092bd --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/segment_traits.hpp @@ -0,0 +1,50 @@ +// Boost.Polygon library segment_traits.hpp header file + +// Copyright (c) Intel Corporation 2008. +// Copyright (c) 2008-2012 Simonson Lucanus. +// Copyright (c) 2012-2012 Andrii Sydorchuk. + +// See http://www.boost.org for updates, documentation, and revision history. +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_POLYGON_SEGMENT_TRAITS_HPP +#define BOOST_POLYGON_SEGMENT_TRAITS_HPP + +#include "isotropy.hpp" + +namespace boost { +namespace polygon { + +template +struct segment_traits { + typedef Segment segment_type; + typedef typename segment_type::point_type point_type; + typedef typename segment_type::coordinate_type coordinate_type; + + static point_type get( + const segment_type& segment, direction_1d dir) { + return segment.get(dir); + } +}; + +template +struct segment_mutable_traits { + typedef Segment segment_type; + typedef typename segment_type::point_type point_type; + typedef typename segment_type::coordinate_type coordinate_type; + + static void set( + segment_type& segment, direction_1d dir, const point_type& point) { + segment.set(dir, point); + } + + static segment_type construct(const point_type& low, const point_type& high) { + return segment_type(low, high); + } +}; +} // polygon +} // boost + +#endif // BOOST_POLYGON_SEGMENT_TRAITS_HPP diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/segment_utils.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/segment_utils.hpp new file mode 100644 index 0000000..075f7c3 --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/segment_utils.hpp @@ -0,0 +1,164 @@ +/* + Copyright 2012 Lucanus Simonson + + Use, modification and distribution are subject to the Boost Software License, + Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at + http://www.boost.org/LICENSE_1_0.txt). +*/ + +#ifndef BOOST_POLYGON_SEGMENT_UTILS_HPP +#define BOOST_POLYGON_SEGMENT_UTILS_HPP + +#include +#include +#include + +#include "detail/scan_arbitrary.hpp" +#include "isotropy.hpp" +#include "rectangle_concept.hpp" +#include "segment_concept.hpp" + +namespace boost { +namespace polygon { + +template +typename enable_if< + typename gtl_and< + typename gtl_if< + typename is_segment_concept< + typename geometry_concept< + typename std::iterator_traits::value_type + >::type + >::type + >::type, + typename gtl_if< + typename is_segment_concept< + typename geometry_concept::type + >::type + >::type + >::type, + void +>::type +intersect_segments( + std::vector >& result, + SegmentIterator first, SegmentIterator last) { + typedef typename segment_traits::coordinate_type Unit; + typedef typename scanline_base::Point Point; + typedef typename scanline_base::half_edge half_edge; + typedef int segment_id; + std::vector > half_edges; + std::vector > half_edges_out; + segment_id id_in = 0; + half_edges.reserve(std::distance(first, last)); + for (; first != last; ++first) { + Point l, h; + assign(l, low(*first)); + assign(h, high(*first)); + half_edges.push_back(std::make_pair(half_edge(l, h), id_in++)); + } + half_edges_out.reserve(half_edges.size()); + // Apparently no need to pre-sort data when calling validate_scan. + if (half_edges.size() != 0) { + line_intersection::validate_scan( + half_edges_out, half_edges.begin(), half_edges.end()); + } + + result.reserve(result.size() + half_edges_out.size()); + for (std::size_t i = 0; i < half_edges_out.size(); ++i) { + std::size_t id = (std::size_t)(half_edges_out[i].second); + Point l = half_edges_out[i].first.first; + Point h = half_edges_out[i].first.second; + result.push_back(std::make_pair(id, construct(l, h))); + } +} + +template +typename enable_if< + typename gtl_and< + typename gtl_if< + typename is_segment_concept< + typename geometry_concept< + typename std::iterator_traits::value_type + >::type + >::type + >::type, + typename gtl_if< + typename is_segment_concept< + typename geometry_concept< + typename SegmentContainer::value_type + >::type + >::type + >::type + >::type, + void +>::type +intersect_segments( + SegmentContainer& result, + SegmentIterator first, + SegmentIterator last) { + typedef typename SegmentContainer::value_type segment_type; + typedef typename segment_traits::coordinate_type Unit; + typedef typename scanline_base::Point Point; + typedef typename scanline_base::half_edge half_edge; + typedef int segment_id; + std::vector > half_edges; + std::vector > half_edges_out; + segment_id id_in = 0; + half_edges.reserve(std::distance(first, last)); + for (; first != last; ++first) { + Point l, h; + assign(l, low(*first)); + assign(h, high(*first)); + half_edges.push_back(std::make_pair(half_edge(l, h), id_in++)); + } + half_edges_out.reserve(half_edges.size()); + // Apparently no need to pre-sort data when calling validate_scan. + if (half_edges.size() != 0) { + line_intersection::validate_scan( + half_edges_out, half_edges.begin(), half_edges.end()); + } + + result.reserve(result.size() + half_edges_out.size()); + for (std::size_t i = 0; i < half_edges_out.size(); ++i) { + Point l = half_edges_out[i].first.first; + Point h = half_edges_out[i].first.second; + result.push_back(construct(l, h)); + } +} + +template +typename enable_if< + typename gtl_and< + typename gtl_if< + typename is_rectangle_concept< + typename geometry_concept::type + >::type + >::type, + typename gtl_if< + typename is_segment_concept< + typename geometry_concept< + typename std::iterator_traits::value_type + >::type + >::type + >::type + >::type, + bool +>::type +envelope_segments( + Rectangle& rect, + SegmentIterator first, + SegmentIterator last) { + for (SegmentIterator it = first; it != last; ++it) { + if (it == first) { + set_points(rect, low(*it), high(*it)); + } else { + encompass(rect, low(*it)); + encompass(rect, high(*it)); + } + } + return first != last; +} +} // polygon +} // boost + +#endif // BOOST_POLYGON_SEGMENT_UTILS_HPP diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/transform.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/transform.hpp new file mode 100644 index 0000000..1bb0cd9 --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/transform.hpp @@ -0,0 +1,476 @@ +// Boost.Polygon library transform.hpp header file + +// Copyright (c) Intel Corporation 2008. +// Copyright (c) 2008-2012 Simonson Lucanus. +// Copyright (c) 2012-2012 Andrii Sydorchuk. + +// See http://www.boost.org for updates, documentation, and revision history. +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_POLYGON_TRANSFORM_HPP +#define BOOST_POLYGON_TRANSFORM_HPP + +#include "isotropy.hpp" + +namespace boost { +namespace polygon { +// Transformation of Coordinate System. +// Enum meaning: +// Select which direction_2d to change the positive direction of each +// axis in the old coordinate system to map it to the new coordiante system. +// The first direction_2d listed for each enum is the direction to map the +// positive horizontal direction to. +// The second direction_2d listed for each enum is the direction to map the +// positive vertical direction to. +// The zero position bit (LSB) indicates whether the horizontal axis flips +// when transformed. +// The 1st postion bit indicates whether the vertical axis flips when +// transformed. +// The 2nd position bit indicates whether the horizontal and vertical axis +// swap positions when transformed. +// Enum Values: +// 000 EAST NORTH +// 001 WEST NORTH +// 010 EAST SOUTH +// 011 WEST SOUTH +// 100 NORTH EAST +// 101 SOUTH EAST +// 110 NORTH WEST +// 111 SOUTH WEST +class axis_transformation { + public: + enum ATR { +#ifdef BOOST_POLYGON_ENABLE_DEPRECATED + EN = 0, + WN = 1, + ES = 2, + WS = 3, + NE = 4, + SE = 5, + NW = 6, + SW = 7, +#endif + NULL_TRANSFORM = 0, + BEGIN_TRANSFORM = 0, + EAST_NORTH = 0, + WEST_NORTH = 1, FLIP_X = 1, + EAST_SOUTH = 2, FLIP_Y = 2, + WEST_SOUTH = 3, FLIP_XY = 3, + NORTH_EAST = 4, SWAP_XY = 4, + SOUTH_EAST = 5, ROTATE_LEFT = 5, + NORTH_WEST = 6, ROTATE_RIGHT = 6, + SOUTH_WEST = 7, FLIP_SWAP_XY = 7, + END_TRANSFORM = 7 + }; + + // Individual axis enum values indicate which axis an implicit individual + // axis will be mapped to. + // The value of the enum paired with an axis provides the information + // about what the axis will transform to. + // Three individual axis values, one for each axis, are equivalent to one + // ATR enum value, but easier to work with because they are independent. + // Converting to and from the individual axis values from the ATR value + // is a convenient way to implement tranformation related functionality. + // Enum meanings: + // PX: map to positive x axis + // NX: map to negative x axis + // PY: map to positive y axis + // NY: map to negative y axis + enum INDIVIDUAL_AXIS { + PX = 0, + NX = 1, + PY = 2, + NY = 3 + }; + + axis_transformation() : atr_(NULL_TRANSFORM) {} + explicit axis_transformation(ATR atr) : atr_(atr) {} + axis_transformation(const axis_transformation& atr) : atr_(atr.atr_) {} + + explicit axis_transformation(const orientation_2d& orient) { + const ATR tmp[2] = { + NORTH_EAST, // sort x, then y + EAST_NORTH // sort y, then x + }; + atr_ = tmp[orient.to_int()]; + } + + explicit axis_transformation(const direction_2d& dir) { + const ATR tmp[4] = { + SOUTH_EAST, // sort x, then y + NORTH_EAST, // sort x, then y + EAST_SOUTH, // sort y, then x + EAST_NORTH // sort y, then x + }; + atr_ = tmp[dir.to_int()]; + } + + // assignment operator + axis_transformation& operator=(const axis_transformation& a) { + atr_ = a.atr_; + return *this; + } + + // assignment operator + axis_transformation& operator=(const ATR& atr) { + atr_ = atr; + return *this; + } + + // equivalence operator + bool operator==(const axis_transformation& a) const { + return atr_ == a.atr_; + } + + // inequivalence operator + bool operator!=(const axis_transformation& a) const { + return !(*this == a); + } + + // ordering + bool operator<(const axis_transformation& a) const { + return atr_ < a.atr_; + } + + // concatenate this with that + axis_transformation& operator+=(const axis_transformation& a) { + bool abit2 = (a.atr_ & 4) != 0; + bool abit1 = (a.atr_ & 2) != 0; + bool abit0 = (a.atr_ & 1) != 0; + bool bit2 = (atr_ & 4) != 0; + bool bit1 = (atr_ & 2) != 0; + bool bit0 = (atr_ & 1) != 0; + int indexes[2][2] = { + { (int)bit2, (int)(!bit2) }, + { (int)abit2, (int)(!abit2) } + }; + int zero_bits[2][2] = { + {bit0, bit1}, {abit0, abit1} + }; + int nbit1 = zero_bits[0][1] ^ zero_bits[1][indexes[0][1]]; + int nbit0 = zero_bits[0][0] ^ zero_bits[1][indexes[0][0]]; + indexes[0][0] = indexes[1][indexes[0][0]]; + indexes[0][1] = indexes[1][indexes[0][1]]; + int nbit2 = indexes[0][0] & 1; // swap xy + atr_ = (ATR)((nbit2 << 2) + (nbit1 << 1) + nbit0); + return *this; + } + + // concatenation operator + axis_transformation operator+(const axis_transformation& a) const { + axis_transformation retval(*this); + return retval+=a; + } + + // populate_axis_array writes the three INDIVIDUAL_AXIS values that the + // ATR enum value of 'this' represent into axis_array + void populate_axis_array(INDIVIDUAL_AXIS axis_array[]) const { + bool bit2 = (atr_ & 4) != 0; + bool bit1 = (atr_ & 2) != 0; + bool bit0 = (atr_ & 1) != 0; + axis_array[1] = (INDIVIDUAL_AXIS)(((int)(!bit2) << 1) + bit1); + axis_array[0] = (INDIVIDUAL_AXIS)(((int)(bit2) << 1) + bit0); + } + + // it is recommended that the directions stored in an array + // in the caller code for easier isotropic access by orientation value + void get_directions(direction_2d& horizontal_dir, + direction_2d& vertical_dir) const { + bool bit2 = (atr_ & 4) != 0; + bool bit1 = (atr_ & 2) != 0; + bool bit0 = (atr_ & 1) != 0; + vertical_dir = direction_2d((direction_2d_enum)(((int)(!bit2) << 1) + !bit1)); + horizontal_dir = direction_2d((direction_2d_enum)(((int)(bit2) << 1) + !bit0)); + } + + // combine_axis_arrays concatenates this_array and that_array overwriting + // the result into this_array + static void combine_axis_arrays(INDIVIDUAL_AXIS this_array[], + const INDIVIDUAL_AXIS that_array[]) { + int indexes[2] = { this_array[0] >> 1, this_array[1] >> 1 }; + int zero_bits[2][2] = { + { this_array[0] & 1, this_array[1] & 1 }, + { that_array[0] & 1, that_array[1] & 1 } + }; + this_array[0] = (INDIVIDUAL_AXIS)((int)this_array[0] | + ((int)zero_bits[0][0] ^ + (int)zero_bits[1][indexes[0]])); + this_array[1] = (INDIVIDUAL_AXIS)((int)this_array[1] | + ((int)zero_bits[0][1] ^ + (int)zero_bits[1][indexes[1]])); + } + + // write_back_axis_array converts an array of three INDIVIDUAL_AXIS values + // to the ATR enum value and sets 'this' to that value + void write_back_axis_array(const INDIVIDUAL_AXIS this_array[]) { + int bit2 = ((int)this_array[0] & 2) != 0; // swap xy + int bit1 = ((int)this_array[1] & 1); + int bit0 = ((int)this_array[0] & 1); + atr_ = ATR((bit2 << 2) + (bit1 << 1) + bit0); + } + + // behavior is deterministic but undefined in the case where illegal + // combinations of directions are passed in. + axis_transformation& set_directions(const direction_2d& horizontal_dir, + const direction_2d& vertical_dir) { + int bit2 = (static_cast(horizontal_dir).to_int()) != 0; + int bit1 = !(vertical_dir.to_int() & 1); + int bit0 = !(horizontal_dir.to_int() & 1); + atr_ = ATR((bit2 << 2) + (bit1 << 1) + bit0); + return *this; + } + + // transform the three coordinates by reference + template + void transform(coordinate_type& x, coordinate_type& y) const { + int bit2 = (atr_ & 4) != 0; + int bit1 = (atr_ & 2) != 0; + int bit0 = (atr_ & 1) != 0; + x *= -((bit0 << 1) - 1); + y *= -((bit1 << 1) - 1); + predicated_swap(bit2 != 0, x, y); + } + + // invert this axis_transformation + axis_transformation& invert() { + int bit2 = ((atr_ & 4) != 0); + int bit1 = ((atr_ & 2) != 0); + int bit0 = ((atr_ & 1) != 0); + // swap bit 0 and bit 1 if bit2 is 1 + predicated_swap(bit2 != 0, bit0, bit1); + bit1 = bit1 << 1; + atr_ = (ATR)(atr_ & (32+16+8+4)); // mask away bit0 and bit1 + atr_ = (ATR)(atr_ | bit0 | bit1); + return *this; + } + + // get the inverse axis_transformation of this + axis_transformation inverse() const { + axis_transformation retval(*this); + return retval.invert(); + } + + private: + ATR atr_; +}; + +// Scaling object to be used to store the scale factor for each axis. +// For use by the transformation object, in that context the scale factor +// is the amount that each axis scales by when transformed. +template +class anisotropic_scale_factor { + public: + anisotropic_scale_factor() { + scale_[0] = 1; + scale_[1] = 1; + } + anisotropic_scale_factor(scale_factor_type xscale, + scale_factor_type yscale) { + scale_[0] = xscale; + scale_[1] = yscale; + } + + // get a component of the anisotropic_scale_factor by orientation + scale_factor_type get(orientation_2d orient) const { + return scale_[orient.to_int()]; + } + + // set a component of the anisotropic_scale_factor by orientation + void set(orientation_2d orient, scale_factor_type value) { + scale_[orient.to_int()] = value; + } + + scale_factor_type x() const { + return scale_[HORIZONTAL]; + } + + scale_factor_type y() const { + return scale_[VERTICAL]; + } + + void x(scale_factor_type value) { + scale_[HORIZONTAL] = value; + } + + void y(scale_factor_type value) { + scale_[VERTICAL] = value; + } + + // concatination operator (convolve scale factors) + anisotropic_scale_factor operator+(const anisotropic_scale_factor& s) const { + anisotropic_scale_factor retval(*this); + return retval += s; + } + + // concatinate this with that + const anisotropic_scale_factor& operator+=( + const anisotropic_scale_factor& s) { + scale_[0] *= s.scale_[0]; + scale_[1] *= s.scale_[1]; + return *this; + } + + // transform this scale with an axis_transform + anisotropic_scale_factor& transform(axis_transformation atr) { + direction_2d dirs[2]; + atr.get_directions(dirs[0], dirs[1]); + scale_factor_type tmp[2] = {scale_[0], scale_[1]}; + for (int i = 0; i < 2; ++i) { + scale_[orientation_2d(dirs[i]).to_int()] = tmp[i]; + } + return *this; + } + + // scale the two coordinates + template + void scale(coordinate_type& x, coordinate_type& y) const { + x = scaling_policy::round( + (scale_factor_type)x * get(HORIZONTAL)); + y = scaling_policy::round( + (scale_factor_type)y * get(HORIZONTAL)); + } + + // invert this scale factor to give the reverse scale factor + anisotropic_scale_factor& invert() { + x(1/x()); + y(1/y()); + return *this; + } + + private: + scale_factor_type scale_[2]; +}; + +// Transformation object, stores and provides services for transformations. +// Consits of axis transformation, scale factor and translation. +// The tranlation is the position of the origin of the new coordinate system of +// in the old system. Coordinates are scaled before they are transformed. +template +class transformation { + public: + transformation() : atr_(), p_(0, 0) {} + explicit transformation(axis_transformation atr) : atr_(atr), p_(0, 0) {} + explicit transformation(axis_transformation::ATR atr) : atr_(atr), p_(0, 0) {} + transformation(const transformation& tr) : atr_(tr.atr_), p_(tr.p_) {} + + template + explicit transformation(const point_type& p) : atr_(), p_(0, 0) { + set_translation(p); + } + + template + transformation(axis_transformation atr, + const point_type& p) : atr_(atr), p_(0, 0) { + set_translation(p); + } + + template + transformation(axis_transformation atr, + const point_type& referencePt, + const point_type& destinationPt) : atr_(), p_(0, 0) { + transformation tmp(referencePt); + transformation rotRef(atr); + transformation tmpInverse = tmp.inverse(); + point_type decon(referencePt); + deconvolve(decon, destinationPt); + transformation displacement(decon); + tmp += rotRef; + tmp += tmpInverse; + tmp += displacement; + (*this) = tmp; + } + + // equivalence operator + bool operator==(const transformation& tr) const { + return (atr_ == tr.atr_) && (p_ == tr.p_); + } + + // inequivalence operator + bool operator!=(const transformation& tr) const { + return !(*this == tr); + } + + // ordering + bool operator<(const transformation& tr) const { + return (atr_ < tr.atr_) || ((atr_ == tr.atr_) && (p_ < tr.p_)); + } + + // concatenation operator + transformation operator+(const transformation& tr) const { + transformation retval(*this); + return retval+=tr; + } + + // concatenate this with that + const transformation& operator+=(const transformation& tr) { + coordinate_type x, y; + transformation inv = inverse(); + inv.transform(x, y); + p_.set(HORIZONTAL, p_.get(HORIZONTAL) + x); + p_.set(VERTICAL, p_.get(VERTICAL) + y); + // concatenate axis transforms + atr_ += tr.atr_; + return *this; + } + + // get the axis_transformation portion of this + axis_transformation get_axis_transformation() const { + return atr_; + } + + // set the axis_transformation portion of this + void set_axis_transformation(const axis_transformation& atr) { + atr_ = atr; + } + + // get the translation + template + void get_translation(point_type& p) const { + assign(p, p_); + } + + // set the translation + template + void set_translation(const point_type& p) { + assign(p_, p); + } + + // apply the 2D portion of this transformation to the two coordinates given + void transform(coordinate_type& x, coordinate_type& y) const { + y -= p_.get(VERTICAL); + x -= p_.get(HORIZONTAL); + atr_.transform(x, y); + } + + // invert this transformation + transformation& invert() { + coordinate_type x = p_.get(HORIZONTAL), y = p_.get(VERTICAL); + atr_.transform(x, y); + x *= -1; + y *= -1; + p_ = point_data(x, y); + atr_.invert(); + return *this; + } + + // get the inverse of this transformation + transformation inverse() const { + transformation ret_val(*this); + return ret_val.invert(); + } + + void get_directions(direction_2d& horizontal_dir, + direction_2d& vertical_dir) const { + return atr_.get_directions(horizontal_dir, vertical_dir); + } + + private: + axis_transformation atr_; + point_data p_; +}; +} // polygon +} // boost + +#endif // BOOST_POLYGON_TRANSFORM_HPP diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/voronoi.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/voronoi.hpp new file mode 100644 index 0000000..bca6add --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/voronoi.hpp @@ -0,0 +1,157 @@ +// Boost.Polygon library voronoi.hpp header file + +// Copyright Andrii Sydorchuk 2010-2012. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +#ifndef BOOST_POLYGON_VORONOI +#define BOOST_POLYGON_VORONOI + +#include "isotropy.hpp" +#include "point_concept.hpp" +#include "segment_concept.hpp" + +#include "voronoi_builder.hpp" +#include "voronoi_diagram.hpp" + +// Public methods to compute Voronoi diagram of a set of points and segments. +// Coordinates of the points and of the endpoints of the segments should belong +// to the 32-bit signed integer range [-2^31, 2^31-1]. To use wider input +// coordinate range voronoi_builder configuration via coordinate type traits +// is required. +// Complexity - O(N*logN), memory usage - O(N), N - number of input objects. +namespace boost { +namespace polygon { + +template +typename enable_if< + typename gtl_if< + typename is_point_concept< + typename geometry_concept::type + >::type + >::type, + std::size_t +>::type insert(const Point& point, VB* vb) { + return vb->insert_point(x(point), y(point)); +} + +template +typename enable_if< + typename gtl_if< + typename is_point_concept< + typename geometry_concept< + typename std::iterator_traits::value_type + >::type + >::type + >::type, + void +>::type insert(const PointIterator first, const PointIterator last, VB* vb) { + for (PointIterator it = first; it != last; ++it) { + insert(*it, vb); + } +} + +template +typename enable_if< + typename gtl_if< + typename is_segment_concept< + typename geometry_concept::type + >::type + >::type, + std::size_t +>::type insert(const Segment& segment, VB* vb) { + return vb->insert_segment( + x(low(segment)), y(low(segment)), + x(high(segment)), y(high(segment))); +} + +template +typename enable_if< + typename gtl_if< + typename is_segment_concept< + typename geometry_concept< + typename std::iterator_traits::value_type + >::type + >::type + >::type, + void +>::type insert(const SegmentIterator first, + const SegmentIterator last, + VB* vb) { + for (SegmentIterator it = first; it != last; ++it) { + insert(*it, vb); + } +} + +template +typename enable_if< + typename gtl_if< + typename is_point_concept< + typename geometry_concept< + typename std::iterator_traits::value_type + >::type + >::type + >::type, + void +>::type construct_voronoi(const PointIterator first, + const PointIterator last, + VD* vd) { + default_voronoi_builder builder; + insert(first, last, &builder); + builder.construct(vd); +} + +template +typename enable_if< + typename gtl_if< + typename is_segment_concept< + typename geometry_concept< + typename std::iterator_traits::value_type + >::type + >::type + >::type, + void +>::type construct_voronoi(const SegmentIterator first, + const SegmentIterator last, + VD* vd) { + default_voronoi_builder builder; + insert(first, last, &builder); + builder.construct(vd); +} + +template +typename enable_if< + typename gtl_and< + typename gtl_if< + typename is_point_concept< + typename geometry_concept< + typename std::iterator_traits::value_type + >::type + >::type + >::type, + typename gtl_if< + typename is_segment_concept< + typename geometry_concept< + typename std::iterator_traits::value_type + >::type + >::type + >::type + >::type, + void +>::type construct_voronoi(const PointIterator p_first, + const PointIterator p_last, + const SegmentIterator s_first, + const SegmentIterator s_last, + VD* vd) { + default_voronoi_builder builder; + insert(p_first, p_last, &builder); + insert(s_first, s_last, &builder); + builder.construct(vd); +} +} // polygon +} // boost + +#endif // BOOST_POLYGON_VORONOI diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/voronoi_builder.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/voronoi_builder.hpp new file mode 100644 index 0000000..6a3d504 --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/voronoi_builder.hpp @@ -0,0 +1,521 @@ +// Boost.Polygon library voronoi_builder.hpp header file + +// Copyright Andrii Sydorchuk 2010-2012. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +#ifndef BOOST_POLYGON_VORONOI_BUILDER +#define BOOST_POLYGON_VORONOI_BUILDER + +#include +#include +#include +#include +#include + +#include "detail/voronoi_ctypes.hpp" +#include "detail/voronoi_predicates.hpp" +#include "detail/voronoi_structures.hpp" + +#include "voronoi_geometry_type.hpp" + +namespace boost { +namespace polygon { +// GENERAL INFO: +// The sweepline algorithm implementation to compute Voronoi diagram of +// points and non-intersecting segments (excluding endpoints). +// Complexity - O(N*logN), memory usage - O(N), where N is the total number +// of input geometries. +// +// CONTRACT: +// 1) Input geometries should have integral (e.g. int32, int64) coordinate type. +// 2) Input geometries should not intersect except their endpoints. +// +// IMPLEMENTATION DETAILS: +// Each input point creates one input site. Each input segment creates three +// input sites: two for its endpoints and one for the segment itself (this is +// made to simplify output construction). All the site objects are constructed +// and sorted at the algorithm initialization step. Priority queue is used to +// dynamically hold circle events. At each step of the algorithm execution the +// leftmost event is retrieved by comparing the current site event and the +// topmost element from the circle event queue. STL map (red-black tree) +// container was chosen to hold state of the beach line. The keys of the map +// correspond to the neighboring sites that form a bisector and values map to +// the corresponding Voronoi edges in the output data structure. +template , + typename VP = detail::voronoi_predicates > +class voronoi_builder { + public: + typedef typename CTT::int_type int_type; + typedef typename CTT::fpt_type fpt_type; + + voronoi_builder() : index_(0) {} + + // Each point creates a single site event. + std::size_t insert_point(const int_type& x, const int_type& y) { + site_events_.push_back(site_event_type(x, y)); + site_events_.back().initial_index(index_); + site_events_.back().source_category(SOURCE_CATEGORY_SINGLE_POINT); + return index_++; + } + + // Each segment creates three site events that correspond to: + // 1) the start point of the segment; + // 2) the end point of the segment; + // 3) the segment itself defined by its start point. + std::size_t insert_segment( + const int_type& x1, const int_type& y1, + const int_type& x2, const int_type& y2) { + // Set up start point site. + point_type p1(x1, y1); + site_events_.push_back(site_event_type(p1)); + site_events_.back().initial_index(index_); + site_events_.back().source_category(SOURCE_CATEGORY_SEGMENT_START_POINT); + + // Set up end point site. + point_type p2(x2, y2); + site_events_.push_back(site_event_type(p2)); + site_events_.back().initial_index(index_); + site_events_.back().source_category(SOURCE_CATEGORY_SEGMENT_END_POINT); + + // Set up segment site. + if (point_comparison_(p1, p2)) { + site_events_.push_back(site_event_type(p1, p2)); + site_events_.back().source_category(SOURCE_CATEGORY_INITIAL_SEGMENT); + } else { + site_events_.push_back(site_event_type(p2, p1)); + site_events_.back().source_category(SOURCE_CATEGORY_REVERSE_SEGMENT); + } + site_events_.back().initial_index(index_); + return index_++; + } + + // Run sweepline algorithm and fill output data structure. + template + void construct(OUTPUT* output) { + // Init structures. + output->_reserve(site_events_.size()); + init_sites_queue(); + init_beach_line(output); + + // The algorithm stops when there are no events to process. + event_comparison_predicate event_comparison; + while (!circle_events_.empty() || + !(site_event_iterator_ == site_events_.end())) { + if (circle_events_.empty()) { + process_site_event(output); + } else if (site_event_iterator_ == site_events_.end()) { + process_circle_event(output); + } else { + if (event_comparison(*site_event_iterator_, + circle_events_.top().first)) { + process_site_event(output); + } else { + process_circle_event(output); + } + } + while (!circle_events_.empty() && + !circle_events_.top().first.is_active()) { + circle_events_.pop(); + } + } + beach_line_.clear(); + + // Finish construction. + output->_build(); + } + + void clear() { + index_ = 0; + site_events_.clear(); + } + + private: + typedef detail::point_2d point_type; + typedef detail::site_event site_event_type; + typedef typename std::vector::const_iterator + site_event_iterator_type; + typedef detail::circle_event circle_event_type; + typedef typename VP::template point_comparison_predicate + point_comparison_predicate; + typedef typename VP:: + template event_comparison_predicate + event_comparison_predicate; + typedef typename VP:: + template circle_formation_predicate + circle_formation_predicate_type; + typedef void edge_type; + typedef detail::beach_line_node_key key_type; + typedef detail::beach_line_node_data + value_type; + typedef typename VP::template node_comparison_predicate + node_comparer_type; + typedef std::map< key_type, value_type, node_comparer_type > beach_line_type; + typedef typename beach_line_type::iterator beach_line_iterator; + typedef std::pair event_type; + struct event_comparison_type { + bool operator()(const event_type& lhs, const event_type& rhs) const { + return predicate(rhs.first, lhs.first); + } + event_comparison_predicate predicate; + }; + typedef detail::ordered_queue + circle_event_queue_type; + typedef std::pair end_point_type; + + void init_sites_queue() { + // Sort site events. + std::sort(site_events_.begin(), site_events_.end(), + event_comparison_predicate()); + + // Remove duplicates. + site_events_.erase(std::unique( + site_events_.begin(), site_events_.end()), site_events_.end()); + + // Index sites. + for (std::size_t cur = 0; cur < site_events_.size(); ++cur) { + site_events_[cur].sorted_index(cur); + } + + // Init site iterator. + site_event_iterator_ = site_events_.begin(); + } + + template + void init_beach_line(OUTPUT* output) { + if (site_events_.empty()) + return; + if (site_events_.size() == 1) { + // Handle single site event case. + output->_process_single_site(site_events_[0]); + ++site_event_iterator_; + } else { + int skip = 0; + + while (site_event_iterator_ != site_events_.end() && + VP::is_vertical(site_event_iterator_->point0(), + site_events_.begin()->point0()) && + VP::is_vertical(*site_event_iterator_)) { + ++site_event_iterator_; + ++skip; + } + + if (skip == 1) { + // Init beach line with the first two sites. + init_beach_line_default(output); + } else { + // Init beach line with collinear vertical sites. + init_beach_line_collinear_sites(output); + } + } + } + + // Init beach line with the two first sites. + // The first site is always a point. + template + void init_beach_line_default(OUTPUT* output) { + // Get the first and the second site event. + site_event_iterator_type it_first = site_events_.begin(); + site_event_iterator_type it_second = site_events_.begin(); + ++it_second; + insert_new_arc( + *it_first, *it_first, *it_second, beach_line_.end(), output); + // The second site was already processed. Move the iterator. + ++site_event_iterator_; + } + + // Init beach line with collinear sites. + template + void init_beach_line_collinear_sites(OUTPUT* output) { + site_event_iterator_type it_first = site_events_.begin(); + site_event_iterator_type it_second = site_events_.begin(); + ++it_second; + while (it_second != site_event_iterator_) { + // Create a new beach line node. + key_type new_node(*it_first, *it_second); + + // Update the output. + edge_type* edge = output->_insert_new_edge(*it_first, *it_second).first; + + // Insert a new bisector into the beach line. + beach_line_.insert(beach_line_.end(), + std::pair(new_node, value_type(edge))); + + // Update iterators. + ++it_first; + ++it_second; + } + } + + void deactivate_circle_event(value_type* value) { + if (value->circle_event()) { + value->circle_event()->deactivate(); + value->circle_event(NULL); + } + } + + template + void process_site_event(OUTPUT* output) { + // Get next site event to process. + site_event_type site_event = *site_event_iterator_; + + // Move site iterator. + site_event_iterator_type last = site_event_iterator_ + 1; + + // If a new site is an end point of some segment, + // remove temporary nodes from the beach line data structure. + if (!site_event.is_segment()) { + while (!end_points_.empty() && + end_points_.top().first == site_event.point0()) { + beach_line_iterator b_it = end_points_.top().second; + end_points_.pop(); + beach_line_.erase(b_it); + } + } else { + while (last != site_events_.end() && + last->is_segment() && last->point0() == site_event.point0()) + ++last; + } + + // Find the node in the binary search tree with left arc + // lying above the new site point. + key_type new_key(*site_event_iterator_); + beach_line_iterator right_it = beach_line_.lower_bound(new_key); + + for (; site_event_iterator_ != last; ++site_event_iterator_) { + site_event = *site_event_iterator_; + beach_line_iterator left_it = right_it; + + // Do further processing depending on the above node position. + // For any two neighboring nodes the second site of the first node + // is the same as the first site of the second node. + if (right_it == beach_line_.end()) { + // The above arc corresponds to the second arc of the last node. + // Move the iterator to the last node. + --left_it; + + // Get the second site of the last node + const site_event_type& site_arc = left_it->first.right_site(); + + // Insert new nodes into the beach line. Update the output. + right_it = insert_new_arc( + site_arc, site_arc, site_event, right_it, output); + + // Add a candidate circle to the circle event queue. + // There could be only one new circle event formed by + // a new bisector and the one on the left. + activate_circle_event(left_it->first.left_site(), + left_it->first.right_site(), + site_event, right_it); + } else if (right_it == beach_line_.begin()) { + // The above arc corresponds to the first site of the first node. + const site_event_type& site_arc = right_it->first.left_site(); + + // Insert new nodes into the beach line. Update the output. + left_it = insert_new_arc( + site_arc, site_arc, site_event, right_it, output); + + // If the site event is a segment, update its direction. + if (site_event.is_segment()) { + site_event.inverse(); + } + + // Add a candidate circle to the circle event queue. + // There could be only one new circle event formed by + // a new bisector and the one on the right. + activate_circle_event(site_event, right_it->first.left_site(), + right_it->first.right_site(), right_it); + right_it = left_it; + } else { + // The above arc corresponds neither to the first, + // nor to the last site in the beach line. + const site_event_type& site_arc2 = right_it->first.left_site(); + const site_event_type& site3 = right_it->first.right_site(); + + // Remove the candidate circle from the event queue. + deactivate_circle_event(&right_it->second); + --left_it; + const site_event_type& site_arc1 = left_it->first.right_site(); + const site_event_type& site1 = left_it->first.left_site(); + + // Insert new nodes into the beach line. Update the output. + beach_line_iterator new_node_it = + insert_new_arc(site_arc1, site_arc2, site_event, right_it, output); + + // Add candidate circles to the circle event queue. + // There could be up to two circle events formed by + // a new bisector and the one on the left or right. + activate_circle_event(site1, site_arc1, site_event, new_node_it); + + // If the site event is a segment, update its direction. + if (site_event.is_segment()) { + site_event.inverse(); + } + activate_circle_event(site_event, site_arc2, site3, right_it); + right_it = new_node_it; + } + } + } + + // In general case circle event is made of the three consecutive sites + // that form two bisectors in the beach line data structure. + // Let circle event sites be A, B, C, two bisectors that define + // circle event are (A, B), (B, C). During circle event processing + // we remove (A, B), (B, C) and insert (A, C). As beach line comparison + // works correctly only if one of the nodes is a new one we remove + // (B, C) bisector and change (A, B) bisector to the (A, C). That's + // why we use const_cast there and take all the responsibility that + // map data structure keeps correct ordering. + template + void process_circle_event(OUTPUT* output) { + // Get the topmost circle event. + const event_type& e = circle_events_.top(); + const circle_event_type& circle_event = e.first; + beach_line_iterator it_first = e.second; + beach_line_iterator it_last = it_first; + + // Get the C site. + site_event_type site3 = it_first->first.right_site(); + + // Get the half-edge corresponding to the second bisector - (B, C). + edge_type* bisector2 = it_first->second.edge(); + + // Get the half-edge corresponding to the first bisector - (A, B). + --it_first; + edge_type* bisector1 = it_first->second.edge(); + + // Get the A site. + site_event_type site1 = it_first->first.left_site(); + + if (!site1.is_segment() && site3.is_segment() && + site3.point1() == site1.point0()) { + site3.inverse(); + } + + // Change the (A, B) bisector node to the (A, C) bisector node. + const_cast(it_first->first).right_site(site3); + + // Insert the new bisector into the beach line. + it_first->second.edge(output->_insert_new_edge( + site1, site3, circle_event, bisector1, bisector2).first); + + // Remove the (B, C) bisector node from the beach line. + beach_line_.erase(it_last); + it_last = it_first; + + // Pop the topmost circle event from the event queue. + circle_events_.pop(); + + // Check new triplets formed by the neighboring arcs + // to the left for potential circle events. + if (it_first != beach_line_.begin()) { + deactivate_circle_event(&it_first->second); + --it_first; + const site_event_type& site_l1 = it_first->first.left_site(); + activate_circle_event(site_l1, site1, site3, it_last); + } + + // Check the new triplet formed by the neighboring arcs + // to the right for potential circle events. + ++it_last; + if (it_last != beach_line_.end()) { + deactivate_circle_event(&it_last->second); + const site_event_type& site_r1 = it_last->first.right_site(); + activate_circle_event(site1, site3, site_r1, it_last); + } + } + + // Insert new nodes into the beach line. Update the output. + template + beach_line_iterator insert_new_arc( + const site_event_type& site_arc1, const site_event_type &site_arc2, + const site_event_type& site_event, beach_line_iterator position, + OUTPUT* output) { + // Create two new bisectors with opposite directions. + key_type new_left_node(site_arc1, site_event); + key_type new_right_node(site_event, site_arc2); + + // Set correct orientation for the first site of the second node. + if (site_event.is_segment()) { + new_right_node.left_site().inverse(); + } + + // Update the output. + std::pair edges = + output->_insert_new_edge(site_arc2, site_event); + position = beach_line_.insert(position, + typename beach_line_type::value_type( + new_right_node, value_type(edges.second))); + + if (site_event.is_segment()) { + // Update the beach line with temporary bisector, that will + // disappear after processing site event corresponding to the + // second endpoint of the segment site. + key_type new_node(site_event, site_event); + new_node.right_site().inverse(); + position = beach_line_.insert(position, + typename beach_line_type::value_type(new_node, value_type(NULL))); + + // Update the data structure that holds temporary bisectors. + end_points_.push(std::make_pair(site_event.point1(), position)); + } + + position = beach_line_.insert(position, + typename beach_line_type::value_type( + new_left_node, value_type(edges.first))); + + return position; + } + + // Add a new circle event to the event queue. + // bisector_node corresponds to the (site2, site3) bisector. + void activate_circle_event(const site_event_type& site1, + const site_event_type& site2, + const site_event_type& site3, + beach_line_iterator bisector_node) { + circle_event_type c_event; + // Check if the three input sites create a circle event. + if (circle_formation_predicate_(site1, site2, site3, c_event)) { + // Add the new circle event to the circle events queue. + // Update bisector's circle event iterator to point to the + // new circle event in the circle event queue. + event_type& e = circle_events_.push( + std::pair( + c_event, bisector_node)); + bisector_node->second.circle_event(&e.first); + } + } + + private: + point_comparison_predicate point_comparison_; + struct end_point_comparison { + bool operator() (const end_point_type& end1, + const end_point_type& end2) const { + return point_comparison(end2.first, end1.first); + } + point_comparison_predicate point_comparison; + }; + + std::vector site_events_; + site_event_iterator_type site_event_iterator_; + std::priority_queue< end_point_type, std::vector, + end_point_comparison > end_points_; + circle_event_queue_type circle_events_; + beach_line_type beach_line_; + circle_formation_predicate_type circle_formation_predicate_; + std::size_t index_; + + // Disallow copy constructor and operator= + voronoi_builder(const voronoi_builder&); + void operator=(const voronoi_builder&); +}; + +typedef voronoi_builder default_voronoi_builder; +} // polygon +} // boost + +#endif // BOOST_POLYGON_VORONOI_BUILDER diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/voronoi_diagram.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/voronoi_diagram.hpp new file mode 100644 index 0000000..a8eb933 --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/voronoi_diagram.hpp @@ -0,0 +1,620 @@ +// Boost.Polygon library voronoi_diagram.hpp header file + +// Copyright Andrii Sydorchuk 2010-2012. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +#ifndef BOOST_POLYGON_VORONOI_DIAGRAM +#define BOOST_POLYGON_VORONOI_DIAGRAM + +#include +#include + +#include "detail/voronoi_ctypes.hpp" +#include "detail/voronoi_structures.hpp" + +#include "voronoi_geometry_type.hpp" + +namespace boost { +namespace polygon { + +// Forward declarations. +template +class voronoi_edge; + +// Represents Voronoi cell. +// Data members: +// 1) index of the source within the initial input set +// 2) pointer to the incident edge +// 3) mutable color member +// Cell may contain point or segment site inside. +template +class voronoi_cell { + public: + typedef T coordinate_type; + typedef std::size_t color_type; + typedef voronoi_edge voronoi_edge_type; + typedef std::size_t source_index_type; + typedef SourceCategory source_category_type; + + voronoi_cell(source_index_type source_index, + source_category_type source_category) : + source_index_(source_index), + incident_edge_(NULL), + color_(source_category) {} + + // Returns true if the cell contains point site, false else. + bool contains_point() const { + source_category_type source_category = this->source_category(); + return belongs(source_category, GEOMETRY_CATEGORY_POINT); + } + + // Returns true if the cell contains segment site, false else. + bool contains_segment() const { + source_category_type source_category = this->source_category(); + return belongs(source_category, GEOMETRY_CATEGORY_SEGMENT); + } + + source_index_type source_index() const { + return source_index_; + } + + source_category_type source_category() const { + return static_cast(color_ & SOURCE_CATEGORY_BITMASK); + } + + // Degenerate cells don't have any incident edges. + bool is_degenerate() const { return incident_edge_ == NULL; } + + voronoi_edge_type* incident_edge() { return incident_edge_; } + const voronoi_edge_type* incident_edge() const { return incident_edge_; } + void incident_edge(voronoi_edge_type* e) { incident_edge_ = e; } + + color_type color() const { return color_ >> BITS_SHIFT; } + void color(color_type color) const { + color_ &= BITS_MASK; + color_ |= color << BITS_SHIFT; + } + + private: + // 5 color bits are reserved. + enum Bits { + BITS_SHIFT = 0x5, + BITS_MASK = 0x1F + }; + + source_index_type source_index_; + voronoi_edge_type* incident_edge_; + mutable color_type color_; +}; + +// Represents Voronoi vertex. +// Data members: +// 1) vertex coordinates +// 2) pointer to the incident edge +// 3) mutable color member +template +class voronoi_vertex { + public: + typedef T coordinate_type; + typedef std::size_t color_type; + typedef voronoi_edge voronoi_edge_type; + + voronoi_vertex(const coordinate_type& x, const coordinate_type& y) : + x_(x), + y_(y), + incident_edge_(NULL), + color_(0) {} + + const coordinate_type& x() const { return x_; } + const coordinate_type& y() const { return y_; } + + bool is_degenerate() const { return incident_edge_ == NULL; } + + voronoi_edge_type* incident_edge() { return incident_edge_; } + const voronoi_edge_type* incident_edge() const { return incident_edge_; } + void incident_edge(voronoi_edge_type* e) { incident_edge_ = e; } + + color_type color() const { return color_ >> BITS_SHIFT; } + void color(color_type color) const { + color_ &= BITS_MASK; + color_ |= color << BITS_SHIFT; + } + + private: + // 5 color bits are reserved. + enum Bits { + BITS_SHIFT = 0x5, + BITS_MASK = 0x1F + }; + + coordinate_type x_; + coordinate_type y_; + voronoi_edge_type* incident_edge_; + mutable color_type color_; +}; + +// Half-edge data structure. Represents Voronoi edge. +// Data members: +// 1) pointer to the corresponding cell +// 2) pointer to the vertex that is the starting +// point of the half-edge +// 3) pointer to the twin edge +// 4) pointer to the CCW next edge +// 5) pointer to the CCW prev edge +// 6) mutable color member +template +class voronoi_edge { + public: + typedef T coordinate_type; + typedef voronoi_cell voronoi_cell_type; + typedef voronoi_vertex voronoi_vertex_type; + typedef voronoi_edge voronoi_edge_type; + typedef std::size_t color_type; + + voronoi_edge(bool is_linear, bool is_primary) : + cell_(NULL), + vertex_(NULL), + twin_(NULL), + next_(NULL), + prev_(NULL), + color_(0) { + if (is_linear) + color_ |= BIT_IS_LINEAR; + if (is_primary) + color_ |= BIT_IS_PRIMARY; + } + + voronoi_cell_type* cell() { return cell_; } + const voronoi_cell_type* cell() const { return cell_; } + void cell(voronoi_cell_type* c) { cell_ = c; } + + voronoi_vertex_type* vertex0() { return vertex_; } + const voronoi_vertex_type* vertex0() const { return vertex_; } + void vertex0(voronoi_vertex_type* v) { vertex_ = v; } + + voronoi_vertex_type* vertex1() { return twin_->vertex0(); } + const voronoi_vertex_type* vertex1() const { return twin_->vertex0(); } + + voronoi_edge_type* twin() { return twin_; } + const voronoi_edge_type* twin() const { return twin_; } + void twin(voronoi_edge_type* e) { twin_ = e; } + + voronoi_edge_type* next() { return next_; } + const voronoi_edge_type* next() const { return next_; } + void next(voronoi_edge_type* e) { next_ = e; } + + voronoi_edge_type* prev() { return prev_; } + const voronoi_edge_type* prev() const { return prev_; } + void prev(voronoi_edge_type* e) { prev_ = e; } + + // Returns a pointer to the rotation next edge + // over the starting point of the half-edge. + voronoi_edge_type* rot_next() { return prev_->twin(); } + const voronoi_edge_type* rot_next() const { return prev_->twin(); } + + // Returns a pointer to the rotation prev edge + // over the starting point of the half-edge. + voronoi_edge_type* rot_prev() { return twin_->next(); } + const voronoi_edge_type* rot_prev() const { return twin_->next(); } + + // Returns true if the edge is finite (segment, parabolic arc). + // Returns false if the edge is infinite (ray, line). + bool is_finite() const { return vertex0() && vertex1(); } + + // Returns true if the edge is infinite (ray, line). + // Returns false if the edge is finite (segment, parabolic arc). + bool is_infinite() const { return !vertex0() || !vertex1(); } + + // Returns true if the edge is linear (segment, ray, line). + // Returns false if the edge is curved (parabolic arc). + bool is_linear() const { + return (color_ & BIT_IS_LINEAR) ? true : false; + } + + // Returns true if the edge is curved (parabolic arc). + // Returns false if the edge is linear (segment, ray, line). + bool is_curved() const { + return (color_ & BIT_IS_LINEAR) ? false : true; + } + + // Returns false if edge goes through the endpoint of the segment. + // Returns true else. + bool is_primary() const { + return (color_ & BIT_IS_PRIMARY) ? true : false; + } + + // Returns true if edge goes through the endpoint of the segment. + // Returns false else. + bool is_secondary() const { + return (color_ & BIT_IS_PRIMARY) ? false : true; + } + + color_type color() const { return color_ >> BITS_SHIFT; } + void color(color_type color) const { + color_ &= BITS_MASK; + color_ |= color << BITS_SHIFT; + } + + private: + // 5 color bits are reserved. + enum Bits { + BIT_IS_LINEAR = 0x1, // linear is opposite to curved + BIT_IS_PRIMARY = 0x2, // primary is opposite to secondary + + BITS_SHIFT = 0x5, + BITS_MASK = 0x1F + }; + + voronoi_cell_type* cell_; + voronoi_vertex_type* vertex_; + voronoi_edge_type* twin_; + voronoi_edge_type* next_; + voronoi_edge_type* prev_; + mutable color_type color_; +}; + +template +struct voronoi_diagram_traits { + typedef T coordinate_type; + typedef voronoi_cell cell_type; + typedef voronoi_vertex vertex_type; + typedef voronoi_edge edge_type; + class vertex_equality_predicate_type { + public: + enum { ULPS = 128 }; + bool operator()(const vertex_type& v1, const vertex_type& v2) const { + return (ulp_cmp(v1.x(), v2.x(), ULPS) == + detail::ulp_comparison::EQUAL) && + (ulp_cmp(v1.y(), v2.y(), ULPS) == + detail::ulp_comparison::EQUAL); + } + private: + typename detail::ulp_comparison ulp_cmp; + }; +}; + +// Voronoi output data structure. +// CCW ordering is used on the faces perimeter and around the vertices. +template > +class voronoi_diagram { + public: + typedef typename TRAITS::coordinate_type coordinate_type; + typedef typename TRAITS::cell_type cell_type; + typedef typename TRAITS::vertex_type vertex_type; + typedef typename TRAITS::edge_type edge_type; + + typedef std::vector cell_container_type; + typedef typename cell_container_type::const_iterator const_cell_iterator; + + typedef std::vector vertex_container_type; + typedef typename vertex_container_type::const_iterator const_vertex_iterator; + + typedef std::vector edge_container_type; + typedef typename edge_container_type::const_iterator const_edge_iterator; + + voronoi_diagram() {} + + void clear() { + cells_.clear(); + vertices_.clear(); + edges_.clear(); + } + + const cell_container_type& cells() const { + return cells_; + } + + const vertex_container_type& vertices() const { + return vertices_; + } + + const edge_container_type& edges() const { + return edges_; + } + + std::size_t num_cells() const { + return cells_.size(); + } + + std::size_t num_edges() const { + return edges_.size(); + } + + std::size_t num_vertices() const { + return vertices_.size(); + } + + void _reserve(std::size_t num_sites) { + cells_.reserve(num_sites); + vertices_.reserve(num_sites << 1); + edges_.reserve((num_sites << 2) + (num_sites << 1)); + } + + template + void _process_single_site(const detail::site_event& site) { + cells_.push_back(cell_type(site.initial_index(), site.source_category())); + } + + // Insert a new half-edge into the output data structure. + // Takes as input left and right sites that form a new bisector. + // Returns a pair of pointers to a new half-edges. + template + std::pair _insert_new_edge( + const detail::site_event& site1, + const detail::site_event& site2) { + // Get sites' indexes. + std::size_t site_index1 = site1.sorted_index(); + std::size_t site_index2 = site2.sorted_index(); + + bool is_linear = is_linear_edge(site1, site2); + bool is_primary = is_primary_edge(site1, site2); + + // Create a new half-edge that belongs to the first site. + edges_.push_back(edge_type(is_linear, is_primary)); + edge_type& edge1 = edges_.back(); + + // Create a new half-edge that belongs to the second site. + edges_.push_back(edge_type(is_linear, is_primary)); + edge_type& edge2 = edges_.back(); + + // Add the initial cell during the first edge insertion. + if (cells_.empty()) { + cells_.push_back(cell_type( + site1.initial_index(), site1.source_category())); + } + + // The second site represents a new site during site event + // processing. Add a new cell to the cell records. + cells_.push_back(cell_type( + site2.initial_index(), site2.source_category())); + + // Set up pointers to cells. + edge1.cell(&cells_[site_index1]); + edge2.cell(&cells_[site_index2]); + + // Set up twin pointers. + edge1.twin(&edge2); + edge2.twin(&edge1); + + // Return a pointer to the new half-edge. + return std::make_pair(&edge1, &edge2); + } + + // Insert a new half-edge into the output data structure with the + // start at the point where two previously added half-edges intersect. + // Takes as input two sites that create a new bisector, circle event + // that corresponds to the intersection point of the two old half-edges, + // pointers to those half-edges. Half-edges' direction goes out of the + // new Voronoi vertex point. Returns a pair of pointers to a new half-edges. + template + std::pair _insert_new_edge( + const detail::site_event& site1, + const detail::site_event& site3, + const detail::circle_event& circle, + void* data12, void* data23) { + edge_type* edge12 = static_cast(data12); + edge_type* edge23 = static_cast(data23); + + // Add a new Voronoi vertex. + vertices_.push_back(vertex_type(circle.x(), circle.y())); + vertex_type& new_vertex = vertices_.back(); + + // Update vertex pointers of the old edges. + edge12->vertex0(&new_vertex); + edge23->vertex0(&new_vertex); + + bool is_linear = is_linear_edge(site1, site3); + bool is_primary = is_primary_edge(site1, site3); + + // Add a new half-edge. + edges_.push_back(edge_type(is_linear, is_primary)); + edge_type& new_edge1 = edges_.back(); + new_edge1.cell(&cells_[site1.sorted_index()]); + + // Add a new half-edge. + edges_.push_back(edge_type(is_linear, is_primary)); + edge_type& new_edge2 = edges_.back(); + new_edge2.cell(&cells_[site3.sorted_index()]); + + // Update twin pointers. + new_edge1.twin(&new_edge2); + new_edge2.twin(&new_edge1); + + // Update vertex pointer. + new_edge2.vertex0(&new_vertex); + + // Update Voronoi prev/next pointers. + edge12->prev(&new_edge1); + new_edge1.next(edge12); + edge12->twin()->next(edge23); + edge23->prev(edge12->twin()); + edge23->twin()->next(&new_edge2); + new_edge2.prev(edge23->twin()); + + // Return a pointer to the new half-edge. + return std::make_pair(&new_edge1, &new_edge2); + } + + void _build() { + // Remove degenerate edges. + edge_iterator last_edge = edges_.begin(); + for (edge_iterator it = edges_.begin(); it != edges_.end(); it += 2) { + const vertex_type* v1 = it->vertex0(); + const vertex_type* v2 = it->vertex1(); + if (v1 && v2 && vertex_equality_predicate_(*v1, *v2)) { + remove_edge(&(*it)); + } else { + if (it != last_edge) { + edge_type* e1 = &(*last_edge = *it); + edge_type* e2 = &(*(last_edge + 1) = *(it + 1)); + e1->twin(e2); + e2->twin(e1); + if (e1->prev()) { + e1->prev()->next(e1); + e2->next()->prev(e2); + } + if (e2->prev()) { + e1->next()->prev(e1); + e2->prev()->next(e2); + } + } + last_edge += 2; + } + } + edges_.erase(last_edge, edges_.end()); + + // Set up incident edge pointers for cells and vertices. + for (edge_iterator it = edges_.begin(); it != edges_.end(); ++it) { + it->cell()->incident_edge(&(*it)); + if (it->vertex0()) { + it->vertex0()->incident_edge(&(*it)); + } + } + + // Remove degenerate vertices. + vertex_iterator last_vertex = vertices_.begin(); + for (vertex_iterator it = vertices_.begin(); it != vertices_.end(); ++it) { + if (it->incident_edge()) { + if (it != last_vertex) { + *last_vertex = *it; + vertex_type* v = &(*last_vertex); + edge_type* e = v->incident_edge(); + do { + e->vertex0(v); + e = e->rot_next(); + } while (e != v->incident_edge()); + } + ++last_vertex; + } + } + vertices_.erase(last_vertex, vertices_.end()); + + // Set up next/prev pointers for infinite edges. + if (vertices_.empty()) { + if (!edges_.empty()) { + // Update prev/next pointers for the line edges. + edge_iterator edge_it = edges_.begin(); + edge_type* edge1 = &(*edge_it); + edge1->next(edge1); + edge1->prev(edge1); + ++edge_it; + edge1 = &(*edge_it); + ++edge_it; + + while (edge_it != edges_.end()) { + edge_type* edge2 = &(*edge_it); + ++edge_it; + + edge1->next(edge2); + edge1->prev(edge2); + edge2->next(edge1); + edge2->prev(edge1); + + edge1 = &(*edge_it); + ++edge_it; + } + + edge1->next(edge1); + edge1->prev(edge1); + } + } else { + // Update prev/next pointers for the ray edges. + for (cell_iterator cell_it = cells_.begin(); + cell_it != cells_.end(); ++cell_it) { + if (cell_it->is_degenerate()) + continue; + // Move to the previous edge while + // it is possible in the CW direction. + edge_type* left_edge = cell_it->incident_edge(); + while (left_edge->prev() != NULL) { + left_edge = left_edge->prev(); + // Terminate if this is not a boundary cell. + if (left_edge == cell_it->incident_edge()) + break; + } + + if (left_edge->prev() != NULL) + continue; + + edge_type* right_edge = cell_it->incident_edge(); + while (right_edge->next() != NULL) + right_edge = right_edge->next(); + left_edge->prev(right_edge); + right_edge->next(left_edge); + } + } + } + + private: + typedef typename cell_container_type::iterator cell_iterator; + typedef typename vertex_container_type::iterator vertex_iterator; + typedef typename edge_container_type::iterator edge_iterator; + typedef typename TRAITS::vertex_equality_predicate_type + vertex_equality_predicate_type; + + template + bool is_primary_edge(const SEvent& site1, const SEvent& site2) const { + bool flag1 = site1.is_segment(); + bool flag2 = site2.is_segment(); + if (flag1 && !flag2) { + return (site1.point0() != site2.point0()) && + (site1.point1() != site2.point0()); + } + if (!flag1 && flag2) { + return (site2.point0() != site1.point0()) && + (site2.point1() != site1.point0()); + } + return true; + } + + template + bool is_linear_edge(const SEvent& site1, const SEvent& site2) const { + if (!is_primary_edge(site1, site2)) { + return true; + } + return !(site1.is_segment() ^ site2.is_segment()); + } + + // Remove degenerate edge. + void remove_edge(edge_type* edge) { + // Update the endpoints of the incident edges to the second vertex. + vertex_type* vertex = edge->vertex0(); + edge_type* updated_edge = edge->twin()->rot_next(); + while (updated_edge != edge->twin()) { + updated_edge->vertex0(vertex); + updated_edge = updated_edge->rot_next(); + } + + edge_type* edge1 = edge; + edge_type* edge2 = edge->twin(); + + edge_type* edge1_rot_prev = edge1->rot_prev(); + edge_type* edge1_rot_next = edge1->rot_next(); + + edge_type* edge2_rot_prev = edge2->rot_prev(); + edge_type* edge2_rot_next = edge2->rot_next(); + + // Update prev/next pointers for the incident edges. + edge1_rot_next->twin()->next(edge2_rot_prev); + edge2_rot_prev->prev(edge1_rot_next->twin()); + edge1_rot_prev->prev(edge2_rot_next->twin()); + edge2_rot_next->twin()->next(edge1_rot_prev); + } + + cell_container_type cells_; + vertex_container_type vertices_; + edge_container_type edges_; + vertex_equality_predicate_type vertex_equality_predicate_; + + // Disallow copy constructor and operator= + voronoi_diagram(const voronoi_diagram&); + void operator=(const voronoi_diagram&); +}; +} // polygon +} // boost + +#endif // BOOST_POLYGON_VORONOI_DIAGRAM diff --git a/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/voronoi_geometry_type.hpp b/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/voronoi_geometry_type.hpp new file mode 100644 index 0000000..1de80e5 --- /dev/null +++ b/PCUT/MinkowskiCpp/boost_1_84_0/boost/polygon/voronoi_geometry_type.hpp @@ -0,0 +1,48 @@ +// Boost.Polygon library voronoi_geometry_type.hpp header file + +// Copyright Andrii Sydorchuk 2010-2012. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +#ifndef BOOST_POLYGON_VORONOI_GEOMETRY_TYPE +#define BOOST_POLYGON_VORONOI_GEOMETRY_TYPE + +#include + +namespace boost { +namespace polygon { +// Represents topology type of the voronoi site. +enum GeometryCategory { + GEOMETRY_CATEGORY_POINT = 0x0, + GEOMETRY_CATEGORY_SEGMENT = 0x1 +}; + +// Represents category of the input source that forms Voronoi cell. +enum SourceCategory { + // Point subtypes. + SOURCE_CATEGORY_SINGLE_POINT = 0x0, + SOURCE_CATEGORY_SEGMENT_START_POINT = 0x1, + SOURCE_CATEGORY_SEGMENT_END_POINT = 0x2, + + // Segment subtypes. + SOURCE_CATEGORY_INITIAL_SEGMENT = 0x8, + SOURCE_CATEGORY_REVERSE_SEGMENT = 0x9, + + SOURCE_CATEGORY_GEOMETRY_SHIFT = 0x3, + SOURCE_CATEGORY_BITMASK = 0x1F +}; + +inline bool belongs( + SourceCategory source_category, + GeometryCategory geometry_category) { + return (static_cast(source_category) >> + SOURCE_CATEGORY_GEOMETRY_SHIFT) == + static_cast(geometry_category); +} +} // polygon +} // boost + +#endif // BOOST_POLYGON_VORONOI_GEOMETRY_TYPE diff --git a/PCUT/MinkowskiCpp/pch.cpp b/PCUT/MinkowskiCpp/pch.cpp new file mode 100644 index 0000000..bcb5590 --- /dev/null +++ b/PCUT/MinkowskiCpp/pch.cpp @@ -0,0 +1 @@ +#include "pch.h" diff --git a/PCUT/MinkowskiCpp/pch.h b/PCUT/MinkowskiCpp/pch.h new file mode 100644 index 0000000..10fe677 --- /dev/null +++ b/PCUT/MinkowskiCpp/pch.h @@ -0,0 +1,4 @@ +#pragma once + +#include +#include diff --git a/PCUT/PCUT.API/ApiClient.cs b/PCUT/PCUT.API/ApiClient.cs new file mode 100644 index 0000000..75be7c5 --- /dev/null +++ b/PCUT/PCUT.API/ApiClient.cs @@ -0,0 +1,80 @@ +using System; +using System.Collections.Generic; +using System.Net.Http.Headers; +using System.Net.Http; +using System.Threading.Tasks; +using Newtonsoft.Json; +using System.Text; + +namespace PCUT.API +{ + public static class ApiClient + { + private static HttpClient httpClient { get;set; } + private static string baseApiUrl { get; set; } + + public static void Initial(string baseURL) + { + if (httpClient != null) return; + httpClient = new HttpClient(); + baseApiUrl = baseURL; + httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); + } + + public static void SetAuthToken(string token) + { + httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token); + + } + + public static async Task> GetAllAsync(string path) + { + HttpResponseMessage response = await httpClient.GetAsync($"{baseApiUrl}/{path}"); + response.EnsureSuccessStatusCode(); + string content = await response.Content.ReadAsStringAsync(); + return JsonConvert.DeserializeObject>(content); + } + + public static async Task GetByIdAsync(string path, int id) + { + HttpResponseMessage response = await httpClient.GetAsync($"{baseApiUrl}/{path}/{id}"); + response.EnsureSuccessStatusCode(); + string content = await response.Content.ReadAsStringAsync(); + return JsonConvert.DeserializeObject(content); + } + + public static async Task CreateAsync(string path, T entity) + { + string json = JsonConvert.SerializeObject(entity); + StringContent content = new StringContent(json, Encoding.UTF8, "application/json"); + + HttpResponseMessage response = await httpClient.PostAsync($"{baseApiUrl}/{path}", content); + response.EnsureSuccessStatusCode(); + + string responseContent = await response.Content.ReadAsStringAsync(); + return JsonConvert.DeserializeObject(responseContent); + } + + public static async Task UpdateAsync(string path, int id, T entity) + { + string json = JsonConvert.SerializeObject(entity); + StringContent content = new StringContent(json, Encoding.UTF8, "application/json"); + + HttpResponseMessage response = await httpClient.PutAsync($"{baseApiUrl}/{path}/{id}", content); + response.EnsureSuccessStatusCode(); + + string responseContent = await response.Content.ReadAsStringAsync(); + return JsonConvert.DeserializeObject(responseContent); + } + + public static async Task DeleteAsync(string path, int id) + { + HttpResponseMessage response = await httpClient.DeleteAsync($"{baseApiUrl}/{path}/{id}"); + response.EnsureSuccessStatusCode(); + return response.IsSuccessStatusCode; + } + } + +} + + diff --git a/PCUT/PCUT.API/Managers/CategoriesBase.cs b/PCUT/PCUT.API/Managers/CategoriesBase.cs new file mode 100644 index 0000000..7839953 --- /dev/null +++ b/PCUT/PCUT.API/Managers/CategoriesBase.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace PCUT.API.Managers +{ + public class CategoriesBase + { + public CategoriesBase() + { + ApiClient.Initial("http://192.168.1.106:3000/api/categories"); + } + } +} diff --git a/PCUT/PCUT.API/Managers/CategoryManager.cs b/PCUT/PCUT.API/Managers/CategoryManager.cs new file mode 100644 index 0000000..db7ebeb --- /dev/null +++ b/PCUT/PCUT.API/Managers/CategoryManager.cs @@ -0,0 +1,47 @@ +using PCUT.Entities; +using System; +using System.Collections.Generic; +using System.Net.Http; +using System.Net.Http.Headers; +using System.Text; +using System.Threading.Tasks; + +namespace PCUT.API.Managers +{ + public class CategoryManager : ManagerBase, ICategoriesBase + { + string path = "http://192.168.1.106:3000/api/categories"; + + public async Task CreateAsync(Categories entity) + { + try + { + return await ApiClient.CreateAsync(path, entity); + } + catch { + + return null; + } + } + + public Task DeleteAsync(int id) + { + throw new NotImplementedException(); + } + + public Task> GetAllAsync() + { + throw new NotImplementedException(); + } + + public Task GetByIdAsync(int id) + { + throw new NotImplementedException(); + } + + public Task UpdateAsync(int id, Categories entity) + { + throw new NotImplementedException(); + } + } +} diff --git a/PCUT/PCUT.API/Managers/ICategoriesBase.cs b/PCUT/PCUT.API/Managers/ICategoriesBase.cs new file mode 100644 index 0000000..4c45805 --- /dev/null +++ b/PCUT/PCUT.API/Managers/ICategoriesBase.cs @@ -0,0 +1,12 @@ +using PCUT.Entities; +using System; +using System.Collections.Generic; +using System.Text; + +namespace PCUT.API.Managers +{ + public interface ICategoriesBase : IManager + { + + } +} diff --git a/PCUT/PCUT.API/Managers/IManager.cs b/PCUT/PCUT.API/Managers/IManager.cs new file mode 100644 index 0000000..55fe84a --- /dev/null +++ b/PCUT/PCUT.API/Managers/IManager.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading.Tasks; + +namespace PCUT.API.Managers +{ + public interface IManager + { + Task> GetAllAsync(); + Task GetByIdAsync(int id); + Task CreateAsync(T entity); + Task UpdateAsync(int id, T entity); + Task DeleteAsync(int id); + + } +} diff --git a/PCUT/PCUT.API/Managers/IUserManager.cs b/PCUT/PCUT.API/Managers/IUserManager.cs new file mode 100644 index 0000000..0c7f4f7 --- /dev/null +++ b/PCUT/PCUT.API/Managers/IUserManager.cs @@ -0,0 +1,12 @@ +using PCUT.Entities; +using System; +using System.Collections.Generic; +using System.Text; + +namespace PCUT.API.Managers +{ + public interface IUserManager: IManager + { + + } +} diff --git a/PCUT/PCUT.API/Managers/ManagerBase.cs b/PCUT/PCUT.API/Managers/ManagerBase.cs new file mode 100644 index 0000000..fea5a7e --- /dev/null +++ b/PCUT/PCUT.API/Managers/ManagerBase.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace PCUT.API.Managers +{ + public class ManagerBase + { + public ManagerBase() { + ApiClient.Initial("http://192.168.1.106:3000/api/users"); + } + + } +} diff --git a/PCUT/PCUT.API/Managers/UserManager.cs b/PCUT/PCUT.API/Managers/UserManager.cs new file mode 100644 index 0000000..155091e --- /dev/null +++ b/PCUT/PCUT.API/Managers/UserManager.cs @@ -0,0 +1,72 @@ +using PCUT.Entities; +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace PCUT.API.Managers +{ + public class UserManager: ManagerBase, IUserManager + { + string path = "users"; + public async Task CreateAsync(User entity) + { + try + { + return await ApiClient.CreateAsync(path, entity); + } + catch { + return null; + } + } + + public async Task DeleteAsync(int id) + { + try + { + return await ApiClient.DeleteAsync(path, id); + } + catch + { + return false; + } + } + + public async Task> GetAllAsync() + { + try + { + return await ApiClient.GetAllAsync(path); + } + catch + { + return null; + } + } + + public async Task GetByIdAsync(int id) + { + try + { + return await ApiClient.GetByIdAsync(path, id); + } + catch + { + return null; + } + } + + public async Task UpdateAsync(int id, User entity) + { + try + { + return await ApiClient.UpdateAsync(path, id, entity); + } + catch + { + return null; + } + } + } +} diff --git a/PCUT/PCUT.API/PCUT.API.csproj b/PCUT/PCUT.API/PCUT.API.csproj new file mode 100644 index 0000000..590a7de --- /dev/null +++ b/PCUT/PCUT.API/PCUT.API.csproj @@ -0,0 +1,15 @@ + + + + netstandard2.0 + + + + + + + + + + + diff --git a/PCUT/PCUT.Entities/ApiResponse/MessageResponse.cs b/PCUT/PCUT.Entities/ApiResponse/MessageResponse.cs new file mode 100644 index 0000000..9cc6ec6 --- /dev/null +++ b/PCUT/PCUT.Entities/ApiResponse/MessageResponse.cs @@ -0,0 +1,13 @@ +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Text; + +namespace PCUT.Entities.ApiResponse +{ + public class MessageResponse + { + [JsonProperty("message")] + public string ErrorMessage { get; set; } + } +} diff --git a/PCUT/PCUT.Entities/ApiResponse/PaginationResponse.cs b/PCUT/PCUT.Entities/ApiResponse/PaginationResponse.cs new file mode 100644 index 0000000..9e3f386 --- /dev/null +++ b/PCUT/PCUT.Entities/ApiResponse/PaginationResponse.cs @@ -0,0 +1,19 @@ +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Text; + +namespace PCUT.Entities.ApiResponse +{ + public class DataResponse + { + [JsonProperty("data")] + public TData Data { get; set; } + } + + public class PaginationResponse : DataResponse + { + [JsonProperty("pagination")] + public Pagination Pagination { get; set; } + } +} diff --git a/PCUT/PCUT.Entities/ApiResponse/UserCredentialDto.cs b/PCUT/PCUT.Entities/ApiResponse/UserCredentialDto.cs new file mode 100644 index 0000000..5926932 --- /dev/null +++ b/PCUT/PCUT.Entities/ApiResponse/UserCredentialDto.cs @@ -0,0 +1,19 @@ +using Newtonsoft.Json; + +namespace Http.Core.Models +{ + public class UserCredentialDto + { + [JsonProperty("access_token")] + public string AccessToken { get; set; } + + [JsonProperty("refresh_token")] + public string RefreshToken { get; set; } + + [JsonProperty("deviceId")] + public string DeviceId { get; set; } + + [JsonProperty("username")] + public string Username { get; set; } + } +} diff --git a/PCUT/PCUT.Entities/Category.cs b/PCUT/PCUT.Entities/Category.cs new file mode 100644 index 0000000..e8b937f --- /dev/null +++ b/PCUT/PCUT.Entities/Category.cs @@ -0,0 +1,19 @@ +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Text; + +namespace PCUT.Entities +{ + public class Category + { + [JsonProperty("_id")] + public string Id { get; set; } + + [JsonProperty("name")] + public string Name { get; set; } + + [JsonProperty("description")] + public string Description { get; set; } + } +} diff --git a/PCUT/PCUT.Entities/CategoryMetadata.cs b/PCUT/PCUT.Entities/CategoryMetadata.cs new file mode 100644 index 0000000..1c3220b --- /dev/null +++ b/PCUT/PCUT.Entities/CategoryMetadata.cs @@ -0,0 +1,22 @@ +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Text; + +namespace PCUT.Entities +{ + public class CategoryMetadata + { + [JsonProperty("_id")] + public string Id { get; set; } + + [JsonProperty("type")] + public string Type { get; set; } + + [JsonProperty("value")] + public string Value { get; set; } + + [JsonProperty("categoryId")] + public string CategoryId { get; set; } + } +} diff --git a/PCUT/PCUT.Entities/CdrFile.cs b/PCUT/PCUT.Entities/CdrFile.cs new file mode 100644 index 0000000..f69663f --- /dev/null +++ b/PCUT/PCUT.Entities/CdrFile.cs @@ -0,0 +1,49 @@ +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Text; + +namespace PCUT.Entities +{ + public class CdrFile + { + [JsonProperty("_id")] + public string Id { get; set; } + + [JsonProperty("name")] + public string Name { get; set; } + + [JsonProperty("area")] + public string Area { get; set; } + + [JsonProperty("remarks")] + public string Remarks { get; set; } + + [JsonProperty("file")] + public FileData File { get; set; } + + [JsonProperty("thumbnail")] + public FileData Thumbnail { get; set; } + + [JsonProperty("category")] + public Category Category { get; set; } + + [JsonProperty("brand")] + public CategoryMetadata Brand { get; set; } + + [JsonProperty("type")] + public CategoryMetadata Type { get; set; } + + [JsonProperty("_model")] + public CategoryMetadata Model { get; set; } + + [JsonProperty("series")] + public CategoryMetadata Series { get; set; } + + [JsonProperty("year")] + public CategoryMetadata Year { get; set; } + + [JsonProperty("subType")] + public CategoryMetadata SubType { get; set; } + } +} diff --git a/PCUT/PCUT.Entities/FileData.cs b/PCUT/PCUT.Entities/FileData.cs new file mode 100644 index 0000000..89c50d7 --- /dev/null +++ b/PCUT/PCUT.Entities/FileData.cs @@ -0,0 +1,30 @@ +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Text; + +namespace PCUT.Entities +{ + public class FileData + { + [JsonProperty("_id")] + public string Id { get; set; } + [JsonProperty("filename")] + public string Filename { get; set; } + + [JsonProperty("url")] + public string Url { get; set; } + + [JsonProperty("createdBy")] + public string CreatedBy { get; set; } + + [JsonProperty("updatedAt")] + public DateTime UpdatedAt { get; set; } + + [JsonProperty("createdAt")] + public DateTime CreatedAt { get; set; } + + [JsonProperty("__v")] + public int Version { get; set; } + } +} diff --git a/PCUT/PCUT.Entities/PCUT.Entities.csproj b/PCUT/PCUT.Entities/PCUT.Entities.csproj new file mode 100644 index 0000000..eeda231 --- /dev/null +++ b/PCUT/PCUT.Entities/PCUT.Entities.csproj @@ -0,0 +1,11 @@ + + + + netstandard2.0 + + + + + + + diff --git a/PCUT/PCUT.Entities/Pagination.cs b/PCUT/PCUT.Entities/Pagination.cs new file mode 100644 index 0000000..b4b3cf3 --- /dev/null +++ b/PCUT/PCUT.Entities/Pagination.cs @@ -0,0 +1,22 @@ +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Text; + +namespace PCUT.Entities +{ + public class Pagination + { + [JsonProperty("page")] + public int Page { get; set; } + + [JsonProperty("pageSize")] + public int PageSize { get; set; } + + [JsonProperty("totalPages")] + public int TotalPages { get; set; } + + [JsonProperty("totalRecords")] + public int TotalRecords { get; set; } + } +} diff --git a/PCUT/PCUT.Entities/PasswordChange.cs b/PCUT/PCUT.Entities/PasswordChange.cs new file mode 100644 index 0000000..e274c46 --- /dev/null +++ b/PCUT/PCUT.Entities/PasswordChange.cs @@ -0,0 +1,13 @@ +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Text; + +namespace PCUT.Entities +{ + public class PasswordChange + { + [JsonProperty("password")] + public string Password { get; set; } + } +} diff --git a/PCUT/PCUT.Entities/UpsertCategory.cs b/PCUT/PCUT.Entities/UpsertCategory.cs new file mode 100644 index 0000000..5220fb9 --- /dev/null +++ b/PCUT/PCUT.Entities/UpsertCategory.cs @@ -0,0 +1,13 @@ +using Newtonsoft.Json; + +namespace PCUT.Entities +{ + public class UpsertCategory + { + [JsonProperty("name")] + public string Name { get; set; } + + [JsonProperty("description")] + public string Description { get; set; } + } +} diff --git a/PCUT/PCUT.Entities/UpsertFile.cs b/PCUT/PCUT.Entities/UpsertFile.cs new file mode 100644 index 0000000..a9ca9ab --- /dev/null +++ b/PCUT/PCUT.Entities/UpsertFile.cs @@ -0,0 +1,46 @@ +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Text; + +namespace PCUT.Entities +{ + public class UpsertFile + { + [JsonProperty("file")] + public string FileId { get; set; } + + [JsonProperty("name")] + public string Name { get; set; } + + [JsonProperty("category")] + public string Category { get; set; } + + [JsonProperty("type")] + public string Type { get; set; } + + [JsonProperty("brand")] + public string Brand { get; set; } + + [JsonProperty("year")] + public string Year { get; set; } + + [JsonProperty("series")] + public string Series { get; set; } + + [JsonProperty("_model")] + public string Model { get; set; } + + [JsonProperty("subType")] + public string SubType { get; set; } + + [JsonProperty("area")] + public string Area { get; set; } + + [JsonProperty("remarks")] + public string Remarks { get; set; } + + [JsonProperty("thumbnail")] + public string Thumbnail { get; set; } + } +} diff --git a/PCUT/PCUT.Entities/UpsertMetadata.cs b/PCUT/PCUT.Entities/UpsertMetadata.cs new file mode 100644 index 0000000..7ca2ecc --- /dev/null +++ b/PCUT/PCUT.Entities/UpsertMetadata.cs @@ -0,0 +1,20 @@ +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Text; + +namespace PCUT.Entities +{ + public class UpsertMetadata + { + [JsonProperty("type")] + public string Type { get; set; } + + [JsonProperty("value")] + public string Value { get; set; } + + [JsonProperty("categoryId")] + public string CategoryId { get; set; } + + } +} diff --git a/PCUT/PCUT.Entities/UpsertUser.cs b/PCUT/PCUT.Entities/UpsertUser.cs new file mode 100644 index 0000000..50c495e --- /dev/null +++ b/PCUT/PCUT.Entities/UpsertUser.cs @@ -0,0 +1,31 @@ +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Text; + +namespace PCUT.Entities +{ + public class UpsertUser + { + [JsonProperty("accountName")] + public string AccountName { get; set; } + [JsonProperty("username")] + public string Username { get; set; } + [JsonProperty("role")] + public string Role { get; set; } + [JsonProperty("description")] + public string Description { get; set; } + [JsonProperty("isActive")] + public bool IsActive { get; set; } + [JsonProperty("isPermittedEdit")] + public bool IsPermittedEdit { get; set; } + [JsonProperty("phone")] + public string Phone { get; set; } + [JsonProperty("expiredAt")] + public string ExpiredAt { get; set; } + [JsonProperty("permissions")] + public List Permissions { get; set; } + [JsonProperty("password")] + public string Password { get; set; } + } +} diff --git a/PCUT/PCUT.Entities/UserProfile.cs b/PCUT/PCUT.Entities/UserProfile.cs new file mode 100644 index 0000000..afb13f4 --- /dev/null +++ b/PCUT/PCUT.Entities/UserProfile.cs @@ -0,0 +1,59 @@ +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Text; + +namespace PCUT.Entities +{ + public class UserProfile + { + [JsonProperty("_id")] + public string Id { get; set; } + + [JsonProperty("role")] + public string Role { get; set; } + + [JsonProperty("permissions")] + public string[] Permissions { get; set; } + + [JsonProperty("accountName")] + public string AccountName { get; set; } + + [JsonProperty("username")] + public string UserName { get; set; } + + + [JsonProperty("phone")] + public string Phone { get; set; } + + [JsonProperty("isActive")] + public bool IsActive { get; set; } + + [JsonProperty("isPermittedEdit")] + public bool? IsPermittedEdit { get; set; } + + [JsonProperty("expiredAt")] + public DateTimeOffset? ExpiredAt { get; set; } + + [JsonProperty("description")] + public string Description { get; set; } + + [JsonProperty("updatedAt")] + public DateTime UpdatedAt { get; set; } + + [JsonProperty("createdAt")] + public DateTime CreatedAt { get; set; } + + [JsonProperty("__v")] + public int V { get; set; } + + [JsonProperty("deviceId")] + public string DeviceId { get; set; } + + [JsonProperty("age")] + public int Age { get; set; } + + [JsonProperty("requestedAt")] + public DateTime RequestedAt { get; set; } + } +} diff --git a/PCUT/PCUT.sln b/PCUT/PCUT.sln new file mode 100644 index 0000000..adb4df3 --- /dev/null +++ b/PCUT/PCUT.sln @@ -0,0 +1,169 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.8.34330.188 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PCUT", "PCUT\PCUT.csproj", "{2E7B481D-6F70-41BE-8224-A9D69499E6EE}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PCUT.Entities", "PCUT.Entities\PCUT.Entities.csproj", "{C65442D8-797E-4A98-AD7D-1A1068D8020E}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Clipper.Core", "Clipper.Core\Clipper.Core.csproj", "{6C87A9D3-A2E3-41E0-B112-CD1DCE45D53C}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DeepNestLib.Core", "DeepNestLib.Core\DeepNestLib.Core.csproj", "{09ABFBB8-78BE-4920-8C86-3CBA7693076D}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MinkowskiCpp", "MinkowskiCpp\MinkowskiCpp.vcxproj", "{71998B3C-E08F-4324-A087-2EDEFF1E3256}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Http.Core", "Http.Core\Http.Core.csproj", "{01F0F3EA-71DE-436C-96B0-934E566BF04F}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|ARM = Debug|ARM + Debug|ARM64 = Debug|ARM64 + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|Any CPU = Release|Any CPU + Release|ARM = Release|ARM + Release|ARM64 = Release|ARM64 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {2E7B481D-6F70-41BE-8224-A9D69499E6EE}.Debug|Any CPU.ActiveCfg = Debug|x64 + {2E7B481D-6F70-41BE-8224-A9D69499E6EE}.Debug|Any CPU.Build.0 = Debug|x64 + {2E7B481D-6F70-41BE-8224-A9D69499E6EE}.Debug|Any CPU.Deploy.0 = Debug|x64 + {2E7B481D-6F70-41BE-8224-A9D69499E6EE}.Debug|ARM.ActiveCfg = Debug|ARM + {2E7B481D-6F70-41BE-8224-A9D69499E6EE}.Debug|ARM.Build.0 = Debug|ARM + {2E7B481D-6F70-41BE-8224-A9D69499E6EE}.Debug|ARM.Deploy.0 = Debug|ARM + {2E7B481D-6F70-41BE-8224-A9D69499E6EE}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {2E7B481D-6F70-41BE-8224-A9D69499E6EE}.Debug|ARM64.Build.0 = Debug|ARM64 + {2E7B481D-6F70-41BE-8224-A9D69499E6EE}.Debug|ARM64.Deploy.0 = Debug|ARM64 + {2E7B481D-6F70-41BE-8224-A9D69499E6EE}.Debug|x64.ActiveCfg = Debug|x64 + {2E7B481D-6F70-41BE-8224-A9D69499E6EE}.Debug|x64.Build.0 = Debug|x64 + {2E7B481D-6F70-41BE-8224-A9D69499E6EE}.Debug|x64.Deploy.0 = Debug|x64 + {2E7B481D-6F70-41BE-8224-A9D69499E6EE}.Debug|x86.ActiveCfg = Debug|x86 + {2E7B481D-6F70-41BE-8224-A9D69499E6EE}.Debug|x86.Build.0 = Debug|x86 + {2E7B481D-6F70-41BE-8224-A9D69499E6EE}.Debug|x86.Deploy.0 = Debug|x86 + {2E7B481D-6F70-41BE-8224-A9D69499E6EE}.Release|Any CPU.ActiveCfg = Release|x64 + {2E7B481D-6F70-41BE-8224-A9D69499E6EE}.Release|Any CPU.Build.0 = Release|x64 + {2E7B481D-6F70-41BE-8224-A9D69499E6EE}.Release|Any CPU.Deploy.0 = Release|x64 + {2E7B481D-6F70-41BE-8224-A9D69499E6EE}.Release|ARM.ActiveCfg = Release|ARM + {2E7B481D-6F70-41BE-8224-A9D69499E6EE}.Release|ARM.Build.0 = Release|ARM + {2E7B481D-6F70-41BE-8224-A9D69499E6EE}.Release|ARM.Deploy.0 = Release|ARM + {2E7B481D-6F70-41BE-8224-A9D69499E6EE}.Release|ARM64.ActiveCfg = Release|ARM64 + {2E7B481D-6F70-41BE-8224-A9D69499E6EE}.Release|ARM64.Build.0 = Release|ARM64 + {2E7B481D-6F70-41BE-8224-A9D69499E6EE}.Release|ARM64.Deploy.0 = Release|ARM64 + {2E7B481D-6F70-41BE-8224-A9D69499E6EE}.Release|x64.ActiveCfg = Release|x64 + {2E7B481D-6F70-41BE-8224-A9D69499E6EE}.Release|x64.Build.0 = Release|x64 + {2E7B481D-6F70-41BE-8224-A9D69499E6EE}.Release|x64.Deploy.0 = Release|x64 + {2E7B481D-6F70-41BE-8224-A9D69499E6EE}.Release|x86.ActiveCfg = Release|x86 + {2E7B481D-6F70-41BE-8224-A9D69499E6EE}.Release|x86.Build.0 = Release|x86 + {2E7B481D-6F70-41BE-8224-A9D69499E6EE}.Release|x86.Deploy.0 = Release|x86 + {C65442D8-797E-4A98-AD7D-1A1068D8020E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C65442D8-797E-4A98-AD7D-1A1068D8020E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C65442D8-797E-4A98-AD7D-1A1068D8020E}.Debug|ARM.ActiveCfg = Debug|Any CPU + {C65442D8-797E-4A98-AD7D-1A1068D8020E}.Debug|ARM.Build.0 = Debug|Any CPU + {C65442D8-797E-4A98-AD7D-1A1068D8020E}.Debug|ARM64.ActiveCfg = Debug|Any CPU + {C65442D8-797E-4A98-AD7D-1A1068D8020E}.Debug|ARM64.Build.0 = Debug|Any CPU + {C65442D8-797E-4A98-AD7D-1A1068D8020E}.Debug|x64.ActiveCfg = Debug|Any CPU + {C65442D8-797E-4A98-AD7D-1A1068D8020E}.Debug|x64.Build.0 = Debug|Any CPU + {C65442D8-797E-4A98-AD7D-1A1068D8020E}.Debug|x86.ActiveCfg = Debug|Any CPU + {C65442D8-797E-4A98-AD7D-1A1068D8020E}.Debug|x86.Build.0 = Debug|Any CPU + {C65442D8-797E-4A98-AD7D-1A1068D8020E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C65442D8-797E-4A98-AD7D-1A1068D8020E}.Release|Any CPU.Build.0 = Release|Any CPU + {C65442D8-797E-4A98-AD7D-1A1068D8020E}.Release|ARM.ActiveCfg = Release|Any CPU + {C65442D8-797E-4A98-AD7D-1A1068D8020E}.Release|ARM.Build.0 = Release|Any CPU + {C65442D8-797E-4A98-AD7D-1A1068D8020E}.Release|ARM64.ActiveCfg = Release|Any CPU + {C65442D8-797E-4A98-AD7D-1A1068D8020E}.Release|ARM64.Build.0 = Release|Any CPU + {C65442D8-797E-4A98-AD7D-1A1068D8020E}.Release|x64.ActiveCfg = Release|Any CPU + {C65442D8-797E-4A98-AD7D-1A1068D8020E}.Release|x64.Build.0 = Release|Any CPU + {C65442D8-797E-4A98-AD7D-1A1068D8020E}.Release|x86.ActiveCfg = Release|Any CPU + {C65442D8-797E-4A98-AD7D-1A1068D8020E}.Release|x86.Build.0 = Release|Any CPU + {6C87A9D3-A2E3-41E0-B112-CD1DCE45D53C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6C87A9D3-A2E3-41E0-B112-CD1DCE45D53C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6C87A9D3-A2E3-41E0-B112-CD1DCE45D53C}.Debug|ARM.ActiveCfg = Debug|Any CPU + {6C87A9D3-A2E3-41E0-B112-CD1DCE45D53C}.Debug|ARM.Build.0 = Debug|Any CPU + {6C87A9D3-A2E3-41E0-B112-CD1DCE45D53C}.Debug|ARM64.ActiveCfg = Debug|Any CPU + {6C87A9D3-A2E3-41E0-B112-CD1DCE45D53C}.Debug|ARM64.Build.0 = Debug|Any CPU + {6C87A9D3-A2E3-41E0-B112-CD1DCE45D53C}.Debug|x64.ActiveCfg = Debug|Any CPU + {6C87A9D3-A2E3-41E0-B112-CD1DCE45D53C}.Debug|x64.Build.0 = Debug|Any CPU + {6C87A9D3-A2E3-41E0-B112-CD1DCE45D53C}.Debug|x86.ActiveCfg = Debug|Any CPU + {6C87A9D3-A2E3-41E0-B112-CD1DCE45D53C}.Debug|x86.Build.0 = Debug|Any CPU + {6C87A9D3-A2E3-41E0-B112-CD1DCE45D53C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6C87A9D3-A2E3-41E0-B112-CD1DCE45D53C}.Release|Any CPU.Build.0 = Release|Any CPU + {6C87A9D3-A2E3-41E0-B112-CD1DCE45D53C}.Release|ARM.ActiveCfg = Release|Any CPU + {6C87A9D3-A2E3-41E0-B112-CD1DCE45D53C}.Release|ARM.Build.0 = Release|Any CPU + {6C87A9D3-A2E3-41E0-B112-CD1DCE45D53C}.Release|ARM64.ActiveCfg = Release|Any CPU + {6C87A9D3-A2E3-41E0-B112-CD1DCE45D53C}.Release|ARM64.Build.0 = Release|Any CPU + {6C87A9D3-A2E3-41E0-B112-CD1DCE45D53C}.Release|x64.ActiveCfg = Release|Any CPU + {6C87A9D3-A2E3-41E0-B112-CD1DCE45D53C}.Release|x64.Build.0 = Release|Any CPU + {6C87A9D3-A2E3-41E0-B112-CD1DCE45D53C}.Release|x86.ActiveCfg = Release|Any CPU + {6C87A9D3-A2E3-41E0-B112-CD1DCE45D53C}.Release|x86.Build.0 = Release|Any CPU + {09ABFBB8-78BE-4920-8C86-3CBA7693076D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {09ABFBB8-78BE-4920-8C86-3CBA7693076D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {09ABFBB8-78BE-4920-8C86-3CBA7693076D}.Debug|ARM.ActiveCfg = Debug|Any CPU + {09ABFBB8-78BE-4920-8C86-3CBA7693076D}.Debug|ARM.Build.0 = Debug|Any CPU + {09ABFBB8-78BE-4920-8C86-3CBA7693076D}.Debug|ARM64.ActiveCfg = Debug|Any CPU + {09ABFBB8-78BE-4920-8C86-3CBA7693076D}.Debug|ARM64.Build.0 = Debug|Any CPU + {09ABFBB8-78BE-4920-8C86-3CBA7693076D}.Debug|x64.ActiveCfg = Debug|Any CPU + {09ABFBB8-78BE-4920-8C86-3CBA7693076D}.Debug|x64.Build.0 = Debug|Any CPU + {09ABFBB8-78BE-4920-8C86-3CBA7693076D}.Debug|x86.ActiveCfg = Debug|Any CPU + {09ABFBB8-78BE-4920-8C86-3CBA7693076D}.Debug|x86.Build.0 = Debug|Any CPU + {09ABFBB8-78BE-4920-8C86-3CBA7693076D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {09ABFBB8-78BE-4920-8C86-3CBA7693076D}.Release|Any CPU.Build.0 = Release|Any CPU + {09ABFBB8-78BE-4920-8C86-3CBA7693076D}.Release|ARM.ActiveCfg = Release|Any CPU + {09ABFBB8-78BE-4920-8C86-3CBA7693076D}.Release|ARM.Build.0 = Release|Any CPU + {09ABFBB8-78BE-4920-8C86-3CBA7693076D}.Release|ARM64.ActiveCfg = Release|Any CPU + {09ABFBB8-78BE-4920-8C86-3CBA7693076D}.Release|ARM64.Build.0 = Release|Any CPU + {09ABFBB8-78BE-4920-8C86-3CBA7693076D}.Release|x64.ActiveCfg = Release|Any CPU + {09ABFBB8-78BE-4920-8C86-3CBA7693076D}.Release|x64.Build.0 = Release|Any CPU + {09ABFBB8-78BE-4920-8C86-3CBA7693076D}.Release|x86.ActiveCfg = Release|Any CPU + {09ABFBB8-78BE-4920-8C86-3CBA7693076D}.Release|x86.Build.0 = Release|Any CPU + {71998B3C-E08F-4324-A087-2EDEFF1E3256}.Debug|Any CPU.ActiveCfg = Debug|x64 + {71998B3C-E08F-4324-A087-2EDEFF1E3256}.Debug|Any CPU.Build.0 = Debug|x64 + {71998B3C-E08F-4324-A087-2EDEFF1E3256}.Debug|ARM.ActiveCfg = Debug|ARM + {71998B3C-E08F-4324-A087-2EDEFF1E3256}.Debug|ARM.Build.0 = Debug|ARM + {71998B3C-E08F-4324-A087-2EDEFF1E3256}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {71998B3C-E08F-4324-A087-2EDEFF1E3256}.Debug|ARM64.Build.0 = Debug|ARM64 + {71998B3C-E08F-4324-A087-2EDEFF1E3256}.Debug|x64.ActiveCfg = Debug|x64 + {71998B3C-E08F-4324-A087-2EDEFF1E3256}.Debug|x64.Build.0 = Debug|x64 + {71998B3C-E08F-4324-A087-2EDEFF1E3256}.Debug|x86.ActiveCfg = Debug|Win32 + {71998B3C-E08F-4324-A087-2EDEFF1E3256}.Debug|x86.Build.0 = Debug|Win32 + {71998B3C-E08F-4324-A087-2EDEFF1E3256}.Release|Any CPU.ActiveCfg = Release|x64 + {71998B3C-E08F-4324-A087-2EDEFF1E3256}.Release|Any CPU.Build.0 = Release|x64 + {71998B3C-E08F-4324-A087-2EDEFF1E3256}.Release|ARM.ActiveCfg = Release|ARM + {71998B3C-E08F-4324-A087-2EDEFF1E3256}.Release|ARM.Build.0 = Release|ARM + {71998B3C-E08F-4324-A087-2EDEFF1E3256}.Release|ARM64.ActiveCfg = Release|ARM64 + {71998B3C-E08F-4324-A087-2EDEFF1E3256}.Release|ARM64.Build.0 = Release|ARM64 + {71998B3C-E08F-4324-A087-2EDEFF1E3256}.Release|x64.ActiveCfg = Release|x64 + {71998B3C-E08F-4324-A087-2EDEFF1E3256}.Release|x64.Build.0 = Release|x64 + {71998B3C-E08F-4324-A087-2EDEFF1E3256}.Release|x86.ActiveCfg = Release|Win32 + {71998B3C-E08F-4324-A087-2EDEFF1E3256}.Release|x86.Build.0 = Release|Win32 + {01F0F3EA-71DE-436C-96B0-934E566BF04F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {01F0F3EA-71DE-436C-96B0-934E566BF04F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {01F0F3EA-71DE-436C-96B0-934E566BF04F}.Debug|ARM.ActiveCfg = Debug|Any CPU + {01F0F3EA-71DE-436C-96B0-934E566BF04F}.Debug|ARM.Build.0 = Debug|Any CPU + {01F0F3EA-71DE-436C-96B0-934E566BF04F}.Debug|ARM64.ActiveCfg = Debug|Any CPU + {01F0F3EA-71DE-436C-96B0-934E566BF04F}.Debug|ARM64.Build.0 = Debug|Any CPU + {01F0F3EA-71DE-436C-96B0-934E566BF04F}.Debug|x64.ActiveCfg = Debug|Any CPU + {01F0F3EA-71DE-436C-96B0-934E566BF04F}.Debug|x64.Build.0 = Debug|Any CPU + {01F0F3EA-71DE-436C-96B0-934E566BF04F}.Debug|x86.ActiveCfg = Debug|Any CPU + {01F0F3EA-71DE-436C-96B0-934E566BF04F}.Debug|x86.Build.0 = Debug|Any CPU + {01F0F3EA-71DE-436C-96B0-934E566BF04F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {01F0F3EA-71DE-436C-96B0-934E566BF04F}.Release|Any CPU.Build.0 = Release|Any CPU + {01F0F3EA-71DE-436C-96B0-934E566BF04F}.Release|ARM.ActiveCfg = Release|Any CPU + {01F0F3EA-71DE-436C-96B0-934E566BF04F}.Release|ARM.Build.0 = Release|Any CPU + {01F0F3EA-71DE-436C-96B0-934E566BF04F}.Release|ARM64.ActiveCfg = Release|Any CPU + {01F0F3EA-71DE-436C-96B0-934E566BF04F}.Release|ARM64.Build.0 = Release|Any CPU + {01F0F3EA-71DE-436C-96B0-934E566BF04F}.Release|x64.ActiveCfg = Release|Any CPU + {01F0F3EA-71DE-436C-96B0-934E566BF04F}.Release|x64.Build.0 = Release|Any CPU + {01F0F3EA-71DE-436C-96B0-934E566BF04F}.Release|x86.ActiveCfg = Release|Any CPU + {01F0F3EA-71DE-436C-96B0-934E566BF04F}.Release|x86.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {648CD40F-25EB-4FEB-82C0-A5CDF711F313} + EndGlobalSection +EndGlobal diff --git a/PCUT/PCUT/App.xaml b/PCUT/PCUT/App.xaml new file mode 100644 index 0000000..634b383 --- /dev/null +++ b/PCUT/PCUT/App.xaml @@ -0,0 +1,33 @@ + + + + #FF7700 + /Assets/FontAwesome.ttf#FontAwesome + 1500 + + + + + + diff --git a/PCUT/PCUT/App.xaml.cs b/PCUT/PCUT/App.xaml.cs new file mode 100644 index 0000000..da8cf40 --- /dev/null +++ b/PCUT/PCUT/App.xaml.cs @@ -0,0 +1,133 @@ +using Http.Core; +using Http.Core.Handlers; +using Microsoft.Extensions.DependencyInjection; +using PCUT.Pages; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Runtime.InteropServices.WindowsRuntime; +using Windows.ApplicationModel; +using Windows.ApplicationModel.Activation; +using Windows.Foundation; +using Windows.Foundation.Collections; +using Windows.UI.Core; +using Windows.UI.ViewManagement; +using Windows.UI.Xaml; +using Windows.UI.Xaml.Controls; +using Windows.UI.Xaml.Controls.Primitives; +using Windows.UI.Xaml.Data; +using Windows.UI.Xaml.Input; +using Windows.UI.Xaml.Media; +using Windows.UI.Xaml.Navigation; +using static Http.Core.Constants.HttpConstants; + +namespace PCUT +{ + /// + /// Provides application-specific behavior to supplement the default Application class. + /// + sealed partial class App : Application + { + /// + /// Initializes the singleton application object. This is the first line of authored code + /// executed, and as such is the logical equivalent of main() or WinMain(). + /// + public static NavigationTarget NextPage { get; set; } = NavigationTarget.None; + public enum NavigationTarget + { + None, + DesignCenter, + DataCenter, + AdminCenter + } + public App() + { + this.InitializeComponent(); + this.Suspending += OnSuspending; + AppContainer = ConfigDI(); + HttpClientFactory + .AddHttpClient(ClientNames.AuthClient) + .AddConfigureClient(client => { client.BaseAddress = new Uri(Auth.BaseUrl); }) + .AddHttpMessageHandler(() => new DeviceAuthHandler()); + HttpClientFactory + .AddHttpClient(ClientNames.ApiClient) + .AddConfigureClient(client => { client.BaseAddress = new Uri(Api.BaseUrl); }) + .AddHttpMessageHandler(() => new DeviceAuthHandler()) + .AddHttpMessageHandler(() => new AuthenticationHandler()); + } + public IServiceProvider AppContainer { get; } + + /// + /// Invoked when the application is launched normally by the end user. Other entry points + /// will be used such as when the application is launched to open a specific file. + /// + /// Details about the launch request and process. + protected override void OnLaunched(LaunchActivatedEventArgs e) + { + Frame rootFrame = Window.Current.Content as Frame; + ApplicationView.GetForCurrentView().IsScreenCaptureEnabled = false; + // Do not repeat app initialization when the Window already has content, + // just ensure that the window is active + if (rootFrame == null) + { + // Create a Frame to act as the navigation context and navigate to the first page + rootFrame = new Frame(); + + rootFrame.NavigationFailed += OnNavigationFailed; + + if (e.PreviousExecutionState == ApplicationExecutionState.Terminated) + { + //TODO: Load state from previously suspended application + } + + // Place the frame in the current Window + Window.Current.Content = rootFrame; + } + + if (e.PrelaunchActivated == false) + { + if (rootFrame.Content == null) + { + // When the navigation stack isn't restored navigate to the first page, + // configuring the new page by passing required information as a navigation + // parameter + rootFrame.Navigate(typeof(LoginPage), e.Arguments); + } + // Ensure the current window is active + Window.Current.Activate(); + } + } + + + /// + /// Invoked when Navigation to a certain page fails + /// + /// The Frame which failed navigation + /// Details about the navigation failure + void OnNavigationFailed(object sender, NavigationFailedEventArgs e) + { + throw new Exception("Failed to load Page " + e.SourcePageType.FullName); + } + + /// + /// Invoked when application execution is being suspended. Application state is saved + /// without knowing whether the application will be terminated or resumed with the contents + /// of memory still intact. + /// + /// The source of the suspend request. + /// Details about the suspend request. + private void OnSuspending(object sender, SuspendingEventArgs e) + { + var deferral = e.SuspendingOperation.GetDeferral(); + //TODO: Save application state and stop any background activity + deferral.Complete(); + } + + IServiceProvider ConfigDI() + { + var serviceCollection = new ServiceCollection(); + return serviceCollection.BuildServiceProvider(); + } + } +} diff --git a/PCUT/PCUT/Assets/Backgound.jpg b/PCUT/PCUT/Assets/Backgound.jpg new file mode 100644 index 0000000..45e06eb Binary files /dev/null and b/PCUT/PCUT/Assets/Backgound.jpg differ diff --git a/PCUT/PCUT/Assets/LargeTile.scale-100.png b/PCUT/PCUT/Assets/LargeTile.scale-100.png new file mode 100644 index 0000000..727be35 Binary files /dev/null and b/PCUT/PCUT/Assets/LargeTile.scale-100.png differ diff --git a/PCUT/PCUT/Assets/LargeTile.scale-125.png b/PCUT/PCUT/Assets/LargeTile.scale-125.png new file mode 100644 index 0000000..6fa0733 Binary files /dev/null and b/PCUT/PCUT/Assets/LargeTile.scale-125.png differ diff --git a/PCUT/PCUT/Assets/LargeTile.scale-150.png b/PCUT/PCUT/Assets/LargeTile.scale-150.png new file mode 100644 index 0000000..8c643c1 Binary files /dev/null and b/PCUT/PCUT/Assets/LargeTile.scale-150.png differ diff --git a/PCUT/PCUT/Assets/LargeTile.scale-200.png b/PCUT/PCUT/Assets/LargeTile.scale-200.png new file mode 100644 index 0000000..34f349c Binary files /dev/null and b/PCUT/PCUT/Assets/LargeTile.scale-200.png differ diff --git a/PCUT/PCUT/Assets/LargeTile.scale-400.png b/PCUT/PCUT/Assets/LargeTile.scale-400.png new file mode 100644 index 0000000..0efa6ba Binary files /dev/null and b/PCUT/PCUT/Assets/LargeTile.scale-400.png differ diff --git a/PCUT/PCUT/Assets/LockScreenLogo.scale-200.png b/PCUT/PCUT/Assets/LockScreenLogo.scale-200.png new file mode 100644 index 0000000..735f57a Binary files /dev/null and b/PCUT/PCUT/Assets/LockScreenLogo.scale-200.png differ diff --git a/PCUT/PCUT/Assets/Logo-Pcut.jpg b/PCUT/PCUT/Assets/Logo-Pcut.jpg new file mode 100644 index 0000000..f11e436 Binary files /dev/null and b/PCUT/PCUT/Assets/Logo-Pcut.jpg differ diff --git a/PCUT/PCUT/Assets/SmallTile.scale-100.png b/PCUT/PCUT/Assets/SmallTile.scale-100.png new file mode 100644 index 0000000..a9c085c Binary files /dev/null and b/PCUT/PCUT/Assets/SmallTile.scale-100.png differ diff --git a/PCUT/PCUT/Assets/SmallTile.scale-125.png b/PCUT/PCUT/Assets/SmallTile.scale-125.png new file mode 100644 index 0000000..74c9f65 Binary files /dev/null and b/PCUT/PCUT/Assets/SmallTile.scale-125.png differ diff --git a/PCUT/PCUT/Assets/SmallTile.scale-150.png b/PCUT/PCUT/Assets/SmallTile.scale-150.png new file mode 100644 index 0000000..d7d9ec6 Binary files /dev/null and b/PCUT/PCUT/Assets/SmallTile.scale-150.png differ diff --git a/PCUT/PCUT/Assets/SmallTile.scale-200.png b/PCUT/PCUT/Assets/SmallTile.scale-200.png new file mode 100644 index 0000000..be6e221 Binary files /dev/null and b/PCUT/PCUT/Assets/SmallTile.scale-200.png differ diff --git a/PCUT/PCUT/Assets/SmallTile.scale-400.png b/PCUT/PCUT/Assets/SmallTile.scale-400.png new file mode 100644 index 0000000..d852795 Binary files /dev/null and b/PCUT/PCUT/Assets/SmallTile.scale-400.png differ diff --git a/PCUT/PCUT/Assets/SplashScreen.scale-100.png b/PCUT/PCUT/Assets/SplashScreen.scale-100.png new file mode 100644 index 0000000..dd55654 Binary files /dev/null and b/PCUT/PCUT/Assets/SplashScreen.scale-100.png differ diff --git a/PCUT/PCUT/Assets/SplashScreen.scale-125.png b/PCUT/PCUT/Assets/SplashScreen.scale-125.png new file mode 100644 index 0000000..7e8dade Binary files /dev/null and b/PCUT/PCUT/Assets/SplashScreen.scale-125.png differ diff --git a/PCUT/PCUT/Assets/SplashScreen.scale-150.png b/PCUT/PCUT/Assets/SplashScreen.scale-150.png new file mode 100644 index 0000000..11f69da Binary files /dev/null and b/PCUT/PCUT/Assets/SplashScreen.scale-150.png differ diff --git a/PCUT/PCUT/Assets/SplashScreen.scale-200.png b/PCUT/PCUT/Assets/SplashScreen.scale-200.png new file mode 100644 index 0000000..3777623 Binary files /dev/null and b/PCUT/PCUT/Assets/SplashScreen.scale-200.png differ diff --git a/PCUT/PCUT/Assets/SplashScreen.scale-400.png b/PCUT/PCUT/Assets/SplashScreen.scale-400.png new file mode 100644 index 0000000..ad7dba0 Binary files /dev/null and b/PCUT/PCUT/Assets/SplashScreen.scale-400.png differ diff --git a/PCUT/PCUT/Assets/Square150x150Logo.scale-100.png b/PCUT/PCUT/Assets/Square150x150Logo.scale-100.png new file mode 100644 index 0000000..20e93f5 Binary files /dev/null and b/PCUT/PCUT/Assets/Square150x150Logo.scale-100.png differ diff --git a/PCUT/PCUT/Assets/Square150x150Logo.scale-125.png b/PCUT/PCUT/Assets/Square150x150Logo.scale-125.png new file mode 100644 index 0000000..1e4a3bb Binary files /dev/null and b/PCUT/PCUT/Assets/Square150x150Logo.scale-125.png differ diff --git a/PCUT/PCUT/Assets/Square150x150Logo.scale-150.png b/PCUT/PCUT/Assets/Square150x150Logo.scale-150.png new file mode 100644 index 0000000..c53a1a9 Binary files /dev/null and b/PCUT/PCUT/Assets/Square150x150Logo.scale-150.png differ diff --git a/PCUT/PCUT/Assets/Square150x150Logo.scale-200.png b/PCUT/PCUT/Assets/Square150x150Logo.scale-200.png new file mode 100644 index 0000000..f7caf61 Binary files /dev/null and b/PCUT/PCUT/Assets/Square150x150Logo.scale-200.png differ diff --git a/PCUT/PCUT/Assets/Square150x150Logo.scale-400.png b/PCUT/PCUT/Assets/Square150x150Logo.scale-400.png new file mode 100644 index 0000000..f314dc1 Binary files /dev/null and b/PCUT/PCUT/Assets/Square150x150Logo.scale-400.png differ diff --git a/PCUT/PCUT/Assets/Square44x44Logo.altform-lightunplated_targetsize-16.png b/PCUT/PCUT/Assets/Square44x44Logo.altform-lightunplated_targetsize-16.png new file mode 100644 index 0000000..a0642d4 Binary files /dev/null and b/PCUT/PCUT/Assets/Square44x44Logo.altform-lightunplated_targetsize-16.png differ diff --git a/PCUT/PCUT/Assets/Square44x44Logo.altform-lightunplated_targetsize-24.png b/PCUT/PCUT/Assets/Square44x44Logo.altform-lightunplated_targetsize-24.png new file mode 100644 index 0000000..a712613 Binary files /dev/null and b/PCUT/PCUT/Assets/Square44x44Logo.altform-lightunplated_targetsize-24.png differ diff --git a/PCUT/PCUT/Assets/Square44x44Logo.altform-lightunplated_targetsize-256.png b/PCUT/PCUT/Assets/Square44x44Logo.altform-lightunplated_targetsize-256.png new file mode 100644 index 0000000..c68a020 Binary files /dev/null and b/PCUT/PCUT/Assets/Square44x44Logo.altform-lightunplated_targetsize-256.png differ diff --git a/PCUT/PCUT/Assets/Square44x44Logo.altform-lightunplated_targetsize-32.png b/PCUT/PCUT/Assets/Square44x44Logo.altform-lightunplated_targetsize-32.png new file mode 100644 index 0000000..d3fd438 Binary files /dev/null and b/PCUT/PCUT/Assets/Square44x44Logo.altform-lightunplated_targetsize-32.png differ diff --git a/PCUT/PCUT/Assets/Square44x44Logo.altform-lightunplated_targetsize-48.png b/PCUT/PCUT/Assets/Square44x44Logo.altform-lightunplated_targetsize-48.png new file mode 100644 index 0000000..c82dc0e Binary files /dev/null and b/PCUT/PCUT/Assets/Square44x44Logo.altform-lightunplated_targetsize-48.png differ diff --git a/PCUT/PCUT/Assets/Square44x44Logo.altform-unplated_targetsize-16.png b/PCUT/PCUT/Assets/Square44x44Logo.altform-unplated_targetsize-16.png new file mode 100644 index 0000000..a0642d4 Binary files /dev/null and b/PCUT/PCUT/Assets/Square44x44Logo.altform-unplated_targetsize-16.png differ diff --git a/PCUT/PCUT/Assets/Square44x44Logo.altform-unplated_targetsize-256.png b/PCUT/PCUT/Assets/Square44x44Logo.altform-unplated_targetsize-256.png new file mode 100644 index 0000000..c68a020 Binary files /dev/null and b/PCUT/PCUT/Assets/Square44x44Logo.altform-unplated_targetsize-256.png differ diff --git a/PCUT/PCUT/Assets/Square44x44Logo.altform-unplated_targetsize-32.png b/PCUT/PCUT/Assets/Square44x44Logo.altform-unplated_targetsize-32.png new file mode 100644 index 0000000..d3fd438 Binary files /dev/null and b/PCUT/PCUT/Assets/Square44x44Logo.altform-unplated_targetsize-32.png differ diff --git a/PCUT/PCUT/Assets/Square44x44Logo.altform-unplated_targetsize-48.png b/PCUT/PCUT/Assets/Square44x44Logo.altform-unplated_targetsize-48.png new file mode 100644 index 0000000..c82dc0e Binary files /dev/null and b/PCUT/PCUT/Assets/Square44x44Logo.altform-unplated_targetsize-48.png differ diff --git a/PCUT/PCUT/Assets/Square44x44Logo.scale-100.png b/PCUT/PCUT/Assets/Square44x44Logo.scale-100.png new file mode 100644 index 0000000..4e2dbb6 Binary files /dev/null and b/PCUT/PCUT/Assets/Square44x44Logo.scale-100.png differ diff --git a/PCUT/PCUT/Assets/Square44x44Logo.scale-125.png b/PCUT/PCUT/Assets/Square44x44Logo.scale-125.png new file mode 100644 index 0000000..491a894 Binary files /dev/null and b/PCUT/PCUT/Assets/Square44x44Logo.scale-125.png differ diff --git a/PCUT/PCUT/Assets/Square44x44Logo.scale-150.png b/PCUT/PCUT/Assets/Square44x44Logo.scale-150.png new file mode 100644 index 0000000..74f7ca6 Binary files /dev/null and b/PCUT/PCUT/Assets/Square44x44Logo.scale-150.png differ diff --git a/PCUT/PCUT/Assets/Square44x44Logo.scale-200.png b/PCUT/PCUT/Assets/Square44x44Logo.scale-200.png new file mode 100644 index 0000000..c19b19d Binary files /dev/null and b/PCUT/PCUT/Assets/Square44x44Logo.scale-200.png differ diff --git a/PCUT/PCUT/Assets/Square44x44Logo.scale-400.png b/PCUT/PCUT/Assets/Square44x44Logo.scale-400.png new file mode 100644 index 0000000..e45e593 Binary files /dev/null and b/PCUT/PCUT/Assets/Square44x44Logo.scale-400.png differ diff --git a/PCUT/PCUT/Assets/Square44x44Logo.targetsize-16.png b/PCUT/PCUT/Assets/Square44x44Logo.targetsize-16.png new file mode 100644 index 0000000..c2d0295 Binary files /dev/null and b/PCUT/PCUT/Assets/Square44x44Logo.targetsize-16.png differ diff --git a/PCUT/PCUT/Assets/Square44x44Logo.targetsize-24.png b/PCUT/PCUT/Assets/Square44x44Logo.targetsize-24.png new file mode 100644 index 0000000..cedd1f6 Binary files /dev/null and b/PCUT/PCUT/Assets/Square44x44Logo.targetsize-24.png differ diff --git a/PCUT/PCUT/Assets/Square44x44Logo.targetsize-24_altform-unplated.png b/PCUT/PCUT/Assets/Square44x44Logo.targetsize-24_altform-unplated.png new file mode 100644 index 0000000..a712613 Binary files /dev/null and b/PCUT/PCUT/Assets/Square44x44Logo.targetsize-24_altform-unplated.png differ diff --git a/PCUT/PCUT/Assets/Square44x44Logo.targetsize-256.png b/PCUT/PCUT/Assets/Square44x44Logo.targetsize-256.png new file mode 100644 index 0000000..fd5275e Binary files /dev/null and b/PCUT/PCUT/Assets/Square44x44Logo.targetsize-256.png differ diff --git a/PCUT/PCUT/Assets/Square44x44Logo.targetsize-32.png b/PCUT/PCUT/Assets/Square44x44Logo.targetsize-32.png new file mode 100644 index 0000000..ef488a4 Binary files /dev/null and b/PCUT/PCUT/Assets/Square44x44Logo.targetsize-32.png differ diff --git a/PCUT/PCUT/Assets/Square44x44Logo.targetsize-48.png b/PCUT/PCUT/Assets/Square44x44Logo.targetsize-48.png new file mode 100644 index 0000000..8f16252 Binary files /dev/null and b/PCUT/PCUT/Assets/Square44x44Logo.targetsize-48.png differ diff --git a/PCUT/PCUT/Assets/StoreLogo.backup.png b/PCUT/PCUT/Assets/StoreLogo.backup.png new file mode 100644 index 0000000..7385b56 Binary files /dev/null and b/PCUT/PCUT/Assets/StoreLogo.backup.png differ diff --git a/PCUT/PCUT/Assets/StoreLogo.scale-100.png b/PCUT/PCUT/Assets/StoreLogo.scale-100.png new file mode 100644 index 0000000..ab74642 Binary files /dev/null and b/PCUT/PCUT/Assets/StoreLogo.scale-100.png differ diff --git a/PCUT/PCUT/Assets/StoreLogo.scale-125.png b/PCUT/PCUT/Assets/StoreLogo.scale-125.png new file mode 100644 index 0000000..7afc28f Binary files /dev/null and b/PCUT/PCUT/Assets/StoreLogo.scale-125.png differ diff --git a/PCUT/PCUT/Assets/StoreLogo.scale-150.png b/PCUT/PCUT/Assets/StoreLogo.scale-150.png new file mode 100644 index 0000000..60c1e91 Binary files /dev/null and b/PCUT/PCUT/Assets/StoreLogo.scale-150.png differ diff --git a/PCUT/PCUT/Assets/StoreLogo.scale-200.png b/PCUT/PCUT/Assets/StoreLogo.scale-200.png new file mode 100644 index 0000000..ec42937 Binary files /dev/null and b/PCUT/PCUT/Assets/StoreLogo.scale-200.png differ diff --git a/PCUT/PCUT/Assets/StoreLogo.scale-400.png b/PCUT/PCUT/Assets/StoreLogo.scale-400.png new file mode 100644 index 0000000..2a5c329 Binary files /dev/null and b/PCUT/PCUT/Assets/StoreLogo.scale-400.png differ diff --git a/PCUT/PCUT/Assets/Wide310x150Logo.scale-100.png b/PCUT/PCUT/Assets/Wide310x150Logo.scale-100.png new file mode 100644 index 0000000..687827c Binary files /dev/null and b/PCUT/PCUT/Assets/Wide310x150Logo.scale-100.png differ diff --git a/PCUT/PCUT/Assets/Wide310x150Logo.scale-125.png b/PCUT/PCUT/Assets/Wide310x150Logo.scale-125.png new file mode 100644 index 0000000..982f45a Binary files /dev/null and b/PCUT/PCUT/Assets/Wide310x150Logo.scale-125.png differ diff --git a/PCUT/PCUT/Assets/Wide310x150Logo.scale-150.png b/PCUT/PCUT/Assets/Wide310x150Logo.scale-150.png new file mode 100644 index 0000000..1add272 Binary files /dev/null and b/PCUT/PCUT/Assets/Wide310x150Logo.scale-150.png differ diff --git a/PCUT/PCUT/Assets/Wide310x150Logo.scale-200.png b/PCUT/PCUT/Assets/Wide310x150Logo.scale-200.png new file mode 100644 index 0000000..dd55654 Binary files /dev/null and b/PCUT/PCUT/Assets/Wide310x150Logo.scale-200.png differ diff --git a/PCUT/PCUT/Assets/Wide310x150Logo.scale-400.png b/PCUT/PCUT/Assets/Wide310x150Logo.scale-400.png new file mode 100644 index 0000000..3777623 Binary files /dev/null and b/PCUT/PCUT/Assets/Wide310x150Logo.scale-400.png differ diff --git a/PCUT/PCUT/Assets/add.png b/PCUT/PCUT/Assets/add.png new file mode 100644 index 0000000..f7ac957 Binary files /dev/null and b/PCUT/PCUT/Assets/add.png differ diff --git a/PCUT/PCUT/Assets/back.jpg b/PCUT/PCUT/Assets/back.jpg new file mode 100644 index 0000000..0fafb73 Binary files /dev/null and b/PCUT/PCUT/Assets/back.jpg differ diff --git a/PCUT/PCUT/Assets/home.png b/PCUT/PCUT/Assets/home.png new file mode 100644 index 0000000..1abd400 Binary files /dev/null and b/PCUT/PCUT/Assets/home.png differ diff --git a/PCUT/PCUT/Assets/img_customer.png b/PCUT/PCUT/Assets/img_customer.png new file mode 100644 index 0000000..89ff23b Binary files /dev/null and b/PCUT/PCUT/Assets/img_customer.png differ diff --git a/PCUT/PCUT/Assets/img_order.png b/PCUT/PCUT/Assets/img_order.png new file mode 100644 index 0000000..3b90571 Binary files /dev/null and b/PCUT/PCUT/Assets/img_order.png differ diff --git a/PCUT/PCUT/Assets/img_product.png b/PCUT/PCUT/Assets/img_product.png new file mode 100644 index 0000000..7747066 Binary files /dev/null and b/PCUT/PCUT/Assets/img_product.png differ diff --git a/PCUT/PCUT/Assets/img_setting.png b/PCUT/PCUT/Assets/img_setting.png new file mode 100644 index 0000000..0ad6229 Binary files /dev/null and b/PCUT/PCUT/Assets/img_setting.png differ diff --git a/PCUT/PCUT/Assets/logo.jpg b/PCUT/PCUT/Assets/logo.jpg new file mode 100644 index 0000000..ca95787 Binary files /dev/null and b/PCUT/PCUT/Assets/logo.jpg differ diff --git a/PCUT/PCUT/Assets/shutdown_mo.png b/PCUT/PCUT/Assets/shutdown_mo.png new file mode 100644 index 0000000..7088163 Binary files /dev/null and b/PCUT/PCUT/Assets/shutdown_mo.png differ diff --git a/PCUT/PCUT/Assets/unnamed.jpg b/PCUT/PCUT/Assets/unnamed.jpg new file mode 100644 index 0000000..7b70cad Binary files /dev/null and b/PCUT/PCUT/Assets/unnamed.jpg differ diff --git a/PCUT/PCUT/BundleArtifacts/PCUT.appinstaller.xml b/PCUT/PCUT/BundleArtifacts/PCUT.appinstaller.xml new file mode 100644 index 0000000..4fd4ca9 --- /dev/null +++ b/PCUT/PCUT/BundleArtifacts/PCUT.appinstaller.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/PCUT/PCUT/BundleArtifacts/x64.txt b/PCUT/PCUT/BundleArtifacts/x64.txt new file mode 100644 index 0000000..f52260e --- /dev/null +++ b/PCUT/PCUT/BundleArtifacts/x64.txt @@ -0,0 +1,6 @@ +MainPackage=C:\Users\Admin\Desktop\CODE\PCUT\PCUT\bin\x64\Release\PCUT_1.0.111.0_x64.msix +SymbolPackage=C:\Users\Admin\Desktop\CODE\PCUT\PCUT\obj\x64\Release\Symbols\PCUT_1.0.111.0_x64.appxsym +ResourcePack=C:\Users\Admin\Desktop\CODE\PCUT\PCUT\bin\x64\Release\PCUT_1.0.111.0_scale-100.msix +ResourcePack=C:\Users\Admin\Desktop\CODE\PCUT\PCUT\bin\x64\Release\PCUT_1.0.111.0_scale-125.msix +ResourcePack=C:\Users\Admin\Desktop\CODE\PCUT\PCUT\bin\x64\Release\PCUT_1.0.111.0_scale-150.msix +ResourcePack=C:\Users\Admin\Desktop\CODE\PCUT\PCUT\bin\x64\Release\PCUT_1.0.111.0_scale-400.msix diff --git a/PCUT/PCUT/BundleArtifacts/x86.txt b/PCUT/PCUT/BundleArtifacts/x86.txt new file mode 100644 index 0000000..7832f54 --- /dev/null +++ b/PCUT/PCUT/BundleArtifacts/x86.txt @@ -0,0 +1,2 @@ +MainPackage=C:\Users\Admin\Desktop\CODE\PCUT\PCUT\bin\x86\Release\PCUT_1.0.111.0_x86.msix +SymbolPackage=C:\Users\Admin\Desktop\CODE\PCUT\PCUT\obj\x86\Release\Symbols\PCUT_1.0.111.0_x86.appxsym diff --git a/PCUT/PCUT/Converters/BooleanConverter.cs b/PCUT/PCUT/Converters/BooleanConverter.cs new file mode 100644 index 0000000..ed7ed1d --- /dev/null +++ b/PCUT/PCUT/Converters/BooleanConverter.cs @@ -0,0 +1,34 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Windows.UI.Xaml.Data; + +namespace PCUT.Converters +{ + internal class BooleanConverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, string language) + { + switch(value) + { + case int intValue: + { + return intValue != 0; + } + case double doubleValue: + { + return doubleValue != 0; + } + default: + return false; + } + } + + public object ConvertBack(object value, Type targetType, object parameter, string language) + { + throw new NotImplementedException(); + } + } +} diff --git a/PCUT/PCUT/Converters/BooleanInverter.cs b/PCUT/PCUT/Converters/BooleanInverter.cs new file mode 100644 index 0000000..eeac175 --- /dev/null +++ b/PCUT/PCUT/Converters/BooleanInverter.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Windows.UI.Xaml.Data; + +namespace PCUT.Converters +{ + public class BooleanInverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, string language) + { + return !(bool)value; + } + + public object ConvertBack(object value, Type targetType, object parameter, string language) + { + return !(bool)value; + } + } +} diff --git a/PCUT/PCUT/Converters/BooleanToStringConverter.cs b/PCUT/PCUT/Converters/BooleanToStringConverter.cs new file mode 100644 index 0000000..25b8543 --- /dev/null +++ b/PCUT/PCUT/Converters/BooleanToStringConverter.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Windows.UI.Xaml.Data; + +namespace PCUT.Converters +{ + public class BooleanToStringConverter : IValueConverter + { + public object Convert(object value, Type targetType , object parameter, string language) + { + if(value is bool BoolValue) + { + return BoolValue ? "True" : "False"; + } + return "False"; + } + + public object ConvertBack(object value, Type targetType, object parameter, string language) + { + throw new NotImplementedException(); + } + } +} diff --git a/PCUT/PCUT/Converters/BooleanToVisibilityConverter.cs b/PCUT/PCUT/Converters/BooleanToVisibilityConverter.cs new file mode 100644 index 0000000..b795a02 --- /dev/null +++ b/PCUT/PCUT/Converters/BooleanToVisibilityConverter.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Windows.UI.Xaml; +using Windows.UI.Xaml.Data; + +namespace PCUT.Converters +{ + public class BooleanToVisibilityConverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, string language) + { + if (value is bool boolValue) + { + return boolValue ? Visibility.Visible : Visibility.Collapsed; + } + return Visibility.Collapsed; + } + + public object ConvertBack(object value, Type targetType, object parameter, string language) + { + throw new NotImplementedException(); + } + } +} diff --git a/PCUT/PCUT/Converters/OpacityConverter.cs b/PCUT/PCUT/Converters/OpacityConverter.cs new file mode 100644 index 0000000..0d2dc4b --- /dev/null +++ b/PCUT/PCUT/Converters/OpacityConverter.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Windows.UI.Xaml.Data; + +namespace PCUT.Converters +{ + public class OpacityConverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, string language) + { + return (bool)value ? 0.3 : 1; + } + + public object ConvertBack(object value, Type targetType, object parameter, string language) + { + return (double)value < 1; + } + } +} diff --git a/PCUT/PCUT/Converters/UserRoleToBooleanConverter.cs b/PCUT/PCUT/Converters/UserRoleToBooleanConverter.cs new file mode 100644 index 0000000..e8e87ab --- /dev/null +++ b/PCUT/PCUT/Converters/UserRoleToBooleanConverter.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Windows.UI.Xaml.Data; + +namespace PCUT.Converters +{ + public class UserRoleToBooleanConverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, string language) + { + return value?.ToString().ToLower() == "user"; + } + + public object ConvertBack(object value, Type targetType, object parameter, string language) + { + throw new NotImplementedException(); + } + } +} diff --git a/PCUT/PCUT/Converters/UserStatusConverter.cs b/PCUT/PCUT/Converters/UserStatusConverter.cs new file mode 100644 index 0000000..9ce4ee5 --- /dev/null +++ b/PCUT/PCUT/Converters/UserStatusConverter.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Windows.UI.Xaml.Data; + +namespace PCUT.Converters +{ + public class UserStatusConverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, string language) + { + return (bool)value ? "Active" : "Inactive"; + } + + public object ConvertBack(object value, Type targetType, object parameter, string language) + { + return value?.ToString() == "Active"; + } + } +} diff --git a/PCUT/PCUT/Converters/VisibilityConverter.cs b/PCUT/PCUT/Converters/VisibilityConverter.cs new file mode 100644 index 0000000..49e6bd1 --- /dev/null +++ b/PCUT/PCUT/Converters/VisibilityConverter.cs @@ -0,0 +1,36 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Windows.UI.Xaml; +using Windows.UI.Xaml.Data; + +namespace PCUT.Converters +{ + public class VisibilityConverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, string language) + { + return (bool)value ? Visibility.Visible : Visibility.Collapsed; + } + + public object ConvertBack(object value, Type targetType, object parameter, string language) + { + throw new NotImplementedException(); + } + } + + public class VisibilityInverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, string language) + { + return (bool)value ? Visibility.Collapsed : Visibility.Visible; + } + + public object ConvertBack(object value, Type targetType, object parameter, string language) + { + throw new NotImplementedException(); + } + } +} diff --git a/PCUT/PCUT/Converters/VisibilityToMarginConverter.cs b/PCUT/PCUT/Converters/VisibilityToMarginConverter.cs new file mode 100644 index 0000000..950a6f1 --- /dev/null +++ b/PCUT/PCUT/Converters/VisibilityToMarginConverter.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Windows.UI.Xaml; +using Windows.UI.Xaml.Data; + +namespace PCUT.Converters +{ + public class VisibilityToMarginConverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, string language) + { + Visibility visibility = (Visibility)value; + return visibility == Visibility.Visible ? new Thickness(0) : new Thickness(0, 0, 885, 0); + } + + public object ConvertBack(object value, Type targetType, object parameter, string language) + { + throw new NotImplementedException(); + } + } +} diff --git a/PCUT/PCUT/DeepNestApi/Background.cs b/PCUT/PCUT/DeepNestApi/Background.cs new file mode 100644 index 0000000..08a8fa4 --- /dev/null +++ b/PCUT/PCUT/DeepNestApi/Background.cs @@ -0,0 +1,1802 @@ +using ClipperLib; +using DeepNestLib; +using MinkowskiCpp; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Windows.Foundation; + +namespace PCUT.DeepNestApi +{ + public class Background + { + public static bool EnableCaches = true; + + public static NFP shiftPolygon(NFP p, PlacementItem shift) + { + NFP shifted = new NFP(); + for (var i = 0; i < p.length; i++) + { + shifted.AddPoint(new SvgPoint(p[i].x + shift.x, p[i].y + shift.y) { exact = p[i].exact }); + } + if (p.children != null /*&& p.children.Count*/) + { + shifted.children = new List(); + for (int i = 0; i < p.children.Count; i++) + { + shifted.children.Add(shiftPolygon(p.children[i], shift)); + } + } + + return shifted; + } + + + // returns the square of the length of any merged lines + // filter out any lines less than minlength long + public static MergedResult mergedLength(NFP[] parts, NFP p, double minlength, double tolerance) + { + // var min2 = minlength * minlength; + // var totalLength = 0; + // var segments = []; + + // for (var i = 0; i < p.length; i++) + // { + // var A1 = p[i]; + + // if (i + 1 == p.length) + // { + // A2 = p[0]; + // } + // else + // { + // var A2 = p[i + 1]; + // } + + // if (!A1.exact || !A2.exact) + // { + // continue; + // } + + // var Ax2 = (A2.x - A1.x) * (A2.x - A1.x); + // var Ay2 = (A2.y - A1.y) * (A2.y - A1.y); + + // if (Ax2 + Ay2 < min2) + // { + // continue; + // } + + // var angle = Math.atan2((A2.y - A1.y), (A2.x - A1.x)); + + // var c = Math.cos(-angle); + // var s = Math.sin(-angle); + + // var c2 = Math.cos(angle); + // var s2 = Math.sin(angle); + + // var relA2 = { x: A2.x - A1.x, y: A2.y - A1.y}; + // var rotA2x = relA2.x * c - relA2.y * s; + + // for (var j = 0; j < parts.length; j++) + // { + // var B = parts[j]; + // if (B.length > 1) + // { + // for (var k = 0; k < B.length; k++) + // { + // var B1 = B[k]; + + // if (k + 1 == B.length) + // { + // var B2 = B[0]; + // } + // else + // { + // var B2 = B[k + 1]; + // } + + // if (!B1.exact || !B2.exact) + // { + // continue; + // } + // var Bx2 = (B2.x - B1.x) * (B2.x - B1.x); + // var By2 = (B2.y - B1.y) * (B2.y - B1.y); + + // if (Bx2 + By2 < min2) + // { + // continue; + // } + + // // B relative to A1 (our point of rotation) + // var relB1 = { x: B1.x - A1.x, y: B1.y - A1.y}; + // var relB2 = { x: B2.x - A1.x, y: B2.y - A1.y}; + + + // // rotate such that A1 and A2 are horizontal + // var rotB1 = { x: relB1.x* c -relB1.y * s, y: relB1.x* s +relB1.y * c}; + // var rotB2 = { x: relB2.x* c -relB2.y * s, y: relB2.x* s +relB2.y * c}; + + // if(!GeometryUtil.almostEqual(rotB1.y, 0, tolerance) || !GeometryUtil.almostEqual(rotB2.y, 0, tolerance)){ + // continue; + // } + + // var min1 = Math.min(0, rotA2x); + // var max1 = Math.max(0, rotA2x); + + // var min2 = Math.min(rotB1.x, rotB2.x); + // var max2 = Math.max(rotB1.x, rotB2.x); + + // // not overlapping + // if(min2 >= max1 || max2 <= min1){ + // continue; + // } + + // var len = 0; + // var relC1x = 0; + // var relC2x = 0; + + // // A is B + // if(GeometryUtil.almostEqual(min1, min2) && GeometryUtil.almostEqual(max1, max2)){ + // len = max1-min1; + // relC1x = min1; + // relC2x = max1; + // } + // // A inside B + // else if(min1 > min2 && max1 min1 && max2 min2){ + // totalLength += len; + + // var relC1 = { x: relC1x * c2, y: relC1x * s2 }; + //var relC2 = { x: relC2x * c2, y: relC2x * s2 }; + + //var C1 = { x: relC1.x + A1.x, y: relC1.y + A1.y }; + //var C2 = { x: relC2.x + A1.x, y: relC2.y + A1.y }; + + //segments.push([C1, C2]); + // } + // } + // } + + // if(B.children && B.children.length > 0){ + // var child = mergedLength(B.children, p, minlength, tolerance); + //totalLength += child.totalLength; + // segments = segments.concat(child.segments); + // } + // } + // } + + // return {totalLength: totalLength, segments: segments}; + throw new NotImplementedException(); + } + + public class MergedResult + { + public double totalLength; + public object segments; + } + + + public static NFP[] cloneNfp(NFP[] nfp, bool inner = false) + { + if (!inner) + { + return new[] { clone(nfp.First()) }; + } + + // inner nfp is actually an array of nfps + List newnfp = new List(); + for (var i = 0; i < nfp.Count(); i++) + { + newnfp.Add(clone(nfp[i])); + } + + return newnfp.ToArray(); + } + + public static NFP clone(NFP nfp) + { + NFP newnfp = new NFP(); + newnfp.source = nfp.source; + for (var i = 0; i < nfp.length; i++) + { + newnfp.AddPoint(new SvgPoint(nfp[i].x, nfp[i].y)); + } + + if (nfp.children != null && nfp.children.Count > 0) + { + newnfp.children = new List(); + for (int i = 0; i < nfp.children.Count; i++) + { + var child = nfp.children[i]; + NFP newchild = new NFP(); + for (var j = 0; j < child.length; j++) + { + newchild.AddPoint(new SvgPoint(child[j].x, child[j].y)); + } + newnfp.children.Add(newchild); + } + } + + return newnfp; + } + + + public static int callCounter = 0; + + public static Dictionary cacheProcess = new Dictionary(); + public static NFP[] Process2(NFP A, NFP B, int type) + { + var key = A.source + ";" + B.source + ";" + A.rotation + ";" + B.rotation; + bool cacheAllow = type != 1; + if (cacheProcess.ContainsKey(key) && cacheAllow) + { + return cacheProcess[key]; + } + + Stopwatch swg = Stopwatch.StartNew(); + Dictionary> dic1 = new Dictionary>(); + Dictionary> dic2 = new Dictionary>(); + dic2.Add("A", new List()); + foreach (var item in A.Points) + { + var target = dic2["A"]; + target.Add(item.x); + target.Add(item.y); + } + dic2.Add("B", new List()); + foreach (var item in B.Points) + { + var target = dic2["B"]; + target.Add(item.x); + target.Add(item.y); + } + + + List hdat = new List(); + + foreach (var item in A.children) + { + foreach (var pitem in item.Points) + { + hdat.Add(pitem.x); + hdat.Add(pitem.y); + } + } + + var aa = dic2["A"]; + var bb = dic2["B"]; + var arr1 = A.children.Select(z => z.Points.Count() * 2).ToArray(); + + Minkowski.setData(aa.Count, aa.ToArray(), A.children.Count, arr1, hdat.ToArray(), bb.Count, bb.ToArray()); + Minkowski.calculateNFP(); + + callCounter++; + + int[] sizes = new int[2]; + Minkowski.getSizes1(sizes); + int[] sizes1 = new int[sizes[0]]; + int[] sizes2 = new int[sizes[1]]; + Minkowski.getSizes2(sizes1, sizes2); + double[] dat1 = new double[sizes1.Sum()]; + double[] hdat1 = new double[sizes2.Sum()]; + + Minkowski.getResults(dat1, hdat1); + + if (sizes1.Count() > 1) + { + throw new ArgumentException("sizes1 cnt >1"); + } + + + //convert back to answer here + bool isa = true; + List Apts = new List(); + + + + List> holesval = new List>(); + bool holes = false; + + for (int i = 0; i < dat1.Length; i += 2) + { + var x1 = (float)dat1[i]; + var y1 = (float)dat1[i + 1]; + Apts.Add(new Point(x1, y1)); + } + + int index = 0; + for (int i = 0; i < sizes2.Length; i++) + { + holesval.Add(new List()); + for (int j = 0; j < sizes2[i]; j++) + { + holesval.Last().Add(hdat1[index]); + index++; + } + } + + List> holesout = new List>(); + foreach (var item in holesval) + { + holesout.Add(new List()); + for (int i = 0; i < item.Count; i += 2) + { + var x = (float)item[i]; + var y = (float)item[i + 1]; + holesout.Last().Add(new Point(x, y)); + } + } + + NFP ret = new NFP(); + ret.Points = new SvgPoint[] { }; + foreach (var item in Apts) + { + ret.AddPoint(new SvgPoint(item.X, item.Y)); + } + + + foreach (var item in holesout) + { + if (ret.children == null) + ret.children = new List(); + + ret.children.Add(new NFP()); + ret.children.Last().Points = new SvgPoint[] { }; + foreach (var hitem in item) + { + ret.children.Last().AddPoint(new SvgPoint(hitem.X, hitem.Y)); + } + } + + swg.Stop(); + var msg = swg.ElapsedMilliseconds; + var res = new NFP[] { ret }; + + if (cacheAllow) + { + cacheProcess.Add(key, res); + } + return res; + } + + public static NFP getFrame(NFP A) + { + var bounds = GeometryUtil.getPolygonBounds(A); + + // expand bounds by 10% + bounds.width *= 1.1; + bounds.height *= 1.1; + bounds.x -= 0.5 * (bounds.width - (bounds.width / 1.1)); + bounds.y -= 0.5 * (bounds.height - (bounds.height / 1.1)); + + var frame = NFP.Create( + new SvgPoint(bounds.x, bounds.y), + new SvgPoint(bounds.x + bounds.width, bounds.y), + new SvgPoint(bounds.x + bounds.width, bounds.y + bounds.height), + new SvgPoint(bounds.x, bounds.y + bounds.height) + ); + + + frame.children = new List() { (NFP)A }; + frame.source = A.source; + frame.rotation = 0; + + return frame; + } + + public static NFP[] getInnerNfp(NFP A, NFP B, int type, SvgNestConfig config) + { + if (A.source != null && B.source != null) + { + + var key = new DbCacheKey() + { + A = A.source.Value, + B = B.source.Value, + ARotation = 0, + BRotation = B.rotation, + //Inside =true?? + }; + //var doc = window.db.find({ A: A.source, B: B.source, Arotation: 0, Brotation: B.rotation }, true); + var res = window.db.find(key, true); + if (res != null) + { + return res; + } + } + + + var frame = getFrame(A); + + var nfp = getOuterNfp(frame, B, type, true); + + if (nfp == null || nfp.children == null || nfp.children.Count == 0) + { + return null; + } + List holes = new List(); + if (A.children != null && A.children.Count > 0) + { + for (var i = 0; i < A.children.Count; i++) + { + var hnfp = getOuterNfp(A.children[i], B, 1); + if (hnfp != null) + { + holes.Add(hnfp); + } + } + } + + if (holes.Count == 0) + { + return nfp.children.ToArray(); + } + var clipperNfp = innerNfpToClipperCoordinates(nfp.children.ToArray(), config); + var clipperHoles = innerNfpToClipperCoordinates(holes.ToArray(), config); + + List> finalNfp = new List>(); + var clipper = new ClipperLib.Clipper(); + + clipper.AddPaths(clipperHoles.Select(z => z.ToList()).ToList(), ClipperLib.PolyType.ptClip, true); + clipper.AddPaths(clipperNfp.Select(z => z.ToList()).ToList(), ClipperLib.PolyType.ptSubject, true); + + if (!clipper.Execute(ClipperLib.ClipType.ctDifference, finalNfp, ClipperLib.PolyFillType.pftNonZero, ClipperLib.PolyFillType.pftNonZero)) + { + return nfp.children.ToArray(); + } + + if (finalNfp.Count == 0) + { + return null; + } + + List f = new List(); + for (var i = 0; i < finalNfp.Count; i++) + { + f.Add(toNestCoordinates(finalNfp[i].ToArray(), config.clipperScale)); + } + + if (A.source != null && B.source != null) + { + // insert into db + //console.log('inserting inner: ', A.source, B.source, B.rotation, f); + var doc = new DbCacheKey() + { + A = A.source.Value, + B = B.source.Value, + ARotation = 0, + BRotation = B.rotation, + nfp = f.ToArray() + + + }; + window.db.insert(doc, true); + } + + return f.ToArray(); + + } + public static NFP rotatePolygon(NFP polygon, float degrees) + { + NFP rotated = new NFP(); + + var angle = degrees * Math.PI / 180; + List pp = new List(); + for (var i = 0; i < polygon.length; i++) + { + var x = polygon[i].x; + var y = polygon[i].y; + var x1 = (x * Math.Cos(angle) - y * Math.Sin(angle)); + var y1 = (x * Math.Sin(angle) + y * Math.Cos(angle)); + + pp.Add(new SvgPoint(x1, y1)); + } + rotated.Points = pp.ToArray(); + + if (polygon.children != null && polygon.children.Count > 0) + { + rotated.children = new List(); ; + for (var j = 0; j < polygon.children.Count; j++) + { + rotated.children.Add(rotatePolygon(polygon.children[j], degrees)); + } + } + + return rotated; + } + + public static SheetPlacement placeParts(NFP[] sheets, NFP[] parts, SvgNestConfig config, int nestindex) + { + if (sheets == null || sheets.Count() == 0) return null; + + + int i, j, k, m, n; + double totalsheetarea = 0; + + NFP part = null; + // total length of merged lines + double totalMerged = 0; + + // rotate paths by given rotation + var rotated = new List(); + for (i = 0; i < parts.Length; i++) + { + var r = rotatePolygon(parts[i], parts[i].rotation); + r.Rotation = parts[i].rotation; + r.source = parts[i].source; + r.Id = parts[i].Id; + rotated.Add(r); + } + + parts = rotated.ToArray(); + + List allplacements = new List(); + + double fitness = 0; + + string key; + NFP nfp; + double sheetarea = -1; + int totalPlaced = 0; + int totalParts = parts.Count(); + + while (parts.Length > 0) + { + + List placed = new List(); + + List placements = new List(); + + // open a new sheet + var sheet = sheets.First(); + sheets = sheets.Skip(1).ToArray(); + sheetarea = Math.Abs(GeometryUtil.polygonArea(sheet)); + totalsheetarea += sheetarea; + + fitness += sheetarea; // add 1 for each new sheet opened (lower fitness is better) + + string clipkey = ""; + Dictionary clipCache = new Dictionary(); + var clipper = new ClipperLib.Clipper(); + var combinedNfp = new List>(); + var error = false; + IntPoint[][] clipperSheetNfp = null; + double? minwidth = null; + PlacementItem position = null; + double? minarea = null; + for (i = 0; i < parts.Length; i++) + { + float prog = 0.66f + 0.34f * (totalPlaced / (float)totalParts); + DisplayProgress(prog); + + part = parts[i]; + // inner NFP + NFP[] sheetNfp = null; + // try all possible rotations until it fits + // (only do this for the first part of each sheet, to ensure that all parts that can be placed are, even if we have to to open a lot of sheets) + for (j = 0; j < (360f / config.rotations); j++) + { + sheetNfp = getInnerNfp(sheet, part, 0, config); + + if (sheetNfp != null && sheetNfp.Count() > 0) + { + if (sheetNfp[0].length == 0) + { + throw new ArgumentException(); + } + else + { + break; + } + } + + var r = rotatePolygon(part, 360f / config.rotations); + r.rotation = part.rotation + (360f / config.rotations); + r.source = part.source; + r.id = part.id; + + // rotation is not in-place + part = r; + parts[i] = r; + + if (part.rotation > 360f) + { + part.rotation = part.rotation % 360f; + } + } + // part unplaceable, skip + if (sheetNfp == null || sheetNfp.Count() == 0) + { + continue; + } + + position = null; + + if (placed.Count == 0) + { + // first placement, put it on the top left corner + for (j = 0; j < sheetNfp.Count(); j++) + { + for (k = 0; k < sheetNfp[j].length; k++) + { + if (position == null || + ((sheetNfp[j][k].x - part[0].x) < position.x) || + ( + GeometryUtil._almostEqual(sheetNfp[j][k].x - part[0].x, position.x) + && ((sheetNfp[j][k].y - part[0].y) < position.y)) + ) + { + position = new PlacementItem() + { + x = sheetNfp[j][k].x - part[0].x, + y = sheetNfp[j][k].y - part[0].y, + id = part.id, + rotation = part.rotation, + source = part.source.Value + + }; + + + } + } + } + + if (position == null) + { + throw new Exception("position null"); + //console.log(sheetNfp); + } + placements.Add(position); + placed.Add(part); + totalPlaced++; + + continue; + } + + clipperSheetNfp = innerNfpToClipperCoordinates(sheetNfp, config); + + clipper = new ClipperLib.Clipper(); + combinedNfp = new List>(); + + error = false; + + // check if stored in clip cache + //var startindex = 0; + clipkey = "s:" + part.source + "r:" + part.rotation; + var startindex = 0; + if (EnableCaches && clipCache.ContainsKey(clipkey)) + { + var prevNfp = clipCache[clipkey].nfpp; + clipper.AddPaths(prevNfp.Select(z => z.ToList()).ToList(), ClipperLib.PolyType.ptSubject, true); + startindex = clipCache[clipkey].index; + } + + for (j = startindex; j < placed.Count; j++) + { + nfp = getOuterNfp(placed[j], part, 0); + // minkowski difference failed. very rare but could happen + if (nfp == null) + { + error = true; + break; + } + // shift to placed location + for (m = 0; m < nfp.length; m++) + { + nfp[m].x += placements[j].x; + nfp[m].y += placements[j].y; + } + if (nfp.children != null && nfp.children.Count > 0) + { + for (n = 0; n < nfp.children.Count; n++) + { + for (var o = 0; o < nfp.children[n].length; o++) + { + nfp.children[n][o].x += placements[j].x; + nfp.children[n][o].y += placements[j].y; + } + } + } + + var clipperNfp = nfpToClipperCoordinates(nfp, config.clipperScale); + + clipper.AddPaths(clipperNfp.Select(z => z.ToList()).ToList(), ClipperLib.PolyType.ptSubject, true); + } + //TODO: a lot here to insert + + if (error || !clipper.Execute(ClipperLib.ClipType.ctUnion, combinedNfp, ClipperLib.PolyFillType.pftNonZero, ClipperLib.PolyFillType.pftNonZero)) + { + //console.log('clipper error', error); + continue; + } + + + if (EnableCaches) + { + clipCache[clipkey] = new ClipCacheItem() + { + index = placed.Count - 1, + nfpp = combinedNfp.Select(z => z.ToArray()).ToArray() + }; + } + + //console.log('save cache', placed.length - 1); + + // difference with sheet polygon + List> _finalNfp = new List>(); + clipper = new ClipperLib.Clipper(); + + clipper.AddPaths(combinedNfp, ClipperLib.PolyType.ptClip, true); + + clipper.AddPaths(clipperSheetNfp.Select(z => z.ToList()).ToList(), ClipperLib.PolyType.ptSubject, true); + + + if (!clipper.Execute(ClipperLib.ClipType.ctDifference, _finalNfp, ClipperLib.PolyFillType.pftEvenOdd, ClipperLib.PolyFillType.pftNonZero)) + { + continue; + } + + if (_finalNfp == null || _finalNfp.Count == 0) + { + continue; + } + + + List f = new List(); + for (j = 0; j < _finalNfp.Count; j++) + { + // back to normal scale + f.Add(Background.toNestCoordinates(_finalNfp[j].ToArray(), config.clipperScale)); + } + var finalNfp = f; + //finalNfp = f; + + // choose placement that results in the smallest bounding box/hull etc + // todo: generalize gravity direction + /*var minwidth = null; + var minarea = null; + var minx = null; + var miny = null; + var nf, area, shiftvector;*/ + minwidth = null; + minarea = null; + double? minx = null; + double? miny = null; + NFP nf; + double area = 0; + PlacementItem shiftvector = null; + + + NFP allpoints = new NFP(); + for (m = 0; m < placed.Count; m++) + { + for (n = 0; n < placed[m].length; n++) + { + allpoints.AddPoint( + new SvgPoint( + placed[m][n].x + placements[m].x, placed[m][n].y + placements[m].y)); + } + } + + PolygonBounds allbounds = null; + PolygonBounds partbounds = null; + if (config.placementType == PlacementTypeEnum.gravity || config.placementType == PlacementTypeEnum.box) + { + allbounds = GeometryUtil.getPolygonBounds(allpoints); + + NFP partpoints = new NFP(); + for (m = 0; m < part.length; m++) + { + partpoints.AddPoint(new SvgPoint(part[m].x, part[m].y)); + } + partbounds = GeometryUtil.getPolygonBounds(partpoints); + } + else + { + allpoints = getHull(allpoints); + } + for (j = 0; j < finalNfp.Count; j++) + { + nf = finalNfp[j]; + //console.log('evalnf',nf.length); + for (k = 0; k < nf.length; k++) + { + shiftvector = new PlacementItem() + { + id = part.id, + x = nf[k].x - part[0].x, + y = nf[k].y - part[0].y, + source = part.source.Value, + rotation = part.rotation + }; + PolygonBounds rectbounds = null; + if (config.placementType == PlacementTypeEnum.gravity || config.placementType == PlacementTypeEnum.box) + { + NFP poly = new NFP(); + poly.AddPoint(new SvgPoint(allbounds.x, allbounds.y)); + poly.AddPoint(new SvgPoint(allbounds.x + allbounds.width, allbounds.y)); + poly.AddPoint(new SvgPoint(allbounds.x + allbounds.width, allbounds.y + allbounds.height)); + poly.AddPoint(new SvgPoint(allbounds.x, allbounds.y + allbounds.height)); + /* + [ + // allbounds points + { x: allbounds.x, y: allbounds.y}, + { x: allbounds.x + allbounds.width, y: allbounds.y}, + { x: allbounds.x + allbounds.width, y: allbounds.y + allbounds.height}, + { x: allbounds.x, y: allbounds.y + allbounds.height},*/ + + poly.AddPoint(new SvgPoint(partbounds.x + shiftvector.x, partbounds.y + shiftvector.y)); + poly.AddPoint(new SvgPoint(partbounds.x + partbounds.width + shiftvector.x, partbounds.y + shiftvector.y)); + poly.AddPoint(new SvgPoint(partbounds.x + partbounds.width + shiftvector.x, partbounds.y + partbounds.height + shiftvector.y)); + poly.AddPoint(new SvgPoint(partbounds.x + shiftvector.x, partbounds.y + partbounds.height + shiftvector.y)); + /* + [ + + // part points + { x: partbounds.x + shiftvector.x, y: partbounds.y + shiftvector.y}, + { x: partbounds.x + partbounds.width + shiftvector.x, y: partbounds.y + shiftvector.y}, + { x: partbounds.x + partbounds.width + shiftvector.x, y: partbounds.y + partbounds.height + shiftvector.y}, + { x: partbounds.x + shiftvector.x, y: partbounds.y + partbounds.height + shiftvector.y} + ]*/ + rectbounds = GeometryUtil.getPolygonBounds(poly); + + // weigh width more, to help compress in direction of gravity + if (config.placementType == PlacementTypeEnum.gravity) + { + area = rectbounds.width * 2 + rectbounds.height; + } + else + { + area = rectbounds.width * rectbounds.height; + } + } + else + { + // must be convex hull + var localpoints = clone(allpoints); + + for (m = 0; m < part.length; m++) + { + localpoints.AddPoint(new SvgPoint(part[m].x + shiftvector.x, part[m].y + shiftvector.y)); + } + + area = Math.Abs(GeometryUtil.polygonArea(getHull(localpoints))); + shiftvector.hull = getHull(localpoints); + shiftvector.hullsheet = getHull(sheet); + } + //console.timeEnd('evalbounds'); + //console.time('evalmerge'); + MergedResult merged = null; + if (config.mergeLines) + { + throw new NotImplementedException(); + // if lines can be merged, subtract savings from area calculation + var shiftedpart = shiftPolygon(part, shiftvector); + List shiftedplaced = new List(); + + for (m = 0; m < placed.Count; m++) + { + shiftedplaced.Add(shiftPolygon(placed[m], placements[m])); + } + + // don't check small lines, cut off at about 1/2 in + double minlength = 0.5 * config.scale; + merged = mergedLength(shiftedplaced.ToArray(), shiftedpart, minlength, 0.1 * config.curveTolerance); + area -= merged.totalLength * config.timeRatio; + } + + //console.timeEnd('evalmerge'); + if ( + minarea == null || + area < minarea || + (GeometryUtil._almostEqual(minarea, area) && (minx == null || shiftvector.x < minx)) || + (GeometryUtil._almostEqual(minarea, area) && (minx != null && GeometryUtil._almostEqual(shiftvector.x, minx) && shiftvector.y < miny)) + ) + { + minarea = area; + + minwidth = rectbounds != null ? rectbounds.width : 0; + position = shiftvector; + if (minx == null || shiftvector.x < minx) + { + minx = shiftvector.x; + } + if (miny == null || shiftvector.y < miny) + { + miny = shiftvector.y; + } + + if (config.mergeLines) + { + position.mergedLength = merged.totalLength; + position.mergedSegments = merged.segments; + } + } + } + + } + + if (position != null) + { + placed.Add(part); + totalPlaced++; + placements.Add(position); + if (position.mergedLength != null) + { + totalMerged += position.mergedLength.Value; + } + } + // send placement progress signal + var placednum = placed.Count; + for (j = 0; j < allplacements.Count; j++) + { + placednum += allplacements[j].sheetplacements.Count; + } + //console.log(placednum, totalnum); + //ipcRenderer.send('background-progress', { index: nestindex, progress: 0.5 + 0.5 * (placednum / totalnum)}); + + //console.timeEnd('placement'); + } + //if(minwidth){ + if (!minwidth.HasValue) + { + fitness = double.NaN; + } + else + { + fitness += (minwidth.Value / sheetarea) + minarea.Value; + } + + //} + for (i = 0; i < placed.Count; i++) + { + var index = Array.IndexOf(parts, placed[i]); + if (index >= 0) + { + parts = parts.splice(index, 1); + } + } + if (placements != null && placements.Count > 0) + { + allplacements.Add(new SheetPlacementItem() + { + sheetId = sheet.id, + sheetSource = sheet.source.Value, + sheetplacements = placements + }); + //allplacements.Add({ sheet: sheet.source, sheetid: sheet.id, sheetplacements: placements}); + } + else + { + break; // something went wrong + } + + if (sheets.Count() == 0) + { + break; + } + } + + // there were parts that couldn't be placed + // scale this value high - we really want to get all the parts in, even at the cost of opening new sheets + for (i = 0; i < parts.Count(); i++) + { + fitness += 100000000 * (Math.Abs(GeometryUtil.polygonArea(parts[i])) / totalsheetarea); + } + // send finish progerss signal + //ipcRenderer.send('background-progress', { index: nestindex, progress: -1}); + + + return new SheetPlacement() + { + placements = new[] { allplacements.ToList() }, + fitness = fitness, + // paths = paths, + area = sheetarea, + mergedLength = totalMerged + + + }; + //return { placements: allplacements, fitness: fitness, area: sheetarea, mergedLength: totalMerged }; + } + // jsClipper uses X/Y instead of x/y... + public DataInfo data; + NFP[] parts; + + + + int index; + // run the placement synchronously + + + public static windowUnk window = new windowUnk(); + + public Action ResponseAction; + + public static long LastPlacePartTime = 0; + public void sync() + { + //console.log('starting synchronous calculations', Object.keys(window.nfpCache).length); + //console.log('in sync'); + var c = 0; + foreach (var key in window.nfpCache) + { + c++; + } + //console.log('nfp cached:', c); + Stopwatch sw = Stopwatch.StartNew(); + var placement = placeParts(data.sheets.ToArray(), parts, data.config, index); + sw.Stop(); + LastPlacePartTime = sw.ElapsedMilliseconds; + + placement.index = data.index; + ResponseAction(placement); + //ipcRenderer.send('background-response', placement); + } + public void BackgroundStart(DataInfo data) + { + this.data = data; + var index = data.index; + var individual = data.individual; + + var parts = individual.placements; + var rotations = individual.Rotation; + var ids = data.ids; + var sources = data.sources; + var children = data.children; + + for (var i = 0; i < parts.Count; i++) + { + parts[i].rotation = rotations[i]; + parts[i].id = ids[i]; + parts[i].source = sources[i]; + if (!data.config.simplify) + { + parts[i].children = children[i]; + } + } + + for (int i = 0; i < data.sheets.Count; i++) + { + data.sheets[i].id = data.sheetids[i]; + data.sheets[i].source = data.sheetsources[i]; + data.sheets[i].children = data.sheetchildren[i]; + } + + // preprocess + List pairs = new List(); + + if (Background.UseParallel) + { + object lobj = new object(); + Parallel.For(0, parts.Count, i => + { + { + var B = parts[i]; + for (var j = 0; j < i; j++) + { + var A = parts[j]; + var key = NfpPair.Create(A, B); + //var key = new NfpPair() + //{ + // A = A, + // B = B, + // ARotation = A.rotation, + // BRotation = B.rotation, + // Asource = A.source.Value, + // Bsource = B.source.Value + + //}; + var doc = new DbCacheKey() + { + A = A.source.Value, + B = B.source.Value, + + ARotation = A.rotation, + BRotation = B.rotation + + }; + lock (lobj) + { + if (!inpairs(key, pairs.ToArray()) && !window.db.has(doc)) + { + pairs.Add(key); + } + } + } + } + }); + } + else + { + for (var i = 0; i < parts.Count; i++) + { + var B = parts[i]; + for (var j = 0; j < i; j++) + { + var A = parts[j]; + var key = NfpPair.Create(A, B); + //var key = new NfpPair() + //{ + // A = A, + // B = B, + // ARotation = A.rotation, + // BRotation = B.rotation, + // Asource = A.source.Value, + // Bsource = B.source.Value + + //}; + var doc = new DbCacheKey() + { + A = A.source.Value, + B = B.source.Value, + + ARotation = A.rotation, + BRotation = B.rotation + }; + if (!inpairs(key, pairs.ToArray()) && !window.db.has(doc)) + { + pairs.Add(key); + } + } + } + } + + //console.log('pairs: ', pairs.length); + //console.time('Total'); + + this.parts = parts.ToArray(); + if (pairs.Count > 0) + { + + var ret1 = pmapDeepNest(pairs); + thenDeepNest(ret1, parts); + } + else + { + sync(); + } + } + public NFP getPart(int source, List parts) + { + for (var k = 0; k < parts.Count; k++) + { + if (parts[k].source == source) + { + return parts[k]; + } + } + return null; + } + + public void thenIterate(NfpPair processed, List parts) + { + + // returned data only contains outer nfp, we have to account for any holes separately in the synchronous portion + // this is because the c++ addon which can process interior nfps cannot run in the worker thread + var A = getPart(processed.Asource, parts); + var B = getPart(processed.Bsource, parts); + + List Achildren = new List(); + + + if (A.children != null) + { + for (int j = 0; j < A.children.Count; j++) + { + Achildren.Add(rotatePolygon(A.children[j], processed.ARotation)); + } + } + + if (Achildren.Count > 0) + { + var Brotated = rotatePolygon(B, processed.BRotation); + var bbounds = GeometryUtil.getPolygonBounds(Brotated); + List cnfp = new List(); + + for (int j = 0; j < Achildren.Count; j++) + { + var cbounds = GeometryUtil.getPolygonBounds(Achildren[j]); + if (cbounds.width > bbounds.width && cbounds.height > bbounds.height) + { + var n = getInnerNfp(Achildren[j], Brotated, 1, data.config); + if (n != null && n.Count() > 0) + { + cnfp.AddRange(n); + } + } + } + + processed.nfp.children = cnfp; + } + DbCacheKey doc = new DbCacheKey() + { + A = processed.Asource, + B = processed.Bsource, + ARotation = processed.ARotation, + BRotation = processed.BRotation, + nfp = new[] { processed.nfp } + }; + + /*var doc = { + A: processed[i].Asource, + B: processed[i].Bsource, + Arotation: processed[i].Arotation, + Brotation: processed[i].Brotation, + nfp: processed[i].nfp + + };*/ + window.db.insert(doc); + } + + public static Action displayProgress; + public static void DisplayProgress(double p) + { + if (displayProgress != null) + { + displayProgress(p); + } + } + public void thenDeepNest(NfpPair[] processed, List parts) + { + int cnt = 0; + if (UseParallel) + { + Parallel.For(0, processed.Count(), (i) => + { + float progress = 0.33f + 0.33f * (cnt / (float)processed.Count()); + cnt++; + DisplayProgress(progress); + thenIterate(processed[i], parts); + }); + + } + else + { + for (var i = 0; i < processed.Count(); i++) + { + float progress = 0.33f + 0.33f * (cnt / (float)processed.Count()); + cnt++; + DisplayProgress(progress); + thenIterate(processed[i], parts); + } + } + + //console.timeEnd('Total'); + //console.log('before sync'); + sync(); + } + + + public bool inpairs(NfpPair key, NfpPair[] p) + { + for (var i = 0; i < p.Length; i++) + { + if (p[i].Asource == key.Asource && p[i].Bsource == key.Bsource && p[i].ARotation == key.ARotation && p[i].BRotation == key.BRotation) + { + return true; + } + } + return false; + } + + public static bool UseParallel = false; + public NfpPair[] pmapDeepNest(List pairs) + { + + + NfpPair[] ret = new NfpPair[pairs.Count()]; + int cnt = 0; + if (UseParallel) + { + Parallel.For(0, pairs.Count, (i) => + { + ret[i] = process(pairs[i]); + float progress = 0.33f * (cnt / (float)pairs.Count); + cnt++; + DisplayProgress(progress); + }); + } + else + { + for (int i = 0; i < pairs.Count; i++) + { + var item = pairs[i]; + ret[i] = process(item); + float progress = 0.33f * (cnt / (float)pairs.Count); + cnt++; + DisplayProgress(progress); + } + } + return ret.ToArray(); + } + public NfpPair process(NfpPair pair) + { + var A = rotatePolygon(pair.A, pair.ARotation); + var B = rotatePolygon(pair.B, pair.BRotation); + + /////////////////// + var Ac = _Clipper.ScaleUpPaths(A, 10000000); + + var Bc = _Clipper.ScaleUpPaths(B, 10000000); + for (var i = 0; i < Bc.Length; i++) + { + Bc[i].X *= -1; + Bc[i].Y *= -1; + } + var solution = ClipperLib.Clipper.MinkowskiSum(new List(Ac), new List(Bc), true); + NFP clipperNfp = null; + + double? largestArea = null; + for (int i = 0; i < solution.Count(); i++) + { + var n = toNestCoordinates(solution[i].ToArray(), 10000000); + var sarea = -GeometryUtil.polygonArea(n); + if (largestArea == null || largestArea < sarea) + { + clipperNfp = n; + largestArea = sarea; + } + } + + for (var i = 0; i < clipperNfp.length; i++) + { + clipperNfp[i].x += B[0].x; + clipperNfp[i].y += B[0].y; + } + + //return new SvgNestPort.NFP[] { new SvgNestPort.NFP() { Points = clipperNfp.Points } }; + + ////////////// + + pair.A = null; + pair.B = null; + pair.nfp = clipperNfp; + return pair; + + + } + + public static NFP toNestCoordinates(IntPoint[] polygon, double scale) + { + var clone = new List(); + + for (var i = 0; i < polygon.Count(); i++) + { + clone.Add(new SvgPoint( + polygon[i].X / scale, + polygon[i].Y / scale + )); + } + return new NFP() { Points = clone.ToArray() }; + } + + public static NFP getHull(NFP polygon) + { + // convert to hulljs format + /*var hull = new ConvexHullGrahamScan(); + for(var i=0; i clipperNfp = new List(); + + // children first + if (nfp.children != null && nfp.children.Count > 0) + { + for (var j = 0; j < nfp.children.Count; j++) + { + if (GeometryUtil.polygonArea(nfp.children[j]) < 0) + { + nfp.children[j].reverse(); + } + //var childNfp = SvgNest.toClipperCoordinates(nfp.children[j]); + var childNfp = _Clipper.ScaleUpPaths(nfp.children[j], clipperScale); + clipperNfp.Add(childNfp); + } + } + + if (GeometryUtil.polygonArea(nfp) > 0) + { + nfp.reverse(); + } + + + //var outerNfp = SvgNest.toClipperCoordinates(nfp); + + // clipper js defines holes based on orientation + + var outerNfp = _Clipper.ScaleUpPaths(nfp, clipperScale); + + //var cleaned = ClipperLib.Clipper.CleanPolygon(outerNfp, 0.00001*config.clipperScale); + + clipperNfp.Add(outerNfp); + //var area = Math.abs(ClipperLib.Clipper.Area(cleaned)); + + return clipperNfp.ToArray(); + } + // inner nfps can be an array of nfps, outer nfps are always singular + public static IntPoint[][] innerNfpToClipperCoordinates(NFP[] nfp, SvgNestConfig config) + { + List clipperNfp = new List(); + for (var i = 0; i < nfp.Count(); i++) + { + var clip = nfpToClipperCoordinates(nfp[i], config.clipperScale); + clipperNfp.AddRange(clip); + //clipperNfp = clipperNfp.Concat(new[] { clip }).ToList(); + } + + return clipperNfp.ToArray(); + } + + static object lockobj = new object(); + + public static NFP[] NewMinkowskiSum(NFP pattern, NFP path, int type, bool useChilds = false, bool takeOnlyBiggestArea = true) + { + var key = pattern.source + ";" + path.source + ";" + pattern.rotation + ";" + path.rotation; + bool cacheAllow = type != 1; + if (cacheProcess.ContainsKey(key) && cacheAllow) + { + return cacheProcess[key]; + } + + var ac = _Clipper.ScaleUpPaths(pattern, 10000000); + List> solution = null; + if (useChilds) + { + var bc = Background.nfpToClipperCoordinates(path, 10000000); + for (var i = 0; i < bc.Length; i++) + { + for (int j = 0; j < bc[i].Length; j++) + { + bc[i][j].X *= -1; + bc[i][j].Y *= -1; + } + } + + solution = ClipperLib.Clipper.MinkowskiSum(new List(ac), new List>(bc.Select(z => z.ToList())), true); + } + else + { + var bc = _Clipper.ScaleUpPaths(path, 10000000); + for (var i = 0; i < bc.Length; i++) + { + bc[i].X *= -1; + bc[i].Y *= -1; + } + solution = Clipper.MinkowskiSum(new List(ac), new List(bc), true); + } + NFP clipperNfp = null; + + double? largestArea = null; + int largestIndex = -1; + + for (int i = 0; i < solution.Count(); i++) + { + var n = toNestCoordinates(solution[i].ToArray(), 10000000); + var sarea = Math.Abs(GeometryUtil.polygonArea(n)); + if (largestArea == null || largestArea < sarea) + { + clipperNfp = n; + largestArea = sarea; + largestIndex = i; + } + } + if (!takeOnlyBiggestArea) + { + for (int j = 0; j < solution.Count; j++) + { + if (j == largestIndex) continue; + var n = toNestCoordinates(solution[j].ToArray(), 10000000); + if (clipperNfp.children == null) + clipperNfp.children = new List(); + clipperNfp.children.Add(n); + } + } + for (var i = 0; i < clipperNfp.Length; i++) + { + + clipperNfp[i].x *= -1; + clipperNfp[i].y *= -1; + clipperNfp[i].x += pattern[0].x; + clipperNfp[i].y += pattern[0].y; + + } + if (clipperNfp.children != null) + foreach (var nFP in clipperNfp.children) + { + for (int j = 0; j < nFP.Length; j++) + { + + nFP.Points[j].x *= -1; + nFP.Points[j].y *= -1; + nFP.Points[j].x += pattern[0].x; + nFP.Points[j].y += pattern[0].y; + } + } + var res = new[] { clipperNfp }; + if (cacheAllow) + { + cacheProcess.Add(key, res); + } + return res; + } + public static void ExecuteSTA(Action act) + { + if (!Debugger.IsAttached) return; + Thread thread = new Thread(() => { act(); }); + thread.SetApartmentState(ApartmentState.STA); + thread.Start(); + thread.Join(); + } + + public static bool UseExternalDll = false; + public static NFP getOuterNfp(NFP A, NFP B, int type, bool inside = false)//todo:?inside def? + { + NFP[] nfp = null; + + + var key = new DbCacheKey() + { + A = A.source, + B = B.source, + ARotation = A.rotation, + BRotation = B.rotation, + //Type = type + }; + + var doc = window.db.find(key); + if (doc != null) + { + return doc.First(); + } + + /* + + // try the file cache if the calculation will take a long time + var doc = window.db.find({ A: A.source, B: B.source, Arotation: A.rotation, Brotation: B.rotation }); + + if (doc) + { + return doc; + }*/ + + + // not found in cache + if (inside || (A.children != null && A.children.Count > 0)) + { + lock (lockobj) + { + if (UseExternalDll) + { + nfp = Process2(A, B, type); + + } + else + { + nfp = NewMinkowskiSum(B, A, type, true, takeOnlyBiggestArea: false); + } + } + } + else + { + var Ac = _Clipper.ScaleUpPaths(A, 10000000); + + var Bc = _Clipper.ScaleUpPaths(B, 10000000); + for (var i = 0; i < Bc.Length; i++) + { + Bc[i].X *= -1; + Bc[i].Y *= -1; + } + var solution = ClipperLib.Clipper.MinkowskiSum(new List(Ac), new List(Bc), true); + NFP clipperNfp = null; + + double? largestArea = null; + for (int i = 0; i < solution.Count(); i++) + { + var n = Background.toNestCoordinates(solution[i].ToArray(), 10000000); + var sarea = GeometryUtil.polygonArea(n); + if (largestArea == null || largestArea > sarea) + { + clipperNfp = n; + largestArea = sarea; + } + } + + for (var i = 0; i < clipperNfp.length; i++) + { + clipperNfp[i].x += B[0].x; + clipperNfp[i].y += B[0].y; + } + nfp = new NFP[] { new NFP() { Points = clipperNfp.Points } }; + + + } + + if (nfp == null || nfp.Length == 0) + { + //console.log('holy shit', nfp, A, B, JSON.stringify(A), JSON.stringify(B)); + return null; + } + + NFP nfps = nfp.First(); + /* + nfp = nfp.pop(); + */ + if (nfps == null || nfps.Length == 0) + { + return null; + } + /* + if (!nfp || nfp.length == 0) + { + return null; + } + */ + if (!inside && A.source != null && B.source != null) + { + var doc2 = new DbCacheKey() + { + A = A.source.Value, + B = B.source.Value, + ARotation = A.rotation, + BRotation = B.rotation, + nfp = nfp + }; + window.db.insert(doc2); + + + } + /* + if (!inside && typeof A.source !== 'undefined' && typeof B.source !== 'undefined') + { + // insert into db + doc = { + A: A.source, + B: B.source, + Arotation: A.rotation, + Brotation: B.rotation, + nfp: nfp + + }; + window.db.insert(doc); + } + */ + return nfps; + + + + } + } + + public class ClipCacheItem + { + public int index; + public IntPoint[][] nfpp; + } + + public class dbCache + { + public dbCache(windowUnk w) + { + window = w; + } + public bool has(DbCacheKey obj) + { + lock (lockobj) + { + var key = getKey(obj); + //var key = "A" + obj.A + "B" + obj.B + "Arot" + (int)Math.Round(obj.ARotation) + "Brot" + (int)Math.Round(obj.BRotation); + if (window.nfpCache.ContainsKey(key)) + { + return true; + } + return false; + } + + } + + public windowUnk window; + public object lockobj = new object(); + + string getKey(DbCacheKey obj) + { + var key = "A" + obj.A + "B" + obj.B + "Arot" + (int)Math.Round(obj.ARotation * 10000) + "Brot" + (int)Math.Round((obj.BRotation * 10000)) + ";" + obj.Type; + return key; + } + internal void insert(DbCacheKey obj, bool inner = false) + { + + var key = getKey(obj); + //if (window.performance.memory.totalJSHeapSize < 0.8 * window.performance.memory.jsHeapSizeLimit) + { + lock (lockobj) + { + if (!window.nfpCache.ContainsKey(key)) + { + window.nfpCache.Add(key, Background.cloneNfp(obj.nfp, inner).ToList()); + } + else + { + throw new Exception("trouble .cache allready has such key"); + // window.nfpCache[key] = Background.cloneNfp(new[] { obj.nfp }, inner).ToList(); + } + } + //console.log('cached: ',window.cache[key].poly); + //console.log('using', window.performance.memory.totalJSHeapSize/window.performance.memory.jsHeapSizeLimit); + } + } + public NFP[] find(DbCacheKey obj, bool inner = false) + { + lock (lockobj) + { + var key = getKey(obj); + //var key = "A" + obj.A + "B" + obj.B + "Arot" + (int)Math.Round(obj.ARotation) + "Brot" + (int)Math.Round((obj.BRotation)); + + //console.log('key: ', key); + if (window.nfpCache.ContainsKey(key)) + { + return Background.cloneNfp(window.nfpCache[key].ToArray(), inner); + } + + return null; + } + } + + } + public class windowUnk + { + public windowUnk() + { + db = new dbCache(this); + } + public Dictionary> nfpCache = new Dictionary>(); + public dbCache db; + } +} diff --git a/PCUT/PCUT/DeepNestApi/DraftElement.cs b/PCUT/PCUT/DeepNestApi/DraftElement.cs new file mode 100644 index 0000000..1e676e5 --- /dev/null +++ b/PCUT/PCUT/DeepNestApi/DraftElement.cs @@ -0,0 +1,19 @@ +using Windows.Foundation; + +namespace PCUT.DeepNestApi +{ + public abstract class DraftElement + { + public object Tag; + public Point Start; + public Point End; + + public abstract double Length { get; } + + public abstract void Reverse(); + public abstract Point[] GetPoints(); + + internal abstract void Mult(double mult); + + } +} diff --git a/PCUT/PCUT/DeepNestApi/LineElement.cs b/PCUT/PCUT/DeepNestApi/LineElement.cs new file mode 100644 index 0000000..cbfbeef --- /dev/null +++ b/PCUT/PCUT/DeepNestApi/LineElement.cs @@ -0,0 +1,26 @@ +using PCUT.Extensions; +using Windows.Foundation; + +namespace PCUT.DeepNestApi +{ + public class LineElement : DraftElement + { + public override Point[] GetPoints() + { + return new[] { Start, End }; + } + public override double Length => Start.DistTo(End); + public override void Reverse() + { + var temp = End; + End = Start; + Start = temp; + } + + internal override void Mult(double mult) + { + Start = Start.Mult(mult); + } + } + +} diff --git a/PCUT/PCUT/DeepNestApi/LocalContour.cs b/PCUT/PCUT/DeepNestApi/LocalContour.cs new file mode 100644 index 0000000..4b819f4 --- /dev/null +++ b/PCUT/PCUT/DeepNestApi/LocalContour.cs @@ -0,0 +1,37 @@ +using System; +using System.Collections.Generic; +using Windows.Foundation; + +namespace PCUT.DeepNestApi +{ + public class LocalContour + { + public double Len + { + get + { + double len = 0; + for (int i = 1; i <= Points.Count; i++) + { + var p1 = Points[i - 1]; + var p2 = Points[i % Points.Count]; + len += Math.Sqrt(Math.Pow(p1.X - p2.X, 2) + Math.Pow(p1.Y - p2.Y, 2)); + } + return len; + } + } + public List Points = new List(); + public bool Enable = true; + public List Childrens = new List(); + public LocalContour Parent; + public object Tag; + + public void Scale(double v) + { + for (int i = 0; i < Points.Count; i++) + { + Points[i] = new Point((Points[i].X * v), (Points[i].Y * v)); + } + } + } +} diff --git a/PCUT/PCUT/DeepNestApi/NestingContext.cs b/PCUT/PCUT/DeepNestApi/NestingContext.cs new file mode 100644 index 0000000..dad6370 --- /dev/null +++ b/PCUT/PCUT/DeepNestApi/NestingContext.cs @@ -0,0 +1,357 @@ +using DeepNestLib; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Xml.Linq; + +namespace PCUT.DeepNestApi +{ + public class NestingContext + { + public List Polygons { get; private set; } = new List(); + public List Sheets { get; private set; } = new List(); + + + public double MaterialUtilization { get; private set; } = 0; + public int PlacedPartsCount { get; private set; } = 0; + + + SheetPlacement current = null; + public SheetPlacement Current { get { return current; } } + public SvgNest Nest { get; private set; } + + public int Iterations { get; private set; } = 0; + + public void StartNest() + { + current = null; + Nest = new SvgNest(); + Background.cacheProcess = new Dictionary(); + Background.window = new windowUnk(); + Background.callCounter = 0; + Iterations = 0; + } + + bool offsetTreePhase = true; + public void NestIterate() + { + List lsheets = new List(); + List lpoly = new List(); + + for (int i = 0; i < Polygons.Count; i++) + { + Polygons[i].id = i; + } + for (int i = 0; i < Sheets.Count; i++) + { + Sheets[i].id = i; + } + foreach (var item in Polygons) + { + NFP clone = new NFP(); + clone.id = item.id; + clone.source = item.source; + clone.Points = item.Points.Select(z => new SvgPoint(z.x, z.y) { exact = z.exact }).ToArray(); + if (item.children != null) + { + clone.children = new List(); + foreach (var citem in item.children) + { + clone.children.Add(new NFP()); + var l = clone.children.Last(); + l.id = citem.id; + l.source = citem.source; + l.Points = citem.Points.Select(z => new SvgPoint(z.x, z.y) { exact = z.exact }).ToArray(); + } + } + lpoly.Add(clone); + } + + + foreach (var item in Sheets) + { + NFP clone = new NFP(); + clone.id = item.id; + clone.source = item.source; + clone.Points = item.Points.Select(z => new SvgPoint(z.x, z.y) { exact = z.exact }).ToArray(); + if (item.children != null) + { + clone.children = new List(); + foreach (var citem in item.children) + { + clone.children.Add(new NFP()); + var l = clone.children.Last(); + l.id = citem.id; + l.source = citem.source; + l.Points = citem.Points.Select(z => new SvgPoint(z.x, z.y) { exact = z.exact }).ToArray(); + } + } + lsheets.Add(clone); + } + + if (offsetTreePhase) + { + var grps = lpoly.GroupBy(z => z.source).ToArray(); + if (Background.UseParallel) + { + Parallel.ForEach(grps, (item) => + { + SvgNest.offsetTree(item.First(), 0.5 * SvgNest.Config.spacing, SvgNest.Config); + foreach (var zitem in item) + { + zitem.Points = item.First().Points.ToArray(); + } + + }); + + } + else + { + foreach (var item in grps) + { + SvgNest.offsetTree(item.First(), 0.5 * SvgNest.Config.spacing, SvgNest.Config); + foreach (var zitem in item) + { + zitem.Points = item.First().Points.ToArray(); + } + } + } + + foreach (var item in lsheets) + { + var gap = SvgNest.Config.sheetSpacing - SvgNest.Config.spacing / 2; + SvgNest.offsetTree(item, -gap, SvgNest.Config, true); + } + } + + List partsLocal = new List(); + var p1 = lpoly.GroupBy(z => z.source).Select(z => new NestItem() + { + Polygon = z.First(), + IsSheet = false, + Quanity = z.Count() + }); + + var p2 = lsheets.GroupBy(z => z.source).Select(z => new NestItem() + { + Polygon = z.First(), + IsSheet = true, + Quanity = z.Count() + }); + + + partsLocal.AddRange(p1); + partsLocal.AddRange(p2); + int srcc = 0; + foreach (var item in partsLocal) + { + item.Polygon.source = srcc++; + } + + + Nest.launchWorkers(partsLocal.ToArray()); + var plcpr = Nest.nests.First(); + + if (current == null || plcpr.fitness < current.fitness) + { + AssignPlacement(plcpr); + } + Iterations++; + } + + public void AssignPlacement(SheetPlacement plcpr) + { + current = plcpr; + double totalSheetsArea = 0; + double totalPartsArea = 0; + + PlacedPartsCount = 0; + List placed = new List(); + foreach (var item in Polygons) + { + item.sheet = null; + } + List sheetsIds = new List(); + + foreach (var item in plcpr.placements) + { + foreach (var zitem in item) + { + var sheetid = zitem.sheetId; + if (!sheetsIds.Contains(sheetid)) + { + sheetsIds.Add(sheetid); + } + + var sheet = Sheets.First(z => z.id == sheetid); + totalSheetsArea += GeometryUtil.polygonArea(sheet); + + foreach (var ssitem in zitem.sheetplacements) + { + PlacedPartsCount++; + var poly = Polygons.First(z => z.id == ssitem.id); + totalPartsArea += GeometryUtil.polygonArea(poly); + placed.Add(poly); + poly.sheet = sheet; + poly.x = ssitem.x + sheet.x; + poly.y = ssitem.y + sheet.y; + poly.rotation = ssitem.rotation; + } + } + } + + var emptySheets = Sheets.Where(z => !sheetsIds.Contains(z.id)).ToArray(); + + MaterialUtilization = Math.Abs(totalPartsArea / totalSheetsArea); + + var ppps = Polygons.Where(z => !placed.Contains(z)); + foreach (var item in ppps) + { + item.x = -1000; + item.y = 0; + } + } + + public void ReorderSheets() + { + double x = 0; + double y = 0; + int gap = 10; + for (int i = 0; i < Sheets.Count; i++) + { + Sheets[i].x = x; + Sheets[i].y = y; + if (Sheets[i] is Sheet) + { + var r = Sheets[i] as Sheet; + x += r.Width + gap; + } + else + { + var maxx = Sheets[i].Points.Max(z => z.x); + var minx = Sheets[i].Points.Min(z => z.x); + var w = maxx - minx; + x += w + gap; + } + } + } + + public void AddSheet(int w, int h, int src) + { + var tt = new RectangleSheet(); + tt.Name = "sheet" + (Sheets.Count + 1); + Sheets.Add(tt); + + tt.source = src; + tt.Height = h; + tt.Width = w; + tt.Rebuild(); + ReorderSheets(); + } + + public void AddSheet(NFP nfp, int src) + { + Sheet sheet = new Sheet(); + var ns = Background.clone(nfp); + sheet.Points = ns.Points; + sheet.children = ns.children; + + sheet.Width = sheet.WidthCalculated; + sheet.Height = sheet.HeightCalculated; + sheet.source = src; + + sheet.Name = "sheet" + (Sheets.Count + 1); + Sheets.Add(sheet); + ReorderSheets(); + } + + public void LoadSampleData() + { + Console.WriteLine("Adding sheets.."); + //add sheets + for (int i = 0; i < 5; i++) + { + AddSheet(3000, 1500, 0); + } + + Console.WriteLine("Adding parts.."); + //add parts + int src1 = GetNextSource(); + for (int i = 0; i < 200; i++) + { + AddRectanglePart(src1, 250, 220); + } + + } + //public void LoadInputData(string path, int count) + //{ + // var dir = new DirectoryInfo(path); + // foreach (var item in dir.GetFiles("*.svg")) + // { + // try + // { + // var dets = SvgParser.LoadSvg(item.FullName); + // foreach (var r in dets) + // { + // var src = GetNextSource(); + // for (int i = 0; i < count; i++) + // { + // ImportFromRawDetail(r, src); + // } + // } + // } + // catch (Exception ex) + // { + // Console.WriteLine("Error loading " + item.FullName + ". skip"); + // } + // } + //} + + public NFP ImportFromRawDetail(RawDetail raw, int src) + { + var d = raw.ToNfp(); + if (d == null) + return null; + + d.source = src; + Polygons.Add(d); + return d; + } + + public int GetNextSource() + { + if (Polygons.Any()) + { + return Polygons.Max(z => z.source.Value) + 1; + } + return 0; + } + + public int GetNextSheetSource() + { + if (Sheets.Any()) + { + return Sheets.Max(z => z.source.Value) + 1; + } + return 0; + } + public void AddRectanglePart(int src, int ww = 50, int hh = 80) + { + int xx = 0; + int yy = 0; + NFP pl = new NFP(); + + Polygons.Add(pl); + pl.source = src; + pl.Points = new SvgPoint[] { }; + pl.AddPoint(new SvgPoint(xx, yy)); + pl.AddPoint(new SvgPoint(xx + ww, yy)); + pl.AddPoint(new SvgPoint(xx + ww, yy + hh)); + pl.AddPoint(new SvgPoint(xx, yy + hh)); + } + + } +} diff --git a/PCUT/PCUT/DeepNestApi/PolylineElement.cs b/PCUT/PCUT/DeepNestApi/PolylineElement.cs new file mode 100644 index 0000000..32fccdc --- /dev/null +++ b/PCUT/PCUT/DeepNestApi/PolylineElement.cs @@ -0,0 +1,46 @@ +using System.Linq; +using PCUT.Extensions; +using Windows.Foundation; + +namespace PCUT.DeepNestApi +{ + public class PolylineElement : DraftElement + { + public Point[] Points; + + public override double Length + { + get + { + double len = 0; + for (int i = 1; i < Points.Length; i++) + { + len += Points[i - 1].DistTo(Points[i]); + } + return len; + } + } + + public override Point[] GetPoints() + { + return Points; + } + + public override void Reverse() + { + Points = Points.Reverse().ToArray(); + Start = Points[0]; + End = Points[Points.Length - 1]; + } + + internal override void Mult(double mult) + { + for (int i = 0; i < Points.Length; i++) + { + Points[i] = Points[i].Mult(mult); + } + Start = Points[0]; + End = Points[Points.Length - 1]; + } + } +} diff --git a/PCUT/PCUT/DeepNestApi/RawDetail.cs b/PCUT/PCUT/DeepNestApi/RawDetail.cs new file mode 100644 index 0000000..975c800 --- /dev/null +++ b/PCUT/PCUT/DeepNestApi/RawDetail.cs @@ -0,0 +1,91 @@ +using DeepNestLib; +using System.Collections.Generic; +using System.Linq; +using PCUT.Extensions; +using Windows.Foundation; +using Windows.UI.Xaml.Media; + +namespace PCUT.DeepNestApi +{ + public class RawDetail + { + public List Outers = new List(); + public List Holes = new List(); + public object Tag; + public bool Hidden; + + public string Name { get; set; } + + public NFP ToNfp() + { + + NFP po = null; + List nfps = new List(); + foreach (var item in Outers) + { + var nn = new NFP(); + nfps.Add(nn); + foreach (var pitem in item.Points) + { + nn.AddPoint(new SvgPoint(pitem.X, pitem.Y)); + } + foreach (var ch in item.Childrens) + { + nn = new NFP(); + nfps.Add(nn); + foreach (var pitem in ch.Points) + { + nn.AddPoint(new SvgPoint(pitem.X, pitem.Y)); + } + } + } + + if (nfps.Any()) + { + var tt = nfps.OrderByDescending(z => z.Area).First(); + po = tt; + po.Name = Name; + + foreach (var r in nfps) + { + if (r == tt) + continue; + + if (po.children == null) + { + po.children = new List(); + } + po.children.Add(r); + } + + + + } + return po; + } + + public Rect BoundingBox() + { + GeometryGroup gp = new GeometryGroup(); + //GraphicsPath gp = new GraphicsPath(); + foreach (var item in Outers) + { + //gp.AddPolygon(item.Points.ToArray());) + gp.Children.Add(item.Points.BuildPath()); + } + return gp.Bounds; + } + + public void Scale(double v) + { + foreach (var item in Outers) + { + item.Scale(v); + } + foreach (var item in Holes) + { + item.Scale(v); + } + } + } +} \ No newline at end of file diff --git a/PCUT/PCUT/DeepNestApi/SvgNest.cs b/PCUT/PCUT/DeepNestApi/SvgNest.cs new file mode 100644 index 0000000..42fc5cf --- /dev/null +++ b/PCUT/PCUT/DeepNestApi/SvgNest.cs @@ -0,0 +1,1069 @@ +using ClipperLib; +using DeepNestLib; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Xml.Linq; + +namespace PCUT.DeepNestApi +{ + public class SvgNest + { + + public SvgNest() + { + + } + public class InrangeItem + { + public SvgPoint point; + public double distance; + } + + #region experimental features + public static SvgPoint RotatePoint(SvgPoint p, double cx, double cy, double angle) + { + return new SvgPoint(Math.Cos(angle) * (p.x - cx) - Math.Sin(angle) * (p.y - cy) + cx, + Math.Sin(angle) * (p.x - cx) + Math.Cos(angle) * (p.y - cy) + cy); + } + + public static NFP GetMinimumBox(NFP vv) + { + var hull = Background.getHull(new NFP() { Points = vv.Points.Select(z => new SvgPoint(z.x, z.y)).ToArray() }); + double minArea = double.MaxValue; + List rect = new List(); + for (int i = 0; i < hull.Length; i++) + { + var p0 = hull.Points[i]; + var p1 = hull.Points[(i + 1) % hull.Length]; + var dx = p1.x - p0.x; + var dy = p1.y - p0.y; + var atan = Math.Atan2(dy, dx); + + List dd = new List(); + for (int j = 0; j < vv.Length; j++) + { + var r = RotatePoint(new SvgPoint(vv[j].x, vv[j].y), 0, 0, -atan); + dd.Add(r); + } + var maxx = dd.Max(z => z.x); + var maxy = dd.Max(z => z.y); + var minx = dd.Min(z => z.x); + var miny = dd.Min(z => z.y); + + var area = (maxx - minx) * (maxy - miny); + + if (area < minArea) + { + minArea = area; + rect.Clear(); + + rect.Add(new SvgPoint(minx, miny)); + rect.Add(new SvgPoint(maxx, miny)); + rect.Add(new SvgPoint(maxx, maxy)); + rect.Add(new SvgPoint(minx, maxy)); + for (int j = 0; j < rect.Count; j++) + { + rect[j] = RotatePoint(new SvgPoint(rect[j].x, rect[j].y), 0, 0, atan); + } + } + } + + NFP ret = new NFP(); + ret.Points = rect.ToArray(); + return ret; + } + static NFP boundingBox(NFP offset) + { + NFP ret = new NFP(); + var maxx = offset.Points.Max(z => z.x); + var maxy = offset.Points.Max(z => z.y); + var minx = offset.Points.Min(z => z.x); + var miny = offset.Points.Min(z => z.y); + ret.AddPoint(new SvgPoint(minx, miny)); + ret.AddPoint(new SvgPoint(maxx, miny)); + ret.AddPoint(new SvgPoint(maxx, maxy)); + ret.AddPoint(new SvgPoint(minx, maxy)); + return ret; + } + /// + /// Clip the subject so it stays inside the clipBounds. + /// + /// + /// + /// + /// + internal static NFP ClipSubject(NFP subject, NFP clipBounds, double clipperScale) + { + var clipperSubject = Background.innerNfpToClipperCoordinates(new NFP[] { subject }, SvgNest.Config); + var clipperClip = Background.innerNfpToClipperCoordinates(new NFP[] { clipBounds }, SvgNest.Config); + + var clipper = new Clipper(); + clipper.AddPaths(clipperClip.Select(z => z.ToList()).ToList(), PolyType.ptClip, true); + clipper.AddPaths(clipperSubject.Select(z => z.ToList()).ToList(), PolyType.ptSubject, true); + + List> finalNfp = new List>(); + if (clipper.Execute(ClipType.ctIntersection, finalNfp, PolyFillType.pftNonZero, PolyFillType.pftNonZero) && finalNfp != null && finalNfp.Count > 0) + { + return Background.toNestCoordinates(finalNfp[0].ToArray(), clipperScale); + } + + return subject; + } + #endregion + + public static SvgPoint getTarget(SvgPoint o, NFP simple, double tol) + { + List inrange = new List(); + // find closest points within 2 offset deltas + for (var j = 0; j < simple.length; j++) + { + var s = simple[j]; + var d2 = (o.x - s.x) * (o.x - s.x) + (o.y - s.y) * (o.y - s.y); + if (d2 < tol * tol) + { + inrange.Add(new InrangeItem() { point = s, distance = d2 }); + } + } + + SvgPoint target = null; + if (inrange.Count > 0) + { + var filtered = inrange.Where((p) => + { + return p.point.exact; + }).ToList(); + + // use exact points when available, normal points when not + inrange = filtered.Count > 0 ? filtered : inrange; + + + inrange = inrange.OrderBy((b) => + { + return b.distance; + }).ToList(); + + target = inrange[0].point; + } + else + { + double? mind = null; + for (int j = 0; j < simple.length; j++) + { + var s = simple[j]; + var d2 = (o.x - s.x) * (o.x - s.x) + (o.y - s.y) * (o.y - s.y); + if (mind == null || d2 < mind) + { + target = s; + mind = d2; + } + } + } + + return target; + } + + public static SvgNestConfig Config = new SvgNestConfig(); + + + public static NFP clone(NFP p) + { + var newp = new NFP(); + for (var i = 0; i < p.length; i++) + { + newp.AddPoint(new SvgPoint( + + p[i].x, + p[i].y + + )); + } + + return newp; + } + + + public static bool pointInPolygon(SvgPoint point, NFP polygon) + { + // scaling is deliberately coarse to filter out points that lie *on* the polygon + + var p = svgToClipper2(polygon, 1000); + var pt = new ClipperLib.IntPoint(1000 * point.x, 1000 * point.y); + + return ClipperLib.Clipper.PointInPolygon(pt, p.ToList()) > 0; + } + + // returns true if any complex vertices fall outside the simple polygon + public static bool exterior(NFP simple, NFP complex, bool inside) + { + // find all protruding vertices + for (var i = 0; i < complex.length; i++) + { + var v = complex[i]; + if (!inside && !pointInPolygon(v, simple) && find(v, simple) == null) + { + return true; + } + if (inside && pointInPolygon(v, simple) && find(v, simple) != null) + { + return true; + } + } + return false; + } + + public static NFP simplifyFunction(NFP polygon, bool inside) + { + return simplifyFunction(polygon, inside, SvgNest.Config); + } + public static NFP simplifyFunction(NFP polygon, bool inside, SvgNestConfig config) + { + var tolerance = 4 * config.curveTolerance; + + // give special treatment to line segments above this length (squared) + var fixedTolerance = 40 * config.curveTolerance * 40 * config.curveTolerance; + int i, j, k; + + var hull = Background.getHull(polygon); + if (config.simplify) + { + /* + // use convex hull + var hull = new ConvexHullGrahamScan(); + for(var i=0; i 1) + { + polygon = cleaned; + } + else + { + return polygon; + } + // polygon to polyline + var copy = polygon.slice(0); + copy.push(copy[0]); + // mark all segments greater than ~0.25 in to be kept + // the PD simplification algo doesn't care about the accuracy of long lines, only the absolute distance of each point + // we care a great deal + for (i = 0; i < copy.length - 1; i++) + { + var p1 = copy[i]; + var p2 = copy[i + 1]; + var sqd = (p2.x - p1.x) * (p2.x - p1.x) + (p2.y - p1.y) * (p2.y - p1.y); + if (sqd > fixedTolerance) + { + p1.marked = true; + p2.marked = true; + } + } + + var simple = Simplify.simplify(copy, tolerance, true); + // now a polygon again + //simple.pop(); + simple.Points = simple.Points.Take(simple.Points.Count() - 1).ToArray(); + + // could be dirty again (self intersections and/or coincident points) + simple = cleanPolygon2(simple); + + // simplification process reduced poly to a line or point + if (simple == null) + { + simple = polygon; + } + + var offsets = polygonOffsetDeepNest(simple, inside ? -tolerance : tolerance); + + NFP offset = null; + double offsetArea = 0; + List holes = new List(); + for (i = 0; i < offsets.Length; i++) + { + var area = GeometryUtil.polygonArea(offsets[i]); + if (offset == null || area < offsetArea) + { + offset = offsets[i]; + offsetArea = area; + } + if (area > 0) + { + holes.Add(offsets[i]); + } + } + + // mark any points that are exact + for (i = 0; i < simple.length; i++) + { + var seg = new NFP(); + seg.AddPoint(simple[i]); + seg.AddPoint(simple[i + 1 == simple.length ? 0 : i + 1]); + + var index1 = find(seg[0], polygon); + var index2 = find(seg[1], polygon); + + if (index1 + 1 == index2 || index2 + 1 == index1 || (index1 == 0 && index2 == polygon.length - 1) || (index2 == 0 && index1 == polygon.length - 1)) + { + seg[0].exact = true; + seg[1].exact = true; + } + } + var numshells = 4; + NFP[] shells = new NFP[numshells]; + + for (j = 1; j < numshells; j++) + { + var delta = j * (tolerance / numshells); + delta = inside ? -delta : delta; + var shell = polygonOffsetDeepNest(simple, delta); + if (shell.Count() > 0) + { + shells[j] = shell.First(); + } + else + { + //shells[j] = shell; + } + } + + if (offset == null) + { + return polygon; + } + // selective reversal of offset + for (i = 0; i < offset.length; i++) + { + var o = offset[i]; + var target = getTarget(o, simple, 2 * tolerance); + + // reverse point offset and try to find exterior points + var test = clone(offset); + test.Points[i] = new SvgPoint(target.x, target.y); + + if (!exterior(test, polygon, inside)) + { + o.x = target.x; + o.y = target.y; + } + else + { + // a shell is an intermediate offset between simple and offset + for (j = 1; j < numshells; j++) + { + if (shells[j] != null) + { + var shell = shells[j]; + var delta = j * (tolerance / numshells); + target = getTarget(o, shell, 2 * delta); + test = clone(offset); + test.Points[i] = new SvgPoint(target.x, target.y); + if (!exterior(test, polygon, inside)) + { + o.x = target.x; + o.y = target.y; + break; + } + } + } + } + } + + // straighten long lines + // a rounded rectangle would still have issues at this point, as the long sides won't line up straight + + var straightened = false; + + for (i = 0; i < offset.length; i++) + { + var p1 = offset[i]; + var p2 = offset[i + 1 == offset.length ? 0 : i + 1]; + + var sqd = (p2.x - p1.x) * (p2.x - p1.x) + (p2.y - p1.y) * (p2.y - p1.y); + + if (sqd < fixedTolerance) + { + continue; + } + for (j = 0; j < simple.length; j++) + { + var s1 = simple[j]; + var s2 = simple[j + 1 == simple.length ? 0 : j + 1]; + + var sqds = (p2.x - p1.x) * (p2.x - p1.x) + (p2.y - p1.y) * (p2.y - p1.y); + + if (sqds < fixedTolerance) + { + continue; + } + + if ((GeometryUtil._almostEqual(s1.x, s2.x) || GeometryUtil._almostEqual(s1.y, s2.y)) && // we only really care about vertical and horizontal lines + GeometryUtil._withinDistance(p1, s1, 2 * tolerance) && + GeometryUtil._withinDistance(p2, s2, 2 * tolerance) && + (!GeometryUtil._withinDistance(p1, s1, config.curveTolerance / 1000) || + !GeometryUtil._withinDistance(p2, s2, config.curveTolerance / 1000))) + { + p1.x = s1.x; + p1.y = s1.y; + p2.x = s2.x; + p2.y = s2.y; + straightened = true; + } + } + } + + //if (straightened) + { + + var Ac = _Clipper.ScaleUpPaths(offset, 10000000); + var Bc = _Clipper.ScaleUpPaths(polygon, 10000000); + + var combined = new List>(); + var clipper = new ClipperLib.Clipper(); + + clipper.AddPath(Ac.ToList(), ClipperLib.PolyType.ptSubject, true); + clipper.AddPath(Bc.ToList(), ClipperLib.PolyType.ptSubject, true); + + // the line straightening may have made the offset smaller than the simplified + if (clipper.Execute(ClipperLib.ClipType.ctUnion, combined, ClipperLib.PolyFillType.pftNonZero, ClipperLib.PolyFillType.pftNonZero)) + { + double? largestArea = null; + for (i = 0; i < combined.Count; i++) + { + var n = Background.toNestCoordinates(combined[i].ToArray(), 10000000); + var sarea = -GeometryUtil.polygonArea(n); + if (largestArea == null || largestArea < sarea) + { + offset = n; + largestArea = sarea; + } + } + } + } + + cleaned = cleanPolygon2(offset); + if (cleaned != null && cleaned.length > 1) + { + offset = cleaned; + } + + #region experimental + if (config.clipByHull) + { + offset = ClipSubject(offset, hull, config.clipperScale); + } + else if (config.clipByRects) + { + NFP rect1 = boundingBox(hull); + offset = ClipSubject(offset, rect1, config.clipperScale); + var mbox = GetMinimumBox(hull); + offset = ClipSubject(offset, mbox, config.clipperScale); + } + #endregion + + // mark any points that are exact (for line merge detection) + for (i = 0; i < offset.length; i++) + { + var seg = new SvgPoint[] { offset[i], offset[i + 1 == offset.length ? 0 : i + 1] }; + var index1 = find(seg[0], polygon); + var index2 = find(seg[1], polygon); + if (index1 == null) + { + index1 = 0; + } + if (index2 == null) + { + index2 = 0; + } + if (index1 + 1 == index2 || index2 + 1 == index1 + || (index1 == 0 && index2 == polygon.length - 1) || + (index2 == 0 && index1 == polygon.length - 1)) + { + seg[0].exact = true; + seg[1].exact = true; + } + } + + if (!inside && holes != null && holes.Count > 0) + { + offset.children = holes; + } + + return offset; + + } + public static int? find(SvgPoint v, NFP p) + { + for (var i = 0; i < p.length; i++) + { + if (GeometryUtil._withinDistance(v, p[i], Config.curveTolerance / 1000)) + { + return i; + } + } + return null; + } + // offset tree recursively + public static void offsetTree(NFP t, double offset, SvgNestConfig config, bool? inside = null) + { + var simple = simplifyFunction(t, (inside == null) ? false : inside.Value); + var offsetpaths = new NFP[] { simple }; + if (Math.Abs(offset) > 0) + { + offsetpaths = polygonOffsetDeepNest(simple, offset); + } + + if (offsetpaths.Count() > 0) + { + + List rett = new List(); + rett.AddRange(offsetpaths[0].Points); + rett.AddRange(t.Points.Skip(t.length)); + t.Points = rett.ToArray(); + + // replace array items in place + + //Array.prototype.splice.apply(t, [0, t.length].concat(offsetpaths[0])); + } + + if (t != simple && simple.children != null && simple.children.Count > 0) + { + if (t.children == null) + { + t.children = new List(); + } + + for (var i = 0; i < simple.children.Count; i++) + { + t.children.Add(simple.children[i]); + } + } + + if (t.children != null && t.children.Count > 0) + { + for (var i = 0; i < t.children.Count; i++) + { + + offsetTree(t.children[i], -offset, config, (inside == null) ? true : (!inside)); + } + } + } + + + // use the clipper library to return an offset to the given polygon. Positive offset expands the polygon, negative contracts + // note that this returns an array of polygons + public static NFP[] polygonOffsetDeepNest(NFP polygon, double offset) + { + + if (offset == 0 || GeometryUtil._almostEqual(offset, 0)) + { + return new[] { polygon }; + } + + var p = svgToClipper(polygon).ToList(); + + var miterLimit = 4; + var co = new ClipperLib.ClipperOffset(miterLimit, Config.curveTolerance * Config.clipperScale); + co.AddPath(p.ToList(), ClipperLib.JoinType.jtMiter, ClipperLib.EndType.etClosedPolygon); + + var newpaths = new List>(); + co.Execute(ref newpaths, offset * Config.clipperScale); + + + var result = new List(); + for (var i = 0; i < newpaths.Count; i++) + { + result.Add(clipperToSvg(newpaths[i])); + } + + + return result.ToArray(); + } + + + + // converts a polygon from normal float coordinates to integer coordinates used by clipper, as well as x/y -> X/Y + public static IntPoint[] svgToClipper2(NFP polygon, double? scale = null) + { + + + var d = _Clipper.ScaleUpPaths(polygon, scale == null ? Config.clipperScale : scale.Value); + return d.ToArray(); + + } + + // converts a polygon from normal float coordinates to integer coordinates used by clipper, as well as x/y -> X/Y + public static ClipperLib.IntPoint[] svgToClipper(NFP polygon) + { + + + + var d = _Clipper.ScaleUpPaths(polygon, Config.clipperScale); + return d.ToArray(); + + return polygon.Points.Select(z => new IntPoint((long)z.x, (long)z.y)).ToArray(); + } + // returns a less complex polygon that satisfies the curve tolerance + public static NFP cleanPolygon(NFP polygon) + { + var p = svgToClipper2(polygon); + // remove self-intersections and find the biggest polygon that's left + var simple = ClipperLib.Clipper.SimplifyPolygon(p.ToList(), ClipperLib.PolyFillType.pftNonZero); + + if (simple == null || simple.Count == 0) + { + return null; + } + + var biggest = simple[0]; + var biggestarea = Math.Abs(ClipperLib.Clipper.Area(biggest)); + for (var i = 1; i < simple.Count; i++) + { + var area = Math.Abs(ClipperLib.Clipper.Area(simple[i])); + if (area > biggestarea) + { + biggest = simple[i]; + biggestarea = area; + } + } + + // clean up singularities, coincident points and edges + var clean = ClipperLib.Clipper.CleanPolygon(biggest, 0.01 * + Config.curveTolerance * Config.clipperScale); + + if (clean == null || clean.Count == 0) + { + return null; + } + return clipperToSvg(clean); + + } + + public static NFP cleanPolygon2(NFP polygon) + { + var p = svgToClipper(polygon); + // remove self-intersections and find the biggest polygon that's left + var simple = ClipperLib.Clipper.SimplifyPolygon(p.ToList(), ClipperLib.PolyFillType.pftNonZero); + + if (simple == null || simple.Count == 0) + { + return null; + } + + var biggest = simple[0]; + var biggestarea = Math.Abs(ClipperLib.Clipper.Area(biggest)); + for (var i = 1; i < simple.Count; i++) + { + var area = Math.Abs(ClipperLib.Clipper.Area(simple[i])); + if (area > biggestarea) + { + biggest = simple[i]; + biggestarea = area; + } + } + + // clean up singularities, coincident points and edges + var clean = ClipperLib.Clipper.CleanPolygon(biggest, 0.01 * + Config.curveTolerance * Config.clipperScale); + + if (clean == null || clean.Count == 0) + { + return null; + } + var cleaned = clipperToSvg(clean); + + // remove duplicate endpoints + var start = cleaned[0]; + var end = cleaned[cleaned.length - 1]; + if (start == end || (GeometryUtil._almostEqual(start.x, end.x) + && GeometryUtil._almostEqual(start.y, end.y))) + { + cleaned.Points = cleaned.Points.Take(cleaned.Points.Count() - 1).ToArray(); + } + + return cleaned; + + } + + public static NFP clipperToSvg(IList polygon) + { + List ret = new List(); + + for (var i = 0; i < polygon.Count; i++) + { + ret.Add(new SvgPoint(polygon[i].X / Config.clipperScale, polygon[i].Y / Config.clipperScale)); + } + + return new NFP() { Points = ret.ToArray() }; + } + + + public int toTree(PolygonTreeItem[] list, int idstart = 0) + { + List parents = new List(); + int i, j; + + // assign a unique id to each leaf + //var id = idstart || 0; + var id = idstart; + + for (i = 0; i < list.Length; i++) + { + var p = list[i]; + + var ischild = false; + for (j = 0; j < list.Length; j++) + { + if (j == i) + { + continue; + } + if (GeometryUtil.pointInPolygon(p.Polygon.Points[0], list[j].Polygon).Value) + { + if (list[j].Childs == null) + { + list[j].Childs = new List(); + } + list[j].Childs.Add(p); + p.Parent = list[j]; + ischild = true; + break; + } + } + + if (!ischild) + { + parents.Add(p); + } + } + + for (i = 0; i < list.Length; i++) + { + if (parents.IndexOf(list[i]) < 0) + { + list = list.Skip(i).Take(1).ToArray(); + i--; + } + } + + for (i = 0; i < parents.Count; i++) + { + parents[i].Polygon.Id = id; + id++; + } + + for (i = 0; i < parents.Count; i++) + { + if (parents[i].Childs != null) + { + id = toTree(parents[i].Childs.ToArray(), id); + } + } + + return id; + } + + public static NFP cloneTree(NFP tree) + { + NFP newtree = new NFP(); + foreach (var t in tree.Points) + { + newtree.AddPoint(new SvgPoint(t.x, t.y) { exact = t.exact }); + } + + + if (tree.children != null && tree.children.Count > 0) + { + newtree.children = new List(); + foreach (var c in tree.children) + { + newtree.children.Add(cloneTree(c)); + } + + } + + return newtree; + } + + + public Background background = new Background(); + + + PopulationItem individual = null; + NFP[] placelist; + GeneticAlgorithm ga; + + public List nests = new List(); + + public void ResponseProcessor(SheetPlacement payload) + { + //console.log('ipc response', payload); + if (ga == null) + { + // user might have quit while we're away + return; + } + ga.population[payload.index].processing = null; + ga.population[payload.index].fitness = payload.fitness; + + // render placement + if (this.nests.Count == 0 || this.nests[0].fitness > payload.fitness) + { + this.nests.Insert(0, payload); + + if (this.nests.Count > Config.populationSize) + { + this.nests.RemoveAt(nests.Count - 1); + } + //if (displayCallback) + { + // displayCallback(); + } + } + } + + public void launchWorkers(NestItem[] parts) + { + background.ResponseAction = ResponseProcessor; + if (ga == null) + { + List adam = new List(); + var id = 0; + for (int i = 0; i < parts.Count(); i++) + { + if (!parts[i].IsSheet) + { + for (int j = 0; j < parts[i].Quanity; j++) + { + var poly = cloneTree(parts[i].Polygon); // deep copy + poly.id = id; // id is the unique id of all parts that will be nested, including cloned duplicates + poly.source = i; // source is the id of each unique part from the main part list + + adam.Add(poly); + id++; + } + } + } + + adam = adam.OrderByDescending(z => Math.Abs(GeometryUtil.polygonArea(z))).ToList(); + /*List shuffle = new List(); + Random r = new Random(DateTime.Now.Millisecond); + while (adam.Any()) + { + var rr = r.Next(adam.Count); + shuffle.Add(adam[rr]); + adam.RemoveAt(rr); + } + adam = shuffle;*/ + + /*#region special case + var temp = adam[1]; + adam.RemoveAt(1); + adam.Insert(9, temp); + + #endregion*/ + ga = new GeneticAlgorithm(adam.ToArray(), Config); + } + individual = null; + + // check if current generation is finished + var finished = true; + for (int i = 0; i < ga.population.Count; i++) + { + if (ga.population[i].fitness == null) + { + finished = false; + break; + } + } + if (finished) + { + //console.log('new generation!'); + // all individuals have been evaluated, start next generation + ga.generation(); + } + + var running = ga.population.Where((p) => + { + return p.processing != null; + }).Count(); + + List sheets = new List(); + List sheetids = new List(); + List sheetsources = new List(); + List> sheetchildren = new List>(); + var sid = 0; + for (int i = 0; i < parts.Count(); i++) + { + if (parts[i].IsSheet) + { + var poly = parts[i].Polygon; + for (int j = 0; j < parts[i].Quanity; j++) + { + var cln = cloneTree(poly); + cln.id = sid; // id is the unique id of all parts that will be nested, including cloned duplicates + cln.source = poly.source; // source is the id of each unique part from the main part list + + sheets.Add(cln); + sheetids.Add(sid); + sheetsources.Add(i); + sheetchildren.Add(poly.children); + sid++; + } + } + } + for (int i = 0; i < ga.population.Count; i++) + { + //if(running < config.threads && !GA.population[i].processing && !GA.population[i].fitness){ + // only one background window now... + if (running < 1 && ga.population[i].processing == null && ga.population[i].fitness == null) + { + ga.population[i].processing = true; + + // hash values on arrays don't make it across ipc, store them in an array and reassemble on the other side.... + List ids = new List(); + List sources = new List(); + List> children = new List>(); + + for (int j = 0; j < ga.population[i].placements.Count; j++) + { + var id = ga.population[i].placements[j].id; + var source = ga.population[i].placements[j].source; + var child = ga.population[i].placements[j].children; + //ids[j] = id; + ids.Add(id); + //sources[j] = source; + sources.Add(source.Value); + //children[j] = child; + children.Add(child); + } + + DataInfo data = new DataInfo() + { + index = i, + sheets = sheets, + sheetids = sheetids.ToArray(), + sheetsources = sheetsources.ToArray(), + sheetchildren = sheetchildren, + individual = ga.population[i], + config = Config, + ids = ids.ToArray(), + sources = sources.ToArray(), + children = children + + }; + + background.BackgroundStart(data); + //ipcRenderer.send('background-start', { index: i, sheets: sheets, sheetids: sheetids, sheetsources: sheetsources, sheetchildren: sheetchildren, individual: GA.population[i], config: config, ids: ids, sources: sources, children: children}); + running++; + } + } + } + + public PolygonTreeItem[] tree; + + + public bool useHoles; + public bool searchEdges; + } + + public class DataInfo + { + + public int index; + public List sheets; + public int[] sheetids; + public int[] sheetsources; + public List> sheetchildren; + public PopulationItem individual; + public SvgNestConfig config; + public int[] ids; + public int[] sources; + public List> children; + //ipcRenderer.send('background-start', { index: i, sheets: sheets, sheetids: sheetids, sheetsources: sheetsources, sheetchildren: sheetchildren, + //individual: GA.population[i], config: config, ids: ids, sources: sources, children: children}); + } + + public class PolygonTreeItem + { + public NFP Polygon; + public PolygonTreeItem Parent; + public List Childs = new List(); + } + + public class DbCacheKey + { + public int? A; + public int? B; + public float ARotation; + public float BRotation; + public NFP[] nfp; + public int Type; + } + + public class NfpPair + { + public NFP A; + public NFP B; + public NfpKey Key; + public NFP nfp; + + public float ARotation; + public float BRotation; + + public int Asource { get; internal set; } + public int Bsource { get; internal set; } + + public static NfpPair Create(NFP A, NFP B) + { + return new NfpPair() + { + A = A, + B = B, + ARotation = A.rotation, + BRotation = B.rotation, + Asource = A.source.Value, + Bsource = B.source.Value + + }; + } + } + + public class NonameReturn + { + public NfpKey key; + public NFP[] nfp; + public NFP[] value + { + get + { + return nfp; + } + } + public NonameReturn(NfpKey key, NFP[] nfp) + { + this.key = key; + this.nfp = nfp; + } + } + + public class NestItem + { + public NFP Polygon; + public int Quanity; + public bool IsSheet; + } +} \ No newline at end of file diff --git a/PCUT/PCUT/DeepNestApi/SvgParser.cs b/PCUT/PCUT/DeepNestApi/SvgParser.cs new file mode 100644 index 0000000..0a79e12 --- /dev/null +++ b/PCUT/PCUT/DeepNestApi/SvgParser.cs @@ -0,0 +1,558 @@ +using DeepNestLib; +using SvgPathProperties; +using System; +using System.Collections.Generic; +using System.Data.Common; +using System.Globalization; +using System.IO; +using System.Linq; +using System.Text; +using System.Xml.Linq; +using PCUT.Extensions; +using Windows.Foundation; +using static PCUT.Extensions.PointExtensions; +using static PCUT.Extensions.XmlExtensions; +using PCUT.Extensions.Transforms; +using PCUT.ViewModels; + +namespace PCUT.DeepNestApi +{ + public class SvgParser + { + public static (RawDetail[] Details, double Scale) LoadSvg(XDocument doc, bool split = false) + { + RawDetail s = new RawDetail(); + s.Name = "temp"; + //List paths = new List(); + var ns = doc.Descendants().First().Name.Namespace.NamespaceName; + double scale = 1; + double rightMax = 0; + List ret = new List(); + foreach (var item in doc.Descendants().Where(z => z.Name.LocalName == "path")) + { + var id = item.GetId(); + + var dd = item.Attribute("d").Value; + SvgPath p = new SvgPath(dd, unarc: true); + var bbox = p.GetBBox(); + rightMax = Math.Max(bbox.Right, rightMax); + List pp = new List(); + List cntrs2 = new List(); + foreach (var ss in p.Segments) + { + var len = ss.Length; + if (len > 0 || ss is MoveCommand) + { + try + { + for (double t = 0; t <= 1.0; t += 0.0625) + { + var p1 = ss.GetPointAtLength(t * len); + pp.Add(new SvgPoint(p1.X, p1.Y)); + } + } + catch (Exception ex) + { + + } + } + if (ss is LineCommand lc && lc.ClosePath) + { + cntrs2.Add(new LocalContour() { Points = pp.Select(z => new Point((float)z.x, (float)z.y)).ToList() }); + pp.Clear(); + } + } + // var top = nfps.SingleOrDefault(z => z.Parent == null); + //if (top != null) + { + // var inners = nfps.Where(z => z.Parent != null); + //s.Outers.Add(new LocalContour() { Points = top.Points.ToList() }); + s.Outers.AddRange(cntrs2.Select(z => new LocalContour() { Points = z.Points.ToList(), Tag = new[] { id } })); + } + } + + foreach (var item in doc.Descendants("rect")) + { + var id = item.GetId(); + if (id == null && item.Parent != null) + id = item.Parent.GetId(); + if (id.StartsWith("PCUT_BOUNDING")) + continue; + + float xx = 0; + float yy = 0; + if (item.Attribute("x") != null) + { + xx = float.Parse(item.Attribute("x").Value); + } + if (item.Attribute("y") != null) + { + yy = float.Parse(item.Attribute("y").Value); + } + var ww = float.Parse(item.Attribute("width").Value); + var hh = float.Parse(item.Attribute("height").Value); + //GraphicsPath p = new GraphicsPath(); + //p.AddRectangle(new RectangleF(xx, yy, ww, hh)); + var rect = new Rect(xx, yy, ww, hh); + + //s.Outers.Add(new LocalContour() { Points = p.PathPoints.ToList() }); + s.Outers.Add(new LocalContour() { Points = rect.PathPoints().ToList(), Tag = new[] { id } }); + rightMax = Math.Max(rightMax, xx + ww); + } + + foreach (var item in doc.Descendants(XName.Get("polygon", ns))) + { + var id = item.GetId(); + if (id == null && item.Parent != null) + id = item.Parent.GetId(); + + var str = item.Attribute("points").Value.ToString(); + var spl = str.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries); + List points = new List(); + foreach (var sitem in spl) + { + var spl2 = sitem.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries).ToArray(); + var ar = spl2.Select(z => float.Parse(z, CultureInfo.InvariantCulture)).ToArray(); + points.Add(new Point(ar[0], ar[1])); + rightMax = Math.Max(rightMax, ar[0]); + } + s.Outers.Add(new LocalContour() { Points = points.ToList(), Tag = new[] { id } }); + } + + if (split) + { + //split + //var nfps = s.Outers; + //for (int i = 0; i < nfps.Count; i++) + //{ + // for (int j = 0; j < nfps.Count; j++) + // { + // if (i != j) + // { + // var d2 = nfps[i]; + // var d3 = nfps[j]; + // var f0 = d3.Points[0]; + + // if (GeometryUtil.pnpoly(d2.Points.Select(p => (p.X, p.Y)).ToArray(), f0.X, f0.Y)) + // { + // d3.Parent = d2; + // if (!d2.Childrens.Contains(d3)) + // { + // d2.Childrens.Add(d3); + // } + // } + // } + // } + //} + //var tops = nfps.Where(z => z.Parent == null).ToArray(); + + // split + var nfps = s.Outers; + + // build a forest of local contour trees + var tops = new List(); + for (int i = 0; i < nfps.Count; i++) + { + var nfp = nfps[i]; + foreach (var root in tops) + { + var root0 = root.Points[0]; + if (IsContains(nfp, root)) // nfp is root parent + { + root.Parent = nfp; + nfp.Childrens.Add(root); + } + else if (IsContains(root, nfp)) + { + RecursiveInsert(root, nfp); + break; + } + } + if (nfp.Parent == null) + { + foreach (var child in nfp.Childrens) + tops.Remove(child); + tops.Add(nfp); + } + } + + // move all even level children to roots + for (int i = 0; i < tops.Count; i++) + { + var root = tops[i]; + foreach (var child in root.Childrens) + { + foreach (var grandChild in child.Childrens) + { + grandChild.Parent = null; + tops.Add(grandChild); + } + child.Childrens.Clear(); + } + } + + var names = new HashSet(); + for (int i = 0; i < tops.Count; i++) + { + LocalContour item = tops[i]; + RawDetail rr = new RawDetail(); + var name = $"{(item.Tag as object[])[0]}"; + if (names.Contains(name)) + name = $"{name}_{Guid.NewGuid()}"; + names.Add(name); + rr.Name = name; + rr.Outers.Add(item); + rr.Holes.AddRange(item.Childrens); + ret.Add(rr); + } + } + else + { + ret.Add(s); + } + + //scale /= rightMax; + foreach (var item in ret) + { + item.Scale(scale); + } + + return (ret.ToArray(), scale); + } + + // return true if a contains b + private static bool IsContains(LocalContour a, LocalContour b) + { + var b0 = b.Points[0]; + return GeometryUtil.pnpoly(a.Points.Select(p => (p.X, p.Y)).ToArray(), b0.X, b0.Y); + } + + // assuming root contains b + private static void RecursiveInsert(LocalContour root, LocalContour b) + { + LocalContour parent = root; + var queue = new Queue(); + foreach (var child in parent.Childrens) + { + queue.Enqueue(child); + } + + while (queue.Count > 0) + { + var item = queue.Dequeue(); + if (IsContains(b, item)) + { + parent.Childrens.Remove(item); + item.Parent = b; + b.Childrens.Add(item); + } + else if (IsContains(item, b)) + { + parent = item; + queue.Clear(); + foreach (var child in parent.Childrens) + { + queue.Enqueue(child); + } + } + } + b.Parent = parent; + parent.Childrens.Add(b); + } + + public static SvgPathProperties.Base.Rect GetBBox(XDocument doc) + { + double left = double.PositiveInfinity, top = double.PositiveInfinity, right = double.NegativeInfinity, bottom = double.NegativeInfinity; + foreach (var item in doc.Descendants().Where(z => z.Name.LocalName == "path")) + { + var dd = item.Attribute("d").Value; + SvgPath p = new SvgPath(dd, unarc: true); + var bbox = p.GetBBox(); + left = Math.Min(left, bbox.Left); + top = Math.Min(top, bbox.Top); + right = Math.Max(right, bbox.Right); + bottom = Math.Max(bottom, bbox.Bottom); + } + return new SvgPathProperties.Base.Rect(left, top, right, bottom); + } + + //public static void Export(XDocument doc, IEnumerable polygons, double scale) + //{ + // var builder = new StringBuilder(); + // foreach (var polygon in polygons) + // { + // builder.Clear(); + // builder.Append("translate(").Append(polygon.x * scale).Append(" ").Append(polygon.y * scale).Append(") ") + // .Append("rotate(").Append(polygon.rotation).Append(")"); + // foreach (var tag in polygon.Tag as object[]) + // { + // doc.ApplyTransform(tag as string, builder.ToString()); + // } + // } + //} + + public static (XDocument Data, double Width, double Height) Export(IEnumerable polygons) + { + StringBuilder sb = new StringBuilder(); + sb.AppendLine(""); + var width = 0d; + var height = 0d; + foreach (var item in polygons.OrderByDescending(x => x.WidthCalculated * x.HeightCalculated)) + { + //if (!sheets.Contains(item)) + //{ + // if (!item.fitted) continue; + //} + //var m = new Matrix(); + //m.Translate((float)item.x, (float)item.y); + //m.Rotate(item.rotation); + SvgTransform m = new TranslateTransform(item.x, item.y); + var rotate = new RotateTransform(item.rotation); + rotate.SetNext(m); + m = rotate; + + var points = item.Points.Select(z => { var (x, y) = m.Transform(z.x, z.y); return new SvgPoint(x, y); }).ToArray(); + width = Math.Max(width, points.Max(point => point.x)); + height = Math.Max(height, points.Max(point => point.y)); + + string fill = "lightblue"; + //if (sheets.Contains(item)) + //{ + // fill = "none"; + //} + + sb.Append($""); + + if (item.children != null && item.children.Any()) + { + foreach (var citem in item.children) + { + sb.Append($" { var (x, y) = m.Transform(z.x, z.y); return new SvgPoint(x, y); }).Reverse().ToArray(); + + for (int i = 0; i < points.Count(); i++) + { + var p = points[i]; + string coord = p.x.ToString().Replace(",", ".") + " " + p.y.ToString().Replace(",", "."); + if (i == 0) + { + sb.Append("M" + coord + " "); + continue; + } + + sb.Append("L" + coord + " "); + } + sb.AppendLine("z \"/>"); + } + } + } + sb.AppendLine(""); + return (XDocument.Parse(sb.ToString()), width, height); + } + + //public static SvgConfig Conf = new SvgConfig(); + //// return a polygon from the given SVG element in the form of an array of points + //public static NFP polygonify(XElement element) + //{ + // List poly = new List(); + // int i; + + // switch (element.Name.LocalName) + // { + // case "polygon": + // case "polyline": + // { + // var pp = element.Attribute("points").Value; + // var spl = pp.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); + // foreach (var item in spl) + // { + // var spl2 = item.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToArray(); + // var x = float.Parse(spl2[0], CultureInfo.InvariantCulture); + // var y = float.Parse(spl2[1], CultureInfo.InvariantCulture); + // poly.Add(new SvgPoint(x, y)); + // } + + // } + // break; + // case "rect": + // { + // float x = 0; + // float y = 0; + // if (element.Attribute("x") != null) + // { + // x = float.Parse(element.Attribute("x").Value, CultureInfo.InvariantCulture); + // } + // if (element.Attribute("y") != null) + // { + // y = float.Parse(element.Attribute("y").Value, CultureInfo.InvariantCulture); + // } + // var w = float.Parse(element.Attribute("width").Value, CultureInfo.InvariantCulture); + // var h = float.Parse(element.Attribute("height").Value, CultureInfo.InvariantCulture); + // poly.Add(new SvgPoint(x, y)); + // poly.Add(new SvgPoint(x + w, y)); + // poly.Add(new SvgPoint(x + w, y + h)); + // poly.Add(new SvgPoint(x, y + h)); + // } + + + // break; + // case "circle": + // throw new NotImplementedException(); + + // break; + // case "ellipse": + // throw new NotImplementedException(); + + // break; + // case "path": + // throw new NotImplementedException(); + + // // // we'll assume that splitpath has already been run on this path, and it only has one M/m command + // // var seglist = element.pathSegList; + + // // var firstCommand = seglist.getItem(0); + // // var lastCommand = seglist.getItem(seglist.numberOfItems - 1); + + // // var x = 0, y = 0, x0 = 0, y0 = 0, x1 = 0, y1 = 0, x2 = 0, y2 = 0, prevx = 0, prevy = 0, prevx1 = 0, prevy1 = 0, prevx2 = 0, prevy2 = 0; + + // // for (var i = 0; i < seglist.numberOfItems; i++) + // // { + // // var s = seglist.getItem(i); + // // var command = s.pathSegTypeAsLetter; + + // // prevx = x; + // // prevy = y; + + // // prevx1 = x1; + // // prevy1 = y1; + + // // prevx2 = x2; + // // prevy2 = y2; + + // // if (/[MLHVCSQTA] /.test(command)) + // // { + // // if ('x1' in s) x1 = s.x1; + // // if ('x2' in s) x2 = s.x2; + // // if ('y1' in s) y1 = s.y1; + // // if ('y2' in s) y2 = s.y2; + // // if ('x' in s) x = s.x; + // // if ('y' in s) y = s.y; + // // } + // // else{ + // // if ('x1' in s) x1=x+s.x1; + // // if ('x2' in s) x2=x+s.x2; + // // if ('y1' in s) y1=y+s.y1; + // // if ('y2' in s) y2=y+s.y2; + // // if ('x' in s) x+=s.x; + // // if ('y' in s) y+=s.y; + // // } + // // switch(command){ + // // // linear line types + // // case 'm': + // // case 'M': + // // case 'l': + // // case 'L': + // // case 'h': + // // case 'H': + // // case 'v': + // // case 'V': + // // var point = { }; + // // point.x = x; + // // point.y = y; + // // poly.push(point); + // // break; + // // // Quadratic Beziers + // // case 't': + // // case 'T': + // // // implicit control point + // // if(i > 0 && /[QqTt]/.test(seglist.getItem(i-1).pathSegTypeAsLetter)){ + // // x1 = prevx + (prevx-prevx1); + // // y1 = prevy + (prevy-prevy1); + // // } + // // else{ + // // x1 = prevx; + // // y1 = prevy; + // // } + // // case 'q': + // // case 'Q': + // // var pointlist = GeometryUtil.QuadraticBezier.linearize({x: prevx, y: prevy}, {x: x, y: y}, {x: x1, y: y1}, this.conf.tolerance); + // //pointlist.shift(); // firstpoint would already be in the poly + // // for(var j=0; j 0 && /[CcSs]/.test(seglist.getItem(i-1).pathSegTypeAsLetter)){ + // // x1 = prevx + (prevx - prevx2); + // // y1 = prevy + (prevy - prevy2); + // //} + // // else{ + // // x1 = prevx; + // // y1 = prevy; + // //} + // // case 'c': + // // case 'C': + // // var pointlist = GeometryUtil.CubicBezier.linearize({ x: prevx, y: prevy}, { x: x, y: y}, { x: x1, y: y1}, { x: x2, y: y2}, this.conf.tolerance); + // //pointlist.shift(); // firstpoint would already be in the poly + // // for(var j=0; j 0 && GeometryUtil._almostEqual(poly[0].x, poly[poly.Count - 1].x, Conf.toleranceSvg) + // && GeometryUtil._almostEqual(poly[0].y, poly[poly.Count - 1].y, Conf.toleranceSvg)) + // { + // poly.RemoveAt(0); + // } + + // return new NFP() { Points = poly.ToArray() }; + //} + } + + public class SvgConfig + { + public float tolerance = 2f; // max bound for bezier->line segment conversion, in native SVG units + public float toleranceSvg = 0.005f;// fudge factor for browser inaccuracy in SVG unit handling + } +} diff --git a/PCUT/PCUT/Extensions/BindExtensions.cs b/PCUT/PCUT/Extensions/BindExtensions.cs new file mode 100644 index 0000000..085e605 --- /dev/null +++ b/PCUT/PCUT/Extensions/BindExtensions.cs @@ -0,0 +1,35 @@ +namespace PCUT.Extensions +{ + public static class BindExtensions + { + public static bool And(bool condition1, bool condition2) + { + return condition1 && condition2; + } + + public static bool Or(bool condition1, bool condition2) + { + return condition1 || condition2; + } + + public static bool NotAnd(bool condition1, bool condition2) + { + return !(condition1 && condition2); + } + + public static bool NotOr(bool condition1, bool condition2) + { + return !(condition1 || condition2); + } + + public static bool AlternateAnd(bool condition1, bool condition2) + { + return condition1 && !condition2; + } + + public static bool AlternateOr(bool condition1, bool condition2) + { + return condition1 || !condition2; + } + } +} diff --git a/PCUT/PCUT/Extensions/Converters/CircleElementConverter.cs b/PCUT/PCUT/Extensions/Converters/CircleElementConverter.cs new file mode 100644 index 0000000..e91f51c --- /dev/null +++ b/PCUT/PCUT/Extensions/Converters/CircleElementConverter.cs @@ -0,0 +1,35 @@ +using SvgPathProperties; +using System.Collections.Generic; +using System.Text; +using System.Xml.Linq; + +namespace PCUT.Extensions.Converters +{ + internal class CircleElementConverter : PathConverter + { + private static readonly string[] CircleExcludedAttributes = new[] { "transform", "cx", "cy", "r" }; + protected override IEnumerable ExcludedAttributes => CircleExcludedAttributes; + + internal CircleElementConverter() + { + } + + protected override bool CanApply(XElement element) => element.Name.LocalName == "circle"; + + protected override SvgPath GetPathFromElement(XElement element) + { + var cx = double.Parse(element.Attribute("cx")?.Value ?? "0"); + var cy = double.Parse(element.Attribute("cy")?.Value ?? "0"); + var r = double.Parse(element.Attribute("r").Value); + var arcCommonParam = $"{r} {r} 0 0 1 "; + var builder = new StringBuilder(); + builder.Append("M ").Append($"{cx + r} {cy} ") + .Append("A ").Append($"{arcCommonParam}").Append($"{cx} {cy + r} ") + .Append($"{arcCommonParam}").Append($"{cx - r} {cy} ") + .Append($"{arcCommonParam}").Append($"{cx} {cy - r} ") + .Append($"{arcCommonParam}").Append($"{cx + r} {cy} ") + .Append("Z"); + return new SvgPath(builder.ToString(), unarc: true); + } + } +} diff --git a/PCUT/PCUT/Extensions/Converters/EllipseElementConverter.cs b/PCUT/PCUT/Extensions/Converters/EllipseElementConverter.cs new file mode 100644 index 0000000..a7a3b36 --- /dev/null +++ b/PCUT/PCUT/Extensions/Converters/EllipseElementConverter.cs @@ -0,0 +1,36 @@ +using SvgPathProperties; +using System.Collections.Generic; +using System.Text; +using System.Xml.Linq; + +namespace PCUT.Extensions.Converters +{ + internal class EllipseElementConverter : PathConverter + { + private static readonly string[] EllipseExcludedAttributes = new[] { "transform", "cx", "cy", "rx", "ry" }; + protected override IEnumerable ExcludedAttributes => EllipseExcludedAttributes; + + internal EllipseElementConverter() + { + } + + protected override bool CanApply(XElement element) => element.Name.LocalName == "ellipse"; + + protected override SvgPath GetPathFromElement(XElement element) + { + var cx = double.Parse(element.Attribute("cx")?.Value ?? "0"); + var cy = double.Parse(element.Attribute("cy")?.Value ?? "0"); + var rx = double.Parse(element.Attribute("rx").Value); + var ry = double.Parse(element.Attribute("ry").Value); + var arcCommonParam = $"{rx} {ry} 0 0 1 "; + var builder = new StringBuilder(); + builder.Append("M ").Append($"{cx + rx} {cy} ") + .Append("A ").Append($"{arcCommonParam}").Append($"{cx} {cy + ry} ") + .Append($"{arcCommonParam}").Append($"{cx - rx} {cy} ") + .Append($"{arcCommonParam}").Append($"{cx} {cy - ry} ") + .Append($"{arcCommonParam}").Append($"{cx + rx} {cy} ") + .Append("Z"); + return new SvgPath(builder.ToString(), unarc: true); + } + } +} diff --git a/PCUT/PCUT/Extensions/Converters/PathConverter.cs b/PCUT/PCUT/Extensions/Converters/PathConverter.cs new file mode 100644 index 0000000..d5c6d1d --- /dev/null +++ b/PCUT/PCUT/Extensions/Converters/PathConverter.cs @@ -0,0 +1,94 @@ +using SvgPathProperties; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Xml.Linq; + +namespace PCUT.Extensions.Converters +{ + internal abstract class PathConverter + { + private PathConverter _next; + + private void SetNext(PathConverter next) + { + _next = next; + } + + public SvgPath GetSvgPath(XElement element) + { + if (CanApply(element)) + { + return GetPathFromElement(element); + } + else if (_next != null) + { + return _next.GetSvgPath(element); + } + else + { + return null; + } + } + + protected abstract bool CanApply(XElement element); + protected abstract SvgPath GetPathFromElement(XElement element); + + public void CopyAttribute(XElement source, XElement target) + { + foreach (var attribute in source.Attributes().Where(x => !ExcludedAttributes.Contains(x.Name.LocalName))) + { + target.SetAttributeValue(attribute.Name, attribute.Value); + } + } + protected abstract IEnumerable ExcludedAttributes { get; } + + public static PathConverterBuilder Builder() => new PathConverterBuilder(); + public class PathConverterBuilder + { + private readonly Stack _pathConverters = new Stack(); + + public PathConverterBuilder AddPath() + { + _pathConverters.Push(new PathElementConverter()); + return this; + } + + public PathConverterBuilder AddRect() + { + _pathConverters.Push(new RectElementConverter()); + return this; + } + + public PathConverterBuilder AddPolygon() + { + _pathConverters.Push(new PolygonElementConverter()); + return this; + } + + public PathConverterBuilder AddCircle() + { + _pathConverters.Push(new CircleElementConverter()); + return this; + } + + public PathConverterBuilder AddEllipse() + { + _pathConverters.Push(new EllipseElementConverter()); + return this; + } + + public PathConverter Build() + { + PathConverter current = null; + while (_pathConverters.Count > 0) + { + var converter = _pathConverters.Pop(); + converter.SetNext(current); + current = converter; + } + return current; + } + } + } +} diff --git a/PCUT/PCUT/Extensions/Converters/PathElementConverter.cs b/PCUT/PCUT/Extensions/Converters/PathElementConverter.cs new file mode 100644 index 0000000..0f161bb --- /dev/null +++ b/PCUT/PCUT/Extensions/Converters/PathElementConverter.cs @@ -0,0 +1,23 @@ +using SvgPathProperties; +using System.Collections.Generic; +using System.Xml.Linq; + +namespace PCUT.Extensions.Converters +{ + internal class PathElementConverter : PathConverter + { + private static readonly string[] PathExcludedAttributes = new[] { "transform", "d" }; + protected override IEnumerable ExcludedAttributes => PathExcludedAttributes; + + internal PathElementConverter() + { + } + + protected override bool CanApply(XElement element) => element.Name.LocalName == "path"; + + protected override SvgPath GetPathFromElement(XElement element) + { + return new SvgPath(element.Attribute("d").Value, unarc: true); + } + } +} diff --git a/PCUT/PCUT/Extensions/Converters/PolygonElementConverter.cs b/PCUT/PCUT/Extensions/Converters/PolygonElementConverter.cs new file mode 100644 index 0000000..b6db0e2 --- /dev/null +++ b/PCUT/PCUT/Extensions/Converters/PolygonElementConverter.cs @@ -0,0 +1,52 @@ +using SvgPathProperties; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Xml.Linq; + +namespace PCUT.Extensions.Converters +{ + internal class PolygonElementConverter : PathConverter + { + private static readonly string[] PolygonExcludedAttributes = new[] { "transform", "points" }; + protected override IEnumerable ExcludedAttributes => PolygonExcludedAttributes; + + internal PolygonElementConverter() + { + } + + protected override bool CanApply(XElement element) => element.Name.LocalName == "polygon"; + + protected override SvgPath GetPathFromElement(XElement element) + { + var points = GetPolygonPoints(element.Attribute("points")?.Value); + if (!points.Any()) + return null; + + var builder = new StringBuilder(); + foreach (var (x, y) in points) + { + builder.Append(builder.Length == 0 ? "M " : "L ").Append($"{x} {y}"); + } + builder.Append("Z"); + return new SvgPath(builder.ToString(), unarc: true); + } + + private IEnumerable<(double X, double Y)> GetPolygonPoints(string pointsValue) + { + if (pointsValue == null) + yield break; + + var points = pointsValue.Split(new[] { ',', ' ' }, StringSplitOptions.RemoveEmptyEntries); + if (points.Length % 2 != 0) + yield break; + + for (int i = 0; i < points.Length; i += 2) + { + yield return (double.Parse(points[i]), double.Parse(points[i + 1])); + } + yield break; + } + } +} diff --git a/PCUT/PCUT/Extensions/Converters/RectElementConverter.cs b/PCUT/PCUT/Extensions/Converters/RectElementConverter.cs new file mode 100644 index 0000000..8b4df11 --- /dev/null +++ b/PCUT/PCUT/Extensions/Converters/RectElementConverter.cs @@ -0,0 +1,76 @@ +using SvgPathProperties; +using System.Collections.Generic; +using System.Text; +using System.Xml.Linq; + +namespace PCUT.Extensions.Converters +{ + internal class RectElementConverter : PathConverter + { + private static readonly string[] RectExcludedAttributes = new[] { "transform", "x", "y", "width", "height", "rx", "ry" }; + protected override IEnumerable ExcludedAttributes => RectExcludedAttributes; + + internal RectElementConverter() + { + } + + protected override bool CanApply(XElement element) => element.Name.LocalName == "rect"; + + protected override SvgPath GetPathFromElement(XElement element) + { + var x = double.Parse(element.Attribute("x")?.Value ?? "0"); + var y = double.Parse(element.Attribute("y")?.Value ?? "0"); + var width = double.Parse(element.Attribute("width")?.Value ?? "0"); + var height = double.Parse(element.Attribute("height")?.Value ?? "0"); + var (rx, ry) = CalculateRoundedCorner(element.Attribute("rx")?.Value, element.Attribute("ry")?.Value); + if (width == 0 || height == 0) + return null; + + var hasRoundCorner = rx > 0 && ry > 0; + var arcCommonParam = $"{rx} {ry} 0 0 1 "; + var builder = new StringBuilder(); + builder.Append("M ").Append($"{x + rx} {y} "); + + builder.Append("H ").Append($"{x + width - rx}"); + if (hasRoundCorner) + builder.Append("A ").Append($"{arcCommonParam}").Append($"{x + width} {y + ry} "); + + builder.Append("V ").Append($"{y + height - ry} "); + if (hasRoundCorner) + builder.Append("A ").Append($"{arcCommonParam}").Append($"{x + width - rx} {y + height} "); + + builder.Append("H ").Append($"{x + rx}"); + if (hasRoundCorner) + builder.Append("A ").Append($"{arcCommonParam}").Append($"{x} {y + height - ry} "); + + builder.Append("V ").Append($"{y + ry} "); + if (hasRoundCorner) + builder.Append("A ").Append($"{arcCommonParam}").Append($"{x + rx} {y} "); + + builder.Append("Z"); + return new SvgPath(builder.ToString(), unarc: true); + } + + private (double Rx, double Ry) CalculateRoundedCorner(string rxValue, string ryValue) + { + if (rxValue == null) rxValue = "auto"; + if (ryValue == null) ryValue = "auto"; + + if (rxValue == "auto" && ryValue == "auto") + return (0, 0); + + double? rx = null, ry = null; + if (rxValue != "auto") + rx = double.Parse(rxValue); + if (ryValue != "auto") + ry = double.Parse(ryValue); + + if (rx == null) + rx = ry; + else if (ry == null) + ry = rx; + + return (rx.Value, ry.Value); + } + } +} diff --git a/PCUT/PCUT/Extensions/EnumerableExtensions.cs b/PCUT/PCUT/Extensions/EnumerableExtensions.cs new file mode 100644 index 0000000..8c63ac4 --- /dev/null +++ b/PCUT/PCUT/Extensions/EnumerableExtensions.cs @@ -0,0 +1,46 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace PCUT.Extensions +{ + public static class EnumerableExtension + { + public static void Filter(this ObservableCollection collection, IList data, Predicate filter, int startIndex = 0) + { + int currentIndex = startIndex; + var current = currentIndex < collection.Count ? collection[currentIndex] : default; + int i = startIndex; + while (i < data.Count() && currentIndex < collection.Count) + { + var item = data[i]; + var isValidItem = filter(item); + var isCurrentItem = EqualityComparer.Default.Equals(item, current); + if (isValidItem) + { + currentIndex++; + if (!isCurrentItem) + collection.Insert(currentIndex - 1, item); + else + current = currentIndex < collection.Count ? collection[currentIndex] : default; + } + else if (isCurrentItem) + { + collection.RemoveAt(currentIndex); + current = currentIndex < collection.Count ? collection[currentIndex] : default; + } + i++; + } + while (i < data.Count) + { + var item = data[i]; + if (filter(item)) + collection.Add(item); + i++; + } + } + } +} diff --git a/PCUT/PCUT/Extensions/HpglExtensions.cs b/PCUT/PCUT/Extensions/HpglExtensions.cs new file mode 100644 index 0000000..63ed203 --- /dev/null +++ b/PCUT/PCUT/Extensions/HpglExtensions.cs @@ -0,0 +1,173 @@ +using PCUT.Extensions.Transforms; +using SvgPathProperties; +using SvgPathProperties.Base; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Xml.Linq; + +namespace PCUT.Extensions +{ + public static class HpglExtensions + { + private const double MinimumCurveSegmentLength = 1; // mm + private const double UnitLength = 0.025; // mm + private const int BufferLength = 15000; // byte + + class StartPointComparer : IComparer + { + public static StartPointComparer Instance = new StartPointComparer(); + public int Compare(Point x, Point y) + { + return x.X != y.X ? x.X.CompareTo(y.X) : y.Y.CompareTo(x.Y); + } + } + + public static IEnumerable<(string Path, TimeSpan EstimateTime)> ToHPGL( + this XDocument svg, + (double Width, double Height) size, + (double Width, double Height) sheetSize, + int speed, // mm/s + int pen = 0) + { + var minCurveSegmentLength = MinimumCurveSegmentLength / UnitLength; + + var widthUnit = (int)Math.Ceiling(size.Width / UnitLength); + var heightUnit = (int)Math.Ceiling(size.Height / UnitLength); + + SvgTransform transform = new TranslateTransform(0, (int)Math.Ceiling(sheetSize.Height / UnitLength)); + + var flipTransform = new ScaleTransform(1, -1); + flipTransform.SetNext(transform); + transform = flipTransform; + + var scaleTransform = new ScaleTransform(1 / UnitLength, 1 / UnitLength); + scaleTransform.SetNext(transform); + transform = scaleTransform; + + var paths = new List(); + svg.GetPaths(paths, transform); + + yield return ($"IN;SP{pen};", TimeSpan.FromMilliseconds(200)); + var builder = new StringBuilder(); + TimeSpan timeSpan = TimeSpan.Zero; + var maxX = 0d; + var length = 0d; + foreach (var data in paths.OrderBy(x => x.GetPointAtLength(0), StartPointComparer.Instance)) + { + foreach (var segment in data.Segments) + { + switch (segment) + { + case MoveCommand moveCommand: + { + var lengthX = Math.Abs(maxX - moveCommand.X); + builder.AddHpglMove(moveCommand.X, moveCommand.Y, ref maxX); + length += (lengthX + (sheetSize.Height / UnitLength)) * 0.75; + break; + } + case LineCommand lineCommand: + { + builder.AddHpglLine(lineCommand.ToX, lineCommand.ToY, ref maxX); + length += lineCommand.Length; + break; + } + case BezierCommand bezierCommand: + { + var iterationCount = (int)Math.Ceiling(bezierCommand.Length / minCurveSegmentLength); + for (int i = 1; i < iterationCount; i++) + { + var point = bezierCommand.GetPointAtLength(i * minCurveSegmentLength); + builder.AddHpglLine(point.X, point.Y, ref maxX); + length += minCurveSegmentLength; + if (builder.Length > BufferLength) + { + timeSpan = CalculateWaitTime(length, speed); + yield return (builder.ToString(), timeSpan); + builder.Clear(); + length = 0; + } + } + var end = bezierCommand.IsQuadratic ? bezierCommand.Cp2OrEnd : bezierCommand.End; + builder.AddHpglLine(end.X, end.Y, ref maxX); + length += minCurveSegmentLength; + break; + } + case ArcCommand arcCommand: + { + var iterationCount = (int)Math.Ceiling(arcCommand.Length / minCurveSegmentLength); + for (int i = 1; i < iterationCount; i++) + { + var point = arcCommand.GetPointAtLength(i * minCurveSegmentLength); + builder.AddHpglLine(point.X, point.Y, ref maxX); + length += minCurveSegmentLength; + if (builder.Length > BufferLength) + { + timeSpan = CalculateWaitTime(length, speed); + yield return (builder.ToString(), timeSpan); + builder.Clear(); + length = 0; + } + } + builder.AddHpglLine(arcCommand.ToX, arcCommand.ToY, ref maxX); + length += minCurveSegmentLength; + break; + } + } + if (builder.Length > BufferLength) + { + timeSpan = CalculateWaitTime(length, speed); + yield return (builder.ToString(), timeSpan); + builder.Clear(); + length = 0; + } + } + timeSpan = CalculateWaitTime(length, speed); + yield return (builder.ToString(), timeSpan); + builder.Clear(); + length = 0; + } + yield return ($"PU{maxX + 2000},0;IN;", TimeSpan.Zero); + } + + private static void GetPaths(this XDocument document, List paths, SvgTransform transform = null) + { + foreach (var component in document.Root.Descendants().Where(z => z.Name.LocalName == "path")) + { + if (!component.IsHidden()) + { + var path = transform.Apply(new SvgPath(component.Attribute("d").Value, unarc: true)); + paths.Add(path); + } + } + } + + private static TimeSpan CalculateWaitTime(double length, int speed) + { + return TimeSpan.FromSeconds((int)Math.Ceiling((length * UnitLength) / speed)); + } + + private static StringBuilder AddHpglMove(this StringBuilder builder, double x, double y, ref double maxX) + { + x = Math.Round(x); + y = Math.Round(y); + maxX = Math.Max(x, maxX); + return builder + .Append("PU") + .Append(x).Append(',') + .Append(y).Append(";"); + } + + private static StringBuilder AddHpglLine(this StringBuilder builder, double x, double y, ref double maxX) + { + x = Math.Round(x); + y = Math.Round(y); + maxX = Math.Max(x, maxX); + return builder + .Append("PD") + .Append(x).Append(',') + .Append(y).Append(";"); + } + } +} diff --git a/PCUT/PCUT/Extensions/ImageSourceExtensions.cs b/PCUT/PCUT/Extensions/ImageSourceExtensions.cs new file mode 100644 index 0000000..23f98ce --- /dev/null +++ b/PCUT/PCUT/Extensions/ImageSourceExtensions.cs @@ -0,0 +1,75 @@ +using System; +using System.IO; +using System.Runtime.InteropServices.WindowsRuntime; +using System.Threading.Tasks; +using System.Xml.Linq; +using Windows.Graphics.Imaging; +using Windows.Storage.Streams; +using Windows.UI.Xaml.Controls; +using Windows.UI.Xaml.Media; +using Windows.UI.Xaml.Media.Imaging; + +namespace PCUT.Extensions +{ + public static class ImageSourceExtensions + { + public static async Task LoadStreamAsync(this ImageSource source, IRandomAccessStream data) + { + switch (source) + { + case SvgImageSource svgSource: + { + await svgSource.SetSourceAsync(data); + break; + } + case BitmapSource bitmapSource: + { + await bitmapSource.SetSourceAsync(data); + break; + } + default: + return; + } + } + + public static async Task LoadSvgAsync(this ImageSource source, XDocument svg) + { + if (source is SvgImageSource svgSource) + { + using (var stream = new MemoryStream()) + { + await svg.SaveAsync(stream, SaveOptions.None, default); + stream.Seek(0, SeekOrigin.Begin); + await svgSource.SetSourceAsync(stream.AsRandomAccessStream()); + } + } + } + + public static async Task CreateThumbnailAsync(this Image image) + { + var stream = new InMemoryRandomAccessStream(); + var bitmap = new RenderTargetBitmap(); + await bitmap.RenderAsync(image); + var pixelBuffer = await bitmap.GetPixelsAsync(); + var sb = SoftwareBitmap.CreateCopyFromBuffer(pixelBuffer, BitmapPixelFormat.Bgra8, bitmap.PixelWidth, bitmap.PixelHeight); + try + { + var encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.PngEncoderId, stream); + encoder.SetSoftwareBitmap(sb); + var scale = bitmap.PixelHeight > bitmap.PixelWidth + ? bitmap.PixelHeight > 480 ? 480m / bitmap.PixelHeight : 1 + : bitmap.PixelWidth > 640 ? 640m / bitmap.PixelWidth : 1; + encoder.BitmapTransform.ScaledWidth = (uint)(scale * bitmap.PixelWidth); + encoder.BitmapTransform.ScaledHeight = (uint)(scale * bitmap.PixelHeight); + await encoder.FlushAsync(); + stream.Seek(0); + return stream; + } + catch + { + stream.Dispose(); + return null; + } + } + } +} diff --git a/PCUT/PCUT/Extensions/ManipulationExtensions.cs b/PCUT/PCUT/Extensions/ManipulationExtensions.cs new file mode 100644 index 0000000..64eb34a --- /dev/null +++ b/PCUT/PCUT/Extensions/ManipulationExtensions.cs @@ -0,0 +1,15 @@ +using System; +using Windows.UI.Input; + +namespace PCUT.Extensions +{ + public static class ManipulationExtensions + { + public static (double OffsetX, double OffsetY) CalculateTranslation(this ManipulationDelta d, ManipulationVelocities v) + { + var vx_factor = Math.Max(v.Linear.X * v.Linear.X, 1); + var vy_factor = Math.Max(v.Linear.Y * v.Linear.Y, 1); + return (d.Translation.X * vx_factor, d.Translation.Y * vy_factor); + } + } +} diff --git a/PCUT/PCUT/Extensions/NumericExtensions.cs b/PCUT/PCUT/Extensions/NumericExtensions.cs new file mode 100644 index 0000000..af37561 --- /dev/null +++ b/PCUT/PCUT/Extensions/NumericExtensions.cs @@ -0,0 +1,49 @@ +namespace PCUT.Extensions +{ + public static class NumericExtensions + { + public static double GetValueByUnit(this string value) + { + if (value == null) + return 0; + + double scale = 1; + if (value.EndsWith("in")) + { + value = value.Replace("in", string.Empty); + scale = 25.4; + } + else if (value.EndsWith("cm")) + { + value = value.Replace("cm", string.Empty); + scale = 10; + } + else if (value.EndsWith("mm")) + { + value = value.Replace("mm", string.Empty); + scale = 1; + } + else if (value.EndsWith("pc")) + { + value = value.Replace("pc", string.Empty); + scale = (25.4 / 16); + } + else if (value.EndsWith("pt")) + { + value = value.Replace("pt", string.Empty); + scale = (25.4 / 72); + } + else if (value.EndsWith("px")) + { + value = value.Replace("px", string.Empty); + scale = (25.4 / 96); + } + + if (double.TryParse(value, out var doubleValue)) + { + return doubleValue * scale; + } + return 0; + } + } +} diff --git a/PCUT/PCUT/Extensions/PointExtensions.cs b/PCUT/PCUT/Extensions/PointExtensions.cs new file mode 100644 index 0000000..6455d31 --- /dev/null +++ b/PCUT/PCUT/Extensions/PointExtensions.cs @@ -0,0 +1,50 @@ +using DeepNestLib; +using System; +using System.Collections.Generic; +using System.Linq; +using Windows.Foundation; +using Windows.UI.Xaml.Media; + +namespace PCUT.Extensions +{ + public static class PointExtensions + { + public static double DistTo(this SvgPoint p, SvgPoint p2) + { + return Math.Sqrt(Math.Pow(p.x - p2.x, 2) + Math.Pow(p.y - p2.y, 2)); + } + + public static double DistTo(this Point p, Point p2) + { + return Math.Sqrt(Math.Pow(p.X - p2.X, 2) + Math.Pow(p.Y - p2.Y, 2)); + } + + public static Point Mult(this Point p, double m) + { + return new Point((p.X * m), (p.Y * m)); + } + + public static PathGeometry BuildPath(this IEnumerable points) + { + if (points.Count() < 2) + return null; + + var figure = new PathFigure { StartPoint = points.First() }; + foreach (var point in points) + figure.Segments.Add(new LineSegment { Point = point }); + + var path = new PathGeometry(); + path.Figures.Add(figure); + return path; + } + + public static IEnumerable PathPoints(this Rect rect) + { + yield return new Point(rect.Top, rect.Left); + yield return new Point(rect.Top, rect.Right); + yield return new Point(rect.Bottom, rect.Right); + yield return new Point(rect.Bottom, rect.Left); + yield break; + } + } +} diff --git a/PCUT/PCUT/Extensions/SettingExtensions.cs b/PCUT/PCUT/Extensions/SettingExtensions.cs new file mode 100644 index 0000000..44ebcc7 --- /dev/null +++ b/PCUT/PCUT/Extensions/SettingExtensions.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace PCUT.Extensions +{ + public static class SettingExtensions + { + public static bool TryGetValue (this Windows.Storage.ApplicationDataContainer settings, string key, out T value) + { + if (settings.Values.TryGetValue(key, out var obj) && !(obj is null) && obj is T tValue) + { + value = tValue; + return true; + } + value = default; + return false; + } + } +} diff --git a/PCUT/PCUT/Extensions/SvgExtensions.cs b/PCUT/PCUT/Extensions/SvgExtensions.cs new file mode 100644 index 0000000..54b3f42 --- /dev/null +++ b/PCUT/PCUT/Extensions/SvgExtensions.cs @@ -0,0 +1,295 @@ +using PCUT.Extensions.Converters; +using PCUT.Extensions.Transforms; +using SvgPathProperties; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.Xml.Linq; + +namespace PCUT.Extensions +{ + public static class SvgExtensions + { + private static readonly PathConverter _pathConverter = PathConverter.Builder() + .AddPath() + .AddRect() + .AddPolygon() + .AddCircle() + .AddEllipse().Build(); + + public static XDocument PreProcessSvg(this XDocument document, out double width, out double height) + { + var data = document.ScaleToUnit(); + width = data.Width; + height = data.Height; + var queue = new Queue<(XElement, SvgTransform)>(); + queue.Enqueue((document.Root, data.ScaleTransform)); + ConvertToPath(queue); + return document.ApplyCssStyle(data.ScaleTransform).SetAutoSize(); + } + + private static void ConvertToPath(Queue<(XElement Element, SvgTransform RootTransform)> queue) + { + while (queue.TryDequeue(out var item)) + { + var element = item.Element; + var rootTransform = item.RootTransform; + + var svgPath = _pathConverter.GetSvgPath(element); + if (svgPath != null) + { + var transform = element.GetTransform(rootTransform); + transform.SetNext(rootTransform); + + var newElement = GetTransformedPath(svgPath, transform); + + _pathConverter.CopyAttribute(element, newElement); + + newElement.SetAttributeValue("id", $"P_{Guid.NewGuid():N}"); + element.ReplaceWith(newElement); + } + + if (element.Name.LocalName == "g" || element.Name.LocalName == "svg") + { + var transform = element.GetTransform(rootTransform); + transform.SetNext(rootTransform); + element.RemoveAttribute("transform"); + if (element.Name.LocalName == "g") + element.SetAttributeValue("id", $"G_{Guid.NewGuid():N}"); + + foreach (var childElement in element.Elements()) + queue.Enqueue((childElement, transform)); + } + } + } + + private static XElement GetTransformedPath(SvgPath path, SvgTransform transform) + { + var builder = new StringBuilder(); + path = transform.Apply(path); + foreach (var segment in path.Segments) + { + switch (segment) + { + case MoveCommand moveCommand: + { + builder.Append("M ") + .Append(moveCommand.X).Append(',').Append(moveCommand.Y) + .Append(' '); + break; + } + case LineCommand lineCommand: + { + if (lineCommand.ClosePath) + builder.Append('Z'); + else + builder.Append("L ") + .Append(lineCommand.ToX).Append(',').Append(lineCommand.ToY) + .Append(' '); + break; + } + case BezierCommand curveCommand: + { + builder.Append(curveCommand.IsQuadratic ? "Q " : "C ") + .Append(curveCommand.Cp1.X).Append(',').Append(curveCommand.Cp1.Y) + .Append(' ') + .Append(curveCommand.Cp2OrEnd.X).Append(',').Append(curveCommand.Cp2OrEnd.Y) + .Append(' '); + if (!curveCommand.IsQuadratic) + builder.Append(curveCommand.End.X).Append(',').Append(curveCommand.End.Y) + .Append(' '); + break; + } + default: + { + break; + } + } + } + var transformedPath = new XElement(XName.Get("path", "http://www.w3.org/2000/svg")); + transformedPath.SetAttributeValue("d", builder.ToString()); + return transformedPath; + } + + public static SvgTransform GetTransform(this XElement element, SvgTransform rootTransform = null) + { + if (rootTransform == null) + rootTransform = SvgTransform.Default; + + var transforms = new List<(int Index, SvgTransform Transform)>(); + + var transformAttribute = element.Attribute("transform")?.Value; + if (transformAttribute != null) + { + foreach (var (i, translateData) in transformAttribute.GetTransform("translate", 2)) + { + var dx = double.Parse(translateData[0]); + var dy = translateData.Length > 1 ? double.Parse(translateData[1]) : 0; + var translate = new TranslateTransform(dx, dy); + transforms.Add((i, translate)); + } + + foreach (var (i, rotateData) in transformAttribute.GetTransform("rotate", 3)) + { + var degree = double.Parse(rotateData[0]); + var originX = rotateData.Length > 2 ? double.Parse(rotateData[1]) : 0; + var originY = rotateData.Length > 2 ? double.Parse(rotateData[2]) : 0; + var rotate = new RotateTransform(degree, originX, originY); + transforms.Add((i, rotate)); + } + + foreach (var (i, scaleData) in transformAttribute.GetTransform("scale", 2)) + { + var scaleX = double.Parse(scaleData[0]); + var scaleY = scaleData.Length > 1 ? double.Parse(scaleData[1]) : scaleX; + var scale = new ScaleTransform(scaleX, scaleY); + transforms.Add((i, scale)); + } + + foreach (var (i, scaleData) in transformAttribute.GetTransform("matrix", 6)) + { + var a = double.Parse(scaleData[0]); + var b = double.Parse(scaleData[1]); + var c = double.Parse(scaleData[2]); + var d = double.Parse(scaleData[3]); + var e = double.Parse(scaleData[4]); + var f = double.Parse(scaleData[5]); + var matrix = new MatrixTransform(a, b, c, d, e, f); + transforms.Add((i, matrix)); + } + } + + SvgTransform transform; + if (!transforms.Any()) + { + transform = rootTransform; + } + else + { + transforms.Sort((x, y) => x.Index.CompareTo(y.Index)); + transform = transforms.First().Transform; + transform.SetNext(rootTransform); + + foreach (var item in transforms.Skip(1)) + { + item.Transform.SetNext(transform); + transform = item.Transform; + } + } + return transform; + } + + private static IEnumerable<(int Index, string[] Data)> GetTransform(this string transformAttribute, string key, int maxLength) + { + var index = transformAttribute.IndexOf(key); + while (index != -1) + { + var s = transformAttribute.IndexOf('(', index); + var e = transformAttribute.IndexOf(')', index); + yield return (index, transformAttribute.Substring(s + 1, e - s - 1).Split(new[] { ' ', ',' }, maxLength, StringSplitOptions.RemoveEmptyEntries)); + index = transformAttribute.IndexOf(key, e); + } + yield break; + } + + public static (double Width, double Height, SvgTransform ScaleTransform) ScaleToUnit(this XDocument document) + { + var width = ConvertToUnit(document, "width"); + var height = ConvertToUnit(document, "height"); + var (scaleX, scaleY) = ScaleViewBox(document, width, height); + + SvgTransform scaleTransform; + if (scaleX == 1 && scaleY == 1) + scaleTransform = SvgTransform.Default; + else + scaleTransform = new ScaleTransform(scaleX, scaleY); + return (width, height, scaleTransform); + } + + private static double ConvertToUnit(XDocument document, string dimension) + { + var dimensionAttribute = document.Root.Attribute(dimension); + var dimensionValue = dimensionAttribute.Value; + var match = Regex.Match(dimensionValue, "^(?[\\d]+(?:[\\.,][\\d]*)?)(?mm|cm|in|pt|pc|px)?$"); + double scale; + switch (match.Groups["unit"].Value) + { + case "in": { scale = 25.4; break; } + case "cm": { scale = 10; break; } + case "pc": { scale = 25.4 / 16; break; } + case "pt": { scale = 25.4 / 72; break; } + case "px": { scale = 25.4 / 96; break; } + default: { scale = 1; break; } + } + var value = double.Parse(match.Groups["value"].Value) * scale; + document.Root.SetAttributeValue(dimension, value); + return value; + } + + private static (double ScaleX, double ScaleY) ScaleViewBox(XDocument document, double width, double height) + { + var viewBoxAttribute = document.Root.Attribute("viewBox"); + var viewBox = viewBoxAttribute.Value; + var viewBoxData = viewBox.Split(' ', 4); + var minX = double.Parse(viewBoxData[0]); + var minY = double.Parse(viewBoxData[1]); + var viewWidth = double.Parse(viewBoxData[2]); + var viewHeight = double.Parse(viewBoxData[3]); + document.Root.SetAttributeValue("viewBox", $"{minX} {minY} {width} {height}"); + return (width / viewWidth, height / viewHeight); + } + + public static XDocument ApplyCssStyle(this XDocument doc, SvgTransform rootTransform) + { + var styles = doc.GetCssStyleDefinitions(); + var scale = rootTransform is ScaleTransform scaleTransform ? scaleTransform.ScaleX : 1d; + if (styles.Any() && scale != 1d) + { + foreach (var key in styles.Keys.ToArray()) + { + styles[key] = Regex.Replace(styles[key], "stroke-width:(?[\\d]+(?:[\\.,][\\d]*)?)", match => $"stroke-width:{double.Parse(match.Groups["value"].Value) * scale}"); + } + } + foreach (var element in doc.Descendants(XName.Get("path", "http://www.w3.org/2000/svg"))) + { + var classes = element.Attribute("class")?.Value.Split(' ', StringSplitOptions.RemoveEmptyEntries).Select(x => $".{x}"); + if (classes != null) + { + var style = string.Join(';', classes.Select(@class => styles.TryGetValue(@class, out var value) ? value : null).Where(x => x != null)); + element.SetAttributeValue("style", style); + } + else + { + var styleAttribute = element.Attribute("style"); + if (styleAttribute != null) + { + var style = Regex.Replace(styleAttribute.Value, "stroke-width:(?[\\d]+(?:[\\.,][\\d]*)?)", match => $"stroke-width:{double.Parse(match.Groups["value"].Value) * scale}"); + styleAttribute.SetValue(style); + } + } + } + return doc; + } + + public static IDictionary GetCssStyleDefinitions(this XDocument doc) + { + var cdata = doc.DescendantNodes() + .OfType() + .Where(x => x.Parent.Name.LocalName == "style" && x.Parent.Attribute("type")?.Value == "text/css") + .FirstOrDefault(); + if (cdata == null) + return new Dictionary(); + + var styles = cdata.Value.Replace("\n", "") + .Split(' ', StringSplitOptions.RemoveEmptyEntries) + .Where(x => !string.IsNullOrEmpty(x)) + .Select((x, i) => (Value: x, Index: i / 2)) + .GroupBy(x => x.Index, x => x.Value) + .ToDictionary(x => x.ElementAt(0), x => x.ElementAt(1).Trim('{', '}')); + cdata.Remove(); + return styles; + } + } +} diff --git a/PCUT/PCUT/Extensions/SvgTransformExtensions.cs b/PCUT/PCUT/Extensions/SvgTransformExtensions.cs new file mode 100644 index 0000000..84c68bd --- /dev/null +++ b/PCUT/PCUT/Extensions/SvgTransformExtensions.cs @@ -0,0 +1,88 @@ +using PCUT.Extensions.Transforms; +using SvgPathProperties; +using SvgPathProperties.Base; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace PCUT.Extensions +{ + public static class SvgTransformExtensions + { + public static SvgPath Apply(this SvgTransform transform, SvgPath path) + { + if (transform == null || path == null) + return path; + + var transformedPath = new SvgPath(); + foreach (var segment in path.Segments) + { + switch (segment) + { + case MoveCommand moveSegment: + var moveCommand = transform.Apply(moveSegment); + transformedPath.AddMoveTo(moveCommand.X, moveCommand.Y); + break; + case LineCommand lineSegment: + if (lineSegment.ClosePath) + { + transformedPath.AddClosePath(); + } + else + { + var lineCommand = transform.Apply(lineSegment); + transformedPath.AddLineTo(lineCommand.ToX, lineCommand.ToY); + } + break; + case BezierCommand bezierSegment: + var bezierCommand = transform.Apply(bezierSegment); + if (!bezierCommand.IsQuadratic) + transformedPath.AddCubicBezierCurve(bezierCommand.Cp1.X, bezierCommand.Cp1.Y, bezierCommand.Cp2OrEnd.X, bezierCommand.Cp2OrEnd.Y, bezierCommand.End.X, bezierCommand.End.Y); + else + transformedPath.AddQuadraticBezierCurve(bezierCommand.Cp1.X, bezierCommand.Cp1.Y, bezierCommand.Cp2OrEnd.X, bezierCommand.Cp2OrEnd.Y); + break; + case ArcCommand arcSegment: + var arcCommand = transform.Apply(arcSegment); + transformedPath.AddArc(arcCommand.Rx, arcCommand.Ry, arcCommand.XAxisRotate, arcCommand.LargeArcFlag, arcCommand.SweepFlag, arcCommand.ToX, arcCommand.ToY); + break; + } + } + return transformedPath; + } + + private static MoveCommand Apply(this SvgTransform transform, MoveCommand command) + { + var (x, y) = transform.Transform(command.X, command.Y); + return new MoveCommand(x, y); + } + + private static LineCommand Apply(this SvgTransform transform, LineCommand command) + { + var (fromX, fromY) = transform.Transform(command.FromX, command.FromY); + var (toX, toY) = transform.Transform(command.ToX, command.ToY); + return new LineCommand(fromX, toX, fromY, toY, command.ClosePath); + } + + private static BezierCommand Apply(this SvgTransform transform, BezierCommand command) + { + var from = transform.Apply(command.From); + var cp1 = transform.Apply(command.Cp1); + var cp2 = transform.Apply(command.Cp2OrEnd); + (double? X, double? Y) end = command.IsQuadratic ? default : transform.Transform(command.End.X, command.End.Y); + return new BezierCommand(from.X, from.Y, cp1.X, cp1.Y, cp2.X, cp2.Y, end.X, end.Y); + } + + private static ArcCommand Apply(this SvgTransform transform, ArcCommand command) + { + throw new NotImplementedException(); + } + + private static Point Apply(this SvgTransform transform, Point point) + { + var (x, y) = transform.Transform(point.X, point.Y); + return new Point(x, y); + } + } +} diff --git a/PCUT/PCUT/Extensions/Transforms/MatrixTransform.cs b/PCUT/PCUT/Extensions/Transforms/MatrixTransform.cs new file mode 100644 index 0000000..6c015bd --- /dev/null +++ b/PCUT/PCUT/Extensions/Transforms/MatrixTransform.cs @@ -0,0 +1,35 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace PCUT.Extensions.Transforms +{ + public class MatrixTransform : SvgTransform + { + public double A { get; private set; } + public double B { get; private set; } + public double C { get; private set; } + public double D { get; private set; } + public double E { get; private set; } + public double F { get; private set; } + + public MatrixTransform(double a, double b, double c, double d, double e, double f) + { + A = a; + B = b; + C = c; + D = d; + E = e; + F = f; + } + + protected override (double X, double Y) InternalTransform(double x, double y) + { + var x1 = A * x + C * y + E; + var y1 = B * x + D * y + F; + return (x1, y1); + } + } +} diff --git a/PCUT/PCUT/Extensions/Transforms/RotateTransform.cs b/PCUT/PCUT/Extensions/Transforms/RotateTransform.cs new file mode 100644 index 0000000..66e09e7 --- /dev/null +++ b/PCUT/PCUT/Extensions/Transforms/RotateTransform.cs @@ -0,0 +1,40 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace PCUT.Extensions.Transforms +{ + public class RotateTransform : SvgTransform + { + private readonly double _sin; + private readonly double _cos; + + public double Degree { get; private set; } + public double OriginX { get; private set; } + public double OriginY { get; private set; } + + public RotateTransform(double degree, double originX, double originY) + { + Degree = degree; + OriginX = originX; + OriginY = originY; + + var angle = degree * DToRFactor; + _sin = Math.Sin(angle); + _cos = Math.Cos(angle); + } + + public RotateTransform(double degree) : this(degree, 0, 0) + { + } + + protected override (double X, double Y) InternalTransform(double x, double y) + { + var x1 = (x - OriginX) * _cos - (y - OriginY) * _sin + OriginX; + var y1 = (x - OriginX) * _sin + (y - OriginY) * _cos + OriginY; + return (x1, y1); + } + } +} diff --git a/PCUT/PCUT/Extensions/Transforms/ScaleTransform.cs b/PCUT/PCUT/Extensions/Transforms/ScaleTransform.cs new file mode 100644 index 0000000..670c601 --- /dev/null +++ b/PCUT/PCUT/Extensions/Transforms/ScaleTransform.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace PCUT.Extensions.Transforms +{ + public class ScaleTransform : SvgTransform + { + public double ScaleX { get; private set; } + public double ScaleY { get; private set; } + + public ScaleTransform(double scaleX, double scaleY) + { + ScaleX = scaleX; + ScaleY = scaleY; + } + + protected override (double X, double Y) InternalTransform(double x, double y) + { + var x1 = ScaleX * x; + var y1 = ScaleY * y; + return (x1, y1); + } + } +} diff --git a/PCUT/PCUT/Extensions/Transforms/SkewTransform.cs b/PCUT/PCUT/Extensions/Transforms/SkewTransform.cs new file mode 100644 index 0000000..d502c81 --- /dev/null +++ b/PCUT/PCUT/Extensions/Transforms/SkewTransform.cs @@ -0,0 +1,50 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace PCUT.Extensions.Transforms +{ + public abstract class SkewTransform : SvgTransform + { + protected readonly double _tan; + + public double Degree { get; set; } + + public SkewTransform(double degree) + { + Degree = degree; + var angle = degree * DToRFactor; + _tan = Math.Tan(angle); + } + } + + public class SkewXTransform : SkewTransform + { + public SkewXTransform(double degree) : base(degree) + { + } + + protected override (double X, double Y) InternalTransform(double x, double y) + { + var x1 = x + y * _tan; + var y1 = y; + return (x1, y1); + } + } + + public class SkewYTransform : SkewTransform + { + public SkewYTransform(double degree) : base(degree) + { + } + + protected override (double X, double Y) InternalTransform(double x, double y) + { + var x1 = x; + var y1 = y + x * _tan; + return (x1, y1); + } + } +} diff --git a/PCUT/PCUT/Extensions/Transforms/SvgTransform.cs b/PCUT/PCUT/Extensions/Transforms/SvgTransform.cs new file mode 100644 index 0000000..bd058fd --- /dev/null +++ b/PCUT/PCUT/Extensions/Transforms/SvgTransform.cs @@ -0,0 +1,39 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace PCUT.Extensions.Transforms +{ + public abstract class SvgTransform + { + protected static readonly double DToRFactor = Math.PI / 180; + protected SvgTransform _nextTransform { get; private set; } + public void SetNext(SvgTransform nextTransform) + { + if (this != nextTransform) + _nextTransform = nextTransform; + } + + public (double X, double Y) Transform(double x, double y) + { + (x, y) = InternalTransform(x, y); + if (_nextTransform != null) + (x, y) = _nextTransform.Transform(x, y); + + return (x, y); + } + + protected abstract (double X, double Y) InternalTransform(double x, double y); + + public static readonly SvgTransform Default = new DefaultTransform(); + private class DefaultTransform : SvgTransform + { + protected override (double X, double Y) InternalTransform(double x, double y) + { + return (x, y); + } + } + } +} diff --git a/PCUT/PCUT/Extensions/Transforms/TranslateTransform.cs b/PCUT/PCUT/Extensions/Transforms/TranslateTransform.cs new file mode 100644 index 0000000..aba34fb --- /dev/null +++ b/PCUT/PCUT/Extensions/Transforms/TranslateTransform.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace PCUT.Extensions.Transforms +{ + public class TranslateTransform : SvgTransform + { + public double Dx { get; private set; } + public double Dy { get; private set; } + + public TranslateTransform(double dx, double dy) + { + Dx = dx; + Dy = dy; + } + + protected override (double X, double Y) InternalTransform(double x, double y) + { + var x1 = x + Dx; + var y1 = y + Dy; + return (x1, y1); + } + } +} diff --git a/PCUT/PCUT/Extensions/XmlExtensions.cs b/PCUT/PCUT/Extensions/XmlExtensions.cs new file mode 100644 index 0000000..d1cb682 --- /dev/null +++ b/PCUT/PCUT/Extensions/XmlExtensions.cs @@ -0,0 +1,253 @@ +using PCUT.DeepNestApi; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Xml.Linq; + +namespace PCUT.Extensions +{ + public static class XmlExtensions + { + public static string GetId(this XElement element) + { + return element.Attribute("id")?.Value; + } + + public static void SetId(this XElement element, string id) + { + element.SetAttributeValue("id", id); + } + + public static XElement GetDescendantById(this XDocument doc, string id) + { + return doc.Root.GetDescendantById(id); + } + + public static XElement GetDescendantById(this XElement element, string id) + { + return element.Descendants().FirstOrDefault(x => x.GetId() == id); + } + + public static string GetViewBox(this XDocument doc) + { + return doc.Root.Attribute("viewBox")?.Value; + } + + public static XElement RemoveAttribute(this XElement element, string attributeName) + { + var attribute = element.Attribute(attributeName); + attribute?.Remove(); + return element; + } + + public static int Count(this XElement element, params string[] names) + { + return names.Sum(name => element.Elements(XName.Get(name, element.GetDefaultNamespace().NamespaceName)).Count()); + } + + public static XDocument SetAutoSize(this XDocument doc) + { + doc.Root.SetAttributeValue("height", "auto"); + doc.Root.SetAttributeValue("width", "auto"); + return doc; + } + + public static void SetSize(this XDocument doc, double width, double height) + { + doc.Root.SetAttributeValue("width", width); + doc.Root.SetAttributeValue("height", height); + } + + public static XElement GetChild(this XDocument doc, string tag) + { + return doc.Root.GetChild(tag); + } + + public static XElement GetChild(this XElement root, string tag) + { + var name = XName.Get(tag, root.GetDefaultNamespace().NamespaceName); + return root.Element(name); + } + + //public static IEnumerable GetChildren(this XDocument doc, string path = null, params string[] tags) + //{ + // var root = doc.Root; + // if (path != null) + // foreach (var tag in path.TrimStart('.').Split("/")) + // root = root.GetChild(tag); + // return root.GetChildren(tags); + //} + + public static IEnumerable GetChildren(this XElement root, params string[] tags) + { + return root.Elements().Where(x => tags.Contains(x.Name.LocalName)); + } + + public static bool IsHidden(this XElement element) + { + if (element.Attribute("visibility")?.Value == "hidden") + return true; + + while (element.Parent != null) + { + element = element.Parent; + if (element.Attribute("visibility")?.Value == "hidden") + return true; + } + return false; + } + + public static void HideById(this XDocument doc, string id) + { + var element = doc.GetDescendantById(id); + element?.SetAttributeValue("visibility", "hidden"); + } + + public static void RestoreById(this XDocument doc, string id) + { + var element = doc.GetDescendantById(id); + element?.Attribute("visibility")?.Remove(); + } + + public static void RemoveHidden(this XDocument doc) + { + var elements = doc.Descendants().Where(element => element.IsHidden()).ToArray(); + foreach (var element in elements) + { + element.Remove(); + } + } + + public static void ApplyTransform(this XDocument doc, string id, string transform) + { + var element = doc.GetDescendantById(id); + if (element.Attribute("transform") == null) + { + element.SetAttributeValue("transform", transform); + } + else + { + var parent = element.Parent; + + var transformElement = XElement.Parse($""); + transformElement.SetId(id); + if (element.IsHidden()) + transformElement.SetAttributeValue("visibility", "hidden"); + transformElement.SetAttributeValue("transform", transform); + + element.Attribute("id")?.Remove(); + element.Attribute("visibility")?.Remove(); + element.Remove(); + transformElement.Add(element); + parent.Add(transformElement); + } + } + + public static IEnumerable<(string Id, bool Deleted, XDocument Component, double BoundWidth, double BoundHeight)> SplitDocument(this XDocument doc, double width, double height) + { + var root = doc.Root; + while (root.Count("g") == 1 && root.Count("path") == 0) + { + root = root.GetChild("g"); + } + foreach (var element in root.GetChildren("g", "path")) + { + var componentElement = new XElement(element); + var deleted = componentElement.IsHidden(); + componentElement.Attribute("visibility")?.Remove(); + var id = componentElement.GetId(); + + var rootElement = CreateRoot(doc); + if (element.Name.LocalName != "g") + { + var groupElement = new XElement(XName.Get("g", root.GetDefaultNamespace().NamespaceName)); + groupElement.Add(componentElement); + componentElement = groupElement; + } + rootElement.Add(componentElement); + var componentDoc = new XDocument(rootElement); + + var (bWidth, bHeight) = componentDoc.ProcessComponent(width, height); + yield return (id, deleted, componentDoc, bWidth, bHeight); + } + yield break; + } + + private static XElement CreateRoot(XDocument doc) + { + var newRoot = new XElement(XName.Get("svg", doc.Root.GetDefaultNamespace().NamespaceName)); + newRoot.SetAttributeValue("width", "auto"); + newRoot.SetAttributeValue("height", "auto"); + newRoot.SetAttributeValue("viewBox", doc.Root.Attribute("viewBox")?.Value); + return newRoot; + } + + private static (double BoundWidth, double BoundHeight) ProcessComponent(this XDocument component, double width, double height) + { + var bbox = SvgParser.GetBBox(component); + var boundWidth = bbox.Width; + var boundHeight = bbox.Height; + var size = bbox.Width > bbox.Height ? bbox.Width : bbox.Height; + var scale = 0.8 * (bbox.Width > bbox.Height ? width : height) / size; + var tx = (width - (scale * bbox.Width)) / 2 - (scale * bbox.Left); + var ty = (height - (scale * bbox.Height)) / 2 - (scale * bbox.Top); + var element = component.Root.Elements().First(); + element.SetAttributeValue("transform", $"translate({tx} {ty}) scale({scale})"); + return (boundWidth, boundHeight); + } + + public static (double MinX, double MinY, double Width, double Height) GetViewBoxData(this string viewBox) + { + var viewBoxData = viewBox.Split(' ', 4); + return ( + double.Parse(viewBoxData[0]), + double.Parse(viewBoxData[1]), + double.Parse(viewBoxData[2]), + double.Parse(viewBoxData[3]) + ); + } + + //public static void IdentifyComponents(this XDocument document, string path, params string[] tags) + //{ + // foreach (var component in document.GetChildren(path: path, tags)) + // { + // if (component.GetId() == null) + // { + // component.SetId($"_{Guid.NewGuid():N}"); + // } + // } + //} + + //public static void PropagateTransform(this XElement element, string previousTransform = null) + //{ + // if (element.Name.LocalName == "g" || element.Name.LocalName == "path") + // { + // var transformAttribute = element.Attribute("transform"); + // var transformAttributeValue = transformAttribute?.Value; + // transformAttributeValue = $"{previousTransform} {transformAttributeValue}".Trim(); + // if (transformAttribute != null) + // transformAttribute.Remove(); + // if (element.Name.LocalName == "path") + // { + // if (!string.IsNullOrWhiteSpace(transformAttributeValue)) + // element.SetAttributeValue("transform", transformAttributeValue); + // return; + // } + // else if (element.Name.LocalName == "g") + // { + // foreach (var child in element.Elements()) + // { + // PropagateTransform(child, transformAttributeValue); + // } + // } + // } + // else if (element.Name.LocalName == "svg") + // { + // foreach (var child in element.Elements()) + // { + // PropagateTransform(child, previousTransform); + // } + // } + //} + } +} diff --git a/PCUT/PCUT/Factories/FileFactory.cs b/PCUT/PCUT/Factories/FileFactory.cs new file mode 100644 index 0000000..f6390f9 --- /dev/null +++ b/PCUT/PCUT/Factories/FileFactory.cs @@ -0,0 +1,112 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Net.Http; +using System.Text; +using System.Threading.Tasks; +using System.Xml.Linq; +using Http.Core; +using Http.Core.Extensions; +using PCUT.Extensions; +using Windows.Security.Cryptography.Certificates; +using Windows.Storage; +using Windows.Storage.Pickers; +using Windows.Storage.Streams; +using static Http.Core.Constants.HttpConstants; + +namespace PCUT.Factories +{ + class FileFactory + { + public static Task GetFileAsync() + { + return LocalFileFactory.Instance.GetFileAsync(); + } + + public static Task GetFileAsync(string id) + { + return RemoteFileFactory.Instance.GetFileAsync(id); + } + + public static async Task<(XDocument Data, double Width, double Height)> PreProcessSvgAsync(Stream stream) + { + try + { + var document = await XDocument.LoadAsync(stream, LoadOptions.None, default); + //document.IdentifyComponents(path: "g", "path", "g"); + //document.ApplyCssStyle(); + //document.Root.PropagateTransform(); + //var (width, height) = document.SetAutoSize(); + document.PreProcessSvg(out var width, out var height); + return (document, width, height); + } + catch + { + return default; + } + } + } + + interface IFileFactory + { + Task GetFileAsync(string id = null); + } + + class LocalFileFactory : IFileFactory + { + public static readonly IFileFactory Instance = new LocalFileFactory(); + public async Task GetFileAsync(string id = null) + { + try + { + var file = await CreatePicker().PickSingleFileAsync(); + if (file == null) + return null; + var stream = await file.OpenReadAsync(); + return stream.AsStream(); + } + catch + { + return null; + } + } + + private static FileOpenPicker CreatePicker() + { + var picker = new FileOpenPicker(); + picker.ViewMode = PickerViewMode.Thumbnail; + picker.SuggestedStartLocation = PickerLocationId.Downloads; + picker.FileTypeFilter.Add(".svg"); + return picker; + } + } + class RemoteFileFactory : IFileFactory + { + public static readonly IFileFactory Instance = new RemoteFileFactory(); + public async Task GetFileAsync(string id = null) + { + using (var httpClient = HttpClientFactory.CreateClient(ClientNames.ApiClient)) + { + try + { + var stream = new MemoryStream(); + var response = await httpClient.DownloadAsync(Api.Download.FormatRoute(id), stream); + if (response) + { + stream.Seek(0, SeekOrigin.Begin); + return stream; + } + else + { + stream.Dispose(); + } + } + catch (Exception ex) + { + } + } + return null; + } + } +} diff --git a/PCUT/PCUT/Helpers/Converters/BooleanNegationConverter.cs b/PCUT/PCUT/Helpers/Converters/BooleanNegationConverter.cs new file mode 100644 index 0000000..ea81d4a --- /dev/null +++ b/PCUT/PCUT/Helpers/Converters/BooleanNegationConverter.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Windows.UI.Xaml.Data; + +namespace PCUT.Helpers.Converters +{ + public class BooleanNegationConverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, string language) + { + return (bool)value ? "Active" : "Inactive"; + } + + public object ConvertBack(object value, Type targetType, object parameter, string language) + { + return (string)value == "Active"; + } + } +} diff --git a/PCUT/PCUT/Helpers/Converters/DateTimeToFormattedStringConverter.cs b/PCUT/PCUT/Helpers/Converters/DateTimeToFormattedStringConverter.cs new file mode 100644 index 0000000..e0e0f95 --- /dev/null +++ b/PCUT/PCUT/Helpers/Converters/DateTimeToFormattedStringConverter.cs @@ -0,0 +1,34 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace PCUT.Helpers.Converters +{ + public class DateTimeToFormattedStringConverter + { + public object Convert(object value, Type targetType, object parameter, string language) + { + if (value is DateTimeOffset dateTimeOffset) + { + return dateTimeOffset.ToString("MM/dd/yyyy", CultureInfo.InvariantCulture); + } + return string.Empty; + } + + public object ConvertBack(object value, Type targetType, object parameter, string language) + { + if (value is string stringValue) + { + if (DateTimeOffset.TryParseExact(stringValue, "MM/dd/yyyy", CultureInfo.InvariantCulture, DateTimeStyles.None, out var result)) + { + return result; + } + + } + return value; + } + } +} diff --git a/PCUT/PCUT/Helpers/RelayCommand.cs b/PCUT/PCUT/Helpers/RelayCommand.cs new file mode 100644 index 0000000..8aabae6 --- /dev/null +++ b/PCUT/PCUT/Helpers/RelayCommand.cs @@ -0,0 +1,67 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Input; + +namespace PCUT.Helpers +{ + public class RelayCommand : ICommand + { + private readonly Action _execute; + private readonly Func _executeAsync; + private readonly Func _canExecute; + private readonly Action _executeWithParam; + + + // Constructor for synchronous action without parameters + public RelayCommand(Action execute, Func canExecute = null) + { + _execute = execute ?? throw new ArgumentNullException(nameof(execute)); + _canExecute = canExecute; + } + + // Constructor for asynchronous action without parameters + public RelayCommand(Func executeAsync, Func canExecute = null) + { + _executeAsync = executeAsync ?? throw new ArgumentNullException(nameof(executeAsync)); + _canExecute = canExecute; + } + + // Added constructor for synchronous action with a parameter + public RelayCommand(Action executeWithParam, Func canExecute = null) + { + _executeWithParam = executeWithParam ?? throw new ArgumentNullException(nameof(executeWithParam)); + _canExecute = canExecute; + } + + public bool CanExecute(object parameter) + { + return _canExecute == null || _canExecute(); + } + + public async void Execute(object parameter) + { + if (_execute != null) + { + _execute(); + } + else if (_executeWithParam != null) + { + _executeWithParam(parameter); + } + else if (_executeAsync != null) + { + await _executeAsync(); + } + } + + public event EventHandler CanExecuteChanged; + + public void RaiseCanExecuteChanged() + { + CanExecuteChanged?.Invoke(this, EventArgs.Empty); + } + } +} diff --git a/PCUT/PCUT/Models/Categories/CategoryModel.cs b/PCUT/PCUT/Models/Categories/CategoryModel.cs new file mode 100644 index 0000000..39d4d31 --- /dev/null +++ b/PCUT/PCUT/Models/Categories/CategoryModel.cs @@ -0,0 +1,61 @@ +using PCUT.Entities; +using PCUT.ViewModels; +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace PCUT.Models.Categories +{ + public class CategoryModel : Category + { + public string DisplayId { get; set; } + public ObservableCollection CategoryMetadata { get; } + + public CategoryModel() + { + CategoryMetadata = new ObservableCollection + { + new MetadataTypeModel(this, 1, MetadataViewModel.TypeHeader), + new MetadataTypeModel(this, 2, MetadataViewModel.BrandHeader), + new MetadataTypeModel(this, 3, MetadataViewModel.SerieHeader), + new MetadataTypeModel(this, 4, MetadataViewModel.ModelHeader), + new MetadataTypeModel(this, 5, MetadataViewModel.SubTypeHeader), + new MetadataTypeModel(this, 6, MetadataViewModel.YearHeader) + }; + } + } + + public class MetadataTypeModel : NotificationBase + { + public CategoryModel Category { get; } + public int DisplayId { get; set; } + public string Name { get; } + public bool IsLoaded { get; set; } + + private bool _isExpanded; + public bool IsExpanded + { + get { return _isExpanded; } + set { SetProperty(ref _isExpanded, value); } + } + + public ObservableCollection Metadata { get; } = new ObservableCollection(); + + public MetadataTypeModel(CategoryModel category, int displayId, string name) + { + Category = category; + DisplayId = displayId; + Name = name; + IsLoaded = false; + } + } + + public class CategoryMetadataModel : CategoryMetadata + { + public MetadataTypeModel MetadataType { get; set; } + public int DisplayId { get; set; } + } +} diff --git a/PCUT/PCUT/Models/Categories/CategoryTemplateSelector.cs b/PCUT/PCUT/Models/Categories/CategoryTemplateSelector.cs new file mode 100644 index 0000000..70a0698 --- /dev/null +++ b/PCUT/PCUT/Models/Categories/CategoryTemplateSelector.cs @@ -0,0 +1,26 @@ +using Windows.UI.Xaml; +using Windows.UI.Xaml.Controls; + +namespace PCUT.Models.Categories +{ + public class CategoryTemplateSelector : DataTemplateSelector + { + public DataTemplate CategoryTemplate { get; set; } + public DataTemplate MetadataTypeTemplate { get; set; } + public DataTemplate MetadataTemplate { get; set; } + protected override DataTemplate SelectTemplateCore(object item) + { + switch (item) + { + case CategoryModel _: + return CategoryTemplate; + case MetadataTypeModel _: + return MetadataTypeTemplate; + case CategoryMetadataModel _: + return MetadataTemplate; + default: + return null; + } + } + } +} diff --git a/PCUT/PCUT/Models/NotificationBase.cs b/PCUT/PCUT/Models/NotificationBase.cs new file mode 100644 index 0000000..702b5e3 --- /dev/null +++ b/PCUT/PCUT/Models/NotificationBase.cs @@ -0,0 +1,50 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Runtime.CompilerServices; +using System.Text; +using System.Threading.Tasks; + +namespace PCUT.Models +{ + public class NotificationBase : INotifyPropertyChanged + { + public event PropertyChangedEventHandler PropertyChanged; + + // SetField (Name, value); // where there is a data member + protected bool SetProperty(ref T field, T value, [CallerMemberName] String property = null) + { + if (EqualityComparer.Default.Equals(field, value)) return false; + field = value; + RaisePropertyChanged(property); + return true; + } + + // SetField(()=> somewhere.Name = value; somewhere.Name, value) // Advanced case where you rely on another property + protected bool SetProperty(T currentValue, T newValue, Action DoSet, [CallerMemberName] String property = null) + { + if (EqualityComparer.Default.Equals(currentValue, newValue)) return false; + DoSet.Invoke(); + RaisePropertyChanged(property); + return true; + } + + protected void RaisePropertyChanged(string property) + { + if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(property)); } + } + } + + //public class NotificationBase : NotificationBase where T : class, new() + //{ + // protected T This; + + // public static implicit operator T(NotificationBase thing) { return thing.This; } + + // public NotificationBase(T thing = null) + // { + // This = (thing == null) ? new T() : thing; + // } + //} +} diff --git a/PCUT/PCUT/Models/SelectableCollection.cs b/PCUT/PCUT/Models/SelectableCollection.cs new file mode 100644 index 0000000..4bb2afe --- /dev/null +++ b/PCUT/PCUT/Models/SelectableCollection.cs @@ -0,0 +1,132 @@ +using PCUT.Extensions; +using PCUT.Models; +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Windows.UI.Xaml.Controls; +using Windows.UI.Xaml.Controls.Primitives; + +namespace PCUT.Models +{ + public abstract class SelectableCollection : NotificationBase + { + protected readonly bool _withDefault; + + protected int _selectedIndex; + public int SelectedIndex + { + get => _selectedIndex; + set + { + if (_withDefault && value == 0) + { + _selectedIndex = 0; + } + else + { + SetProperty(ref _selectedIndex, value); + } + } + } + + protected SelectableCollection(bool withDefault) + { + _withDefault = withDefault; + _selectedIndex = -1; + } + + private void Selector_SelectionChanged(object sender, SelectionChangedEventArgs e) + { + var selector = sender as Selector; + if (_withDefault && selector.SelectedIndex == 0) + { + selector.SelectedIndex = -1; + } + } + + public void Bind(Selector selector) + { + if (selector != null) + selector.SelectionChanged += Selector_SelectionChanged; + } + } + + public class SelectableCollection : SelectableCollection + { + private readonly T DefaultItem; + + private readonly List _items; + public ObservableCollection Items { get; } + public T SelectedItem => _selectedIndex >= 0 ? Items[_selectedIndex] : default; + + public SelectableCollection(T defaultItem) : base(true) + { + DefaultItem = defaultItem; + _selectedIndex = -1; + _items = new List(); + Items = new ObservableCollection(); + } + + public SelectableCollection(bool withDefault = false) : base(withDefault) + { + if (withDefault) + DefaultItem = default; + _selectedIndex = -1; + _items = new List(); + Items = new ObservableCollection(); + } + + public SelectableCollection(params T[] items) : this() + { + AddRange(items); + } + + public SelectableCollection(bool withDefault = false, params T[] items) : this(withDefault) + { + AddRange(items); + } + + public SelectableCollection(T defaultItem, params T[] items) : this(defaultItem) + { + AddRange(items); + } + + public void SelectBy(Func predicate) + { + var item = Items.FirstOrDefault(predicate); + var index = (item == null) ? -1 : Items.IndexOf(item); + SelectedIndex = index; + } + + public void Load(IEnumerable items) + { + SelectedIndex = -1; + AddRange(items); + } + + private void AddRange(IEnumerable items) + { + _items.Clear(); + Items.Clear(); + if (_withDefault) + { + _items.Add(DefaultItem); + Items.Add(DefaultItem); + } + foreach (var item in items) + { + _items.Add(item); + Items.Add(item); + } + } + + public void Filter(Predicate filter) + { + var start = _withDefault ? 1 : 0; + Items.Filter(_items, filter, start); + } + } +} diff --git a/PCUT/PCUT/Models/Users/UsersModel.cs b/PCUT/PCUT/Models/Users/UsersModel.cs new file mode 100644 index 0000000..6b9186e --- /dev/null +++ b/PCUT/PCUT/Models/Users/UsersModel.cs @@ -0,0 +1,9 @@ +using PCUT.Entities; + +namespace PCUT.Models.Users +{ + public class UsersModel : UserProfile + { + public string DisplayId { get; set; } + } +} diff --git a/PCUT/PCUT/PCUT.csproj b/PCUT/PCUT/PCUT.csproj new file mode 100644 index 0000000..fb7e32a --- /dev/null +++ b/PCUT/PCUT/PCUT.csproj @@ -0,0 +1,479 @@ + + + + + Debug + x86 + {2E7B481D-6F70-41BE-8224-A9D69499E6EE} + AppContainerExe + Properties + PCUT + PCUT + en-US + UAP + 10.0.22621.0 + 10.0.17763.0 + 14 + 512 + {A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + true + True + True + False + True + Always + x86|x64 + C:/PCUT + 0 + C:\PCUT\ + pcut.pfx + SHA256 + + + False + + + true + bin\x86\Debug\ + DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP + ;2008 + full + x86 + false + prompt + true + + + bin\x86\Release\ + TRACE;NETFX_CORE;WINDOWS_UWP + true + ;2008 + pdbonly + x86 + false + prompt + true + true + + + true + bin\ARM\Debug\ + DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP + ;2008 + full + ARM + false + prompt + true + + + bin\ARM\Release\ + TRACE;NETFX_CORE;WINDOWS_UWP + true + ;2008 + pdbonly + ARM + false + prompt + true + true + + + true + bin\ARM64\Debug\ + DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP + ;2008 + full + ARM64 + false + prompt + true + true + + + bin\ARM64\Release\ + TRACE;NETFX_CORE;WINDOWS_UWP + true + ;2008 + pdbonly + ARM64 + false + prompt + true + true + + + true + bin\x64\Debug\ + DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP + ;2008 + full + x64 + false + prompt + true + false + + + bin\x64\Release\ + TRACE;NETFX_CORE;WINDOWS_UWP + true + ;2008 + pdbonly + x64 + false + prompt + true + true + + + PackageReference + + + + App.xaml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + CategoryUpsertDialog.xaml + + + MetadataUpsertDialog.xaml + + + AdminCenterPage.xaml + + + CategoriesViewPage.xaml + + + UserGuidePage.xaml + + + ChangePasswordDialog.xaml + + + CutFilesDialog.xaml + + + DataCenterPage.xaml + + + DesignCenterPage.xaml + + + EditPage.xaml + + + FileAddDialog.xaml + + + FileEditDialog.xaml + + + FileManagerPage.xaml + + + LoginPage.xaml + + + MainMenuPage.xaml + + + PortSettingDialog.xaml + + + SvgNestPage.xaml + + + SvgNestSettingDialog.xaml + + + UpsertUserPage.xaml + + + UserListPage.xaml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Designer + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + MSBuild:Compile + Designer + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + MSBuild:Compile + Designer + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + MSBuild:Compile + Designer + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + MSBuild:Compile + Designer + + + MSBuild:Compile + Designer + + + MSBuild:Compile + Designer + + + Designer + MSBuild:Compile + + + + + 8.0.0 + + + 6.2.14 + + + 7.1.3 + + + + + {6c87a9d3-a2e3-41e0-b112-cd1dce45d53c} + Clipper.Core + + + {09abfbb8-78be-4920-8c86-3cba7693076d} + DeepNestLib.Core + + + {01f0f3ea-71de-436c-96b0-934e566bf04f} + Http.Core + + + {71998b3c-e08f-4324-a087-2edeff1e3256} + MinkowskiCpp + + + {C65442D8-797E-4A98-AD7D-1A1068D8020E} + PCUT.Entities + + + + + + + + + + 14.0 + + + + \ No newline at end of file diff --git a/PCUT/PCUT/Package.appxmanifest b/PCUT/PCUT/Package.appxmanifest new file mode 100644 index 0000000..f2dc745 --- /dev/null +++ b/PCUT/PCUT/Package.appxmanifest @@ -0,0 +1,54 @@ + + + + + + + + + + PCUT + ADMINN + Assets\StoreLogo.png + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/PCUT/PCUT/Pages/AdminCenterPage.xaml b/PCUT/PCUT/Pages/AdminCenterPage.xaml new file mode 100644 index 0000000..55ea1c2 --- /dev/null +++ b/PCUT/PCUT/Pages/AdminCenterPage.xaml @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/PCUT/PCUT/Pages/AdminCenterPage.xaml.cs b/PCUT/PCUT/Pages/AdminCenterPage.xaml.cs new file mode 100644 index 0000000..5318e06 --- /dev/null +++ b/PCUT/PCUT/Pages/AdminCenterPage.xaml.cs @@ -0,0 +1,92 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Runtime.InteropServices.WindowsRuntime; +using Windows.ApplicationModel.UserDataTasks; +using Windows.Foundation; +using Windows.Foundation.Collections; +using Windows.UI.Core; +using Windows.UI.Xaml; +using Windows.UI.Xaml.Controls; +using Windows.UI.Xaml.Controls.Primitives; +using Windows.UI.Xaml.Data; +using Windows.UI.Xaml.Input; +using Windows.UI.Xaml.Media; +using Windows.UI.Xaml.Navigation; + +// The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=234238 + +namespace PCUT.Pages +{ + /// + /// An empty page that can be used on its own or navigated to within a Frame. + /// + public sealed partial class AdminCenterPage : Page + { + public AdminCenterPage() + { + this.InitializeComponent(); + } + private string _currentSelectedNavItemTag; + + private void NavigationViewItem_Invoked(NavigationView sender, NavigationViewItemInvokedEventArgs args) + { + var item = args.InvokedItemContainer as NavigationViewItem; + var itemTag = item.Tag.ToString(); + + if (_currentSelectedNavItemTag == itemTag) + { + return; + } + + _currentSelectedNavItemTag = itemTag; + + switch (itemTag) + { + case "Categories": + ContentFrame.Navigate(typeof(CategoriesViewPage)); + break; + case "Files": + ContentFrame.Navigate(typeof(FileManagerPage)); + break; + case "Users": + ContentFrame.Navigate(typeof(UserListPage)); + break; + } + sender.IsPaneOpen = true; + } + + private void AdminCenterPage_BackRequested(object sender, BackRequestedEventArgs e) + { + if (ContentFrame.CanGoBack) + { + ContentFrame.GoBack(); + e.Handled = true; + } + } + + protected override void OnNavigatedTo(NavigationEventArgs e) + { + base.OnNavigatedTo(e); + SystemNavigationManager.GetForCurrentView().AppViewBackButtonVisibility = AppViewBackButtonVisibility.Visible; + SystemNavigationManager.GetForCurrentView().BackRequested += Page_BackRequested; + } + + protected override void OnNavigatedFrom(NavigationEventArgs e) + { + base.OnNavigatedFrom(e); + SystemNavigationManager.GetForCurrentView().BackRequested -= Page_BackRequested; + } + + private void Page_BackRequested(object sender, BackRequestedEventArgs e) + { + Frame rootFrame = this.Frame; + if (rootFrame.CanGoBack) + { + rootFrame.GoBack(); + e.Handled = true; + } + } + } +} diff --git a/PCUT/PCUT/Pages/CategoriesManagement/CategoriesViewPage.xaml b/PCUT/PCUT/Pages/CategoriesManagement/CategoriesViewPage.xaml new file mode 100644 index 0000000..dcec63b --- /dev/null +++ b/PCUT/PCUT/Pages/CategoriesManagement/CategoriesViewPage.xaml @@ -0,0 +1,236 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/PCUT/PCUT/Pages/DesignCenter/CutFilesDialog.xaml.cs b/PCUT/PCUT/Pages/DesignCenter/CutFilesDialog.xaml.cs new file mode 100644 index 0000000..4b53ac9 --- /dev/null +++ b/PCUT/PCUT/Pages/DesignCenter/CutFilesDialog.xaml.cs @@ -0,0 +1,207 @@ +using PCUT.Extensions; +using PCUT.Factories; +using PCUT.ViewModels; +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.IO; +using System.IO.Ports; +using System.Linq; +using System.Runtime.InteropServices.WindowsRuntime; +using System.Threading; +using System.Threading.Tasks; +using System.Xml.Linq; +using Windows.Foundation; +using Windows.Foundation.Collections; +using Windows.UI.Popups; +using Windows.UI.Xaml; +using Windows.UI.Xaml.Controls; +using Windows.UI.Xaml.Controls.Primitives; +using Windows.UI.Xaml.Data; +using Windows.UI.Xaml.Input; +using Windows.UI.Xaml.Media; +using Windows.UI.Xaml.Navigation; + +// The Content Dialog item template is documented at https://go.microsoft.com/fwlink/?LinkId=234238 + +namespace PCUT.Pages +{ + public sealed partial class CutFilesDialog : ContentDialog + { + private SvgData _svgData => SvgData.Instance; + public ImageViewModel DisplayModel { get; set; } + private readonly string _portName; + private readonly PortSettingViewModel _portSettings; + private readonly DesignCenterViewModel _designCenterViewModel; + + public CutFilesDialog( + string portName, + PortSettingViewModel portSetting, + DesignCenterViewModel designCenterViewModel) + { + this.InitializeComponent(); + DisplayModel = new ImageViewModel(); + _portName = portName; + _portSettings = portSetting; + _designCenterViewModel = designCenterViewModel; + StartButton.IsEnabled = !(portName is null); + } + + private Task _printTask; + private void ContentDialog_Opened(ContentDialog sender, ContentDialogOpenedEventArgs args) + { + var data = _designCenterViewModel.UseOrigin ? _svgData.Data : _svgData.NestedData; + PreviewWidthDisplay.Text = Math.Ceiling(_designCenterViewModel.UseOrigin ? _svgData.OriginWidth.Value : _svgData.NestedWidth.Value).ToString(); + PreviewHeightDisplay.Text = Math.Ceiling(_designCenterViewModel.UseOrigin ? _svgData.OriginHeight.Value : _svgData.NestedHeight.Value).ToString(); + DisplayModel.SetSource(data); + } + + private void MainScroll_Loading(FrameworkElement sender, object args) + { + var borderRatio = MainColumnDefinition.ActualWidth / PreviewRowDefinition.ActualHeight; + var width = Math.Ceiling(_designCenterViewModel.UseOrigin ? _svgData.OriginWidth.Value : _svgData.NestedWidth.Value); + var height = Math.Ceiling(_designCenterViewModel.UseOrigin ? _svgData.OriginHeight.Value : _svgData.NestedHeight.Value); + var ratio = width / height; + if (ratio < borderRatio) + ((ComponentStyle)Resources["previewStyle"]).SetSize(PreviewRowDefinition, ratio); + else + ((ComponentStyle)Resources["previewStyle"]).SetSize(MainColumnDefinition, ratio); + } + + private CancellationTokenSource _cancellationTokenSource; + private async Task Print(XDocument nested) + { + if (nested == null) + { + CancelButton.Content = "Done"; + StartButton.IsEnabled = true; + return; + } + + _cancellationTokenSource = new CancellationTokenSource(); + using (var serialPort = new SerialPort(_portName, _portSettings.BaudRate) + { + DataBits = _portSettings.Databits, + Parity = _portSettings.ParityList[_portSettings.SelectedParity], + StopBits = _portSettings.StopbitsList[_portSettings.SelectedStopbits] + }) + { + var errorMessage = string.Empty; + try + { + await Task.Factory.StartNew(() => + { + var data = nested.ToHPGL( + (_svgData.OriginWidth.Value, _svgData.OriginHeight.Value), + (_designCenterViewModel.Width, _designCenterViewModel.Height), + _portSettings.Speed); + serialPort.Open(); + Task waitTask = Task.CompletedTask; + foreach (var (path, waitTime) in data) + { + _cancellationTokenSource.Token.ThrowIfCancellationRequested(); + waitTask.Wait(); + try + { + serialPort.Write(path); + } + catch + { + throw new TimeoutException(); + } + waitTask = Task.Delay(waitTime, _cancellationTokenSource.Token); + } + }, _cancellationTokenSource.Token, TaskCreationOptions.LongRunning, TaskScheduler.Default); + } + catch (Exception ex) + { + if (ex is AggregateException) + ex = ex.InnerException; + + switch (ex) + { + case UnauthorizedAccessException unauthorizedAccessException: + errorMessage = "Access Denied. Port is currently in used."; + break; + case ArgumentOutOfRangeException argumentOutOfRangeException: + errorMessage = "Wrong port settings. Please verify settings value is valid."; + break; + case IOException iOException: + errorMessage = "Port is in invalid state or port settings is not matched. Please check port connection and settings"; + break; + case InvalidOperationException invalidOperationException: + errorMessage = "Port is currently in used."; + break; + case TimeoutException timeoutException: + errorMessage = "Failed to send data to port."; + break; + } + } + finally + { + try + { + serialPort.Close(); + Task.Delay(1000).Wait(); + } + catch + { + } + } + + if (!string.IsNullOrEmpty(errorMessage)) + { + DispatchAsync(async () => + { + var dialog = new MessageDialog(errorMessage); + await dialog.ShowAsync(); + }); + } + } + _printTask = null; + StartButton.IsEnabled = true; + CancelButton.Content = "Done"; + } + + private async void DispatchAsync(Action action) + { + await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () => action.Invoke()); + } + + private void MainScroll_ManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs e) + { + var (offsetX, offsetY) = e.Delta.CalculateTranslation(e.Velocities); + var scrollViewer = sender as ScrollViewer; + _ = scrollViewer.ChangeView(scrollViewer.HorizontalOffset - offsetX, scrollViewer.VerticalOffset - offsetY, scrollViewer.ZoomFactor); + } + + private async void CancelButton_Click(object sender, RoutedEventArgs e) + { + CancelButton.IsEnabled = false; + StartButton.IsEnabled = false; + CloseButton.IsEnabled = false; + _cancellationTokenSource?.Cancel(); + if (_printTask != null) + { + await _printTask; + CancelButton.IsEnabled = true; + StartButton.IsEnabled = true; + CloseButton.IsEnabled = true; + if (sender == CloseButton) + Hide(); + } + else + { + Hide(); + } + } + + private void StartButton_Click(object sender, RoutedEventArgs e) + { + StartButton.IsEnabled = false; + CancelButton.Content = "Cancel"; + var data = _designCenterViewModel.UseOrigin ? _svgData.Data : _svgData.NestedData; + _printTask = Print(data); + } + } +} diff --git a/PCUT/PCUT/Pages/DesignCenter/DesignCenterPage.xaml b/PCUT/PCUT/Pages/DesignCenter/DesignCenterPage.xaml new file mode 100644 index 0000000..aa6e72c --- /dev/null +++ b/PCUT/PCUT/Pages/DesignCenter/DesignCenterPage.xaml @@ -0,0 +1,234 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/PCUT/PCUT/Pages/DesignCenter/DesignCenterPage.xaml.cs b/PCUT/PCUT/Pages/DesignCenter/DesignCenterPage.xaml.cs new file mode 100644 index 0000000..0dec773 --- /dev/null +++ b/PCUT/PCUT/Pages/DesignCenter/DesignCenterPage.xaml.cs @@ -0,0 +1,196 @@ +using Http.Core.Contexts; +using PCUT.ViewModels; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Runtime.InteropServices.WindowsRuntime; +using System.Threading; +using System.Threading.Tasks; +using Windows.Devices.Enumeration; +using Windows.Devices.SerialCommunication; +using Windows.Foundation; +using Windows.Foundation.Collections; +using Windows.Graphics.Display; +using Windows.UI.Core; +using Windows.UI.Popups; +using Windows.UI.ViewManagement; +using Windows.UI.Xaml; +using Windows.UI.Xaml.Controls; +using Windows.UI.Xaml.Controls.Primitives; +using Windows.UI.Xaml.Data; +using Windows.UI.Xaml.Input; +using Windows.UI.Xaml.Media; +using Windows.UI.Xaml.Navigation; +using static PCUT.Pages.DataCenterPage; + +// The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=234238 + +namespace PCUT.Pages +{ + /// + /// An empty page that can be used on its own or navigated to within a Frame. + /// + public sealed partial class DesignCenterPage : Page + { + private SvgData _svgData => SvgData.Instance; + DesignCenterViewModel viewModel { get; set; } + PortSettingViewModel SettingModel { get; set; } + public DesignCenterPage() + { + this.InitializeComponent(); + viewModel = new DesignCenterViewModel(); + SettingModel = new PortSettingViewModel(); + this.DataContext = viewModel; + + var isPermittedEdit = UserContext.Instance.IsPermittedEdit; + WidthInput.IsEnabled = isPermittedEdit; + HeightInput.IsEnabled = isPermittedEdit; + HeightSelector.IsEnabled = !isPermittedEdit; + if (isPermittedEdit) + { + HeightInput.Visibility = Visibility.Visible; + HeightSelector.Visibility = Visibility.Collapsed; + } + else + { + HeightInput.Visibility = Visibility.Collapsed; + HeightSelector.Visibility = Visibility.Visible; + } + } + + protected async override void OnNavigatedTo(NavigationEventArgs e) + { + base.OnNavigatedTo(e); + string itemId = null; + if (e.Parameter is string id && !string.IsNullOrEmpty(id)) + { + itemId = id; + if (itemId != _svgData.ItemId) + _svgData.SetData(null); + } + else if (_svgData.Data != null) + { + itemId = _svgData.ItemId; + } + + if (!string.IsNullOrEmpty(itemId)) + { + var loadSuccess = await viewModel.GetCdrFileAsync(itemId); + if (!loadSuccess) + { + var messageDialog = new MessageDialog("File doesn't exist!"); + await messageDialog.ShowAsync(); + return; + } + NavigateContentFrame(typeof(EditPage), viewModel); + } + var deviceInfo = await GetPortInfos(); + foreach (var info in deviceInfo) + viewModel.Ports.Add(info); + if (deviceInfo.Any()) + viewModel.SelectedPortIndex = 0; + } + + protected override void OnNavigatedFrom(NavigationEventArgs e) + { + base.OnNavigatedFrom(e); + //SvgData.Instance.SetData(null); + } + + private void ComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e) + { + CuttingMachines.Text = viewModel.SelectedDeviceName; + SettingModel.LoadSetting(viewModel.SelectedPortName); + } + + private void SortFiles_Button(object sender, RoutedEventArgs e) + { + NavigateContentFrame(typeof(SvgNestPage), viewModel); + } + + private void NavigateContentFrame(Type pageType, object param = null, bool isGoBack = false) + { + var currentPageType = ContentFrame.Content?.GetType(); + if ((!isGoBack || currentPageType != null) && currentPageType != pageType) + { + BackButton.Visibility = pageType == typeof(EditPage) ? Visibility.Collapsed : Visibility.Visible; + ContentFrame.Navigate(pageType, param); + } + } + + private async void CutFiles_Button(object sender, RoutedEventArgs e) + { + //if (_svgData.NestedData == null) + // NavigateContentFrame(typeof(SvgNestPage), viewModel); + //else + //{ + try + { + string selectedPortName = viewModel.SelectedPortName; + var dialog = new CutFilesDialog(selectedPortName, SettingModel, viewModel); + await dialog.ShowAsync(); + } + catch + { + + } + //} + } + + private void Back_Click(object sender, RoutedEventArgs e) + { + NavigateContentFrame(typeof(EditPage), viewModel, isGoBack: true); + } + + private async Task> GetPortInfos() + { + var infos = await DeviceInformation.FindAllAsync(SerialDevice.GetDeviceSelector()); + if (infos != null && infos.Any()) + { + var portInfos = new List(); + foreach (var info in infos) + { + using (var deviceInfo = await SerialDevice.FromIdAsync(info.Id)) + { + if (deviceInfo != null) + { + portInfos.Add(new PortInfo(deviceInfo.PortName, info.Name)); + } + } + } + return portInfos; + } + return Array.Empty(); + } + + private async void SettingPort_Click(object sender, RoutedEventArgs e) + { + try + { + var categoryEditDialog = new PortSettingDialog(SettingModel); + await categoryEditDialog.ShowAsync(); + SettingModel.SaveSetting(viewModel.SelectedPortName); + } + catch + { + + } + } + + private async void Refresh_Click(object sender, RoutedEventArgs e) + { + var deviceInfo = await GetPortInfos(); + viewModel.Ports.Clear(); + foreach (var info in deviceInfo) + viewModel.Ports.Add(info); + if (deviceInfo.Any()) + viewModel.SelectedPortIndex = 0; + } + + private void TextBox_BeforeTextChanging(TextBox sender, TextBoxBeforeTextChangingEventArgs args) + { + args.Cancel = args.NewText.Any(ch => !char.IsDigit(ch) && ch != '.'); + } + } +} diff --git a/PCUT/PCUT/Pages/DesignCenter/EditPage.xaml b/PCUT/PCUT/Pages/DesignCenter/EditPage.xaml new file mode 100644 index 0000000..74a2468 --- /dev/null +++ b/PCUT/PCUT/Pages/DesignCenter/EditPage.xaml @@ -0,0 +1,112 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/PCUT/PCUT/Pages/DesignCenter/EditPage.xaml.cs b/PCUT/PCUT/Pages/DesignCenter/EditPage.xaml.cs new file mode 100644 index 0000000..eead20a --- /dev/null +++ b/PCUT/PCUT/Pages/DesignCenter/EditPage.xaml.cs @@ -0,0 +1,263 @@ +using System; +using System.ComponentModel; +using System.Linq; +using System.Runtime.InteropServices.WindowsRuntime; +using System.Threading; +using System.Threading.Tasks; +using System.Xml.Linq; +using Http.Core.Contexts; +using PCUT.Extensions; +using PCUT.Factories; +using PCUT.ViewModels; +using Windows.UI.Xaml; +using Windows.UI.Xaml.Controls; +using Windows.UI.Xaml.Input; +using Windows.UI.Xaml.Navigation; + +// The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=234238 + +namespace PCUT.Pages +{ + /// + /// An empty page that can be used on its own or navigated to within a Frame. + /// + public sealed partial class EditPage : Page + { + private SvgData _svgData => SvgData.Instance; + private LoadingModel LoadingModel { get; set; } + public ImageViewModel PreviewModel { get; set; } + public ComponentImageModel ComponentModel { get; set; } + private DesignCenterViewModel _designCenterModel; + + public EditPage() + { + this.InitializeComponent(); + LoadingModel = new LoadingModel(); + PreviewModel = new ImageViewModel(); + ComponentModel = new ComponentImageModel(); + LoadingModel.PropertyChanged += AllImageLoaded; + } + + protected override async void OnNavigatedTo(NavigationEventArgs e) + { + _designCenterModel = e.Parameter as DesignCenterViewModel; + _designCenterModel.UseOrigin = true; + if (_svgData.Data != null && _designCenterModel != null && _svgData.FileId != _designCenterModel?.FileId) + _svgData.SetData(null); + + int dataUnloaded = 0; + if (_svgData.Data == null) + { + if (_designCenterModel == null) + { + _svgData.SetData(null); + return; + } + dataUnloaded = 1; + XDocument data; double width; double height; + using (var fileStream = await FileFactory.GetFileAsync(_designCenterModel.FileId)) + { + if (fileStream == null) + { + LoadingRing.IsActive = false; + LoadingRing.Visibility = Visibility.Collapsed; + await ShowDialog("File Error!", "File has been deleted or its data was corrupted!\nPlease contact admin to re-upload the file"); + return; + } + (data, width, height) = await FileFactory.PreProcessSvgAsync(fileStream); + } + var components = data.SplitDocument(width, height).ToArray(); + data.Root.Add(XElement.Parse($"")); + + _svgData.SetData(data, width, height); + _svgData.ItemId = _designCenterModel.ItemId; + _svgData.FileId = _designCenterModel.FileId; + foreach (var (id, deleted, component, boundWidth, boundHeight) in components) + _svgData.AddComponent(id, deleted, component, boundWidth, boundHeight); + } + + if (UserContext.Instance.IsPermittedEdit) + { + _designCenterModel.Width = _svgData.OriginWidth.Value; + _designCenterModel.Height = _svgData.OriginHeight.Value; + } + _designCenterModel.PropertyChanged += UpdateSizeChanged; + + if (_svgData.Data != null) + { + LoadingModel.SetCount(_svgData.ComponentCount + dataUnloaded); + PreviewModel.SetSource(_svgData.Data); + foreach (var (id, deleted, component) in _svgData.ComponentData) + ComponentModel.AddSource(id, deleted, component); + } + if (!UserContext.Instance.IsPermittedEdit) + _designCenterModel.SelectedHeightIndex = 0; + } + + protected override void OnNavigatedFrom(NavigationEventArgs e) + { + //if (e.SourcePageType != typeof(SvgNestPage)) + // _svgData.SetData(null); + + if (_designCenterModel != null) + _designCenterModel.PropertyChanged -= UpdateSizeChanged; + } + + private static readonly object _boundingSizeLock = new object(); + private void UpdateSizeChanged(object sender, PropertyChangedEventArgs e) + { + if (e.PropertyName == nameof(DesignCenterViewModel.Width)) + { + var width = (sender as DesignCenterViewModel).Width; + _svgData.SetResult(null); + _designCenterModel.MinSize = 0; + _ = HandleSizeChangedAsync(width: width); + } + else if (e.PropertyName == nameof(DesignCenterViewModel.Height)) + { + var height = (sender as DesignCenterViewModel).Height; + _svgData.SetResult(null); + _designCenterModel.MinSize = 0; + _ = HandleSizeChangedAsync(height: height); + } + } + + private async Task HandleSizeChangedAsync(double? width = null, double? height = null) + { + if (Monitor.TryEnter(_boundingSizeLock, 100)) + { + try + { + var bound = _svgData.Data.GetDescendantById("PCUT_BOUNDING"); + if (width != null) + { + bound.SetAttributeValue("width", width.Value); + } + if (height != null) + { + bound.SetAttributeValue("height", height.Value); + } + _svgData.CleanUpContext(); + await PreviewModel.Source.LoadSvgAsync(_svgData.Data); + } + finally + { + Monitor.Exit(_boundingSizeLock); + } + } + } + + private void MainScroll_Loading(FrameworkElement sender, object args) + { + ((ComponentStyle)Resources["previewStyle"]).SetSize(PreviewRowDefinition, PreviewColumnDefinition); + } + + private void ComponentPreview_Loading(FrameworkElement sender, object args) + { + ((ComponentStyle)Resources["componentStyle"]).SetSize(ComponentColumnDefinition, rate: 3); + } + + private void Image_Loaded(object sender, RoutedEventArgs e) + { + LoadingModel.DecreaseCount(); + } + + private void AllImageLoaded(object sender, PropertyChangedEventArgs e) + { + LoadingRing.IsActive = false; + LoadingRing.Visibility = Visibility.Collapsed; + } + + private void MainScroll_ManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs e) + { + var (offsetX, offsetY) = e.Delta.CalculateTranslation(e.Velocities); + var scrollViewer = sender as ScrollViewer; + _ = scrollViewer.ChangeView(scrollViewer.HorizontalOffset - offsetX, scrollViewer.VerticalOffset - offsetY, scrollViewer.ZoomFactor); + } + + private void MainPreviewRefresh_Click(object sender, RoutedEventArgs e) + { + MainScroll.ChangeView(0, 0, 1); + } + + private void MainPreviewSelectAll_Click(object sender, RoutedEventArgs e) + { + foreach (var component in ComponentModel.ComponentList.Where(x => x.Deleted)) + { + _svgData.Data.RestoreById(component.Id); + component.Deleted = false; + } + PreviewModel.SetSource(_svgData.Data); + } + + private void MainPreviewDeleteAll_Click(object sender, RoutedEventArgs e) + { + foreach (var component in ComponentModel.ComponentList.Where(x => !x.Deleted)) + { + _svgData.Data.HideById(component.Id); + component.Deleted = true; + } + PreviewModel.SetSource(_svgData.Data); + } + + private void Image_Tapped(object sender, TappedRoutedEventArgs e) + { + var image = (sender as FrameworkElement); + var id = image.Tag as string; + + var component = ComponentModel.ComponentList.FirstOrDefault(x => x.Id == id); + if (component == null) + return; + + if (component.Deleted) + RestoreComponent(id, component); + else + DeleteComponent(id, component); + } + + private void ComponentDelete(object sender, RoutedEventArgs e) + { + var item = sender as FrameworkElement; + var id = item.Tag as string; + + DeleteComponent(id, item.DataContext as ComponentImageSource); + } + + private void ComponentRestore(object sender, RoutedEventArgs e) + { + var item = sender as FrameworkElement; + var id = item.Tag as string; + + RestoreComponent(id, item.DataContext as ComponentImageSource); + } + + private void DeleteComponent(string id, ComponentImageSource component) + { + if (component == null) return; + _svgData.Data.HideById(id); + component.Deleted = true; + PreviewModel.SetSource(_svgData.Data); + } + + private void RestoreComponent(string id, ComponentImageSource component) + { + if (component == null) return; + _svgData.Data.RestoreById(id); + component.Deleted = false; + PreviewModel.SetSource(_svgData.Data); + } + + private async Task ShowDialog(string title, string content) + { + ContentDialog dialog = new ContentDialog + { + Title = title, + Content = content, + CloseButtonText = "OK" + }; + dialog.CloseButtonStyle = Application.Current.Resources["CloseDialogButton"] as Style; + + await dialog.ShowAsync(); + } + } +} diff --git a/PCUT/PCUT/Pages/DesignCenter/PortSettingDialog.xaml b/PCUT/PCUT/Pages/DesignCenter/PortSettingDialog.xaml new file mode 100644 index 0000000..77aa409 --- /dev/null +++ b/PCUT/PCUT/Pages/DesignCenter/PortSettingDialog.xaml @@ -0,0 +1,82 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/PCUT/PCUT/Pages/DesignCenter/PortSettingDialog.xaml.cs b/PCUT/PCUT/Pages/DesignCenter/PortSettingDialog.xaml.cs new file mode 100644 index 0000000..38b0b0e --- /dev/null +++ b/PCUT/PCUT/Pages/DesignCenter/PortSettingDialog.xaml.cs @@ -0,0 +1,38 @@ +using PCUT.ViewModels; +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.IO; +using System.IO.Ports; +using System.Linq; +using System.Runtime.InteropServices.WindowsRuntime; +using Windows.Foundation; +using Windows.Foundation.Collections; +using Windows.UI.Xaml; +using Windows.UI.Xaml.Controls; +using Windows.UI.Xaml.Controls.Primitives; +using Windows.UI.Xaml.Data; +using Windows.UI.Xaml.Input; +using Windows.UI.Xaml.Media; +using Windows.UI.Xaml.Navigation; + +// The Content Dialog item template is documented at https://go.microsoft.com/fwlink/?LinkId=234238 + +namespace PCUT.Pages +{ + public sealed partial class PortSettingDialog : ContentDialog + { + private PortSettingViewModel ViewModel { get; set; } + + public PortSettingDialog(PortSettingViewModel viewModel) + { + this.InitializeComponent(); + ViewModel = viewModel; + } + + private void TextBox_BeforeTextChanging(TextBox sender, TextBoxBeforeTextChangingEventArgs args) + { + args.Cancel = args.NewText.Any(ch => !char.IsDigit(ch)); + } + } +} diff --git a/PCUT/PCUT/Pages/DesignCenter/SvgNestPage.xaml b/PCUT/PCUT/Pages/DesignCenter/SvgNestPage.xaml new file mode 100644 index 0000000..a66b0f3 --- /dev/null +++ b/PCUT/PCUT/Pages/DesignCenter/SvgNestPage.xaml @@ -0,0 +1,68 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/PCUT/PCUT/Pages/DesignCenter/SvgNestPage.xaml.cs b/PCUT/PCUT/Pages/DesignCenter/SvgNestPage.xaml.cs new file mode 100644 index 0000000..abf1234 --- /dev/null +++ b/PCUT/PCUT/Pages/DesignCenter/SvgNestPage.xaml.cs @@ -0,0 +1,425 @@ +using DeepNestLib; +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices.WindowsRuntime; +using System.Threading; +using System.Threading.Tasks; +using System.Xml.Linq; +using PCUT.Extensions; +using PCUT.DeepNestApi; +using PCUT.ViewModels; +using Windows.UI.Xaml; +using Windows.UI.Xaml.Controls; +using Windows.UI.Xaml.Input; +using Windows.UI.Xaml.Media; +using Windows.UI.Xaml.Media.Imaging; +using Windows.UI.Xaml.Navigation; +using System.ComponentModel; + +// The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=234238 + +namespace PCUT.Pages +{ + /// + /// An empty page that can be used on its own or navigated to within a Frame. + /// + public sealed partial class SvgNestPage : Page + { + private SvgData _svgData => SvgData.Instance; + private SvgNestSettings _settings => SvgNestSettings.Instance; + private DesignCenterViewModel _designCenterModel; + public ImageViewModel PreviewModel { get; set; } + public NestingProgressModel ProgressModel { get; set; } + private ConcurrentQueue<(XDocument Svg, double Width, double Height, double MaterialUtilization)> NestedResult { get; set; } + = new ConcurrentQueue<(XDocument, double, double, double)>(); + public SvgNestPage() + { + this.InitializeComponent(); + PreviewModel = new ImageViewModel(); + ProgressModel = new NestingProgressModel(); + DeepNestApi.Background.UseParallel = true; + _ = _settings; + } + + protected override void OnNavigatedTo(NavigationEventArgs e) + { + if (_svgData.Data == null) + return; + + _designCenterModel = e.Parameter as DesignCenterViewModel; + _designCenterModel.PropertyChanged += UpdateSizeChanged; + DeepNestApi.Background.displayProgress = (progress) => DispatchAsync(DisplayNestingProgress, progress); + _ = Initialize(); + } + + protected override void OnNavigatedFrom(NavigationEventArgs e) + { + //if (e.SourcePageType != typeof(EditPage)) + // _svgData.SetData(null); + StopNesting(); + _designCenterModel.PropertyChanged -= UpdateSizeChanged; + DeepNestApi.Background.displayProgress = null; + } + + private static readonly object _boundingSizeLock = new object(); + private void UpdateSizeChanged(object sender, PropertyChangedEventArgs e) + { + if (e.PropertyName == nameof(DesignCenterViewModel.Width)) + { + var model = sender as DesignCenterViewModel; + StopNesting(); + _svgData.SetResult(null); + _designCenterModel.MinSize = 0; + _ = HandleSizeChangedAsync(width: model.Width); + } + else if (e.PropertyName == nameof(DesignCenterViewModel.Height)) + { + var model = sender as DesignCenterViewModel; + StopNesting(); + _svgData.SetResult(null); + _designCenterModel.MinSize = 0; + _ = HandleSizeChangedAsync(height: model.Height); + } + } + + private async Task HandleSizeChangedAsync(double? width = null, double? height = null) + { + if (Monitor.TryEnter(_boundingSizeLock, 100)) + { + try + { + var bound = _svgData.Data.GetDescendantById("PCUT_BOUNDING"); + if (width != null) + { + bound.SetAttributeValue("width", width.Value); + } + if (height != null) + { + bound.SetAttributeValue("height", height.Value); + } + PreviewModel.ShowDefault(); + _currentResult = null; + _svgData.CleanUpContext(); + await PreviewModel.Source.LoadSvgAsync(_svgData.Data); + } + finally + { + Monitor.Exit(_boundingSizeLock); + } + } + } + + private void MainScroll_Loading(FrameworkElement sender, object args) + { + var borderRatio = PreviewColumnDefinition.ActualWidth / PreviewRowDefinition.ActualHeight; + var ratio = _svgData.OriginWidth.Value / _svgData.OriginHeight.Value; + if (ratio < borderRatio) + ((ComponentStyle)Resources["previewStyle"]).SetSize(PreviewRowDefinition, ratio); + else + ((ComponentStyle)Resources["previewStyle"]).SetSize(PreviewColumnDefinition, ratio); + } + + private void MainPreview_ImageOpened(object sender, RoutedEventArgs e) + { + HideProgressRing(); + } + + private void MainScroll_ManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs e) + { + var (offsetX, offsetY) = e.Delta.CalculateTranslation(e.Velocities); + var scrollViewer = sender as ScrollViewer; + _ = scrollViewer.ChangeView(scrollViewer.HorizontalOffset - offsetX, scrollViewer.VerticalOffset - offsetY, scrollViewer.ZoomFactor); + } + + private void MainPreviewRefresh_Click(object sender, RoutedEventArgs e) + { + MainScroll.ChangeView(0, 0, 1); + } + + private void MainPreviewDefault_Click(object sender, RoutedEventArgs e) + { + PreviewModel.ShowDefault(); + MainScroll.ChangeView(0, 0, 1); + _designCenterModel.UseOrigin = true; + } + + private void NestStart_Click(object sender, RoutedEventArgs e) + { + _ = StartAsync(StartNesting); + } + + private void NestStop_Click(object sender, RoutedEventArgs e) + { + StopNesting(); + } + + private void NestResult_Click(object sender, RoutedEventArgs e) + { + ShowNestedResult(); + } + + private async void NestSettings_Click(object sender, RoutedEventArgs e) + { + var nestSettingDialog = new SvgNestSettingDialog(); + await nestSettingDialog.ShowAsync(); + } + + // private nesting logic + //private double _maxOfMinSize; + //private double _totalArea; + private async Task Initialize() + { + await StartAsync(LoadDetail); + _svgData.ComputeDetailBounds(); + PreviewModel.SetSource(_svgData.Data); + } + + private void LoadDetail() + { + if (_svgData.NestingContext == null) + { + if (_svgData.ComponentDetails == null || !_svgData.ComponentDetails.Any()) + { + var doc = new XDocument(_svgData.Data); + doc.SetSize(_svgData.OriginWidth.Value, _svgData.OriginHeight.Value); + doc.RemoveHidden(); + var (details, scale) = SvgParser.LoadSvg(doc, true); + foreach (var detail in details) + _svgData.AddDetail(detail); + _svgData.DetailScaleFactor = scale; + } + } + if (_svgData.NestedData != null) + { + DispatchAsync(UpdateCurrentSource); + } + } + + private List _sheets => _svgData.NestingContext.Sheets; + private List _polygons => _svgData.NestingContext.Polygons; + private void StartNesting() + { + DispatchAsync(ShowProgressRing); + + var requireStartNest = _svgData.NestingContext == null; + if (requireStartNest) + { + var totalArea = 0d; + var maxOfMinSize = 0d; + foreach (var (cWidth, cHeight) in _svgData.DetailBounds) + { + var minSize = Math.Ceiling(Math.Min(cWidth, cHeight)); + if (maxOfMinSize < minSize) + maxOfMinSize = minSize; + totalArea += cWidth * cHeight; + } + + var width = _designCenterModel.Width; + var height = _designCenterModel.Height; + + // check if width/height (which one is smaller) can accomodate the largest component, based on its smaller dimension. + if (width < height) + { + if (width < maxOfMinSize) + width = maxOfMinSize; + + if (totalArea > width * height) + height = Math.Ceiling(totalArea / width); + } + else + { + if (height < maxOfMinSize) + height = maxOfMinSize; + + if (totalArea > width * height) + width = Math.Ceiling(totalArea / height); + } + + _svgData.NewSheetInfo(width, height); + _svgData.NestingContext = new NestingContext(); + int src = 0; + if (_svgData.SheetInfo != null) + { + src = _svgData.NestingContext.GetNextSheetSource(); + for (int i = 0; i < _svgData.SheetInfo.Quantity; i++) + { + var ns = DeepNestApi.Background.clone(_svgData.SheetInfo.Nfp); + Sheet sheet = new Sheet(); + sheet.Points = ns.Points; + sheet.children = ns.children; + _sheets.Add(sheet); + sheet.Width = sheet.WidthCalculated; + sheet.Height = sheet.HeightCalculated; + sheet.source = src; + } + } + + _svgData.NestingContext.ReorderSheets(); + _svgData.DxfCache.Clear(); + + src = 0; + if (_svgData.ComponentDetails != null && _svgData.ComponentDetails.Any()) + { + foreach (var detail in _svgData.ComponentDetails) + { + var t1 = detail.Outers.Where(z => z.Tag is object[]).Select(z => z.Tag as object[]).SelectMany(z => z).ToArray(); + foreach (var outter in detail.Outers) + { + t1 = t1.Union(outter.Childrens.Where(z => z.Tag is object[]).Select(z => z.Tag as object[]).SelectMany(z => z).ToArray()).ToArray(); + } + _svgData.DxfCache.Add(detail.Name, t1); + } + foreach (var detail in _svgData.ComponentDetails) + { + _svgData.NestingContext.ImportFromRawDetail(detail, src); + src++; + } + } + } + + if (_sheets.Count == 0 || _polygons.Count == 0) + { + DispatchAsync(HideProgressRing); + DispatchAsync(StopNesting); + return; + } + + //menu.SetTab(menu.NestTab); + _svgData.NestingContext.ReorderSheets(); + RunDeepnest(_settings.MaxNumberOfRun, requireStartNest); + } + + private ImageSource _currentResult; + + private readonly ConcurrentQueue _runQueue = new ConcurrentQueue(); + private static readonly object _runCommand = new object(); + private void RunDeepnest(int maxNumberOfRun, bool requiredStartNest) + { + while (maxNumberOfRun > 0) + { + _runQueue.Enqueue(_runCommand); + maxNumberOfRun--; + } + DispatchAsync(HideProgressRing); + DispatchAsync(() => ProgressModel.Running = true); + if (requiredStartNest) + _svgData.NestingContext.StartNest(); + + var cancellationTokenSource = new CancellationTokenSource(TimeSpan.FromMinutes(_settings.MaxRuntimeInMinute)); + while (!cancellationTokenSource.Token.IsCancellationRequested) + { + if (!_runQueue.TryDequeue(out _)) + break; + + double materialUtilization = _svgData.MaterialUtilization; + DispatchAsync(DisplayNestingProgress, 0.0d); + _svgData.NestingContext.NestIterate(); + DispatchAsync(DisplayNestingProgress, 1.0d); + + if (_polygons.Count(z => z.fitted) == _svgData.DetailCount && _svgData.NestingContext.MaterialUtilization <= materialUtilization) + { + materialUtilization = _svgData.NestingContext.MaterialUtilization; + var (doc, width, height) = Export(); + NestedResult.Enqueue((doc, width, height, materialUtilization)); + DispatchAsync(UpdatePreview); + } + } + + if (ProgressModel?.Running ?? false) + DispatchAsync(StopNesting); + } + + private void DisplayNestingProgress(double progress) + { + if (ProgressModel != null) + ProgressModel.Progress = Math.Floor(progress * 100); + } + + private void UpdatePreview() + { + if (NestedResult.TryDequeue(out var result)) + { + _svgData.SetResult(result.Svg, result.Width, result.Height, result.MaterialUtilization); + if (ProgressModel?.Running ?? false) + { + var minSize = Math.Min(_svgData.SheetInfo.Width, _svgData.SheetInfo.Height); + if (minSize > Math.Min(_designCenterModel.Width, _designCenterModel.Height)) + _designCenterModel.MinSize = Math.Ceiling(minSize); + else + _designCenterModel.MinSize = 0; + + var switchToResult = _currentResult == null && PreviewModel.DefaultMode; + UpdateCurrentSource(); + if (switchToResult) + ShowNestedResult(); + } + } + } + + private void UpdateCurrentSource() + { + if (_currentResult == null) + _currentResult = new SvgImageSource(); + _ = _currentResult.LoadSvgAsync(_svgData.NestedData); + } + + private void ShowNestedResult() + { + PreviewModel.SetSource(_currentResult); + _designCenterModel.UseOrigin = false; + } + + private void StopNesting() + { + if (ProgressModel != null) + ProgressModel.Running = false; + _runQueue.Clear(); + } + + private void ShowProgressRing() + { + LoadingRing.IsActive = true; + LoadingRing.Visibility = Visibility.Visible; + } + + private void HideProgressRing() + { + LoadingRing.IsActive = false; + LoadingRing.Visibility = Visibility.Collapsed; + } + + private (XDocument NestedDoc, double Width, double Height) Export() + { + var polygons = _polygons.Where(x => x.fitted).ToArray(); + foreach (var item in polygons) + { + item.Tag = _svgData.DxfCache[item.Name]; + } + var (nestedDoc, nestedWidth, nestedHeight) = SvgParser.Export(polygons); + var width = _svgData.SheetInfo.Width; + var height = _svgData.SheetInfo.Height; + var viewBox = _svgData.OriginViewBox.GetViewBoxData(); + nestedDoc.Root.SetAttributeValue("viewBox", $"{viewBox.MinX - 100} {viewBox.MinY - 100} {nestedWidth + 100} {nestedHeight + 100}"); + nestedDoc.Root.Add(XElement.Parse($"")); + nestedDoc.Root.Add(XElement.Parse($"")); + return (nestedDoc, nestedWidth, nestedHeight); + } + + private Task StartAsync(Action action) + { + return Task.Factory.StartNew(action, TaskCreationOptions.LongRunning); + } + + private async void DispatchAsync(Action action) + { + await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () => action.Invoke()); + } + + private async void DispatchAsync(Action action, T param) + { + await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () => action.Invoke(param)); + } + } +} diff --git a/PCUT/PCUT/Pages/DesignCenter/SvgNestSettingDialog.xaml b/PCUT/PCUT/Pages/DesignCenter/SvgNestSettingDialog.xaml new file mode 100644 index 0000000..50186a8 --- /dev/null +++ b/PCUT/PCUT/Pages/DesignCenter/SvgNestSettingDialog.xaml @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/PCUT/PCUT/Pages/DesignCenter/SvgNestSettingDialog.xaml.cs b/PCUT/PCUT/Pages/DesignCenter/SvgNestSettingDialog.xaml.cs new file mode 100644 index 0000000..3db0115 --- /dev/null +++ b/PCUT/PCUT/Pages/DesignCenter/SvgNestSettingDialog.xaml.cs @@ -0,0 +1,41 @@ +using PCUT.ViewModels; +using System.Linq; +using Windows.UI.Xaml.Controls; + +// The Content Dialog item template is documented at https://go.microsoft.com/fwlink/?LinkId=234238 + +namespace PCUT.Pages +{ + public sealed partial class SvgNestSettingDialog : ContentDialog + { + public SvgNestSettings NestSettings { get; set; } + + public SvgNestSettingDialog() + { + this.InitializeComponent(); + NestSettings = SvgNestSettings.Instance; + } + + private void ContentDialog_PrimaryButtonClick(ContentDialog sender, ContentDialogButtonClickEventArgs args) + { + NestSettings.SaveSettings(); + NestSettings.ApplySettings(); + } + + private void ContentDialog_SecondaryButtonClick(ContentDialog sender, ContentDialogButtonClickEventArgs args) + { + NestSettings.LoadSettings(); + NestSettings.ApplySettings(); + } + + private void TextBox_ValidateInt(TextBox sender, TextBoxBeforeTextChangingEventArgs args) + { + args.Cancel = args.NewText.Any(ch => !char.IsDigit(ch)); + } + + private void TextBox_ValidateDouble(TextBox sender, TextBoxBeforeTextChangingEventArgs args) + { + args.Cancel = args.NewText.Any(ch => !char.IsDigit(ch) && ch != '.'); + } + } +} diff --git a/PCUT/PCUT/Pages/FileManagement/FileAddDialog.xaml b/PCUT/PCUT/Pages/FileManagement/FileAddDialog.xaml new file mode 100644 index 0000000..bbd565d --- /dev/null +++ b/PCUT/PCUT/Pages/FileManagement/FileAddDialog.xaml @@ -0,0 +1,228 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/PCUT/PCUT/Pages/FileManagement/FileAddDialog.xaml.cs b/PCUT/PCUT/Pages/FileManagement/FileAddDialog.xaml.cs new file mode 100644 index 0000000..342303b --- /dev/null +++ b/PCUT/PCUT/Pages/FileManagement/FileAddDialog.xaml.cs @@ -0,0 +1,78 @@ +using PCUT.Extensions; +using PCUT.Factories; +using PCUT.ViewModels; +using System; +using System.IO; +using System.Runtime.InteropServices.WindowsRuntime; +using Windows.Storage; +using Windows.Storage.Pickers; +using Windows.UI.Popups; +using Windows.UI.Xaml; +using Windows.UI.Xaml.Controls; +using Windows.UI.Xaml.Media.Imaging; + +// The Content Dialog item template is documented at https://go.microsoft.com/fwlink/?LinkId=234238 + +namespace PCUT.Pages +{ + public sealed partial class FileAddDialog : ContentDialog + { + private StorageFile _file; + private FileAddViewModel ViewModel { get; set; } + public FileAddDialog() + { + this.InitializeComponent(); + ViewModel = new FileAddViewModel(); + this.DataContext = ViewModel; + } + + private async void ContentDialog_Loaded(object sender, RoutedEventArgs e) + { + ViewModel.MetadataModel.BindAll(Type, Brand, Series, Model, SubType, Year); + ViewModel.Categories.Bind(Category); + + await ViewModel.GetCategoriesAsync(); + await ViewModel.MetadataModel.LoadAllMetadataAsync(); + } + + private void Category_SelectionChanged(object sender, SelectionChangedEventArgs e) + { + ViewModel.MetadataModel.UnselectAll(); + } + + private async void ContentDialog_PrimaryButtonClick(ContentDialog sender, ContentDialogButtonClickEventArgs args) + { + var deferral = args.GetDeferral(); + var success = await ViewModel.AddFileAsync(_file, ThumbnailPreview); + args.Cancel = !success; + deferral.Complete(); + } + + private async void UploadFile_CLick(object sender, RoutedEventArgs e) + { + + FileOpenPicker openPicker = new FileOpenPicker + { + ViewMode = PickerViewMode.List, + SuggestedStartLocation = PickerLocationId.DocumentsLibrary + }; + openPicker.FileTypeFilter.Add(".svg"); + _file = await openPicker.PickSingleFileAsync(); + + if (_file == null) + { + var noFileDialog = new MessageDialog("No file was selected"); + await noFileDialog.ShowAsync(); + return; + } + + using (var stream = await _file.OpenReadAsync()) + { + var (doc, _, _) = await FileFactory.PreProcessSvgAsync(stream.AsStream()); + var source = new SvgImageSource(); + ViewModel.PreviewSource = source; + _ = source.LoadSvgAsync(doc); + } + } + } +} diff --git a/PCUT/PCUT/Pages/FileManagement/FileEditDialog.xaml b/PCUT/PCUT/Pages/FileManagement/FileEditDialog.xaml new file mode 100644 index 0000000..8920b84 --- /dev/null +++ b/PCUT/PCUT/Pages/FileManagement/FileEditDialog.xaml @@ -0,0 +1,228 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/PCUT/PCUT/Pages/FileManagement/FileEditDialog.xaml.cs b/PCUT/PCUT/Pages/FileManagement/FileEditDialog.xaml.cs new file mode 100644 index 0000000..a98daf9 --- /dev/null +++ b/PCUT/PCUT/Pages/FileManagement/FileEditDialog.xaml.cs @@ -0,0 +1,95 @@ +using PCUT.Entities; +using PCUT.Extensions; +using PCUT.Factories; +using PCUT.ViewModels; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Runtime.InteropServices.WindowsRuntime; +using System.Threading.Tasks; +using Windows.Foundation; +using Windows.Foundation.Collections; +using Windows.Storage; +using Windows.Storage.Pickers; +using Windows.UI.Popups; +using Windows.UI.Xaml; +using Windows.UI.Xaml.Controls; +using Windows.UI.Xaml.Controls.Primitives; +using Windows.UI.Xaml.Data; +using Windows.UI.Xaml.Input; +using Windows.UI.Xaml.Media; +using Windows.UI.Xaml.Media.Imaging; +using Windows.UI.Xaml.Navigation; +using static System.Net.WebRequestMethods; + +// The Content Dialog item template is documented at https://go.microsoft.com/fwlink/?LinkId=234238 + +namespace PCUT.Pages +{ + public sealed partial class FileEditDialog : ContentDialog + { + private FileEditViewModel ViewModel { get; set; } + private StorageFile _file; + private readonly string _id; + public FileEditDialog(string id) + { + this.InitializeComponent(); + ViewModel = new FileEditViewModel(); + + _id = id; + + this.DataContext = ViewModel; + } + + private async void ContentDialog_Loaded(object sender, RoutedEventArgs e) + { + ViewModel.MetadataModel.BindAll(Type, Brand, Series, Model, SubType, Year); + ViewModel.Categories.Bind(Category); + + await ViewModel.GetCategoriesAsync(); + await ViewModel.MetadataModel.LoadAllMetadataAsync(); + + await ViewModel.LoadFileData(_id); + } + + private void Category_SelectionChanged(object sender, SelectionChangedEventArgs e) + { + //ViewModel.MetadataModel.UnselectAll(); + } + + private async void ContentDialog_PrimaryButtonClick(ContentDialog sender, ContentDialogButtonClickEventArgs args) + { + var deferral = args.GetDeferral(); + var success = await ViewModel.UpdateFileAsync(_id, _file, ThumbnailPreview); + args.Cancel = !success; + deferral.Complete(); + } + + private async void UploadFile_CLick(object sender, RoutedEventArgs e) + { + FileOpenPicker openPicker = new FileOpenPicker + { + ViewMode = PickerViewMode.List, + SuggestedStartLocation = PickerLocationId.DocumentsLibrary + }; + openPicker.FileTypeFilter.Add(".svg"); + _file = await openPicker.PickSingleFileAsync(); + + if (_file == null) + { + var noFileDialog = new MessageDialog("No file was selected"); + await noFileDialog.ShowAsync(); + return; + } + + using (var stream = await _file.OpenReadAsync()) + { + var (doc, _, _) = await FileFactory.PreProcessSvgAsync(stream.AsStream()); + var source = new SvgImageSource(); + ViewModel.PreviewSource = source; + _ = source.LoadSvgAsync(doc); + } + } + } +} diff --git a/PCUT/PCUT/Pages/FileManagement/FileManagerPage.xaml b/PCUT/PCUT/Pages/FileManagement/FileManagerPage.xaml new file mode 100644 index 0000000..84a449e --- /dev/null +++ b/PCUT/PCUT/Pages/FileManagement/FileManagerPage.xaml @@ -0,0 +1,227 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/PCUT/PCUT/Pages/FileManagement/FileManagerPage.xaml.cs b/PCUT/PCUT/Pages/FileManagement/FileManagerPage.xaml.cs new file mode 100644 index 0000000..a63de8c --- /dev/null +++ b/PCUT/PCUT/Pages/FileManagement/FileManagerPage.xaml.cs @@ -0,0 +1,218 @@ +using Http.Core; +using Microsoft.Toolkit; +using PCUT.Entities; +using PCUT.ViewModels; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Net.Http; +using System.Runtime.InteropServices.WindowsRuntime; +using System.Threading.Tasks; +using Windows.Foundation; +using Windows.Foundation.Collections; +using Windows.Storage; +using Windows.UI.Xaml; +using Windows.UI.Xaml.Controls; +using Windows.UI.Xaml.Controls.Primitives; +using Windows.UI.Xaml.Data; +using Windows.UI.Xaml.Input; +using Windows.UI.Xaml.Media; +using Windows.UI.Xaml.Navigation; +using Http.Core.Extensions; +using static Http.Core.Constants.HttpConstants; +using static PCUT.App; +using Windows.UI.Core; +using System.Threading; +using PCUT.Models; + +// The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=234238 + +namespace PCUT.Pages +{ + /// + /// An empty page that can be used on its own or navigated to within a Frame. + /// + public sealed partial class FileManagerPage : Page + { + private FileListViewModel ViewModels { get; set; } + public FileManagerPage() + { + this.InitializeComponent(); + ViewModels = DataContext as FileListViewModel; + + ViewModels.SetFilterMetadataOnFileChange(); + } + + protected override void OnNavigatedTo(NavigationEventArgs e) + { + ViewModels.Categories = new SelectableCollection(new Category { Name = "-None-" }); + base.OnNavigatedTo(e); + } + + private async void Page_Loaded(object sender, RoutedEventArgs e) + { + ViewModels.MetadataModel.BindAll(Type, Brand, null, null, null, Year); + ViewModels.Categories.Bind(Categories); + + await ViewModels.GetCategoriesAsync(); + await ViewModels.MetadataModel.LoadAllMetadataAsync(); + ViewModels.Pagination.Page = 1; + } + + protected override void OnNavigatedFrom(NavigationEventArgs e) + { + ViewModels.Pagination.Dispose(); + } + + private async void AddFile_Click(object sender, RoutedEventArgs e) + { + var dialog = new FileAddDialog(); + var result = await dialog.ShowAsync(); + if (result == ContentDialogResult.Primary) + await ViewModels.Reload(); + } + + private async void EditFile_Click(object sender, RoutedEventArgs e) + { + if (sender is Button button && button.CommandParameter is string fileId) + { + if (CanEditFile()) + { + var dialog = new FileEditDialog(fileId); + var result = await dialog.ShowAsync(); + if (result == ContentDialogResult.Primary) + await ViewModels.Reload(); + _editFileFlag = false; + } + } + } + + private static readonly object _editFileLock = new object(); + private static bool _editFileFlag = false; + private bool CanEditFile() + { + if (!Monitor.TryEnter(_editFileLock)) + return false; + + try + { + if (_editFileFlag) + return false; + + _editFileFlag = true; + return true; + } + finally + { + Monitor.Exit(_editFileLock); + } + } + + private async void DeleteFile_Click(object sender, RoutedEventArgs e) + { + if (sender is Button button && button.CommandParameter is string fileId) + { + if (CanDeleteFile()) + { + //Confirm diaglog before delete + ContentDialog deleteDialog = new ContentDialog + { + Title = "Confirm Delete?", + Content = "Are you sure want delete this file?", + PrimaryButtonText = "Delete", + CloseButtonText = "Cancel" + }; + deleteDialog.PrimaryButtonStyle = Application.Current.Resources["PrimaryDialogButton"] as Style; + deleteDialog.CloseButtonStyle = Application.Current.Resources["CloseDialogButton"] as Style; + + var result = await deleteDialog.ShowAsync(); + if (result == ContentDialogResult.Primary) + { + await DeleteFileAsync(fileId); + } + _deleteFileFlag = false; + } + } + } + + private static readonly object _deleteFileLock = new object(); + private static bool _deleteFileFlag = false; + private bool CanDeleteFile() + { + if (!Monitor.TryEnter(_deleteFileLock)) + return false; + + try + { + if (_deleteFileFlag) + return false; + + _deleteFileFlag = true; + return true; + } + finally + { + Monitor.Exit(_deleteFileLock); + } + } + + private async Task DeleteFileAsync(string fileId) + { + using (var httpClient = HttpClientFactory.CreateClient(ClientNames.ApiClient)) + { + try + { + var response = await httpClient.DeleteAsync(Api.CdrFileById.FormatRoute(fileId)); + if (response.IsSuccessStatusCode) + { + await ShowDialog("Delete Success", "File Deleted!"); + await ViewModels.Reload(); + } + else + { + await ShowDialog("Error!", "Cant delete file"); + } + } + catch (Exception ex) + { + await ShowDialog("Error!", $"Got exception: {ex.Message}"); + } + } + } + + + private async Task ShowDialog(string title, string content) + { + ContentDialog dialog = new ContentDialog + { + Title = title, + Content = content, + CloseButtonText = "OK" + }; + dialog.CloseButtonStyle = Application.Current.Resources["CloseDialogButton"] as Style; + + await dialog.ShowAsync(); + } + + private void btnFirst_Click(object sender, RoutedEventArgs e) + { + ViewModels.Pagination.Page = 1; + } + + private void btnLast_Click(object sender, RoutedEventArgs e) + { + ViewModels.Pagination.Page = ViewModels.Pagination.TotalPage; + } + + private void btnPrevious_Click(object sender, RoutedEventArgs e) + { + ViewModels.Pagination.Page--; + } + + private void btnNext_Click(object sender, RoutedEventArgs e) + { + ViewModels.Pagination.Page++; + } + } +} diff --git a/PCUT/PCUT/Pages/LoginPage.xaml b/PCUT/PCUT/Pages/LoginPage.xaml new file mode 100644 index 0000000..c466a8a --- /dev/null +++ b/PCUT/PCUT/Pages/LoginPage.xaml @@ -0,0 +1,95 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/PCUT/PCUT/Pages/MainMenuPage.xaml.cs b/PCUT/PCUT/Pages/MainMenuPage.xaml.cs new file mode 100644 index 0000000..92698e4 --- /dev/null +++ b/PCUT/PCUT/Pages/MainMenuPage.xaml.cs @@ -0,0 +1,156 @@ +using Http.Core; +using PCUT.ViewModels; +using System; +using System.Threading.Tasks; +using Windows.Foundation; +using Windows.UI.ViewManagement; +using Windows.UI.Xaml; +using Windows.UI.Xaml.Controls; +using Windows.UI.Xaml.Input; +using Windows.UI.Xaml.Navigation; +using Http.Core.Extensions; +using static Http.Core.Constants.HttpConstants; +using Windows.Graphics.Display; +using Http.Core.Contexts; +using PCUT.Pages.UserGuide; + +// The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=234238 + +namespace PCUT.Pages +{ + /// + /// An empty page that can be used on its own or navigated to within a Frame. + /// + public sealed partial class MainMenuPage : Page + { + private MainMenuPageViewModel ViewModel { get; set; } + public MainMenuPage() + { + this.InitializeComponent(); + ViewModel = DataContext as MainMenuPageViewModel; + } + + private void Page_Loading(FrameworkElement sender, object args) + { + var view = ApplicationView.GetForCurrentView(); + var height = DisplayInformation.GetForCurrentView().ScreenHeightInRawPixels; + var width = DisplayInformation.GetForCurrentView().ScreenWidthInRawPixels; + var size = new Size(width - 15 - 1, height - 40 - 1); + _ = view.TryResizeView(size); + ViewModel.UserName = UserContext.Instance.Profile.UserName; + ViewModel.Expiry = UserContext.Instance.Profile.ExpiredAt?.ToLocalTime().ToString("dd/MM/yyyy"); + } + + private async void Page_Loaded(object sender, RoutedEventArgs e) + { + ViewModel.Categories.Bind(CategoryList); + await ViewModel.GetCategoriesAsync(); + } + + protected override void OnNavigatedTo(NavigationEventArgs e) + { + base.OnNavigatedTo(e); + NavigateContentFrame(ViewModel); + } + + private void NavigationViewItem_Invoked(NavigationView sender, NavigationViewItemInvokedEventArgs args) + { + var item = args.InvokedItemContainer as NavigationViewItem; + var itemTag = item.Tag?.ToString(); + if (itemTag == "Menu") + ViewModel.ToggleMenuDisplay(); + else + { + ViewModel.HideMenuDisplay(); + switch (itemTag) + { + case "DataCenter": + NavigateContentFrame(ViewModel); + break; + case "DesignCenter": + NavigateContentFrame(); + break; + case "UserGuide": + NavigateContentFrame(); + break; + case "AdminCenter": + NavigateContentFrame(); + break; + } + } + } + + private void NavigateContentFrame(object param = null) + { + var destPageType = typeof(TPage); + if (ContentFrame.Content?.GetType() != destPageType) + { + ViewModel.IsMenuEnabled = destPageType == typeof(DataCenterPage); + ContentFrame.Navigate(destPageType, param); + } + } + + private void CategoryList_Tapped(object sender, TappedRoutedEventArgs e) + { + ViewModel.Categories.SelectedIndex = CategoryList.SelectedIndex; + } + + private void LogOutNavItem_Tapped(object sender, TappedRoutedEventArgs e) + { + ShowLogoutConfirmationDialog(); + } + + private async void ShowLogoutConfirmationDialog() + { + ContentDialog logoutConfirmationDialog = new ContentDialog + { + Title = "Confirm Logout", + Content = "Are you sure you want to log out?", + PrimaryButtonText = "Log Out", + CloseButtonText = "Cancel" + }; + logoutConfirmationDialog.PrimaryButtonStyle = Application.Current.Resources["PrimaryDialogButton"] as Style; + logoutConfirmationDialog.CloseButtonStyle = Application.Current.Resources["CloseDialogButton"] as Style; + + ContentDialogResult result = await logoutConfirmationDialog.ShowAsync(); + + if (result == ContentDialogResult.Primary) + { + await PerformLogoutAsync(); + } + } + + private async Task PerformLogoutAsync() + { + using (var httpClient = HttpClientFactory.CreateClient(ClientNames.ApiClient)) + { + var loginSuccess = await httpClient.LogOutAsync(); + } + Frame.Navigate(typeof(LoginPage)); + } + + private void ContentFrame_Navigated(object sender, NavigationEventArgs e) + { + if (e.SourcePageType == typeof(DesignCenterPage)) + { + NavigationView.SelectedItem = DesignCenterNavItem; + } + else if (e.SourcePageType == typeof(DataCenterPage)) + { + NavigationView.SelectedItem = DataCenterNavItem; + } + else if (e.SourcePageType == typeof(UserGuidePage)) + { + NavigationView.SelectedItem = UserGuideNavItem; + } + else if (e.SourcePageType == typeof(AdminCenterPage)) + { + NavigationView.SelectedItem = AdminCenterNavItem; + } + else + { + NavigationView.SelectedItem = null; + } + } + } +} diff --git a/PCUT/PCUT/Pages/UserGuide/UserGuidePage.xaml b/PCUT/PCUT/Pages/UserGuide/UserGuidePage.xaml new file mode 100644 index 0000000..7063bec --- /dev/null +++ b/PCUT/PCUT/Pages/UserGuide/UserGuidePage.xaml @@ -0,0 +1,14 @@ + + + + + + diff --git a/PCUT/PCUT/Pages/UserGuide/UserGuidePage.xaml.cs b/PCUT/PCUT/Pages/UserGuide/UserGuidePage.xaml.cs new file mode 100644 index 0000000..28372c1 --- /dev/null +++ b/PCUT/PCUT/Pages/UserGuide/UserGuidePage.xaml.cs @@ -0,0 +1,30 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Runtime.InteropServices.WindowsRuntime; +using Windows.Foundation; +using Windows.Foundation.Collections; +using Windows.UI.Xaml; +using Windows.UI.Xaml.Controls; +using Windows.UI.Xaml.Controls.Primitives; +using Windows.UI.Xaml.Data; +using Windows.UI.Xaml.Input; +using Windows.UI.Xaml.Media; +using Windows.UI.Xaml.Navigation; + +// The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=234238 + +namespace PCUT.Pages.UserGuide +{ + /// + /// An empty page that can be used on its own or navigated to within a Frame. + /// + public sealed partial class UserGuidePage : Page + { + public UserGuidePage() + { + this.InitializeComponent(); + } + } +} diff --git a/PCUT/PCUT/Pages/UserManagement/ChangePasswordDialog.xaml b/PCUT/PCUT/Pages/UserManagement/ChangePasswordDialog.xaml new file mode 100644 index 0000000..50cc0e8 --- /dev/null +++ b/PCUT/PCUT/Pages/UserManagement/ChangePasswordDialog.xaml @@ -0,0 +1,27 @@ + + + + + + + + + + + diff --git a/PCUT/PCUT/Pages/UserManagement/ChangePasswordDialog.xaml.cs b/PCUT/PCUT/Pages/UserManagement/ChangePasswordDialog.xaml.cs new file mode 100644 index 0000000..d1747a8 --- /dev/null +++ b/PCUT/PCUT/Pages/UserManagement/ChangePasswordDialog.xaml.cs @@ -0,0 +1,73 @@ +using PCUT.ViewModels; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Runtime.InteropServices.WindowsRuntime; +using Windows.Foundation; +using Windows.Foundation.Collections; +using Windows.UI.Popups; +using Windows.UI.Xaml; +using Windows.UI.Xaml.Controls; +using Windows.UI.Xaml.Controls.Primitives; +using Windows.UI.Xaml.Data; +using Windows.UI.Xaml.Input; +using Windows.UI.Xaml.Media; +using Windows.UI.Xaml.Navigation; + +// The Content Dialog item template is documented at https://go.microsoft.com/fwlink/?LinkId=234238 + +namespace PCUT.Pages +{ + public sealed partial class ChangePasswordDialog : ContentDialog + { + private ChangePasswordViewModel ViewModel { get; set; } + public ChangePasswordDialog(string userId) + { + this.InitializeComponent(); + ViewModel = new ChangePasswordViewModel(); + ViewModel.UserId = userId; + this.DataContext = ViewModel; + } + + private async void ContentDialog_SecondaryButtonClick(ContentDialog sender, ContentDialogButtonClickEventArgs args) + { + var confirmDialog = new MessageDialog("Are you sure you want to save the new password?"); + confirmDialog.Commands.Add(new UICommand("Yes") { Id = 1 }); + confirmDialog.Commands.Add(new UICommand("No") { Id = 0 }); + confirmDialog.DefaultCommandIndex = 0; + confirmDialog.CancelCommandIndex = 1; + + var result = await confirmDialog.ShowAsync(); + + if ((int)result.Id == 1) + { + await ViewModel.ChangePassword(); + } + else + { + this.Hide(); + } + } + + private async void ContentDialog_PrimaryButtonClick(ContentDialog sender, ContentDialogButtonClickEventArgs args) + { + var confirmDialog = new MessageDialog("Are you sure you want to reset?"); + confirmDialog.Commands.Add(new UICommand("Yes") { Id = 1 }); + confirmDialog.Commands.Add(new UICommand("No") { Id = 0 }); + confirmDialog.DefaultCommandIndex = 0; + confirmDialog.CancelCommandIndex = 1; + + var result = await confirmDialog.ShowAsync(); + + if ((int)result.Id == 1) + { + await ViewModel.ChangeDefaultPassword(); + } + else + { + this.Hide(); + } + } + } +} diff --git a/PCUT/PCUT/Pages/UserManagement/UpsertUserPage.xaml b/PCUT/PCUT/Pages/UserManagement/UpsertUserPage.xaml new file mode 100644 index 0000000..f571bd7 --- /dev/null +++ b/PCUT/PCUT/Pages/UserManagement/UpsertUserPage.xaml @@ -0,0 +1,374 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Allow Custom Paper Size: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/PCUT/PCUT/Pages/UserManagement/UserListPage.xaml.cs b/PCUT/PCUT/Pages/UserManagement/UserListPage.xaml.cs new file mode 100644 index 0000000..6049743 --- /dev/null +++ b/PCUT/PCUT/Pages/UserManagement/UserListPage.xaml.cs @@ -0,0 +1,176 @@ +using PCUT.ViewModels; +using System; +using System.Threading.Tasks; +using Windows.UI.Xaml; +using Windows.UI.Xaml.Controls; +using Windows.UI.Xaml.Navigation; +using Http.Core; +using Http.Core.Extensions; +using static Http.Core.Constants.HttpConstants; + +// The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=234238 + +namespace PCUT.Pages +{ + /// + /// An empty page that can be used on its own or navigated to within a Frame. + /// + public sealed partial class UserListPage : Page + { + private UserViewModel ViewModels { get; set; } + public UserListPage() + { + this.InitializeComponent(); + ViewModels = DataContext as UserViewModel; + } + + protected override void OnNavigatedTo(NavigationEventArgs e) + { + ViewModels.Pagination.Page = 1; + } + + protected override void OnNavigatedFrom(NavigationEventArgs e) + { + ViewModels.Pagination.Dispose(); + } + + private void AddButton_Click(object sender, RoutedEventArgs e) + { + if (sender is Button button) + { + button.IsEnabled = false; + Frame.Navigate(typeof(UpsertUserPage)); + } + } + + private void EditButton_Click(object sender, RoutedEventArgs e) + { + if (sender is Button button && button.CommandParameter is string userId) + { + button.IsEnabled = false; + if (!string.IsNullOrEmpty(userId)) + Frame.Navigate(typeof(UpsertUserPage), userId); + else + button.IsEnabled = true; + } + } + + private async void PasswordButton_Click(object sender, RoutedEventArgs e) + { + if (sender is Button button && button.CommandParameter is string userId) + { + if (!string.IsNullOrEmpty(userId)) + { + var dialog = new ChangePasswordDialog(userId); + await dialog.ShowAsync(); + } + } + } + + private async void DeleteButton_Click(object sender, RoutedEventArgs e) + { + if(sender is Button button && button.CommandParameter is string userId) + { + //Confirm diaglog before delete + ContentDialog deleteDialog = new ContentDialog + { + Title = "Confirm Delete?", + Content = "Are you sure want delete this user?", + PrimaryButtonText = "Delete", + CloseButtonText = "Cancel" + }; + deleteDialog.PrimaryButtonStyle = Application.Current.Resources["PrimaryDialogButton"] as Style; + deleteDialog.CloseButtonStyle = Application.Current.Resources["CloseDialogButton"] as Style; + + var result = await deleteDialog.ShowAsync(); + if (result == ContentDialogResult.Primary) + { + await DeleteUserAsync(userId); + } + } + } + + private async Task DeleteUserAsync(string userId) + { + using (var httpClient = HttpClientFactory.CreateClient(ClientNames.ApiClient)) + { + try + { + var response = await httpClient.DeleteAsync(Api.UserById.FormatRoute(userId)); + if (response.IsSuccessStatusCode) + { + await ShowDialog("Delete Success", "User Deleted!"); + await ViewModels.Reload(); + } + else + { + await ShowDialog("Error!", "Cant delete user"); + } + } + catch (Exception ex) + { + await ShowDialog("Error!", $"Got exception: {ex.Message}"); + } + } + } + + private async void UnlockDevice_Click(object sender, RoutedEventArgs e) + { + if (sender is Button button && button.CommandParameter is string userId) + { + using (var httpClient = HttpClientFactory.CreateClient(ClientNames.ApiClient)) + { + try + { + var response = await httpClient.DeleteAsync(Api.UserUnlockDevice.FormatRoute(userId)); + if (response.IsSuccessStatusCode) + { + await ShowDialog("Device Unlock Success", "User's device unlocked!"); + } + else + { + await ShowDialog("Error!", "Failed to unlock user's device"); + } + } + catch (Exception ex) + { + await ShowDialog("Error!", $"Got exception: {ex.Message}"); + } + } + } + } + + private async Task ShowDialog(string title, string content) + { + ContentDialog dialog = new ContentDialog + { + Title = title, + Content = content, + CloseButtonText = "OK" + }; + dialog.CloseButtonStyle = Application.Current.Resources["CloseDialogButton"] as Style; + + await dialog.ShowAsync(); + } + + private void btnFirst_Click(object sender, RoutedEventArgs e) + { + ViewModels.Pagination.Page = 1; + } + + private void btnLast_Click(object sender, RoutedEventArgs e) + { + ViewModels.Pagination.Page = ViewModels.Pagination.TotalPage; + } + + private void btnPrevious_Click(object sender, RoutedEventArgs e) + { + ViewModels.Pagination.Page--; + } + + private void btnNext_Click(object sender, RoutedEventArgs e) + { + ViewModels.Pagination.Page++; + } + } +} diff --git a/PCUT/PCUT/Properties/AssemblyInfo.cs b/PCUT/PCUT/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..54a4a95 --- /dev/null +++ b/PCUT/PCUT/Properties/AssemblyInfo.cs @@ -0,0 +1,29 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("PCUT")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("PCUT")] +[assembly: AssemblyCopyright("Copyright © 2024")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] +[assembly: ComVisible(false)] \ No newline at end of file diff --git a/PCUT/PCUT/Properties/Default.rd.xml b/PCUT/PCUT/Properties/Default.rd.xml new file mode 100644 index 0000000..af00722 --- /dev/null +++ b/PCUT/PCUT/Properties/Default.rd.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/PCUT/PCUT/ViewModels/CategoriesViewModel.cs b/PCUT/PCUT/ViewModels/CategoriesViewModel.cs new file mode 100644 index 0000000..8e07dd1 --- /dev/null +++ b/PCUT/PCUT/ViewModels/CategoriesViewModel.cs @@ -0,0 +1,127 @@ +using PCUT.Entities; +using PCUT.Models; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Http.Core; +using Http.Core.Extensions; +using static Http.Core.Constants.HttpConstants; +using PCUT.Entities.ApiResponse; +using PCUT.Models.Categories; +using Windows.ApplicationModel.Core; + +namespace PCUT.ViewModels +{ + public class CategoriesViewModel : NotificationBase + { + public PaginationViewModel Pagination { get; } = new PaginationViewModel(withSearch: true); + public SelectableCollection FilteredCategories { get; } + public CategoriesViewModel() + { + FilteredCategories = new SelectableCollection(); + + Pagination.TextSearched += async (sender, args) => await SearchCategoryAsync(args.Text); + Pagination.PageChanged += OnPageChanged; + } + + private async void OnPageChanged(object sender, PageChangedEventArgs args) + { + await LoadCategoryAsync(args.Page, args.PageSize, Pagination.SearchText); + } + + public async Task SearchCategoryAsync(string searchText) + { + await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, async () => + { + await LoadCategoryAsync(Pagination.Page, Pagination.PageSize, searchText); + }); + } + + public async Task Reload() + { + await LoadCategoryAsync(Pagination.Page, Pagination.PageSize, Pagination.SearchText); + } + + public async Task LoadCategoryAsync(int page, int pageSize, string searchText) + { + var url = CreateFilterUrl(page, pageSize, searchText); + using (var httpClient = HttpClientFactory.CreateClient(ClientNames.ApiClient)) + { + try + { + var response = await httpClient.GetAsync(url); + if (response.IsSuccessStatusCode) + { + var apiResponse = await response.DeserializeObjectAsync>>(); + var data = apiResponse.Data; + Pagination.Page = apiResponse.Pagination.Page; + Pagination.TotalPage = apiResponse.Pagination.TotalPages; + Pagination.TotalRecords = apiResponse.Pagination.TotalRecords; + + int displayId = (apiResponse.Pagination.Page - 1) * pageSize + 1; + var categories = data.Select(category => + { + category.DisplayId = displayId.ToString(); + displayId++; + return category; + }); + FilteredCategories.Load(categories); + } + } + catch (Exception ex) + { + + } + } + } + + public async Task LoadMetadataAsync(MetadataTypeModel metadataType, bool reload = false) + { + if (reload || !metadataType.IsLoaded) + { + metadataType.IsLoaded = true; + using (var client = HttpClientFactory.CreateClient(ClientNames.ApiClient)) + { + try + { + var url = PathBuilder.FromRouteTemplate(Api.Metadata) + .AddQuery("filter", $"[\"type:eq:{metadataType.Name.ToUpper()}\", \"categoryId:eq:{metadataType.Category.Id}\"]") + .AddQuery("sort", "createdAt:desc") + .Build(); + var response = await client.GetAsync(url); + if (response.IsSuccessStatusCode) + { + var content = await response.DeserializeObjectAsync>>(); + metadataType.Metadata.Clear(); + var id = 0; + foreach (var model in content.Data) + { + model.DisplayId = ++id; + model.MetadataType = metadataType; + metadataType.Metadata.Add(model); + } + } + } + catch + { + } + } + } + } + + private string CreateFilterUrl(int page, int pageSize, string searchText) + { + var builder = PathBuilder.FromRouteTemplate(Api.Categories) + .AddQuery("page", page.ToString()) + .AddQuery("pageSize", pageSize.ToString()); + if (!string.IsNullOrEmpty(searchText)) + { + var filter = new StringBuilder().AppendFilter("name", "cn", searchText).BuildFilter().ToString(); + builder.AddQuery("filter", filter); + } + return builder.Build(); + } + } +} diff --git a/PCUT/PCUT/ViewModels/ChangePasswordViewModel.cs b/PCUT/PCUT/ViewModels/ChangePasswordViewModel.cs new file mode 100644 index 0000000..3d68a06 --- /dev/null +++ b/PCUT/PCUT/ViewModels/ChangePasswordViewModel.cs @@ -0,0 +1,157 @@ +using Newtonsoft.Json; +using PCUT.Entities; +using PCUT.Helpers; +using PCUT.Models; +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.ComponentModel; +using System.Linq; +using System.Net.Http; +using System.ServiceModel.Channels; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Input; +using Windows.Storage; +using Windows.UI.Popups; +using Http.Core; +using Http.Core.Extensions; +using static Http.Core.Constants.HttpConstants; +using Microsoft.IdentityModel.Tokens; +using PCUT.Models.Users; + +namespace PCUT.ViewModels +{ + public class ChangePasswordViewModel : NotificationBase + { + + public ICommand ChangePasswordCommand { get; private set; } + public event PropertyChangedEventHandler PropertyChanged; + public ObservableCollection PasswordChanges { get; private set; } + private ObservableCollection _users; + public ObservableCollection Users + { + get { return _users; } + set + { + if (_users != value) + { + _users = value; + OnPropertyChanged(nameof(Users)); + } + } + } + protected void OnPropertyChanged(string propertyName) + { + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); + } + + private string _userId; + public string UserId + { + get { return _userId; } + set { SetProperty(ref _userId, value); } + } + private string _password; + public string Password + { + get { return _password; } + set + { + SetProperty(ref _password, value); + } + } + private string _confirmpassword; + public string ConfirmPassword + { + get { return _confirmpassword; } + set + { + SetProperty(ref _confirmpassword, value); + } + } + + public ChangePasswordViewModel() + { + ChangePasswordCommand = new RelayCommand(async () => await ChangePassword()); + PasswordChanges = new ObservableCollection(); + } + + public async Task ChangePassword() + { + if (Password != ConfirmPassword) + { + var errorDialog = new MessageDialog("Confirm Password is incorrect!"); + await errorDialog.ShowAsync(); + return; + } + + if (string.IsNullOrWhiteSpace(Password) || string.IsNullOrWhiteSpace(ConfirmPassword)) + { + var errorDialog = new MessageDialog("Password and Confirm Password cannot be empty!"); + await errorDialog.ShowAsync(); + return; + } + else + { + try + { + var passwordChange = new PasswordChange + { + Password = this.Password, + }; + await ChangePasswordAsync(UserId, passwordChange); + } + catch (Exception ex) + { + var failDialog = new MessageDialog(ex.Message.ToString()); + await failDialog.ShowAsync(); + } + } + } + + public async Task ChangeDefaultPassword() + { + try + { + var passwordChange = new PasswordChange + { + Password = "123456", + }; + await ChangePasswordAsync(UserId, passwordChange); + } + catch (Exception ex) + { + var failDialog = new MessageDialog(ex.Message.ToString()); + await failDialog.ShowAsync(); + } + } + + private async Task ChangePasswordAsync(string userId, PasswordChange password) + { + using (var httpClient = HttpClientFactory.CreateClient(ClientNames.ApiClient)) + { + try + { + var response = await httpClient.PutAsJsonAsync(Api.UserById.FormatRoute(userId), password); + if (response.IsSuccessStatusCode) + { + var successDialog = new MessageDialog("Password changed successfully!"); + await successDialog.ShowAsync(); + } + else + { + var failDialog = new MessageDialog("Failed to change password!"); + await failDialog.ShowAsync(); + } + } + catch (Exception ex) + { + var errorDialog = new MessageDialog($"error: {ex.Message}"); + await errorDialog.ShowAsync(); + } + } + } + + } +} diff --git a/PCUT/PCUT/ViewModels/ComponentImageModel.cs b/PCUT/PCUT/ViewModels/ComponentImageModel.cs new file mode 100644 index 0000000..71e493f --- /dev/null +++ b/PCUT/PCUT/ViewModels/ComponentImageModel.cs @@ -0,0 +1,100 @@ +using System; +using System.Collections.ObjectModel; +using System.ComponentModel; +using System.Xml.Linq; +using PCUT.Extensions; +using Windows.UI.Xaml.Controls; +using Windows.UI.Xaml.Media; +using Windows.UI.Xaml.Media.Imaging; + +namespace PCUT.ViewModels +{ + public class ComponentImageModel + { + public ObservableCollection ComponentList { get; } = new ObservableCollection(); + + public void AddSource(string id, bool deleted, XDocument doc) + { + var source = new SvgImageSource(); + ComponentList.Add(new ComponentImageSource { Id = id, Deleted = deleted, Source = source }); + _ = source.LoadSvgAsync(doc); + } + } + + public class ComponentImageSource : INotifyPropertyChanged + { + public event PropertyChangedEventHandler PropertyChanged; + + public ImageSource Source { get; set; } + public string Id { get; set; } + + private bool _deleted; + public bool Deleted + { + get => _deleted; + set + { + _deleted = value; + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Deleted))); + } + } + } + + public class ComponentStyle : INotifyPropertyChanged + { + public event PropertyChangedEventHandler PropertyChanged; + + + private double _width; + public double Width + { + get => _width; + set + { + _width = value; + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Width))); + } + } + + private double _height; + public double Height + { + get => _height; + set + { + _height = value; + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Height))); + } + } + + public void SetSize(RowDefinition rowDefinition, ColumnDefinition columnDefinition) + { + Height = rowDefinition.ActualHeight; + Width = columnDefinition.ActualWidth; + } + + public void SetSize(RowDefinition rowDefinition) + { + Width = rowDefinition.ActualHeight; + Height = rowDefinition.ActualHeight; + } + + public void SetSize(RowDefinition rowDefinition, double ratio) + { + Width = rowDefinition.ActualHeight * ratio; + Height = rowDefinition.ActualHeight; + } + + public void SetSize(ColumnDefinition columnDefinition, int rate = 1) + { + Width = rate <= 1 ? columnDefinition.ActualWidth : Math.Floor((columnDefinition.ActualWidth - 25) / rate); + Height = rate <= 1 ? columnDefinition.ActualWidth : Math.Floor((columnDefinition.ActualWidth - 25) / rate); + } + + public void SetSize(ColumnDefinition columnDefinition, double ratio) + { + Width = columnDefinition.ActualWidth; + Height = columnDefinition.ActualWidth / ratio; + } + } +} diff --git a/PCUT/PCUT/ViewModels/CutFilesViewModel.cs b/PCUT/PCUT/ViewModels/CutFilesViewModel.cs new file mode 100644 index 0000000..1a7ef2d --- /dev/null +++ b/PCUT/PCUT/ViewModels/CutFilesViewModel.cs @@ -0,0 +1,64 @@ + using Microsoft.Toolkit.Collections; +using PCUT.Models; +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace PCUT.ViewModels +{ + internal class CutFilesViewModel : NotificationBase + { + private ObservableCollection _ports; + public ObservableCollection Ports + { + get { return _ports; } + set + { + SetProperty(ref _ports, value); + } + } + + private double _width; + public double Width + { + get { return _width; } + set + { + SetProperty(ref _width, value); + } + } + + private double _height; + public double Height + { + get { return _height; } + set + { + SetProperty(ref _height, value); + } + } + + private string _selectedPortName; + public string SelectedPortName + { + get { return _selectedPortName; } + set + { + if (_selectedPortName != value) + { + SetProperty(ref _selectedPortName, value); + } + } + } + + + public CutFilesViewModel() + { + + } + } +} diff --git a/PCUT/PCUT/ViewModels/DesignCenterViewModel.cs b/PCUT/PCUT/ViewModels/DesignCenterViewModel.cs new file mode 100644 index 0000000..5466b25 --- /dev/null +++ b/PCUT/PCUT/ViewModels/DesignCenterViewModel.cs @@ -0,0 +1,209 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Http.Core; +using Http.Core.Extensions; +using Newtonsoft.Json; +using PCUT.Entities; +using PCUT.Entities.ApiResponse; +using PCUT.Models; +using static Http.Core.Constants.HttpConstants; + +namespace PCUT.ViewModels +{ + public class DesignCenterViewModel : NotificationBase + { + public ObservableCollection Ports { get; set; } + public ObservableCollection PaperSizes { get; } + + private double _width; + public double Width + { + get { return _width; } + set + { + SetProperty(ref _width, value); + } + } + + private double _height; + public double Height + { + get { return _height; } + set + { + SetProperty(ref _height, value); + } + } + + private int _selectedHeightIndex = -1; + public int SelectedHeightIndex + { + get { return _selectedHeightIndex; } + set + { + if (_selectedHeightIndex != value && value >= 0 && value < PaperSizes.Count) + { + SetProperty(ref _selectedHeightIndex, value); + Width = PaperSizes[value].Width; + Height = PaperSizes[value].Height; + } + } + } + + private int _selectedPortIndex = -1; + public int SelectedPortIndex + { + get { return _selectedPortIndex; } + set + { + if (_selectedPortIndex != value) + { + SetProperty(ref _selectedPortIndex, value); + } + } + } + + public string SelectedPortName => Ports.Any() && _selectedPortIndex >= 0 && _selectedPortIndex < Ports.Count ? Ports[_selectedPortIndex].PortName : null; + public string SelectedDeviceName => Ports.Any() && _selectedPortIndex >= 0 && _selectedPortIndex < Ports.Count ? Ports[_selectedPortIndex].DeviceName : null; + + private string _name; + public string Name + { + get { return _name; } + set { SetProperty(ref _name, value); } + } + + private string _type; + public string Type + { + get { return _type; } + set { SetProperty(ref _type, value); } + } + + private string _brand; + public string Brand + { + get { return _brand; } + set + { + SetProperty(ref _brand, value); + } + } + + private string _year; + public string Year + { + get { return _year; } + set + { + SetProperty(ref _year, value); + } + } + + private string _model; + public string Model + { + get { return _model; ; } + set + { + SetProperty(ref _model, value); ; + } + } + + private string _series; + public string Series + { + get { return _series; } + set + { + SetProperty(ref _series, value); + } + } + + public string ItemId { get; set; } + public string FileId { get; set; } + public DesignCenterViewModel() + { + Ports = new ObservableCollection(); + PaperSizes = new ObservableCollection + { + new PaperSize(7000, 360), + new PaperSize(10000, 550), + }; + } + + public async Task GetCdrFileAsync(string fileId) + { + using(var httpClient = HttpClientFactory.CreateClient(ClientNames.ApiClient)) + { + try + { + var response = await httpClient.GetAsync(Api.CdrFileById.FormatRoute(fileId)); + if (response.IsSuccessStatusCode) + { + var apiResponse = await response.DeserializeObjectAsync>(); + if (apiResponse?.Data != null) + { + Name = apiResponse.Data.Name ?? string.Empty; + Type = apiResponse.Data.Type?.Value ?? string.Empty; + Brand = apiResponse.Data.Brand?.Value ?? string.Empty; + Year = apiResponse.Data.Year?.Value ?? string.Empty; + Model = apiResponse.Data.Model?.Value ?? string.Empty; + Series = apiResponse.Data.Series?.Value ?? string.Empty; + + ItemId = fileId; + FileId = apiResponse.Data.File?.Id; + return true; + } + } + } + catch + { + + } + } + return false; + } + + private double _minSize = 0; + public double MinSize + { + get => _minSize; + set + { + SetProperty(ref _minSize, value); + } + } + + public bool UseOrigin { get; set; } = true; + } + + public class PortInfo + { + public string PortName { get; set; } + public string DeviceName { get; set; } + + public PortInfo(string portName, string deviceName) + { + PortName = portName; + DeviceName = deviceName; + } + } + + public class PaperSize + { + public double Width { get; set; } + public double Height { get; set; } + + public PaperSize(double width, double height) + { + Width = width; + Height = height; + } + } +} diff --git a/PCUT/PCUT/ViewModels/FileAddViewModel.cs b/PCUT/PCUT/ViewModels/FileAddViewModel.cs new file mode 100644 index 0000000..402632f --- /dev/null +++ b/PCUT/PCUT/ViewModels/FileAddViewModel.cs @@ -0,0 +1,187 @@ +using Newtonsoft.Json; +using PCUT.Entities; +using PCUT.Models; +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.ComponentModel; +using System.IO; +using System.Linq; +using System.Net.Http.Headers; +using System.Net.Http; +using System.Text; +using System.Threading.Tasks; +using Windows.Storage; +using Windows.Storage.Pickers; +using Windows.UI.Popups; +using Windows.UI.Xaml.Media; +using Windows.UI.Xaml.Controls; +using Windows.Storage.Streams; +using PCUT.Extensions; +using PCUT.Pages; +using Http.Core; +using Http.Core.Extensions; +using static Http.Core.Constants.HttpConstants; +using PCUT.Entities.ApiResponse; + +namespace PCUT.ViewModels +{ + public class FileAddViewModel : NotificationBase + { + private string _name; + public string Name + { + get { return _name; } + set { SetProperty(ref _name, value); } + } + + private string _area; + public string Area + { + get { return _area; } + set { SetProperty(ref _area, value); } + } + + private string _remarks; + public string Remarks + { + get { return _remarks; } + set { SetProperty(ref _remarks, value); } + } + + private ImageSource _previewSource; + public ImageSource PreviewSource + { + get { return _previewSource; } + set { SetProperty(ref _previewSource, value); } + } + + public SelectableCollection Categories { get; } + public MetadataViewModel MetadataModel { get; } + + public FileAddViewModel() + { + Categories = new SelectableCollection(); + MetadataModel = new MetadataViewModel(); + + MetadataModel.SetFilterChangedHandle(); + } + + public async Task GetCategoriesAsync() + { + using (var client = HttpClientFactory.CreateClient(ClientNames.ApiClient)) + { + var categories = await client.GetCategoriesAsync(filterByRole: true); + Categories.Load(categories); + } + } + + public async Task AddFileAsync(StorageFile file, Image image) + { + if (file == null) + { + var noFileSelectedDialog = new MessageDialog("Please select a file to upload!"); + await noFileSelectedDialog.ShowAsync(); + return false; + } + string fileId; + using (var stream = await file.OpenReadAsync()) + { + fileId = await UpLoadFileAsync(file.Name, stream.AsStreamForRead()); + } + + if (string.IsNullOrEmpty(fileId)) + { + var uploadAgainDialog = new MessageDialog("Please select a file to upload!"); + await uploadAgainDialog.ShowAsync(); + return false; + } + + string thumbnailId; + using (var stream = await image.CreateThumbnailAsync()) + { + thumbnailId = await UpLoadFileAsync(Path.GetFileNameWithoutExtension(file.Name) + ".png", stream.AsStreamForRead()); + } + if (string.IsNullOrEmpty(thumbnailId)) + { + var uploadAgainDialog = new MessageDialog("Please select a file to upload!"); + await uploadAgainDialog.ShowAsync(); + return false; + } + + try + { + var fileInfo = new UpsertFile + { + FileId = fileId, + Name = this.Name, + Thumbnail = thumbnailId, + Category = Categories.SelectedItem?.Id, + Type = MetadataModel.Types.SelectedItem?.Id, + Brand = MetadataModel.Brands.SelectedItem?.Id, + Series = MetadataModel.Series.SelectedItem?.Id, + Model = MetadataModel.Models.SelectedItem?.Id, + SubType = MetadataModel.SubTypes.SelectedItem?.Id, + Year = MetadataModel.Years.SelectedItem?.Id, + Area = this.Area, + Remarks = this.Remarks + }; + using (HttpClient client = HttpClientFactory.CreateClient(ClientNames.ApiClient)) + { + var response = await client.PostAsJsonAsync(Api.CdrFiles, fileInfo); + if (!response.IsSuccessStatusCode) + { + var failDialog = new MessageDialog("An error occurred while adding the file!"); + await failDialog.ShowAsync(); + return false; + } + } + } + catch (Exception ex) + { + var errorDialog = new MessageDialog($"Error: {ex.Message}"); + await errorDialog.ShowAsync(); + return false; + } + var successDialog = new MessageDialog("File added successfully!"); + await successDialog.ShowAsync(); + return true; + } + + private async Task UpLoadFileAsync(string name, Stream stream) + { + try + { + using (HttpClient client = HttpClientFactory.CreateClient(ClientNames.ApiClient)) + { + var content = new MultipartFormDataContent(); + var streamContent = new StreamContent(stream); + streamContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data") + { + Name = "file", + FileName = name + }; + content.Add(streamContent); + + var response = await client.PostAsync(Api.Upload, content); + if (response.IsSuccessStatusCode) + { + var uploadResponse = await response.DeserializeObjectAsync>(); + return uploadResponse.Data.Id; + } + else + { + var errorDialog = new MessageDialog("Error uploading file!"); + await errorDialog.ShowAsync(); + } + } + } + catch (Exception ex) + { + var exceptionDialog = new MessageDialog($"Error: {ex.Message}"); + await exceptionDialog.ShowAsync(); + } + return null; + } + } +} diff --git a/PCUT/PCUT/ViewModels/FileEditViewModel.cs b/PCUT/PCUT/ViewModels/FileEditViewModel.cs new file mode 100644 index 0000000..b65e25f --- /dev/null +++ b/PCUT/PCUT/ViewModels/FileEditViewModel.cs @@ -0,0 +1,249 @@ + + +using Http.Core; +using Newtonsoft.Json; +using PCUT.Entities; +using PCUT.Entities.ApiResponse; +using PCUT.Extensions; +using PCUT.Models; +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.ComponentModel; +using System.IO; +using System.Linq; +using System.Net.Http; +using System.Net.Http.Headers; +using System.Text; +using System.Threading.Tasks; +using Windows.Storage; +using Windows.Storage.Pickers; +using Windows.Storage.Streams; +using Windows.UI.Popups; +using Windows.UI.Xaml.Controls; +using Http.Core.Extensions; +using static Http.Core.Constants.HttpConstants; +using Windows.Graphics.Imaging; +using Windows.UI.Xaml.Media.Imaging; +using Windows.UI.Xaml.Media; + +namespace PCUT.ViewModels +{ + public class FileEditViewModel : NotificationBase + { + private string _name; + public string Name + { + get { return _name; } + set { SetProperty(ref _name, value); } + } + + private string _area; + public string Area + { + get { return _area; } + set { SetProperty(ref _area, value); } + } + + private string _remarks; + public string Remarks + { + get { return _remarks; } + set { SetProperty(ref _remarks, value); } + } + + private ImageSource _previewSource; + public ImageSource PreviewSource + { + get { return _previewSource; } + set { SetProperty(ref _previewSource, value); } + } + + public SelectableCollection Categories { get; } + public MetadataViewModel MetadataModel { get; } + + private string _fileId; + private string _thumbnailId; + + public FileEditViewModel() + { + Categories = new SelectableCollection(); + MetadataModel = new MetadataViewModel(); + PreviewSource = new BitmapImage(); + + //MetadataModel.SetFilterChangedHandle(); + } + + public async Task GetCategoriesAsync() + { + using (var client = HttpClientFactory.CreateClient(ClientNames.ApiClient)) + { + var categories = await client.GetCategoriesAsync(filterByRole: true); + Categories.Load(categories); + } + } + + public async Task LoadFileData(string id) + { + if (string.IsNullOrEmpty(id)) return; + + using (var httpClient = HttpClientFactory.CreateClient(ClientNames.ApiClient)) + { + try + { + var response = await httpClient.GetAsync(Api.CdrFileById.FormatRoute(id)); + if (response.IsSuccessStatusCode) + { + var json = await response.Content.ReadAsStringAsync(); + var fileData = JsonConvert.DeserializeObject>(json); + if (fileData?.Data != null) + { + var fileApi = fileData.Data; + Name = fileApi.Name; + Area = fileApi.Area; + Remarks = fileApi.Remarks; + Categories.SelectBy(x => x.Id == fileApi.Category?.Id); + MetadataModel.Types.SelectBy(x => x.Id == fileApi.Type?.Id); + MetadataModel.Brands.SelectBy(x => x.Id == fileApi.Brand?.Id); + MetadataModel.Series.SelectBy(x => x.Id == fileApi.Series?.Id); + MetadataModel.Models.SelectBy(x => x.Id == fileApi.Model?.Id); + MetadataModel.SubTypes.SelectBy(x => x.Id == fileApi.SubType?.Id); + MetadataModel.Years.SelectBy(x => x.Id == fileApi.Year?.Id); + + _thumbnailId = fileApi.Thumbnail?.Id; + _fileId = fileApi.File?.Id; + await LoadThumbnail(_thumbnailId); + } + } + } + catch (Exception ex) + { + } + } + } + + public async Task LoadThumbnail(string thumbnailId) + { + using (var httpClient = HttpClientFactory.CreateClient(ClientNames.ApiClient)) + { + using (var stream = new MemoryStream()) + { + var response = await httpClient.DownloadAsync(Api.Download.FormatRoute(thumbnailId), stream); + if (response) + { + stream.Seek(0, SeekOrigin.Begin); + await PreviewSource.LoadStreamAsync(stream.AsRandomAccessStream()); + } + } + } + } + + public async Task UpdateFileAsync(string id, StorageFile file, Image image) + { + string fileId = _fileId; + string thumbnailId = _thumbnailId; + if (file != null) + { + using (var stream = await file.OpenReadAsync()) + { + fileId = await UpLoadFileAsync(file.Name, stream.AsStreamForRead()); + } + if (string.IsNullOrEmpty(fileId)) + { + var uploadAgainDialog = new MessageDialog("Please select a file to upload!"); + await uploadAgainDialog.ShowAsync(); + return false; + } + + using (var stream = await image.CreateThumbnailAsync()) + { + thumbnailId = await UpLoadFileAsync(Path.GetFileNameWithoutExtension(file.Name) + ".png", stream.AsStreamForRead()); + } + if (string.IsNullOrEmpty(thumbnailId)) + { + var uploadAgainDialog = new MessageDialog("Please upload a Image first!"); + await uploadAgainDialog.ShowAsync(); + return false; + } + } + if (string.IsNullOrEmpty(Name)) + { + await new MessageDialog("Name cannot be null").ShowAsync(); + return false; + } + try + { + var fileInfo = new UpsertFile + { + FileId = fileId, + Name = this.Name, + Thumbnail = thumbnailId, + Category = Categories.SelectedItem?.Id, + Type = MetadataModel.Types.SelectedItem?.Id, + Brand = MetadataModel.Brands.SelectedItem?.Id, + Series = MetadataModel.Series.SelectedItem?.Id, + Model = MetadataModel.Models.SelectedItem?.Id, + SubType = MetadataModel.SubTypes.SelectedItem?.Id, + Year = MetadataModel.Years.SelectedItem?.Id, + Area = this.Area, + Remarks = this.Remarks + }; + using (HttpClient client = HttpClientFactory.CreateClient(ClientNames.ApiClient)) + { + var response = await client.PutAsJsonAsync(Api.CdrFileById.FormatRoute(id), fileInfo); + if (!response.IsSuccessStatusCode) + { + var failDialog = new MessageDialog("Error editing the file while editing!"); + await failDialog.ShowAsync(); + return false; + } + } + } + catch (Exception ex) + { + var errorDialog = new MessageDialog($"Error: {ex.Message}"); + await errorDialog.ShowAsync(); + return false; + } + var successDialog = new MessageDialog("File edited successfully!"); + await successDialog.ShowAsync(); + return true; + } + + private async Task UpLoadFileAsync(string name, Stream stream) + { + try + { + using (HttpClient client = HttpClientFactory.CreateClient(ClientNames.ApiClient)) + { + var content = new MultipartFormDataContent(); + var streamContent = new StreamContent(stream); + streamContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data") + { + Name = "file", + FileName = name + }; + content.Add(streamContent); + + var response = await client.PostAsync(Api.Upload, content); + if (response.IsSuccessStatusCode) + { + var uploadResponse = await response.DeserializeObjectAsync>(); + return uploadResponse.Data.Id; + } + else + { + var errorDialog = new MessageDialog("Error uploading file!"); + await errorDialog.ShowAsync(); + } + } + } + catch (Exception ex) + { + var exceptionDialog = new MessageDialog($"Error: {ex.Message}"); + await exceptionDialog.ShowAsync(); + } + return null; + } + } +} diff --git a/PCUT/PCUT/ViewModels/FileListViewModel.cs b/PCUT/PCUT/ViewModels/FileListViewModel.cs new file mode 100644 index 0000000..5be7c61 --- /dev/null +++ b/PCUT/PCUT/ViewModels/FileListViewModel.cs @@ -0,0 +1,328 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Windows.Storage; +using Windows.UI.Xaml.Media; +using Windows.UI.Xaml.Media.Imaging; +using Newtonsoft.Json; +using PCUT.Entities; +using PCUT.Entities.ApiResponse; +using PCUT.Extensions; +using PCUT.Models; +using Http.Core; +using Http.Core.Contexts; +using Http.Core.Extensions; +using static Http.Core.Constants.HttpConstants; +using System.ComponentModel; +using Windows.ApplicationModel.Core; + +namespace PCUT.ViewModels +{ + internal class FileListViewModel : NotificationBase + { + public PaginationViewModel Pagination { get; } + public MetadataViewModel MetadataModel { get; } + + private SelectableCollection _categories; + public SelectableCollection Categories + { + get => _categories; + set + { + if (_categories != null) + MetadataModel.UnbindPropertyChangedHandle(_categories); + SetProperty(ref _categories, value ?? new SelectableCollection(new Category { Name = "-None-" })); + MetadataModel.BindPropertyChangedHandle(_categories); + } + } + + public SelectableCollection FilteredFiles { get; } + private readonly IDictionary _thumbnailSources = new Dictionary(); + private readonly FilterModel _filterModel; + + private bool _filterMetadata; + private readonly Predicate[] _metadataFilters = new Predicate[6]; + + public FileListViewModel() + { + FilteredFiles = new SelectableCollection(); + MetadataModel = new MetadataViewModel(); + + _filterModel = new FilterModel(); + + _metadataFilters[0] = type => _filterModel.TypeIds.Contains(type.Id); + _metadataFilters[1] = brand => _filterModel.BrandIds.Contains(brand.Id); + _metadataFilters[2] = serie => _filterModel.SeriesIds.Contains(serie.Id); + _metadataFilters[3] = model => _filterModel.ModelIds.Contains(model.Id); + _metadataFilters[4] = subType => _filterModel.SubTypeIds.Contains(subType.Id); + _metadataFilters[5] = year => _filterModel.YearIds.Contains(year.Id); + + MetadataModel.MetadataChanged += OnMetadataChanged; + MetadataModel.SetFilterChangedHandle(); + + Pagination = new PaginationViewModel(withSearch: true); + Pagination.TextSearched += async (sender, args) => await SearchFileAsync(args.Text); + Pagination.PageChanged += OnPageChanged; + } + + public void SetFilterMetadataOnFileChange() + { + _filterMetadata = true; + } + + public async Task GetCategoriesAsync() + { + using (var client = HttpClientFactory.CreateClient(ClientNames.ApiClient)) + { + var categories = await client.GetCategoriesAsync(filterByRole: true); + Categories.Load(categories); + } + } + + public async Task Reload() + { + await GetFilesByFilterAsync(Pagination.Page, Pagination.PageSize, Pagination.SearchText); + var loadThumbnailTask = LoadThumbnailsAsync(); + if (_filterMetadata) + FilterMetadata(null); + await loadThumbnailTask; + } + + private async void OnPageChanged(object sender, PageChangedEventArgs args) + { + await GetFilesByFilterAsync(args.Page, args.PageSize, Pagination.SearchText); + var loadThumbnailTask = LoadThumbnailsAsync(); + //if (_filterMetadata) + // FilterMetadata(null); + await loadThumbnailTask; + } + + private async void OnMetadataChanged(object sender, MetadataChangedEventArgs args) + { + Pagination.PageChanged -= OnPageChanged; + Pagination.Page = 1; + _filterModel.Clear(); + await GetFilesAsync(args.MetadataType); + Pagination.PageChanged += OnPageChanged; + } + + public async Task GetFilesAsync(string metadataType = null) + { + await GetFilesByFilterAsync(Pagination.Page, Pagination.PageSize, Pagination.SearchText); + var loadThumbnailTask = LoadThumbnailsAsync(); + if (_filterMetadata) + FilterMetadata(metadataType); + await loadThumbnailTask; + } + + public async Task SearchFileAsync(string searchText) + { + await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, async () => + { + await GetFilesByFilterAsync(Pagination.Page, Pagination.PageSize, searchText); + await LoadThumbnailsAsync(); + }); + } + + private async Task GetFilesByFilterAsync(int page, int pageSize, string searchText) + { + var url = CreateFilterUrl(page, pageSize, searchText); + using (var httpClient = HttpClientFactory.CreateClient(ClientNames.ApiClient)) + { + try + { + var response = await httpClient.GetAsync(url); + if (response.IsSuccessStatusCode) + { + var apiResponse = await response.DeserializeObjectAsync>>(); + var data = apiResponse.Data; + int totalPages; + if (_filterModel.IsLoaded) + { + totalPages = apiResponse.Pagination.TotalPages; + } + else + { + totalPages = (int)Math.Ceiling((double)apiResponse.Pagination.TotalRecords / pageSize); + _filterModel.Load(data); + data = data.Take(pageSize); + } + Pagination.Page = apiResponse.Pagination.Page; + Pagination.TotalPage = totalPages; + Pagination.TotalRecords = apiResponse.Pagination.TotalRecords; + + int displayId = (apiResponse.Pagination.Page - 1) * pageSize + 1; + var files = data.Select(file => + { + file.FileId = file.File?.Id; + file.ThumbnailSource = GetOrCreateThumbnailSource(file); + file.DisplayId = displayId.ToString(); + + displayId++; + return file; + }); + FilteredFiles.Load(files); + } + } + catch (Exception ex) + { + + } + } + } + + private string CreateFilterUrl(int page, int pageSize, string searchText) + { + if (!_filterModel.IsLoaded) + pageSize = int.MaxValue; + + var filterBuilder = new StringBuilder(); + if (Categories.SelectedItem != default) + filterBuilder.AppendFilter("category", Categories.SelectedItem.Id); + if (MetadataModel.Brands.SelectedItem != default) + filterBuilder.AppendFilter("brand", MetadataModel.Brands.SelectedItem.Id); + if (MetadataModel.Types.SelectedItem != default) + filterBuilder.AppendFilter("type", MetadataModel.Types.SelectedItem.Id); + if (MetadataModel.Models.SelectedItem != default) + filterBuilder.AppendFilter("_model", MetadataModel.Models.SelectedItem.Id); + if (MetadataModel.Series.SelectedItem != default) + filterBuilder.AppendFilter("series", MetadataModel.Series.SelectedItem.Id); + if (MetadataModel.Years.SelectedItem != default) + filterBuilder.AppendFilter("year", MetadataModel.Years.SelectedItem.Id); + if (MetadataModel.SubTypes.SelectedItem != default) + filterBuilder.AppendFilter("subType", MetadataModel.SubTypes.SelectedItem.Id); + + if (!string.IsNullOrEmpty(searchText)) + filterBuilder.AppendFilter("name", "cn", searchText); + + var filter = filterBuilder.BuildFilter().ToString(); + + return PathBuilder.FromRouteTemplate(Api.CdrFiles) + .AddQuery("filter", filter) + .AddQuery("page", page.ToString()) + .AddQuery("pageSize", pageSize.ToString()) + .AddQuery("sort", "createdAt:desc") + .Build(); + } + + private void FilterMetadata(string metadataType) + { + MetadataModel.FilterAll(metadataType, _metadataFilters); + } + + private ImageSource GetOrCreateThumbnailSource(CdrFileModel file) + { + if (file.Thumbnail == null) + return null; + + if (_thumbnailSources.TryGetValue(file.Thumbnail.Id, out var thumbnail)) + return thumbnail.Source; + + thumbnail = new ThumbnailSource(new BitmapImage()); + _thumbnailSources[file.Thumbnail.Id] = thumbnail; + return thumbnail.Source; + } + + private async Task LoadThumbnailsAsync() + { + try + { + await Task.WhenAll( + _thumbnailSources.Where(x => !x.Value.IsLoaded).Select(x => x.Value.LoadAsync(x.Key))); + } + catch + { + } + } + + public class CdrFileModel : CdrFile + { + public ImageSource ThumbnailSource { get; set; } + public string FileId { get; set; } + public string DisplayId { get; set; } + } + + private class FilterModel + { + public readonly List TypeIds = new List(); + public readonly List BrandIds = new List(); + public readonly List SeriesIds = new List(); + public readonly List ModelIds = new List(); + public readonly List SubTypeIds = new List(); + public readonly List YearIds = new List(); + + public bool IsLoaded { get; set; } + + public void Clear() + { + TypeIds.Clear(); + BrandIds.Clear(); + SeriesIds.Clear(); + ModelIds.Clear(); + SubTypeIds.Clear(); + YearIds.Clear(); + IsLoaded = false; + } + + public void Load(IEnumerable data) + { + TypeIds.AddRange(data.Select(x => x.Type?.Id).Where(x => x != null).Distinct()); + BrandIds.AddRange(data.Select(x => x.Brand?.Id).Where(x => x != null).Distinct()); + SeriesIds.AddRange(data.Select(x => x.Series?.Id).Where(x => x != null).Distinct()); + ModelIds.AddRange(data.Select(x => x.Model?.Id).Where(x => x != null).Distinct()); + SubTypeIds.AddRange(data.Select(x => x.SubType?.Id).Where(x => x != null).Distinct()); + YearIds.AddRange(data.Select(x => x.Year?.Id).Where(x => x != null).Distinct()); + IsLoaded = true; + } + } + + private class ThumbnailSource + { + public ImageSource Source { get; set; } + public bool IsLoaded { get; set; } + + public ThumbnailSource(ImageSource source) + { + Source = source; + IsLoaded = false; + } + + public async Task LoadAsync(string id) + { + if (!IsLoaded) + { + IsLoaded = true; + try + { + await LoadThumbnailAsync(id); + } + catch + { + IsLoaded = false; + throw; + } + } + } + + private async Task LoadThumbnailAsync(string thumbnailId) + { + using (var httpClient = HttpClientFactory.CreateClient(ClientNames.ApiClient)) + { + using (var stream = new MemoryStream()) + { + var response = await httpClient.DownloadAsync(Api.Download.FormatRoute(thumbnailId), stream); + if (response) + { + stream.Seek(0, SeekOrigin.Begin); + await Source.LoadStreamAsync(stream.AsRandomAccessStream()); + } + } + } + } + } + } +} diff --git a/PCUT/PCUT/ViewModels/ImageViewModel.cs b/PCUT/PCUT/ViewModels/ImageViewModel.cs new file mode 100644 index 0000000..7709d35 --- /dev/null +++ b/PCUT/PCUT/ViewModels/ImageViewModel.cs @@ -0,0 +1,57 @@ +using System.ComponentModel; +using System.Xml.Linq; +using PCUT.Extensions; +using Windows.UI.Xaml.Media; +using Windows.UI.Xaml.Media.Imaging; + +namespace PCUT.ViewModels +{ + public class ImageViewModel : INotifyPropertyChanged + { + public event PropertyChangedEventHandler PropertyChanged; + + private ImageSource _source; + private ImageSource _defaultSource = new SvgImageSource(); + + public ImageSource Source + { + get => _source; + private set + { + _source = value; + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Source))); + DefaultMode = value == _defaultSource; + } + } + + public void SetSource(ImageSource source) + { + if (source == null) + return; + Source = source; + } + + public void SetSource(XDocument doc) + { + Source = _defaultSource; + if (doc != null) + _ = _source.LoadSvgAsync(doc); + } + + public void ShowDefault() + { + Source = _defaultSource; + } + + private bool _defaultMode = true; + public bool DefaultMode + { + get => _defaultMode; + private set + { + _defaultMode = value; + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(DefaultMode))); + } + } + } +} diff --git a/PCUT/PCUT/ViewModels/LoadingModel.cs b/PCUT/PCUT/ViewModels/LoadingModel.cs new file mode 100644 index 0000000..ff62af0 --- /dev/null +++ b/PCUT/PCUT/ViewModels/LoadingModel.cs @@ -0,0 +1,25 @@ +using System.ComponentModel; +using System.Threading; + +namespace PCUT.ViewModels +{ + public class LoadingModel : INotifyPropertyChanged + { + public event PropertyChangedEventHandler PropertyChanged; + + private int _count; + public int Count { get; } + + public void SetCount(int count) + { + _ = Interlocked.Exchange(ref _count, count); + } + + public void DecreaseCount() + { + var count = Interlocked.Decrement(ref _count); + if (count <= 0) + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Count))); + } + } +} diff --git a/PCUT/PCUT/ViewModels/LogOutViewModel.cs b/PCUT/PCUT/ViewModels/LogOutViewModel.cs new file mode 100644 index 0000000..c43efda --- /dev/null +++ b/PCUT/PCUT/ViewModels/LogOutViewModel.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace PCUT.ViewModels +{ + public class LogOutViewModel + { + } +} diff --git a/PCUT/PCUT/ViewModels/LoginViewModel.cs b/PCUT/PCUT/ViewModels/LoginViewModel.cs new file mode 100644 index 0000000..44944d5 --- /dev/null +++ b/PCUT/PCUT/ViewModels/LoginViewModel.cs @@ -0,0 +1,215 @@ +using Http.Core; +using Http.Core.Contexts; +using Http.Core.Extensions; +using Http.Core.Models; +using PCUT.Extensions; +using PCUT.Helpers; +using PCUT.Models; +using PCUT.Pages; +using System; +using System.Security.Cryptography; +using System.Threading.Tasks; +using System.Windows.Input; +using Windows.Security.Credentials; +using Windows.Security.Cryptography; +using Windows.System.Profile; +using Windows.UI.Popups; +using Windows.UI.Xaml; +using Windows.UI.Xaml.Controls; +using static Http.Core.Constants.HttpConstants; +using static Http.Core.Extensions.HttpExtensions; + +namespace PCUT.ViewModels +{ + public class LoginViewModel : NotificationBase + { + private const string REMEMBER_ME_KEY = "RememberMe"; + private const string REMEMBER_USER_KEY = "RememberMeUser"; + private const string DEVICE_ID_KEY = "DeviceId"; + + private bool _rememberMe; + public bool RememberMe + { + get { return _rememberMe; } + set + { + SetProperty(ref _rememberMe, value); + var localSettings = Windows.Storage.ApplicationData.Current.LocalSettings; + localSettings.Values[REMEMBER_ME_KEY] = value; + } + } + + private string _username; + public string Username + { + get { return _username; } + set + { + SetProperty(ref _username, value); + LoginEnabled = CheckLoginEnabled(); + } + } + + private string _password; + public string Password + { + get { return _password; } + set + { + SetProperty(ref _password, value); + LoginEnabled = CheckLoginEnabled(); + } + } + + private bool _loginEnabled = false; + public bool LoginEnabled + { + get { return _loginEnabled; } + private set + { + if (_loginEnabled != value) + SetProperty(ref _loginEnabled, value); + } + } + #region Commands + public ICommand NavigateMainCommand { get; private set; } + #endregion + + private bool _success = false; + private async Task LoginAsync() + { + LoginEnabled = false; + try + { + var localSettings = Windows.Storage.ApplicationData.Current.LocalSettings; + localSettings.Values.Remove(REMEMBER_USER_KEY); + + bool loginSuccess = false; + string errorMessage = null; + using (var client = HttpClientFactory.CreateClient(ClientNames.AuthClient)) + { + try + { + var loginResult = await client.LoginAsync(new LoginRequest(Username, Password), Username); + loginSuccess = loginResult.Success; + if (!loginSuccess) + errorMessage = loginResult.Message; + } + catch (Exception ex) + { + errorMessage = ex.Message; + } + } + + if (!loginSuccess) + { + await new MessageDialog(errorMessage).ShowAsync(); + return; + } + + using (var client = HttpClientFactory.CreateClient(ClientNames.ApiClient)) + { + try + { + await client.LoadUserProfileAsync(); + } + catch { } + } + + if (RememberMe) + { + localSettings.Values[REMEMBER_USER_KEY] = Username; + UpsertRememberMe(Username, Password); + } + + _success = true; + await Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () => + { + ((Frame)Window.Current.Content).Navigate(typeof(MainMenuPage)); + }); + } + finally + { + if (!_success) + LoginEnabled = CheckLoginEnabled(); + } + } + + public LoginViewModel() + { + var localSettings = Windows.Storage.ApplicationData.Current.LocalSettings; + if (localSettings.TryGetValue(REMEMBER_ME_KEY, out var rememberMe) && rememberMe) + { + RememberMe = true; + if (localSettings.TryGetValue(REMEMBER_USER_KEY, out var userName)) + (Username, Password) = LoadRememberMe(userName); + } + if (!localSettings.TryGetValue(DEVICE_ID_KEY, out var deviceId) || string.IsNullOrEmpty(deviceId)) + { + var sysInfo = SystemIdentification.GetSystemIdForPublisher(); + if (sysInfo != null) + { + deviceId = CryptographicBuffer.EncodeToBase64String(sysInfo.Id); + } + else + { + // random int64 number + var salt = new byte[8]; + RandomNumberGenerator.Create().GetNonZeroBytes(salt); + // random guid + var uuid = Guid.NewGuid().ToByteArray(); + // random timestamp + var timestamp = BitConverter.GetBytes(DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()); + + var data = new byte[uuid.Length + timestamp.Length + salt.Length]; + Array.Copy(salt, 0, data, 0, salt.Length); + Array.Copy(uuid, 0, data, 0 + salt.Length, uuid.Length); + Array.Copy(timestamp, 0, data, 0 + salt.Length + uuid.Length, timestamp.Length); + + deviceId = Convert.ToBase64String(data); + } + localSettings.Values[DEVICE_ID_KEY] = deviceId; + } + UserContext.Instance.SetDeviceId(deviceId); + NavigateMainCommand = new RelayCommand(LoginAsync, () => !_success); + } + + private bool CheckLoginEnabled() + { + return !string.IsNullOrWhiteSpace(_username) && !string.IsNullOrWhiteSpace(_password); + } + + private (string UserName, string Password) LoadRememberMe(string userName) + { + if (string.IsNullOrWhiteSpace(userName)) + return default; + + var vault = new PasswordVault(); + try + { + var credential = vault.Retrieve(REMEMBER_ME_KEY, userName); + return (credential?.UserName, credential?.Password); + } + catch + { + return default; + } + } + + private void UpsertRememberMe(string userName, string password) + { + var vault = new PasswordVault(); + PasswordCredential credential; + try + { + credential = vault.Retrieve(REMEMBER_ME_KEY, userName); + credential.Password = password; + } + catch + { + credential = new PasswordCredential(REMEMBER_ME_KEY, userName, password); + } + vault.Add(credential); + } + } +} diff --git a/PCUT/PCUT/ViewModels/MainMenuPageViewModel.cs b/PCUT/PCUT/ViewModels/MainMenuPageViewModel.cs new file mode 100644 index 0000000..873a685 --- /dev/null +++ b/PCUT/PCUT/ViewModels/MainMenuPageViewModel.cs @@ -0,0 +1,103 @@ +using Http.Core; +using PCUT.Entities; +using PCUT.Models; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Runtime.CompilerServices; +using System.Text; +using System.Threading.Tasks; +using Http.Core; +using Http.Core.Extensions; +using static Http.Core.Constants.HttpConstants; +using Newtonsoft.Json; +using Windows.UI.Popups; +using Http.Core.Contexts; +using System.Collections.ObjectModel; +using Windows.UI.Xaml.Controls; +using Windows.UI.Xaml; + +namespace PCUT.ViewModels +{ + public class MainMenuPageViewModel : NotificationBase + { + private string _userName; + public string UserName + { + get => _userName; + set => SetProperty(ref _userName, value); + } + + private string _expiry; + public string Expiry + { + get => _expiry; + set => SetProperty(ref _expiry, value); + } + + private bool _isUserRoleAdmin = false; + public bool IsUserRoleAdmin + { + get => _isUserRoleAdmin; + set + { + if (_isUserRoleAdmin != value) + { + _isUserRoleAdmin = value; + RaisePropertyChanged(nameof(IsUserRoleAdmin)); + } + } + } + + private bool _isMenuEnabled = false; + public bool IsMenuEnabled + { + get => _isMenuEnabled; + set + { + SetProperty(ref _isMenuEnabled, value); + } + } + + private Visibility _isMenuDisplay = Visibility.Collapsed; + public Visibility IsMenuDisplay + { + get => _isMenuDisplay; + set + { + if (_isMenuDisplay != value) + { + SetProperty(ref _isMenuDisplay, value); + } + } + } + + public SelectableCollection Categories { get; } + + public MainMenuPageViewModel() + { + IsUserRoleAdmin = UserContext.Instance.Profile?.Role?.Equals("admin", StringComparison.OrdinalIgnoreCase) ?? false; + Categories = new SelectableCollection(new Category { Name = "-None-" }); + } + + public void ToggleMenuDisplay() + { + IsMenuDisplay = IsMenuDisplay == Visibility.Collapsed ? Visibility.Visible : Visibility.Collapsed; + } + + public void HideMenuDisplay() + { + IsMenuDisplay = Visibility.Collapsed; + } + + public async Task GetCategoriesAsync() + { + using (var client = HttpClientFactory.CreateClient(ClientNames.ApiClient)) + { + var categories = await client.GetCategoriesAsync(filterByRole: true); + Categories.Load(categories); + } + } + } +} diff --git a/PCUT/PCUT/ViewModels/MetadataViewModel.cs b/PCUT/PCUT/ViewModels/MetadataViewModel.cs new file mode 100644 index 0000000..4ee07e4 --- /dev/null +++ b/PCUT/PCUT/ViewModels/MetadataViewModel.cs @@ -0,0 +1,226 @@ +using Http.Core; +using PCUT.Entities; +using PCUT.Entities.ApiResponse; +using PCUT.Models; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Threading.Tasks; +using Http.Core.Extensions; +using Windows.UI.Xaml.Controls.Primitives; +using static Http.Core.Constants.HttpConstants; + +namespace PCUT.ViewModels +{ + public class MetadataViewModel : NotificationBase + { + public event MetadataChangedEventHandler MetadataChanged; + + public const string TypeHeader = "Type"; + public const string BrandHeader = "Brand"; + public const string SerieHeader = "Series"; + public const string ModelHeader = "Model"; + public const string SubTypeHeader = "SubType"; + public const string YearHeader = "Year"; + + public SelectableCollection MetadataTypes { get; } + + public SelectableCollection Types { get; set; } + public SelectableCollection Brands { get; set; } + public SelectableCollection Series { get; set; } + public SelectableCollection Models { get; set; } + public SelectableCollection SubTypes { get; set; } + public SelectableCollection Years { get; set; } + + private readonly List> _collections; + + public MetadataViewModel() + { + MetadataTypes = new SelectableCollection( + withDefault: false, + TypeHeader, + BrandHeader, + SerieHeader, + ModelHeader, + SubTypeHeader, + YearHeader + ); + + var defaultMetadata = new CategoryMetadata { Value = "-None-" }; + Types = new SelectableCollection(defaultMetadata); + Brands = new SelectableCollection(defaultMetadata); + Series = new SelectableCollection(defaultMetadata); + Models = new SelectableCollection(defaultMetadata); + SubTypes = new SelectableCollection(defaultMetadata); + Years = new SelectableCollection(defaultMetadata); + _collections = new List> { Types, Brands, Series, Models, SubTypes, Years }; + + MetadataChanged += OnMetadataChanged; + } + + public void BindAll(params Selector[] selectors) + { + for (int i = 0; i < selectors.Length && i < _collections.Count; i++) + _collections[i].Bind(selectors[i]); + } + + public void FilterAll(string type = null, params Predicate[] filters) + { + var index = type == null ? -1 : MetadataTypes.Items.IndexOf(type); + for (int i = index + 1; i < _collections.Count; i++) + _collections[i].Filter(filters[i]); + } + + public void UnselectAll(string type = null) + { + var index = type == null ? -1 : MetadataTypes.Items.IndexOf(type); + for (int i = index + 1; i < _collections.Count; i++) + _collections[i].SelectedIndex = -1; + } + + public void SetFilterChangedHandle() + { + AssignHandler(OnPropertyChanged); + } + + public void UnsetFilterChangedHandle() + { + RemoveHandler(OnPropertyChanged); + } + + public void BindPropertyChangedHandle(SelectableCollection collection) + { + collection.PropertyChanged += OnPropertyChanged; + } + + public void UnbindPropertyChangedHandle(SelectableCollection collection) + { + collection.PropertyChanged -= OnPropertyChanged; + } + + private void AssignHandler(PropertyChangedEventHandler handler, string type = null) + { + var index = type == null ? -1 : MetadataTypes.Items.IndexOf(type); + for (int i = index + 1; i < _collections.Count; i++) + _collections[i].PropertyChanged += handler; + } + + private void RemoveHandler(PropertyChangedEventHandler handler, string type = null) + { + var index = type == null ? -1 : MetadataTypes.Items.IndexOf(type); + for (int i = index + 1; i < _collections.Count; i++) + _collections[i].PropertyChanged -= handler; + } + + private void OnPropertyChanged(object sender, PropertyChangedEventArgs args) + { + if (args.PropertyName == nameof(SelectableCollection.SelectedIndex)) + { + var metadataType = sender == Types ? TypeHeader + : sender == Brands ? BrandHeader + : sender == Series ? SerieHeader + : sender == Models ? ModelHeader + : sender == SubTypes ? SubTypeHeader + : sender == Years ? YearHeader + : null; + RemoveHandler(OnPropertyChanged, metadataType); + MetadataChanged?.Invoke(sender, new MetadataChangedEventArgs(metadataType, args)); + AssignHandler(OnPropertyChanged, metadataType); + } + } + + private void OnMetadataChanged(object sender, MetadataChangedEventArgs args) + { + UnselectAll(args.MetadataType); + } + + public async Task LoadAllMetadataAsync() + { + await Task.WhenAll( + LoadMetadataAsync(TypeHeader), + LoadMetadataAsync(BrandHeader), + LoadMetadataAsync(SerieHeader), + LoadMetadataAsync(ModelHeader), + LoadMetadataAsync(SubTypeHeader), + LoadMetadataAsync(YearHeader) + ); + } + + private async Task LoadMetadataAsync(string type) + { + var metadataList = await GetMetadataAsync(type); + SelectableCollection collections = null; + switch (type) + { + case TypeHeader: + collections = Types; + break; + case BrandHeader: + collections = Brands; + break; + case SerieHeader: + collections = Series; + break; + case ModelHeader: + collections = Models; + break; + case SubTypeHeader: + collections = SubTypes; + break; + case YearHeader: + collections = Years; + break; + default: + break; + } + collections?.Load(metadataList); + } + + private static async Task> GetMetadataAsync(string type) + { + using (var client = HttpClientFactory.CreateClient(ClientNames.ApiClient)) + { + try + { + var url = PathBuilder.FromRouteTemplate(Api.Metadata) + .AddQuery("filter", $"[\"type:eq:{type.ToUpper()}\"]") + .AddQuery("sort", "createdAt:desc") + .Build(); + var response = await client.GetAsync(url); + if (response.IsSuccessStatusCode) + { + var content = await response.DeserializeObjectAsync>>(); + return content.Data; + } + } + catch + { + } + } + return Enumerable.Empty(); + } + } + + public delegate void MetadataChangedEventHandler(object sender, MetadataChangedEventArgs args); + public class MetadataChangedEventArgs : EventArgs + { + private readonly string _metadataType; + public virtual string MetadataType + { + get => _metadataType; + } + + private readonly PropertyChangedEventArgs _propertyChangedArgs; + public virtual PropertyChangedEventArgs PropertyChangedArgs + { + get => _propertyChangedArgs; + } + + public MetadataChangedEventArgs(string metadataType, PropertyChangedEventArgs propertyChangedArgs) + { + _metadataType = metadataType; + _propertyChangedArgs = propertyChangedArgs; + } + } +} diff --git a/PCUT/PCUT/ViewModels/NestingProgressModel.cs b/PCUT/PCUT/ViewModels/NestingProgressModel.cs new file mode 100644 index 0000000..5a4955b --- /dev/null +++ b/PCUT/PCUT/ViewModels/NestingProgressModel.cs @@ -0,0 +1,31 @@ +using System.ComponentModel; + +namespace PCUT.ViewModels +{ + public class NestingProgressModel : INotifyPropertyChanged + { + public event PropertyChangedEventHandler PropertyChanged; + + private double _progress = 0; + public double Progress + { + get => _progress; + set + { + _progress = value; + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Progress))); + } + } + + private bool _running = false; + public bool Running + { + get => _running; + set + { + _running = value; + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Running))); + } + } + } +} diff --git a/PCUT/PCUT/ViewModels/PaginationViewModel.cs b/PCUT/PCUT/ViewModels/PaginationViewModel.cs new file mode 100644 index 0000000..389fd44 --- /dev/null +++ b/PCUT/PCUT/ViewModels/PaginationViewModel.cs @@ -0,0 +1,139 @@ +using PCUT.Models; +using System; +using System.Collections.Generic; +using System.Timers; +using PCUT.Extensions; + +namespace PCUT.ViewModels +{ + public class PaginationViewModel : NotificationBase, IDisposable + { + private const string PageSizeKey = "PCUT_list_pagesize"; + private const int DefaultPageSize = 20; + + public event PageChangedEventHandler PageChanged; + public event TextSearchedEventHandler TextSearched; + + private readonly Timer _timer; + + public PaginationViewModel(bool withSearch = false) + { + if (withSearch) + { + _timer = new Timer(500); + _timer.AutoReset = false; + _timer.Enabled = true; + _timer.Elapsed += (sender, args) => { + TextSearched?.Invoke(this, new TextSearchEventArgs(SearchText)); + }; + _timer.Stop(); + } + _pageSize = GetPageSize(); + PropertyChanged += (sender, args) => + { + if (args.PropertyName == nameof(Page) || args.PropertyName == nameof(PageSize)) + { + PageChanged?.Invoke(this, new PageChangedEventArgs(Page, PageSize)); + } + }; + } + + public List AvailablePageSizes { get; } = new List { 20, 50, 100, 200 }; + + private string _searchText; + public string SearchText + { + get => _searchText; + set + { + if (_searchText != value) + { + _searchText = value; + RaisePropertyChanged(nameof(SearchText)); + _timer.Stop(); + _timer.Start(); + } + } + } + + private int _page = 0; + public int Page + { + get { return _page; } + set + { + if (_page != value && value > 0 && value <= _totalPage) + SetProperty(ref _page, value); + } + } + + private int _pageSize; + public int PageSize + { + get { return _pageSize; } + set + { + SetProperty(ref _pageSize, value); + SetPageSize(value); + } + } + + private int _totalPage = 1; + public int TotalPage + { + get { return _totalPage; } + set { SetProperty(ref _totalPage, value); } + + } + + private int _totalRecords = 0; + public int TotalRecords + { + get { return _totalRecords; } + set { SetProperty(ref _totalRecords, value); } + } + + public void Dispose() + { + _timer?.Dispose(); + } + + private static int GetPageSize() + { + var localSettings = Windows.Storage.ApplicationData.Current.LocalSettings; + if (localSettings.TryGetValue(PageSizeKey, out var value)) + return value; + else + return DefaultPageSize; + } + + private static void SetPageSize(int pageSize) + { + var localSettings = Windows.Storage.ApplicationData.Current.LocalSettings; + localSettings.Values[PageSizeKey] = pageSize; + } + } + + public delegate void TextSearchedEventHandler(object sender, TextSearchEventArgs args); + public class TextSearchEventArgs : EventArgs + { + public string Text { get; } + public TextSearchEventArgs(string text) + { + Text = text; + } + } + + public delegate void PageChangedEventHandler(object sender, PageChangedEventArgs args); + public class PageChangedEventArgs : EventArgs + { + public int Page { get; } + public int PageSize { get; } + + public PageChangedEventArgs(int page, int pageSize) + { + Page = page; + PageSize = pageSize; + } + } +} diff --git a/PCUT/PCUT/ViewModels/PortSettingViewModel.cs b/PCUT/PCUT/ViewModels/PortSettingViewModel.cs new file mode 100644 index 0000000..7825dd9 --- /dev/null +++ b/PCUT/PCUT/ViewModels/PortSettingViewModel.cs @@ -0,0 +1,128 @@ +using PCUT.Models; +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.IO.Ports; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Windows.Storage; + +namespace PCUT.ViewModels +{ + public class PortSettingViewModel : NotificationBase + { + private int _baudRate; + public int BaudRate + { + get { return _baudRate; } + set { SetProperty(ref _baudRate, value); } + } + + private int _databits; + public int Databits + { + get { return _databits; } + set { SetProperty(ref _databits, value); } + } + + private int _parity; + public int SelectedParity + { + get { return _parity; } + set { SetProperty(ref _parity, value); } + } + + private int _stopbits; + public int SelectedStopbits + { + get { return _stopbits; } + set { SetProperty(ref _stopbits, value); } + } + + private int _speed; + public int Speed + { + get { return _speed; } + set { SetProperty(ref _speed, value); } + } + + private int _pen; + public int SelectedPen + { + get { return _pen; } + set { SetProperty(ref _pen, value); } + } + + public ObservableCollection ParityList = new ObservableCollection() + { + Parity.None, + Parity.Odd, + Parity.Even, + Parity.Mark, + Parity.Space + }; + + public ObservableCollection StopbitsList = new ObservableCollection() + { + StopBits.None, + StopBits.One, + StopBits.Two, + StopBits.OnePointFive, + }; + + public ObservableCollection PenList = new ObservableCollection() + { + 0, + 1, + 2, + 3 + }; + + public void LoadSetting(string portName) + { + var settings = ApplicationData.Current.LocalSettings; + if (settings.Values.TryGetValue($"{portName}_PortBaudrate", out var baudrate)) + BaudRate = (int)baudrate; + else + BaudRate = 9600; + + if (settings.Values.TryGetValue($"{portName}_PortDatabits", out var databits)) + Databits = (int)databits; + else + Databits = 8; + + if (settings.Values.TryGetValue($"{portName}_PortParity", out var parity)) + SelectedParity = (int)parity; + else + SelectedParity = 0; + + if (settings.Values.TryGetValue($"{portName}_PortStopbits", out var stopbits)) + SelectedStopbits = (int)stopbits; + else + SelectedStopbits = 1; + + if (settings.Values.TryGetValue($"{portName}_Speed", out var speed)) + Speed = (int)speed; + else + Speed = 82; + + if (settings.Values.TryGetValue($"{portName}_PortPen", out var pen)) + SelectedPen = (int)pen; + else + SelectedPen = 0; + + } + + public void SaveSetting(string portName) + { + var settings = ApplicationData.Current.LocalSettings; + settings.Values[$"{portName}_PortBaudrate"] = BaudRate; + settings.Values[$"{portName}_PortDatabits"] = Databits; + settings.Values[$"{portName}_PortParity"] = SelectedParity; + settings.Values[$"{portName}_PortStopbits"] = SelectedStopbits; + settings.Values[$"{portName}_Speed"] = Speed; + settings.Values[$"{portName}_PortPen"] = SelectedPen; + } + } +} diff --git a/PCUT/PCUT/ViewModels/SvgData.cs b/PCUT/PCUT/ViewModels/SvgData.cs new file mode 100644 index 0000000..cfbd8ca --- /dev/null +++ b/PCUT/PCUT/ViewModels/SvgData.cs @@ -0,0 +1,318 @@ +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Linq; +using System.Xml.Linq; +using PCUT.Extensions; +using PCUT.DeepNestApi; +using DeepNestLib; + +namespace PCUT.ViewModels +{ + public class SvgData + { + // singleton implementation + private SvgData() { } + private static readonly object _instanceLock = new object(); + private static SvgData _instance; + public static SvgData Instance + { + get + { + if (_instance == null) + { + lock (_instanceLock) + { + if (_instance == null) + _instance = new SvgData(); + } + } + return _instance; + } + } + + // Svg Data + private readonly object _dataLock = new object(); + public XDocument Data { get; private set; } + public string ItemId { get; set; } + public string FileId { get; set; } + + private double? _originWidth; + public double? OriginWidth + { + get => _originWidth; + private set + { + _originWidth = value; + } + } + + private double? _originHeight; + public double? OriginHeight + { + get => _originHeight; + private set + { + _originHeight = value; + } + } + + public string OriginViewBox { get; set; } + + // Only set data once. If required to set data again, need to clear (set to null) first + public void SetData(XDocument data, double? originalWidth = null, double? originalHeight = null) + { + if (Data == null || data == null) + { + lock (_dataLock) + { + if (data == null) + { + if (Data != null) + { + Data.Changing -= DataChangingHandle; + Data.Changed -= DataChangedHandle; + } + CleanUpData(); + } + else if (Data == null) + { + Data = data; + OriginWidth = originalWidth; + OriginHeight = originalHeight; + OriginViewBox = data.GetViewBox(); + data.Changing += DataChangingHandle; + data.Changed += DataChangedHandle; + } + } + } + } + + private readonly ConcurrentDictionary _componentData = new ConcurrentDictionary(); + public int ComponentCount => _componentData.Count; + + public IEnumerable<(string Id, bool Deleted, XDocument Data)> ComponentData => _componentData?.Where(x => x.Value.Data != null) + .OrderBy(x => x.Value.Order) + .Select(x => (x.Key, x.Value.Hidden, x.Value.Data)); + + public IEnumerable<(double Width, double Height)> ComponentBounds => _componentData?.Where(x => x.Value?.Data != null) + .Select(x => (x.Value.Width, x.Value.Height)); + public void AddComponent(string id, bool deleted, XDocument data, double boundWidth, double boundHeight) + { + _ = _componentData.AddOrUpdate( + id, + (_, param) => new SvgComponentData(param.Data, param.Hidden, boundWidth, boundHeight, _componentData.Count), + (_, component, param) => { component.UpdateData(param.Data); return component; }, + (Data: data, Hidden: deleted)); + } + + // Svg Nest Data + private readonly object _resultLock = new object(); + public XDocument NestedData { get; private set; } + public double? NestedWidth { get; private set; } + public double? NestedHeight { get; private set; } + public double MaterialUtilization { get; private set; } = 1; + public void SetResult(XDocument result, double? nestedWidth = null, double? nestedHeight = null, double materialUtilization = 1) + { + lock (_resultLock) + { + NestedData = result; + NestedWidth = nestedWidth; + NestedHeight = nestedHeight; + MaterialUtilization = materialUtilization; + } + } + + private readonly ConcurrentDictionary _detailData = new ConcurrentDictionary(); + public int DetailCount => _detailData.Count; + + public IEnumerable ComponentDetails => _detailData?.Where(x => x.Value?.Detail != null && !x.Value.Hidden) + .Select(x => x.Value.Detail); + + public IEnumerable<(double Width, double Height)> DetailBounds => _detailData?.Where(x => x.Value?.Detail != null && !x.Value.Hidden) + .Select(x => (x.Value.Width, x.Value.Height)); + public void AddDetail(RawDetail detail) + { + _ = _detailData.AddOrUpdate( + detail.Name, + (_, param) => new SvgDetailData(param), + (_, component, param) => { component.UpdateDetail(param); return component; }, + detail); + } + + public void ComputeDetailBounds() + { + foreach (var data in _detailData.Values.Where(x => x.Detail != null)) + { + var bbox = data.Detail.BoundingBox(); + data.Width = bbox.Width; + data.Height = bbox.Height; + } + } + + private readonly object _scaleLock = new object(); + private double? _detailScaleFactor; + public double DetailScaleFactor + { + get => _detailScaleFactor ?? 1; + set + { + if (_detailScaleFactor == null) + { + lock(_scaleLock) + { + if (_detailScaleFactor == null) + _detailScaleFactor = value; + } + } + } + } + + public NestingContext NestingContext { get; set; } + public SheetLoadInfo SheetInfo { get; private set; } + public Dictionary DxfCache { get; } = new Dictionary(); + + public void NewSheetInfo(double width, double height) + { + SheetInfo = new SheetLoadInfo + { + Nfp = NewSheet(width, height), + Width = width, + Height = height, + Quantity = 1 + }; + } + + private Sheet NewSheet(double w = 3000, double h = 1500) + { + var tt = new RectangleSheet(); + tt.Name = "rectSheet"; + tt.Height = h; + tt.Width = w; + tt.Rebuild(); + return tt; + } + + // Clean up + private void CleanUpData() + { + Data = null; + FileId = null; + NestedData = null; + MaterialUtilization = 1; + OriginWidth = null; + OriginHeight = null; + OriginViewBox = null; + _detailScaleFactor = null; + _componentData?.Clear(); + _detailData?.Clear(); + CleanUpContext(); + } + + public void CleanUpContext() + { + NestingContext = null; + SheetInfo = null; + DxfCache?.Clear(); + } + + // Handler + private void DataChangingHandle(object sender, XObjectChangeEventArgs e) + { + switch (sender) + { + case XAttribute attribute: + { + if (attribute.Name.LocalName == "visibility" && e.ObjectChange == XObjectChange.Remove) + { + var id = attribute.Parent.GetId(); + if (_componentData != null && _componentData.ContainsKey(id)) + { + _componentData[id].Hidden = false; + _detailData?.Clear(); + } + } + NestedData = null; + MaterialUtilization = 1; + CleanUpContext(); + break; + } + } + } + + private void DataChangedHandle(object sender, XObjectChangeEventArgs e) + { + switch (sender) + { + case XAttribute attribute: + { + if (attribute.Name.LocalName == "visibility" && e.ObjectChange == XObjectChange.Add && attribute.Value == "hidden") + { + var id = attribute.Parent.GetId(); + if (_componentData != null && _componentData.ContainsKey(id)) + { + _componentData[id].Hidden = true; + _detailData?.Clear(); + } + } + NestedData = null; + MaterialUtilization = 1; + CleanUpContext(); + break; + } + } + } + + public class SvgComponentData + { + public bool Hidden { get; set; } + public XDocument Data { get; set; } + public double Width { get; set; } + public double Height { get; set; } + public int Order { get; set; } + + public SvgComponentData(XDocument data, bool hidden, double width, double height, int order) + { + Data = data; + Hidden = hidden; + Width = width; + Height = height; + Order = order; + } + + public void UpdateData(XDocument data) + { + Data = data; + } + } + + public class SvgDetailData + { + public RawDetail Detail { get; set; } + public double Width { get; set; } + public double Height { get; set; } + public bool Hidden { get; set; } + + public SvgDetailData(RawDetail detail) + { + Detail = detail; + } + + public void UpdateDetail(RawDetail detail) + { + Detail = detail; + } + } + + public class SheetLoadInfo + { + public NFP Nfp; + + public string Info { get; set; } + public double Width { get; set; } + public double Height { get; set; } + public int Quantity { get; set; } + + public double BoundScale { get; set; } + } + } +} diff --git a/PCUT/PCUT/ViewModels/SvgNestSettings.cs b/PCUT/PCUT/ViewModels/SvgNestSettings.cs new file mode 100644 index 0000000..06d301d --- /dev/null +++ b/PCUT/PCUT/ViewModels/SvgNestSettings.cs @@ -0,0 +1,203 @@ +using System.Collections.ObjectModel; +using System.ComponentModel; +using Windows.Storage; + +namespace PCUT.ViewModels +{ + public class SvgNestSettings : INotifyPropertyChanged + { + private SvgNestSettings() { } + private static readonly object _instanceLock = new object(); + private static SvgNestSettings _instance; + public static SvgNestSettings Instance + { + get + { + if (_instance == null) + { + lock (_instanceLock) + { + if (_instance == null) + { + _instance = new SvgNestSettings(); + _instance.LoadSettings(); + _instance.ApplySettings(); + } + } + } + return _instance; + } + } + + public event PropertyChangedEventHandler PropertyChanged; + + private int _maxNumberOfRun = 10; + public int MaxNumberOfRun + { + get => _maxNumberOfRun; + set + { + _maxNumberOfRun = value; + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(MaxNumberOfRun))); + } + } + + private int _maxRuntimeInMinutes = 5; + public int MaxRuntimeInMinute + { + get => _maxRuntimeInMinutes; + set + { + _maxRuntimeInMinutes = value; + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(MaxRuntimeInMinute))); + } + } + + private double _curveTolerance = 0.3; + public double CurveTolerance + { + get => _curveTolerance; + set + { + _curveTolerance = value; + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(CurveTolerance))); + } + } + + private double _spacing = 0; + public double Spacing + { + get => _spacing; + set + { + _spacing = value; + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Spacing))); + } + } + + public ObservableCollection ValidRotations = new ObservableCollection { 2, 4, 8 }; + private int _rotations = 4; + public int Rotations + { + get => _rotations; + set + { + if (_rotations != value) + { + _rotations = value; + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Rotations))); + } + } + } + + private int _populationSize = 10; + public int PopulationSize + { + get => _populationSize; + set + { + _populationSize = value; + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(PopulationSize))); + } + } + + private int _mutationRate = 10; + public int MutationRate + { + get => _mutationRate; + set + { + _mutationRate = value; + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(MutationRate))); + } + } + + + private bool _useHoles = true; + public bool UseHoles + { + get => _useHoles; + set + { + _useHoles = value; + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(UseHoles))); + } + } + + private bool _exploreConcave = true; + public bool ExploreConcave + { + get => _exploreConcave; + set + { + _exploreConcave = value; + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(ExploreConcave))); + } + } + + private object this[string key] + { + get + { + return GetType().GetProperty(key).GetValue(this); + } + set + { + GetType().GetProperty(key).SetValue(this, value); + } + } + + private static readonly string[] Keys = new string[] + { + nameof(MaxNumberOfRun), + nameof(MaxRuntimeInMinute), + nameof(CurveTolerance), + nameof(Spacing), + nameof(Rotations), + nameof(PopulationSize), + nameof(MutationRate), + nameof(UseHoles), + nameof(ExploreConcave) + }; + + public void SaveSettings() + { + foreach (var key in Keys) + { + SaveSetting($"Nest{key}", this[key]); + } + } + + public void LoadSettings() + { + foreach (var key in Keys) + { + var value = LoadSetting($"Nest{key}"); + if (value != null) + this[key] = value; + } + } + + public void ApplySettings() + { + var config = DeepNestApi.SvgNest.Config; + config.curveTolerance = CurveTolerance; + config.spacing = Spacing; + config.rotations = Rotations; + config.populationSize = PopulationSize; + config.mutationRate = MutationRate; + config.useHoles = UseHoles; + config.exploreConcave = ExploreConcave; + } + + private static object LoadSetting(string key) + { + return ApplicationData.Current.LocalSettings.Values[key]; + } + + private static void SaveSetting(string key, object value) + { + ApplicationData.Current.LocalSettings.Values[key] = value; + } + } +} diff --git a/PCUT/PCUT/ViewModels/UpsertCategoryViewModel.cs b/PCUT/PCUT/ViewModels/UpsertCategoryViewModel.cs new file mode 100644 index 0000000..386ffe3 --- /dev/null +++ b/PCUT/PCUT/ViewModels/UpsertCategoryViewModel.cs @@ -0,0 +1,126 @@ +using Newtonsoft.Json; +using PCUT.Entities; +using System; +using System.Net.Http; +using System.Text; +using System.Threading.Tasks; +using Http.Core; +using static Http.Core.Constants.HttpConstants; +using Http.Core.Extensions; +using Windows.UI.Popups; +using PCUT.Models; +using PCUT.Helpers; +using System.Windows.Input; +using PCUT.Entities.ApiResponse; + +namespace PCUT.ViewModels +{ + public class UpsertCategoryViewModel : NotificationBase + { + private string _name; + public string Name + { + get { return _name; } + + set { SetProperty(ref _name, value); } + } + + private string _description; + public string Description + { + get { return _description; } + + set { SetProperty(ref _description, value); } + } + + private string _categoryId; + public ICommand Command { get; } + + public UpsertCategoryViewModel() + { + Command = new RelayCommand(async () => await UpsertCategoryAsync()); + } + + public void Initialize(string categoryId) + { + _categoryId = categoryId; + } + + public async Task LoadAsync() + { + if (_categoryId is null) + return; + + using (var client = HttpClientFactory.CreateClient(ClientNames.ApiClient)) + { + try + { + var response = await client.GetAsync(Api.CategoryById.FormatRoute(_categoryId)); + if (response.IsSuccessStatusCode) + { + var categoryData = await response.DeserializeObjectAsync>(); + Name = categoryData.Data.Name; + Description = categoryData.Data.Description; + } + } + catch { } + } + } + + public async Task UpsertCategoryAsync() + { + using (var client = HttpClientFactory.CreateClient(ClientNames.ApiClient)) + { + string message; + if (_categoryId is null) + message = await AddAsync(client); + else + message = await EditAsync(client); + + await new MessageDialog(message).ShowAsync(); + } + } + + private async Task AddAsync(HttpClient client) + { + var category = new UpsertCategory + { + Name = this.Name, + Description = this.Description + }; + try + { + var response = await client.PostAsJsonAsync(Api.Categories, category); + if (response.IsSuccessStatusCode) + return "Category added successfully!"; + else + return "Failed to add the category!"; + } + catch(Exception ex) + { + return $"error: {ex.Message}"; + } + } + + private async Task EditAsync(HttpClient client) + { + var category = new UpsertCategory + { + Name = this.Name, + Description = this.Description + }; + try + { + var response = await client.PutAsJsonAsync(Api.CategoryById.FormatRoute(_categoryId), category); + if (response.IsSuccessStatusCode) + return "Category edited successfully!"; + else + return "Failed to edit the category!"; + } + catch (Exception ex) + { + return $"error: {ex.Message}"; + } + } + } +} diff --git a/PCUT/PCUT/ViewModels/UpsertMetadataViewModel.cs b/PCUT/PCUT/ViewModels/UpsertMetadataViewModel.cs new file mode 100644 index 0000000..9d0fd1f --- /dev/null +++ b/PCUT/PCUT/ViewModels/UpsertMetadataViewModel.cs @@ -0,0 +1,130 @@ +using Http.Core; +using PCUT.Entities; +using System; +using System.Threading.Tasks; +using Http.Core.Extensions; +using static Http.Core.Constants.HttpConstants; +using Windows.UI.Popups; +using System.Text; +using PCUT.Entities.ApiResponse; +using PCUT.Models.Categories; +using System.Collections.Generic; +using System.Linq; +using System.Net.Http; + +namespace PCUT.ViewModels +{ + public class UpsertMetadataViewModel : UpsertViewModel + { + public UpsertMetadataViewModel() : base("Metadata") + { + } + + private string _categoryId; + public string CategoryId + { + get { return _categoryId; } + set { SetProperty(ref _categoryId, value); } + } + + private string _type; + public string Type + { + get { return _type; } + set + { + SetProperty(ref _type, value); + Entity = value; + } + } + + private string _name; + public string Name + { + get { return _name; } + set { SetProperty(ref _name, value); } + } + + public async Task UpsertMetadataAsync() + { + using (var client = HttpClientFactory.CreateClient(ClientNames.ApiClient)) + { + string message; + if (Mode == AddMode) + message = await AddAsync(client); + else + message = await EditAsync(client); + + await new MessageDialog(message).ShowAsync(); + } + } + + private async Task AddAsync(HttpClient client) + { + var request = new UpsertMetadata + { + Type = Type.ToUpper(), + Value = Name, + CategoryId = CategoryId + }; + try + { + var response = await client.PostAsJsonAsync(Api.Metadata, request); + return response.IsSuccessStatusCode ? "Metadata added successfully!" : "Failed to add the metadata!"; + } + catch (Exception ex) + { + return $"error: {ex.Message}"; + } + } + + private async Task EditAsync(HttpClient client) + { + try + { + var request = new UpsertMetadata + { + Value = Name + }; + var response = await client.PutAsJsonAsync(Api.MetadataById.FormatRoute(Id), request); + return response.IsSuccessStatusCode ? "Metadata edited successfully!" : "Failed to edit the metadata!"; + } + catch (Exception ex) + { + return $"error: {ex.Message}"; + } + } + + protected override async Task LoadAsync(string id) + { + using (var client = HttpClientFactory.CreateClient(ClientNames.ApiClient)) + { + try + { + var url = CreateFilterUrl(id); + var response = await client.GetAsync(url); + if (response.IsSuccessStatusCode) + { + var content = await response.DeserializeObjectAsync>>(); + if (content.Data != null && content.Data.Any()) + { + var metadata = content.Data.First(); + Name = metadata.Value; + } + } + } + catch { } + } + } + + private string CreateFilterUrl(string id) + { + var filter = new StringBuilder().AppendFilter("_id", id) + .BuildFilter() + .ToString(); + return PathBuilder.FromRouteTemplate(Api.Metadata) + .AddQuery("filter", filter) + .Build(); + } + } +} diff --git a/PCUT/PCUT/ViewModels/UpsertUserViewModel.cs b/PCUT/PCUT/ViewModels/UpsertUserViewModel.cs new file mode 100644 index 0000000..08a3c43 --- /dev/null +++ b/PCUT/PCUT/ViewModels/UpsertUserViewModel.cs @@ -0,0 +1,345 @@ + +using Http.Core; +using Http.Core.Extensions; +using PCUT.Entities; +using PCUT.Helpers; +using PCUT.Models; +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.Net.Http; +using System.Threading.Tasks; +using System.Windows.Input; +using static Http.Core.Constants.HttpConstants; +using PCUT.Entities.ApiResponse; +using Windows.Foundation; +using Windows.UI.Xaml.Controls; +using Windows.UI.Xaml; +using System.ComponentModel; +using Newtonsoft.Json.Linq; + +namespace PCUT.ViewModels +{ + internal class UpsertUserViewModel : NotificationBase + { + public event UpsertProcessedEventHandler Processed; + + private const string AdminRole = "admin"; + private const string UserRole = "user"; + private const string ActiveStatus = "Active"; + private const string InactiveStatus = "Inactive"; + private const string AddTitle = "ADD USER"; + private const string EditTitle = "EDIT USER"; + + public List Roles { get; } = new List { AdminRole, UserRole }; + public List Statuses { get; } = new List { ActiveStatus, InactiveStatus }; + + public DateTimeOffset MinimumDate { get; } + public ICommand Command { get; } + + private UserProfile _profile; + + public UpsertUserViewModel() + { + _isActive = true; + var minimumDate = DateTimeOffset.Now.AddDays(1); + minimumDate -= minimumDate.TimeOfDay; + MinimumDate = minimumDate; + _expiredAt = minimumDate; + Command = new RelayCommand(async () => await UpsertUserAsync()); + } + + private bool _addMode; // true: add, false: edit + public bool AddMode + { + get { return _addMode; } + set + { + SetProperty(ref _addMode, value); + Title = value ? AddTitle : EditTitle; + } + } + + private string _title; + public string Title + { + get { return _title; } + private set { SetProperty(ref _title, value); } + } + + private string _accountName; + public string AccountName + { + get { return _accountName; } + set { SetProperty(ref _accountName, value); } + } + + private string _username; + public string Username + { + get { return _username; } + set { SetProperty(ref _username, value); } + } + + private string _phone; + public string Phone + { + get { return _phone; } + set { SetProperty(ref _phone, value); } + } + + private string _role; + public string Role + { + get { return _role; } + set { SetProperty(ref _role, value); } + } + + private bool _isActive; + public bool IsActive + { + get { return _isActive; } + set { SetProperty(ref _isActive, value); } + } + + private bool _isPermittedEdit; + public bool IsPermittedEdit + { + get { return _isPermittedEdit; } + set { SetProperty(ref _isPermittedEdit, value); } + } + + private DateTimeOffset? _expiredAt; + public DateTimeOffset? ExpiredAt + { + get { return _expiredAt; } + set + { + if (value != null) + value -= value?.TimeOfDay; + SetProperty(ref _expiredAt, value); + } + } + + private string _description; + public string Description + { + get { return _description; } + set { SetProperty(ref _description, value); } + } + + private string _password; + public string Password + { + get { return _password; } + set { SetProperty(ref _password, value); } + } + + public ObservableCollection Permissions { get; } = new ObservableCollection(); + private readonly HashSet _currentPermission = new HashSet(); + + private void OnRoleChanged(object sender, PropertyChangedEventArgs args) + { + if (args.PropertyName == nameof(Role)) + { + foreach (var permission in Permissions) + { + permission.PropertyChanged -= OnPermissionSelectedChanged; + permission.IsSelected = Role == AdminRole || _currentPermission.Contains(permission.Category.Id); + permission.PropertyChanged += OnPermissionSelectedChanged; + } + IsPermittedEdit = Role == AdminRole || (_profile.IsPermittedEdit ?? false); + } + } + + private void OnPermissionSelectedChanged(object sender, PropertyChangedEventArgs args) + { + if (args.PropertyName == nameof(Permission.IsSelected)) + { + var permission = sender as Permission; + if (permission.IsSelected) + _currentPermission.Add(permission.Category.Id); + else + _currentPermission.Remove(permission.Category.Id); + } + } + + public async Task LoadCategoriesAsync() + { + var categories = await GetCategoryAsync(); + foreach (var permission in categories.Select(category => new Permission(category))) + { + permission.PropertyChanged += OnPermissionSelectedChanged; + Permissions.Add(permission); + } + PropertyChanged += OnRoleChanged; + } + + private static async Task> GetCategoryAsync() + { + using (HttpClient client = HttpClientFactory.CreateClient(ClientNames.ApiClient)) + { + return await client.GetCategoriesAsync(); + } + } + + public async Task LoadUserAsync(string userId) + { + using (var httpClient = HttpClientFactory.CreateClient(ClientNames.ApiClient)) + { + try + { + var response = await httpClient.GetAsync(Api.UserById.FormatRoute(userId)); + if (response.IsSuccessStatusCode) + { + var apiResponse = await response.DeserializeObjectAsync>(); + _profile = apiResponse.Data; + + foreach (var permissionId in _profile.Permissions) + _currentPermission.Add(permissionId); + + AccountName = _profile.AccountName; + Username = _profile.UserName; + Phone = _profile.Phone; + IsActive = _profile.IsActive; + Role = _profile.Role; + IsPermittedEdit = _profile.Role == AdminRole || (_profile.IsPermittedEdit ?? false); + ExpiredAt = _profile.ExpiredAt?.ToLocalTime(); + Description = _profile.Description; + } + } + catch (Exception ex) + { + } + } + } + + private async Task UpsertUserAsync() + { + var success = false; + if (await ValidateUserAsync()) + { + var user = new UpsertUser + { + AccountName = AccountName, + Username = Username, + Phone = Phone, + Role = Role, + IsActive = IsActive, + IsPermittedEdit = IsPermittedEdit, + ExpiredAt = ExpiredAt?.ToUniversalTime().ToString("o"), + Password = !string.IsNullOrEmpty(Password) ? Password : null, + Permissions = Permissions.Where(c => c.IsSelected).Select(c => c.Category.Id).ToList(), + Description = Description, + }; + success = await UpsertUserAsync(_addMode ? Api.Users : Api.UserById.FormatRoute(_profile?.Id), user); + } + Processed?.Invoke(this, new UpsertProcessedEventArgs(_addMode ? "add" : "edit", success, _profile?.Id)); + } + + private async Task ValidateUserAsync() + { + if (string.IsNullOrEmpty(Username)) + { + await ShowDialogAsync("Cần nhập username!"); + return false; + } + + if (_addMode && string.IsNullOrEmpty(Password)) + { + await ShowDialogAsync("Cần nhập password!"); + return false; + } + + if (string.IsNullOrEmpty(Role)) + { + await ShowDialogAsync("Cần chọn role!"); + return false; + } + + var selectedCategories = Permissions.Where(c => c.IsSelected); + if (Role == UserRole && !selectedCategories.Any()) + { + await ShowDialogAsync("Chọn ít nhất 1 danh mục cho user!"); + return false; + } + + return true; + } + + private async Task UpsertUserAsync(string path, object user) + { + using (var httpClient = HttpClientFactory.CreateClient(ClientNames.ApiClient)) + { + try + { + var response = await (_addMode ? httpClient.PostAsJsonAsync(path, user) : httpClient.PutAsJsonAsync(path, user, ignoreNull: true)); + if (response.IsSuccessStatusCode) + { + await ShowDialogAsync($"Account {(_addMode ? "created" : "updated")} successfully!", $"{(_addMode ? "Add" : "Edit")} successful!"); + } + else + { + var errorMessage = await response.DeserializeObjectAsync(ensureSuccess: false); + await ShowDialogAsync(errorMessage.ErrorMessage); + return false; + } + } + catch (Exception ex) + { + await ShowDialogAsync(ex.Message); + return false; + } + } + return true; + } + + private IAsyncOperation ShowDialogAsync(string message, string title = null) + { + var errorDialog = new ContentDialog() + { + Title = title, + Content = message, + PrimaryButtonText = "OK" + }; + errorDialog.PrimaryButtonStyle = Application.Current.Resources["PrimaryDialogButton"] as Style; + return errorDialog.ShowAsync(); + } + } + + public delegate void UpsertProcessedEventHandler(object sender, UpsertProcessedEventArgs args); + public class UpsertProcessedEventArgs : EventArgs + { + public string Mode { get; } + public bool Successed { get; } + public string Id { get; } + + public UpsertProcessedEventArgs(string mode, bool successed, string id = null) + { + Mode = mode; + Successed = successed; + Id = id; + } + } + + public class Permission : NotificationBase + { + public readonly Category Category; + + public string Name { get => Category.Name; } + + private bool _isSelected; + public bool IsSelected + { + get { return _isSelected; } + set { SetProperty(ref _isSelected, value); } + } + + public Permission(Category category, bool isSelected = false) + { + Category = category; + _isSelected = isSelected; + } + } +} diff --git a/PCUT/PCUT/ViewModels/UpsertViewModel.cs b/PCUT/PCUT/ViewModels/UpsertViewModel.cs new file mode 100644 index 0000000..4f9a326 --- /dev/null +++ b/PCUT/PCUT/ViewModels/UpsertViewModel.cs @@ -0,0 +1,66 @@ +using PCUT.Models; +using System.Threading.Tasks; + +namespace PCUT.ViewModels +{ + public abstract class UpsertViewModel : NotificationBase + { + protected const string AddMode = "ADD"; + protected const string EditMode = "EDIT"; + + public string Title => $"{Mode} {Entity.ToUpper()}"; + + private string _mode; + public string Mode + { + get { return _mode; } + private set + { + SetProperty(ref _mode, value); + RaisePropertyChanged(nameof(Title)); + } + } + + private string _entity; + public string Entity + { + get { return _entity; } + set + { + SetProperty(ref _entity, value); + RaisePropertyChanged(nameof(Title)); + } + } + + private TKey _id; + public TKey Id + { + get { return _id; } + set + { + SetProperty(ref _id, value); + Mode = value == null ? AddMode : EditMode; + } + } + + protected UpsertViewModel(string entity) + { + Entity = entity; + } + + public void Initialize(TKey id) + { + Id = id; + } + + public async Task LoadAsync() + { + if (Mode == EditMode) + { + await LoadAsync(Id); + } + } + + protected abstract Task LoadAsync(TKey id); + } +} diff --git a/PCUT/PCUT/ViewModels/UserViewModel.cs b/PCUT/PCUT/ViewModels/UserViewModel.cs new file mode 100644 index 0000000..3b9991f --- /dev/null +++ b/PCUT/PCUT/ViewModels/UserViewModel.cs @@ -0,0 +1,94 @@ +using Http.Core; +using Http.Core.Extensions; +using PCUT.Entities.ApiResponse; +using PCUT.Extensions; +using PCUT.Models; +using PCUT.Models.Users; +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Windows.ApplicationModel.Core; +using static Http.Core.Constants.HttpConstants; + +namespace PCUT.ViewModels +{ + public class UserViewModel : NotificationBase + { + public PaginationViewModel Pagination { get; } = new PaginationViewModel(withSearch: true); + public SelectableCollection FilteredUsers { get; } + public UserViewModel() + { + FilteredUsers = new SelectableCollection(); + + Pagination.TextSearched += async (sender, args) => await SearchCategoryAsync(args.Text); + Pagination.PageChanged += OnPageChanged; + } + + private async void OnPageChanged(object sender, PageChangedEventArgs args) + { + await LoadUserAsync(args.Page, args.PageSize, Pagination.SearchText); + } + + public async Task SearchCategoryAsync(string searchText) + { + await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, async () => + { + await LoadUserAsync(Pagination.Page, Pagination.PageSize, searchText); + }); + } + + public async Task Reload() + { + await LoadUserAsync(Pagination.Page, Pagination.PageSize, Pagination.SearchText); + } + + public async Task LoadUserAsync(int page, int pageSize, string searchText) + { + var url = CreateFilterUrl(page, pageSize, searchText); + using (var httpClient = HttpClientFactory.CreateClient(ClientNames.ApiClient)) + { + try + { + var response = await httpClient.GetAsync(url); + if (response.IsSuccessStatusCode) + { + var apiResponse = await response.DeserializeObjectAsync>>(); + var data = apiResponse.Data; + Pagination.Page = apiResponse.Pagination.Page; + Pagination.TotalPage = apiResponse.Pagination.TotalPages; + Pagination.TotalRecords = apiResponse.Pagination.TotalRecords; + + int displayId = (apiResponse.Pagination.Page - 1) * pageSize + 1; + var users = data.Select(user => + { + user.DisplayId = displayId.ToString(); + displayId++; + return user; + }); + FilteredUsers.Load(users); + } + } + catch (Exception ex) + { + + } + } + } + + private string CreateFilterUrl(int page, int pageSize, string searchText) + { + var builder = PathBuilder.FromRouteTemplate(Api.Users) + .AddQuery("page", page.ToString()) + .AddQuery("pageSize", pageSize.ToString()); + if (!string.IsNullOrEmpty(searchText)) + { + var filter = new StringBuilder().AppendFilter("username", "cn", searchText).BuildFilter().ToString(); + builder.AddQuery("filter", filter); + } + return builder.Build(); + } + } +} diff --git a/README.md b/README.md new file mode 100644 index 0000000..a5b9864 --- /dev/null +++ b/README.md @@ -0,0 +1,5 @@ +# pcut_uwp + +# require: +- Visual Studio: Universal Windows Platform development + - C++ Universal Windows Platform tools \ No newline at end of file