mirror of
https://github.com/UglyToad/PdfPig.git
synced 2026-03-10 00:23:29 +08:00
tidy up clipper related code
This commit is contained in:
@@ -4,23 +4,27 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using UglyToad.PdfPig.Content;
|
||||
using UglyToad.PdfPig.Graphics;
|
||||
using UglyToad.PdfPig.Graphics.Colors;
|
||||
using UglyToad.PdfPig.Graphics.Core;
|
||||
using Content;
|
||||
using Graphics;
|
||||
using Graphics.Colors;
|
||||
using Graphics.Core;
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
///
|
||||
/// Exports a page as an SVG.
|
||||
/// </summary>
|
||||
public class SvgTextExporter : ITextExporter
|
||||
{
|
||||
static readonly int rounding = 4;
|
||||
private const int Rounding = 4;
|
||||
|
||||
private static readonly Dictionary<string, string> Fonts = new Dictionary<string, string>()
|
||||
{
|
||||
{ "ArialMT", "Arial Rounded MT Bold" }
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// Get the page contents as an SVG.
|
||||
/// </summary>
|
||||
/// <param name="page"></param>
|
||||
/// <returns></returns>
|
||||
public string Get(Page page)
|
||||
{
|
||||
var builder = new StringBuilder($"<svg width='{page.Width}' height='{page.Height}'><g transform=\"scale(1, 1) translate(0, 0)\">");
|
||||
@@ -48,24 +52,19 @@
|
||||
builder.Append("</g></svg>");
|
||||
return builder.ToString();
|
||||
}
|
||||
|
||||
static readonly Dictionary<string, string> _fonts = new Dictionary<string, string>()
|
||||
{
|
||||
{ "ArialMT", "Arial Rounded MT Bold" }
|
||||
};
|
||||
|
||||
|
||||
private static string LetterToSvg(Letter l, double height)
|
||||
{
|
||||
string fontFamily = GetFontFamily(l.FontName, out string style, out string weight);
|
||||
string rotation = "";
|
||||
if (l.GlyphRectangle.Rotation != 0)
|
||||
{
|
||||
rotation = $" transform='rotate({Math.Round(-l.GlyphRectangle.Rotation, rounding)} {Math.Round(l.GlyphRectangle.BottomLeft.X, rounding)},{Math.Round(height - l.GlyphRectangle.TopLeft.Y, rounding)})'";
|
||||
rotation = $" transform='rotate({Math.Round(-l.GlyphRectangle.Rotation, Rounding)} {Math.Round(l.GlyphRectangle.BottomLeft.X, Rounding)},{Math.Round(height - l.GlyphRectangle.TopLeft.Y, Rounding)})'";
|
||||
}
|
||||
|
||||
string fontSize = l.FontSize != 1 ? $"font-size='{l.FontSize.ToString("0")}'" : $"style='font-size:{Math.Round(l.GlyphRectangle.Height, 2)}px'";
|
||||
string fontSize = l.FontSize != 1 ? $"font-size='{l.FontSize:0}'" : $"style='font-size:{Math.Round(l.GlyphRectangle.Height, 2)}px'";
|
||||
|
||||
return $"<text x='{Math.Round(l.StartBaseLine.X, rounding)}' y='{Math.Round(height - l.StartBaseLine.Y, rounding)}'{rotation} font-family='{fontFamily}' font-style='{style}' font-weight='{weight}' {fontSize} fill='{ColorToSvg(l.Color)}'>{l.Value}</text>";
|
||||
return $"<text x='{Math.Round(l.StartBaseLine.X, Rounding)}' y='{Math.Round(height - l.StartBaseLine.Y, Rounding)}'{rotation} font-family='{fontFamily}' font-style='{style}' font-weight='{weight}' {fontSize} fill='{ColorToSvg(l.Color)}'>{l.Value}</text>";
|
||||
}
|
||||
|
||||
private static string GetFontFamily(string fontName, out string style, out string weight)
|
||||
@@ -79,7 +78,7 @@
|
||||
if (fontName.Length > 7 && fontName[6] == '+')
|
||||
{
|
||||
var split = fontName.Split('+');
|
||||
if (split[0].All(c => char.IsUpper(c)))
|
||||
if (split[0].All(char.IsUpper))
|
||||
{
|
||||
fontName = split[1];
|
||||
}
|
||||
@@ -118,7 +117,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
if (_fonts.ContainsKey(fontName)) fontName = _fonts[fontName];
|
||||
if (Fonts.ContainsKey(fontName)) fontName = Fonts[fontName];
|
||||
return fontName;
|
||||
}
|
||||
|
||||
|
||||
@@ -4,4 +4,6 @@
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=CMYK/@EntryIndexedValue">CMYK</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=ICC/@EntryIndexedValue">ICC</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=RGB/@EntryIndexedValue">RGB</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=XY/@EntryIndexedValue">XY</s:String></wpf:ResourceDictionary>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=XY/@EntryIndexedValue">XY</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateInstanceFields/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateStaticFields/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String></wpf:ResourceDictionary>
|
||||
File diff suppressed because it is too large
Load Diff
896
src/UglyToad.PdfPig/Geometry/ClipperLibrary/ClipperBase.cs
Normal file
896
src/UglyToad.PdfPig/Geometry/ClipperLibrary/ClipperBase.cs
Normal file
@@ -0,0 +1,896 @@
|
||||
/*******************************************************************************
|
||||
* *
|
||||
* 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. *
|
||||
* *
|
||||
*******************************************************************************/
|
||||
|
||||
/*******************************************************************************
|
||||
* Boost Software License - Version 1.0 - August 17th, 2003 *
|
||||
* *
|
||||
* Permission is hereby granted, free of charge, to any person or organization *
|
||||
* obtaining a copy of the software and accompanying documentation covered by *
|
||||
* this license (the "Software") to use, reproduce, display, distribute, *
|
||||
* execute, and transmit the Software, and to prepare derivative works of the *
|
||||
* Software, and to permit third-parties to whom the Software is furnished to *
|
||||
* do so, all subject to the following: *
|
||||
* *
|
||||
* The copyright notices in the Software and this entire statement, including *
|
||||
* the above license grant, this restriction and the following disclaimer, *
|
||||
* must be included in all copies of the Software, in whole or in part, and *
|
||||
* all derivative works of the Software, unless such copies or derivative *
|
||||
* works are solely in the form of machine-executable object code generated by *
|
||||
* a source language processor. *
|
||||
* *
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
|
||||
* FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT *
|
||||
* SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE *
|
||||
* FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, *
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *
|
||||
* DEALINGS IN THE SOFTWARE. *
|
||||
*******************************************************************************/
|
||||
|
||||
/*******************************************************************************
|
||||
* *
|
||||
* Code modified for PdfPig *
|
||||
* *
|
||||
*******************************************************************************/
|
||||
|
||||
|
||||
//use_lines: Enables open path clipping. Adds a very minor cost to performance.
|
||||
|
||||
|
||||
namespace UglyToad.PdfPig.Geometry.ClipperLibrary
|
||||
{
|
||||
using System.Collections.Generic;
|
||||
|
||||
internal 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 NearZero(double val) { return (val > -Tolerance) && (val < Tolerance); }
|
||||
|
||||
public const long loRange = 0x3FFFFFFF;
|
||||
|
||||
public const long hiRange = 0x3FFFFFFFFFFFFFFFL;
|
||||
|
||||
internal ClipperLocalMinima m_MinimaList;
|
||||
internal ClipperLocalMinima m_CurrentLM;
|
||||
internal List<List<ClipperTEdge>> m_edges = new List<List<ClipperTEdge>>();
|
||||
internal ClipperScanbeam m_Scanbeam;
|
||||
internal List<ClipperOutRec> m_PolyOuts;
|
||||
internal ClipperTEdge m_ActiveEdges;
|
||||
internal bool m_UseFullRange;
|
||||
internal bool m_HasOpenPaths;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
public bool PreserveCollinear
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
public void Swap(ref long val1, ref long val2)
|
||||
{
|
||||
long tmp = val1;
|
||||
val1 = val2;
|
||||
val2 = tmp;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
internal static bool IsHorizontal(ClipperTEdge e)
|
||||
{
|
||||
return e.Delta.Y == 0;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
internal bool PointIsVertex(ClipperIntPoint pt, ClipperOutPt pp)
|
||||
{
|
||||
ClipperOutPt pp2 = pp;
|
||||
do
|
||||
{
|
||||
if (pp2.Pt == pt) return true;
|
||||
pp2 = pp2.Next;
|
||||
}
|
||||
while (pp2 != pp);
|
||||
return false;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
internal bool PointOnLineSegment(ClipperIntPoint pt,
|
||||
ClipperIntPoint linePt1, ClipperIntPoint 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)) &&
|
||||
((ClipperInt128.Int128Mul((pt.X - linePt1.X), (linePt2.Y - linePt1.Y)) ==
|
||||
ClipperInt128.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(ClipperIntPoint pt, ClipperOutPt pp, bool UseFullRange)
|
||||
{
|
||||
ClipperOutPt 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(ClipperTEdge e1, ClipperTEdge e2, bool UseFullRange)
|
||||
{
|
||||
if (UseFullRange)
|
||||
return ClipperInt128.Int128Mul(e1.Delta.Y, e2.Delta.X) ==
|
||||
ClipperInt128.Int128Mul(e1.Delta.X, e2.Delta.Y);
|
||||
else return (long)(e1.Delta.Y) * (e2.Delta.X) ==
|
||||
(long)(e1.Delta.X) * (e2.Delta.Y);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
internal static bool SlopesEqual(ClipperIntPoint pt1, ClipperIntPoint pt2,
|
||||
ClipperIntPoint pt3, bool UseFullRange)
|
||||
{
|
||||
if (UseFullRange)
|
||||
return ClipperInt128.Int128Mul(pt1.Y - pt2.Y, pt2.X - pt3.X) ==
|
||||
ClipperInt128.Int128Mul(pt1.X - pt2.X, pt2.Y - pt3.Y);
|
||||
else return
|
||||
(pt1.Y - pt2.Y) * (pt2.X - pt3.X) - (pt1.X - pt2.X) * (pt2.Y - pt3.Y) == 0;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
internal static bool SlopesEqual(ClipperIntPoint pt1, ClipperIntPoint pt2,
|
||||
ClipperIntPoint pt3, ClipperIntPoint pt4, bool UseFullRange)
|
||||
{
|
||||
if (UseFullRange)
|
||||
return ClipperInt128.Int128Mul(pt1.Y - pt2.Y, pt3.X - pt4.X) ==
|
||||
ClipperInt128.Int128Mul(pt1.X - pt2.X, pt3.Y - pt4.Y);
|
||||
else return
|
||||
(pt1.Y - pt2.Y) * (pt3.X - pt4.X) - (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)
|
||||
{
|
||||
ClipperLocalMinima tmpLm = m_MinimaList.Next;
|
||||
m_MinimaList = null;
|
||||
m_MinimaList = tmpLm;
|
||||
}
|
||||
m_CurrentLM = null;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void RangeTest(ClipperIntPoint 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(ClipperTEdge e, ClipperTEdge eNext,
|
||||
ClipperTEdge ePrev, ClipperIntPoint pt)
|
||||
{
|
||||
e.Next = eNext;
|
||||
e.Prev = ePrev;
|
||||
e.Curr = pt;
|
||||
e.OutIdx = Unassigned;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
private void InitEdge2(ClipperTEdge e, ClipperPolyType 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 ClipperTEdge FindNextLocMin(ClipperTEdge E)
|
||||
{
|
||||
ClipperTEdge 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 ClipperTEdge ProcessBound(ClipperTEdge E, bool LeftBoundIsForward)
|
||||
{
|
||||
ClipperTEdge EStart, Result = E;
|
||||
ClipperTEdge 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;
|
||||
ClipperLocalMinima locMin = new ClipperLocalMinima
|
||||
{
|
||||
Next = null,
|
||||
Y = E.Bot.Y,
|
||||
LeftBound = null,
|
||||
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(List<ClipperIntPoint> pg, ClipperPolyType polyType, bool Closed)
|
||||
{
|
||||
if (!Closed && polyType == ClipperPolyType.Clip)
|
||||
throw new ClipperException("AddPath: Open paths must be subject.");
|
||||
|
||||
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<ClipperTEdge> edges = new List<ClipperTEdge>(highI + 1);
|
||||
for (int i = 0; i <= highI; i++) edges.Add(new ClipperTEdge());
|
||||
|
||||
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]);
|
||||
}
|
||||
ClipperTEdge eStart = edges[0];
|
||||
|
||||
//2. Remove duplicate vertices, and (when closed) collinear edges ...
|
||||
ClipperTEdge 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;
|
||||
ClipperLocalMinima locMin = new ClipperLocalMinima
|
||||
{
|
||||
Next = null,
|
||||
Y = E.Bot.Y,
|
||||
LeftBound = null,
|
||||
RightBound = E
|
||||
};
|
||||
locMin.RightBound.Side = ClipperEdgeSide.Right;
|
||||
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;
|
||||
ClipperTEdge 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 ...
|
||||
ClipperLocalMinima locMin = new ClipperLocalMinima
|
||||
{
|
||||
Next = null,
|
||||
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 = ClipperEdgeSide.Left;
|
||||
locMin.RightBound.Side = ClipperEdgeSide.Right;
|
||||
|
||||
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);
|
||||
|
||||
ClipperTEdge 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(List<List<ClipperIntPoint>> ppg, ClipperPolyType 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(ClipperIntPoint pt1, ClipperIntPoint pt2, ClipperIntPoint 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);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
ClipperTEdge RemoveEdge(ClipperTEdge e)
|
||||
{
|
||||
//removes e from double_linked_list (but without removing from memory)
|
||||
e.Prev.Next = e.Next;
|
||||
e.Next.Prev = e.Prev;
|
||||
ClipperTEdge result = e.Next;
|
||||
e.Prev = null; //flag as removed (see ClipperBase.Clear)
|
||||
return result;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
private void SetDx(ClipperTEdge 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(ClipperLocalMinima newLm)
|
||||
{
|
||||
if (m_MinimaList == null)
|
||||
{
|
||||
m_MinimaList = newLm;
|
||||
}
|
||||
else if (newLm.Y >= m_MinimaList.Y)
|
||||
{
|
||||
newLm.Next = m_MinimaList;
|
||||
m_MinimaList = newLm;
|
||||
}
|
||||
else
|
||||
{
|
||||
ClipperLocalMinima tmpLm = m_MinimaList;
|
||||
while (tmpLm.Next != null && (newLm.Y < tmpLm.Next.Y))
|
||||
tmpLm = tmpLm.Next;
|
||||
newLm.Next = tmpLm.Next;
|
||||
tmpLm.Next = newLm;
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
internal bool PopLocalMinima(long Y, out ClipperLocalMinima current)
|
||||
{
|
||||
current = m_CurrentLM;
|
||||
if (m_CurrentLM != null && m_CurrentLM.Y == Y)
|
||||
{
|
||||
m_CurrentLM = m_CurrentLM.Next;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
private void ReverseHorizontal(ClipperTEdge 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);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
internal virtual void Reset()
|
||||
{
|
||||
m_CurrentLM = m_MinimaList;
|
||||
if (m_CurrentLM == null) return; //ie nothing to process
|
||||
|
||||
//reset all edges ...
|
||||
m_Scanbeam = null;
|
||||
ClipperLocalMinima lm = m_MinimaList;
|
||||
while (lm != null)
|
||||
{
|
||||
InsertScanbeam(lm.Y);
|
||||
ClipperTEdge 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 ClipperIntRect GetBounds(List<List<ClipperIntPoint>> paths)
|
||||
{
|
||||
int i = 0, cnt = paths.Count;
|
||||
while (i < cnt && paths[i].Count == 0) i++;
|
||||
if (i == cnt) return new ClipperIntRect(0, 0, 0, 0);
|
||||
ClipperIntRect result = new ClipperIntRect
|
||||
{
|
||||
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(long Y)
|
||||
{
|
||||
//single-linked list: sorted descending, ignoring dups.
|
||||
if (m_Scanbeam == null)
|
||||
{
|
||||
m_Scanbeam = new ClipperScanbeam
|
||||
{
|
||||
Next = null,
|
||||
Y = Y
|
||||
};
|
||||
}
|
||||
else if (Y > m_Scanbeam.Y)
|
||||
{
|
||||
ClipperScanbeam newSb = new ClipperScanbeam
|
||||
{
|
||||
Y = Y,
|
||||
Next = m_Scanbeam
|
||||
};
|
||||
m_Scanbeam = newSb;
|
||||
}
|
||||
else
|
||||
{
|
||||
ClipperScanbeam sb2 = m_Scanbeam;
|
||||
while (sb2.Next != null && (Y <= sb2.Next.Y)) sb2 = sb2.Next;
|
||||
if (Y == sb2.Y) return; //ie ignores duplicates
|
||||
ClipperScanbeam newSb = new ClipperScanbeam
|
||||
{
|
||||
Y = Y,
|
||||
Next = sb2.Next
|
||||
};
|
||||
sb2.Next = newSb;
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
internal bool PopScanbeam(out long Y)
|
||||
{
|
||||
if (m_Scanbeam == null)
|
||||
{
|
||||
Y = 0;
|
||||
return false;
|
||||
}
|
||||
Y = m_Scanbeam.Y;
|
||||
m_Scanbeam = m_Scanbeam.Next;
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
internal bool LocalMinimaPending()
|
||||
{
|
||||
return (m_CurrentLM != null);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
internal ClipperOutRec CreateOutRec()
|
||||
{
|
||||
ClipperOutRec result = new ClipperOutRec
|
||||
{
|
||||
Idx = Unassigned,
|
||||
IsHole = false,
|
||||
IsOpen = false,
|
||||
FirstLeft = null,
|
||||
Pts = null,
|
||||
BottomPt = null,
|
||||
PolyNode = null
|
||||
};
|
||||
m_PolyOuts.Add(result);
|
||||
result.Idx = m_PolyOuts.Count - 1;
|
||||
return result;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
internal void DisposeOutRec(int index)
|
||||
{
|
||||
ClipperOutRec outRec = m_PolyOuts[index];
|
||||
outRec.Pts = null;
|
||||
outRec = null;
|
||||
m_PolyOuts[index] = null;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
internal void UpdateEdgeIntoAEL(ref ClipperTEdge e)
|
||||
{
|
||||
if (e.NextInLML == null)
|
||||
throw new ClipperException("UpdateEdgeIntoAEL: invalid call");
|
||||
ClipperTEdge AelPrev = e.PrevInAEL;
|
||||
ClipperTEdge 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(ClipperTEdge edge1, ClipperTEdge 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)
|
||||
{
|
||||
ClipperTEdge next = edge2.NextInAEL;
|
||||
if (next != null)
|
||||
next.PrevInAEL = edge1;
|
||||
ClipperTEdge 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)
|
||||
{
|
||||
ClipperTEdge next = edge1.NextInAEL;
|
||||
if (next != null)
|
||||
next.PrevInAEL = edge2;
|
||||
ClipperTEdge prev = edge2.PrevInAEL;
|
||||
if (prev != null)
|
||||
prev.NextInAEL = edge1;
|
||||
edge1.PrevInAEL = prev;
|
||||
edge1.NextInAEL = edge2;
|
||||
edge2.PrevInAEL = edge1;
|
||||
edge2.NextInAEL = next;
|
||||
}
|
||||
else
|
||||
{
|
||||
ClipperTEdge next = edge1.NextInAEL;
|
||||
ClipperTEdge 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(ClipperTEdge e)
|
||||
{
|
||||
ClipperTEdge AelPrev = e.PrevInAEL;
|
||||
ClipperTEdge 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
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
} //end ClipperLib namespace
|
||||
127
src/UglyToad.PdfPig/Geometry/ClipperLibrary/ClipperEnums.cs
Normal file
127
src/UglyToad.PdfPig/Geometry/ClipperLibrary/ClipperEnums.cs
Normal file
@@ -0,0 +1,127 @@
|
||||
/*******************************************************************************
|
||||
* *
|
||||
* 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. *
|
||||
* *
|
||||
*******************************************************************************/
|
||||
|
||||
/*******************************************************************************
|
||||
* Boost Software License - Version 1.0 - August 17th, 2003 *
|
||||
* *
|
||||
* Permission is hereby granted, free of charge, to any person or organization *
|
||||
* obtaining a copy of the software and accompanying documentation covered by *
|
||||
* this license (the "Software") to use, reproduce, display, distribute, *
|
||||
* execute, and transmit the Software, and to prepare derivative works of the *
|
||||
* Software, and to permit third-parties to whom the Software is furnished to *
|
||||
* do so, all subject to the following: *
|
||||
* *
|
||||
* The copyright notices in the Software and this entire statement, including *
|
||||
* the above license grant, this restriction and the following disclaimer, *
|
||||
* must be included in all copies of the Software, in whole or in part, and *
|
||||
* all derivative works of the Software, unless such copies or derivative *
|
||||
* works are solely in the form of machine-executable object code generated by *
|
||||
* a source language processor. *
|
||||
* *
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
|
||||
* FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT *
|
||||
* SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE *
|
||||
* FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, *
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *
|
||||
* DEALINGS IN THE SOFTWARE. *
|
||||
*******************************************************************************/
|
||||
|
||||
/*******************************************************************************
|
||||
* *
|
||||
* Code modified for PdfPig *
|
||||
* *
|
||||
*******************************************************************************/
|
||||
namespace UglyToad.PdfPig.Geometry.ClipperLibrary
|
||||
{
|
||||
internal enum ClipperClipType : byte
|
||||
{
|
||||
Intersection = 0,
|
||||
Union = 1,
|
||||
Difference = 2,
|
||||
Xor = 3
|
||||
}
|
||||
|
||||
internal enum ClipperDirection : byte
|
||||
{
|
||||
RightToLeft = 0,
|
||||
LeftToRight = 1
|
||||
}
|
||||
|
||||
internal enum ClipperEdgeSide : byte
|
||||
{
|
||||
Left = 0,
|
||||
Right = 1
|
||||
}
|
||||
|
||||
internal enum ClipperEndType : byte
|
||||
{
|
||||
ClosedPolygon = 0,
|
||||
ClosedLine = 1,
|
||||
OpenButt = 2,
|
||||
OpenSquare = 3,
|
||||
OpenRound = 4
|
||||
}
|
||||
|
||||
internal enum ClipperJoinType : byte
|
||||
{
|
||||
Square = 0,
|
||||
Round = 1,
|
||||
Miter = 2
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// By far the most widely used winding rules for polygon filling are
|
||||
/// EvenOdd and 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
|
||||
/// </summary>
|
||||
internal enum ClipperPolyFillType : byte
|
||||
{
|
||||
EvenOdd = 0,
|
||||
NonZero = 1,
|
||||
}
|
||||
|
||||
internal enum ClipperPolyType : byte
|
||||
{
|
||||
Subject = 0,
|
||||
Clip = 1
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
/*******************************************************************************
|
||||
* *
|
||||
* 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. *
|
||||
* *
|
||||
*******************************************************************************/
|
||||
|
||||
/*******************************************************************************
|
||||
* Boost Software License - Version 1.0 - August 17th, 2003 *
|
||||
* *
|
||||
* Permission is hereby granted, free of charge, to any person or organization *
|
||||
* obtaining a copy of the software and accompanying documentation covered by *
|
||||
* this license (the "Software") to use, reproduce, display, distribute, *
|
||||
* execute, and transmit the Software, and to prepare derivative works of the *
|
||||
* Software, and to permit third-parties to whom the Software is furnished to *
|
||||
* do so, all subject to the following: *
|
||||
* *
|
||||
* The copyright notices in the Software and this entire statement, including *
|
||||
* the above license grant, this restriction and the following disclaimer, *
|
||||
* must be included in all copies of the Software, in whole or in part, and *
|
||||
* all derivative works of the Software, unless such copies or derivative *
|
||||
* works are solely in the form of machine-executable object code generated by *
|
||||
* a source language processor. *
|
||||
* *
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
|
||||
* FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT *
|
||||
* SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE *
|
||||
* FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, *
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *
|
||||
* DEALINGS IN THE SOFTWARE. *
|
||||
*******************************************************************************/
|
||||
|
||||
/*******************************************************************************
|
||||
* *
|
||||
* Code modified for PdfPig *
|
||||
* *
|
||||
*******************************************************************************/
|
||||
namespace UglyToad.PdfPig.Geometry.ClipperLibrary
|
||||
{
|
||||
using System;
|
||||
|
||||
internal class ClipperException : Exception
|
||||
{
|
||||
public ClipperException(string description) : base(description)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
223
src/UglyToad.PdfPig/Geometry/ClipperLibrary/ClipperInt128.cs
Normal file
223
src/UglyToad.PdfPig/Geometry/ClipperLibrary/ClipperInt128.cs
Normal file
@@ -0,0 +1,223 @@
|
||||
/*******************************************************************************
|
||||
* *
|
||||
* 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. *
|
||||
* *
|
||||
*******************************************************************************/
|
||||
|
||||
/*******************************************************************************
|
||||
* Boost Software License - Version 1.0 - August 17th, 2003 *
|
||||
* *
|
||||
* Permission is hereby granted, free of charge, to any person or organization *
|
||||
* obtaining a copy of the software and accompanying documentation covered by *
|
||||
* this license (the "Software") to use, reproduce, display, distribute, *
|
||||
* execute, and transmit the Software, and to prepare derivative works of the *
|
||||
* Software, and to permit third-parties to whom the Software is furnished to *
|
||||
* do so, all subject to the following: *
|
||||
* *
|
||||
* The copyright notices in the Software and this entire statement, including *
|
||||
* the above license grant, this restriction and the following disclaimer, *
|
||||
* must be included in all copies of the Software, in whole or in part, and *
|
||||
* all derivative works of the Software, unless such copies or derivative *
|
||||
* works are solely in the form of machine-executable object code generated by *
|
||||
* a source language processor. *
|
||||
* *
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
|
||||
* FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT *
|
||||
* SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE *
|
||||
* FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, *
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *
|
||||
* DEALINGS IN THE SOFTWARE. *
|
||||
*******************************************************************************/
|
||||
|
||||
/*******************************************************************************
|
||||
* *
|
||||
* Code modified for PdfPig *
|
||||
* *
|
||||
*******************************************************************************/
|
||||
namespace UglyToad.PdfPig.Geometry.ClipperLibrary
|
||||
{
|
||||
//------------------------------------------------------------------------------
|
||||
// Int128 struct (enables safe math on signed 64bit integers)
|
||||
// eg Int128 val1((long)9223372036854775807); //ie 2^63 -1
|
||||
// Int128 val2((long)9223372036854775807);
|
||||
// Int128 val3 = val1 * val2;
|
||||
// val3.ToString => "85070591730234615847396907784232501249" (8.5e+37)
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
internal struct ClipperInt128
|
||||
{
|
||||
private long hi;
|
||||
private ulong lo;
|
||||
|
||||
public ClipperInt128(long _lo)
|
||||
{
|
||||
lo = (ulong)_lo;
|
||||
if (_lo < 0) hi = -1;
|
||||
else hi = 0;
|
||||
}
|
||||
|
||||
public ClipperInt128(long _hi, ulong _lo)
|
||||
{
|
||||
lo = _lo;
|
||||
hi = _hi;
|
||||
}
|
||||
|
||||
public ClipperInt128(ClipperInt128 val)
|
||||
{
|
||||
hi = val.hi;
|
||||
lo = val.lo;
|
||||
}
|
||||
|
||||
public bool IsNegative()
|
||||
{
|
||||
return hi < 0;
|
||||
}
|
||||
|
||||
public static bool operator ==(ClipperInt128 val1, ClipperInt128 val2)
|
||||
{
|
||||
if ((object) val1 == (object) val2)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return (val1.hi == val2.hi && val1.lo == val2.lo);
|
||||
}
|
||||
|
||||
public static bool operator !=(ClipperInt128 val1, ClipperInt128 val2)
|
||||
{
|
||||
return !(val1 == val2);
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
if (!(obj is ClipperInt128 i128))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return (i128.hi == hi && i128.lo == lo);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return hi.GetHashCode() ^ lo.GetHashCode();
|
||||
}
|
||||
|
||||
public static bool operator >(ClipperInt128 val1, ClipperInt128 val2)
|
||||
{
|
||||
if (val1.hi != val2.hi)
|
||||
return val1.hi > val2.hi;
|
||||
else
|
||||
return val1.lo > val2.lo;
|
||||
}
|
||||
|
||||
public static bool operator <(ClipperInt128 val1, ClipperInt128 val2)
|
||||
{
|
||||
if (val1.hi != val2.hi)
|
||||
return val1.hi < val2.hi;
|
||||
else
|
||||
return val1.lo < val2.lo;
|
||||
}
|
||||
|
||||
public static ClipperInt128 operator +(ClipperInt128 lhs, ClipperInt128 rhs)
|
||||
{
|
||||
lhs.hi += rhs.hi;
|
||||
lhs.lo += rhs.lo;
|
||||
if (lhs.lo < rhs.lo) lhs.hi++;
|
||||
return lhs;
|
||||
}
|
||||
|
||||
public static ClipperInt128 operator -(ClipperInt128 lhs, ClipperInt128 rhs)
|
||||
{
|
||||
return lhs + -rhs;
|
||||
}
|
||||
|
||||
public static ClipperInt128 operator -(ClipperInt128 val)
|
||||
{
|
||||
if (val.lo == 0)
|
||||
return new ClipperInt128(-val.hi, 0);
|
||||
else
|
||||
return new ClipperInt128(~val.hi, ~val.lo + 1);
|
||||
}
|
||||
|
||||
public static explicit operator double(ClipperInt128 val)
|
||||
{
|
||||
const double shift64 = 18446744073709551616.0; //2^64
|
||||
if (val.hi < 0)
|
||||
{
|
||||
if (val.lo == 0)
|
||||
{
|
||||
return (double)val.hi * shift64;
|
||||
}
|
||||
|
||||
return -(double)(~val.lo + ~val.hi * shift64);
|
||||
}
|
||||
|
||||
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 ClipperInt128 Int128Mul(long lhs, long rhs)
|
||||
{
|
||||
bool negate = (lhs < 0) != (rhs < 0);
|
||||
if (lhs < 0) lhs = -lhs;
|
||||
if (rhs < 0) rhs = -rhs;
|
||||
ulong int1Hi = (ulong)lhs >> 32;
|
||||
ulong int1Lo = (ulong)lhs & 0xFFFFFFFF;
|
||||
ulong int2Hi = (ulong)rhs >> 32;
|
||||
ulong int2Lo = (ulong)rhs & 0xFFFFFFFF;
|
||||
|
||||
//nb: see comments in clipper.pas
|
||||
ulong a = int1Hi * int2Hi;
|
||||
ulong b = int1Lo * int2Lo;
|
||||
ulong c = int1Hi * int2Lo + int1Lo * int2Hi;
|
||||
|
||||
ulong lo;
|
||||
long hi;
|
||||
hi = (long)(a + (c >> 32));
|
||||
|
||||
unchecked { lo = (c << 32) + b; }
|
||||
if (lo < b) hi++;
|
||||
ClipperInt128 result = new ClipperInt128(hi, lo);
|
||||
return negate ? -result : result;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
/*******************************************************************************
|
||||
* *
|
||||
* 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. *
|
||||
* *
|
||||
*******************************************************************************/
|
||||
|
||||
/*******************************************************************************
|
||||
* Boost Software License - Version 1.0 - August 17th, 2003 *
|
||||
* *
|
||||
* Permission is hereby granted, free of charge, to any person or organization *
|
||||
* obtaining a copy of the software and accompanying documentation covered by *
|
||||
* this license (the "Software") to use, reproduce, display, distribute, *
|
||||
* execute, and transmit the Software, and to prepare derivative works of the *
|
||||
* Software, and to permit third-parties to whom the Software is furnished to *
|
||||
* do so, all subject to the following: *
|
||||
* *
|
||||
* The copyright notices in the Software and this entire statement, including *
|
||||
* the above license grant, this restriction and the following disclaimer, *
|
||||
* must be included in all copies of the Software, in whole or in part, and *
|
||||
* all derivative works of the Software, unless such copies or derivative *
|
||||
* works are solely in the form of machine-executable object code generated by *
|
||||
* a source language processor. *
|
||||
* *
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
|
||||
* FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT *
|
||||
* SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE *
|
||||
* FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, *
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *
|
||||
* DEALINGS IN THE SOFTWARE. *
|
||||
*******************************************************************************/
|
||||
|
||||
/*******************************************************************************
|
||||
* *
|
||||
* Code modified for PdfPig *
|
||||
* *
|
||||
*******************************************************************************/
|
||||
namespace UglyToad.PdfPig.Geometry.ClipperLibrary
|
||||
{
|
||||
internal struct ClipperIntRect
|
||||
{
|
||||
public long Left;
|
||||
|
||||
public long Top;
|
||||
|
||||
public long Right;
|
||||
|
||||
public long Bottom;
|
||||
|
||||
public ClipperIntRect(long l, long t, long r, long b)
|
||||
{
|
||||
Left = l;
|
||||
Top = t;
|
||||
Right = r;
|
||||
Bottom = b;
|
||||
}
|
||||
|
||||
public ClipperIntRect(ClipperIntRect ir) : this(ir.Left, ir.Top, ir.Right, ir.Bottom)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
/*******************************************************************************
|
||||
* *
|
||||
* 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. *
|
||||
* *
|
||||
*******************************************************************************/
|
||||
|
||||
/*******************************************************************************
|
||||
* Boost Software License - Version 1.0 - August 17th, 2003 *
|
||||
* *
|
||||
* Permission is hereby granted, free of charge, to any person or organization *
|
||||
* obtaining a copy of the software and accompanying documentation covered by *
|
||||
* this license (the "Software") to use, reproduce, display, distribute, *
|
||||
* execute, and transmit the Software, and to prepare derivative works of the *
|
||||
* Software, and to permit third-parties to whom the Software is furnished to *
|
||||
* do so, all subject to the following: *
|
||||
* *
|
||||
* The copyright notices in the Software and this entire statement, including *
|
||||
* the above license grant, this restriction and the following disclaimer, *
|
||||
* must be included in all copies of the Software, in whole or in part, and *
|
||||
* all derivative works of the Software, unless such copies or derivative *
|
||||
* works are solely in the form of machine-executable object code generated by *
|
||||
* a source language processor. *
|
||||
* *
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
|
||||
* FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT *
|
||||
* SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE *
|
||||
* FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, *
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *
|
||||
* DEALINGS IN THE SOFTWARE. *
|
||||
*******************************************************************************/
|
||||
|
||||
/*******************************************************************************
|
||||
* *
|
||||
* Code modified for PdfPig *
|
||||
* *
|
||||
*******************************************************************************/
|
||||
namespace UglyToad.PdfPig.Geometry.ClipperLibrary
|
||||
{
|
||||
using System.Collections.Generic;
|
||||
|
||||
internal class ClipperIntersectNode
|
||||
{
|
||||
internal ClipperTEdge Edge1;
|
||||
internal ClipperTEdge Edge2;
|
||||
internal ClipperIntPoint Pt;
|
||||
}
|
||||
|
||||
internal class ClipperIntersectNodeSort : IComparer<ClipperIntersectNode>
|
||||
{
|
||||
public int Compare(ClipperIntersectNode node1, ClipperIntersectNode node2)
|
||||
{
|
||||
long i = node2.Pt.Y - node1.Pt.Y;
|
||||
if (i > 0) return 1;
|
||||
|
||||
return i < 0 ? -1 : 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
80
src/UglyToad.PdfPig/Geometry/ClipperLibrary/ClipperJoin.cs
Normal file
80
src/UglyToad.PdfPig/Geometry/ClipperLibrary/ClipperJoin.cs
Normal file
@@ -0,0 +1,80 @@
|
||||
/*******************************************************************************
|
||||
* *
|
||||
* 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. *
|
||||
* *
|
||||
*******************************************************************************/
|
||||
|
||||
/*******************************************************************************
|
||||
* Boost Software License - Version 1.0 - August 17th, 2003 *
|
||||
* *
|
||||
* Permission is hereby granted, free of charge, to any person or organization *
|
||||
* obtaining a copy of the software and accompanying documentation covered by *
|
||||
* this license (the "Software") to use, reproduce, display, distribute, *
|
||||
* execute, and transmit the Software, and to prepare derivative works of the *
|
||||
* Software, and to permit third-parties to whom the Software is furnished to *
|
||||
* do so, all subject to the following: *
|
||||
* *
|
||||
* The copyright notices in the Software and this entire statement, including *
|
||||
* the above license grant, this restriction and the following disclaimer, *
|
||||
* must be included in all copies of the Software, in whole or in part, and *
|
||||
* all derivative works of the Software, unless such copies or derivative *
|
||||
* works are solely in the form of machine-executable object code generated by *
|
||||
* a source language processor. *
|
||||
* *
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
|
||||
* FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT *
|
||||
* SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE *
|
||||
* FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, *
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *
|
||||
* DEALINGS IN THE SOFTWARE. *
|
||||
*******************************************************************************/
|
||||
|
||||
/*******************************************************************************
|
||||
* *
|
||||
* Code modified for PdfPig *
|
||||
* *
|
||||
*******************************************************************************/
|
||||
namespace UglyToad.PdfPig.Geometry.ClipperLibrary
|
||||
{
|
||||
internal class ClipperJoin
|
||||
{
|
||||
public ClipperOutPt OutPt1;
|
||||
public ClipperOutPt OutPt2;
|
||||
public ClipperIntPoint OffPt;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
/*******************************************************************************
|
||||
* *
|
||||
* 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. *
|
||||
* *
|
||||
*******************************************************************************/
|
||||
|
||||
/*******************************************************************************
|
||||
* Boost Software License - Version 1.0 - August 17th, 2003 *
|
||||
* *
|
||||
* Permission is hereby granted, free of charge, to any person or organization *
|
||||
* obtaining a copy of the software and accompanying documentation covered by *
|
||||
* this license (the "Software") to use, reproduce, display, distribute, *
|
||||
* execute, and transmit the Software, and to prepare derivative works of the *
|
||||
* Software, and to permit third-parties to whom the Software is furnished to *
|
||||
* do so, all subject to the following: *
|
||||
* *
|
||||
* The copyright notices in the Software and this entire statement, including *
|
||||
* the above license grant, this restriction and the following disclaimer, *
|
||||
* must be included in all copies of the Software, in whole or in part, and *
|
||||
* all derivative works of the Software, unless such copies or derivative *
|
||||
* works are solely in the form of machine-executable object code generated by *
|
||||
* a source language processor. *
|
||||
* *
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
|
||||
* FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT *
|
||||
* SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE *
|
||||
* FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, *
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *
|
||||
* DEALINGS IN THE SOFTWARE. *
|
||||
*******************************************************************************/
|
||||
|
||||
/*******************************************************************************
|
||||
* *
|
||||
* Code modified for PdfPig *
|
||||
* *
|
||||
*******************************************************************************/
|
||||
namespace UglyToad.PdfPig.Geometry.ClipperLibrary
|
||||
{
|
||||
internal class ClipperLocalMinima
|
||||
{
|
||||
public long Y;
|
||||
public ClipperTEdge LeftBound;
|
||||
public ClipperTEdge RightBound;
|
||||
public ClipperLocalMinima Next;
|
||||
}
|
||||
}
|
||||
80
src/UglyToad.PdfPig/Geometry/ClipperLibrary/ClipperMaxima.cs
Normal file
80
src/UglyToad.PdfPig/Geometry/ClipperLibrary/ClipperMaxima.cs
Normal file
@@ -0,0 +1,80 @@
|
||||
/*******************************************************************************
|
||||
* *
|
||||
* 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. *
|
||||
* *
|
||||
*******************************************************************************/
|
||||
|
||||
/*******************************************************************************
|
||||
* Boost Software License - Version 1.0 - August 17th, 2003 *
|
||||
* *
|
||||
* Permission is hereby granted, free of charge, to any person or organization *
|
||||
* obtaining a copy of the software and accompanying documentation covered by *
|
||||
* this license (the "Software") to use, reproduce, display, distribute, *
|
||||
* execute, and transmit the Software, and to prepare derivative works of the *
|
||||
* Software, and to permit third-parties to whom the Software is furnished to *
|
||||
* do so, all subject to the following: *
|
||||
* *
|
||||
* The copyright notices in the Software and this entire statement, including *
|
||||
* the above license grant, this restriction and the following disclaimer, *
|
||||
* must be included in all copies of the Software, in whole or in part, and *
|
||||
* all derivative works of the Software, unless such copies or derivative *
|
||||
* works are solely in the form of machine-executable object code generated by *
|
||||
* a source language processor. *
|
||||
* *
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
|
||||
* FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT *
|
||||
* SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE *
|
||||
* FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, *
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *
|
||||
* DEALINGS IN THE SOFTWARE. *
|
||||
*******************************************************************************/
|
||||
|
||||
/*******************************************************************************
|
||||
* *
|
||||
* Code modified for PdfPig *
|
||||
* *
|
||||
*******************************************************************************/
|
||||
namespace UglyToad.PdfPig.Geometry.ClipperLibrary
|
||||
{
|
||||
internal class ClipperMaxima
|
||||
{
|
||||
public long X;
|
||||
public ClipperMaxima Next;
|
||||
public ClipperMaxima Previous;
|
||||
}
|
||||
}
|
||||
189
src/UglyToad.PdfPig/Geometry/ClipperLibrary/ClipperOffset.cs
Normal file
189
src/UglyToad.PdfPig/Geometry/ClipperLibrary/ClipperOffset.cs
Normal file
@@ -0,0 +1,189 @@
|
||||
/*******************************************************************************
|
||||
* *
|
||||
* 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. *
|
||||
* *
|
||||
*******************************************************************************/
|
||||
|
||||
/*******************************************************************************
|
||||
* Boost Software License - Version 1.0 - August 17th, 2003 *
|
||||
* *
|
||||
* Permission is hereby granted, free of charge, to any person or organization *
|
||||
* obtaining a copy of the software and accompanying documentation covered by *
|
||||
* this license (the "Software") to use, reproduce, display, distribute, *
|
||||
* execute, and transmit the Software, and to prepare derivative works of the *
|
||||
* Software, and to permit third-parties to whom the Software is furnished to *
|
||||
* do so, all subject to the following: *
|
||||
* *
|
||||
* The copyright notices in the Software and this entire statement, including *
|
||||
* the above license grant, this restriction and the following disclaimer, *
|
||||
* must be included in all copies of the Software, in whole or in part, and *
|
||||
* all derivative works of the Software, unless such copies or derivative *
|
||||
* works are solely in the form of machine-executable object code generated by *
|
||||
* a source language processor. *
|
||||
* *
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
|
||||
* FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT *
|
||||
* SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE *
|
||||
* FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, *
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *
|
||||
* DEALINGS IN THE SOFTWARE. *
|
||||
*******************************************************************************/
|
||||
|
||||
/*******************************************************************************
|
||||
* *
|
||||
* Code modified for PdfPig *
|
||||
* *
|
||||
*******************************************************************************/
|
||||
namespace UglyToad.PdfPig.Geometry.ClipperLibrary
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
internal class ClipperOffset
|
||||
{
|
||||
private const double DefArcTolerance = 0.25;
|
||||
|
||||
private ClipperIntPoint lowest;
|
||||
private readonly ClipperPolyNode polyNodes = new ClipperPolyNode();
|
||||
|
||||
public double ArcTolerance { get; set; }
|
||||
|
||||
public double MiterLimit { get; set; }
|
||||
|
||||
public ClipperOffset(
|
||||
double miterLimit = 2.0, double arcTolerance = DefArcTolerance)
|
||||
{
|
||||
MiterLimit = miterLimit;
|
||||
ArcTolerance = arcTolerance;
|
||||
lowest.X = -1;
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
polyNodes.Children.Clear();
|
||||
lowest.X = -1;
|
||||
}
|
||||
|
||||
public void AddPath(List<ClipperIntPoint> path, ClipperJoinType joinType, ClipperEndType endType)
|
||||
{
|
||||
var highI = path.Count - 1;
|
||||
if (highI < 0) return;
|
||||
var newNode = new ClipperPolyNode
|
||||
{
|
||||
JoinType = joinType,
|
||||
EndType = endType
|
||||
};
|
||||
|
||||
//strip duplicate points from path and also get index to the lowest point ...
|
||||
if (endType == ClipperEndType.ClosedLine || endType == ClipperEndType.ClosedPolygon)
|
||||
{
|
||||
while (highI > 0 && path[0] == path[highI])
|
||||
{
|
||||
highI--;
|
||||
}
|
||||
}
|
||||
|
||||
newNode.Polygon.Capacity = highI + 1;
|
||||
newNode.Polygon.Add(path[0]);
|
||||
int j = 0, k = 0;
|
||||
for (var i = 1; i <= highI; i++)
|
||||
if (newNode.Polygon[j] != path[i])
|
||||
{
|
||||
j++;
|
||||
newNode.Polygon.Add(path[i]);
|
||||
if (path[i].Y > newNode.Polygon[k].Y ||
|
||||
(path[i].Y == newNode.Polygon[k].Y &&
|
||||
path[i].X < newNode.Polygon[k].X)) k = j;
|
||||
}
|
||||
|
||||
if (endType == ClipperEndType.ClosedPolygon && j < 2)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
polyNodes.AddChild(newNode);
|
||||
|
||||
//if this path's lowest pt is lower than all the others then update m_lowest
|
||||
if (endType != ClipperEndType.ClosedPolygon)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (lowest.X < 0)
|
||||
{
|
||||
lowest = new ClipperIntPoint(polyNodes.ChildCount - 1, k);
|
||||
}
|
||||
else
|
||||
{
|
||||
var ip = polyNodes.Children[(int)lowest.X].Polygon[(int)lowest.Y];
|
||||
if (newNode.Polygon[k].Y > ip.Y ||
|
||||
(newNode.Polygon[k].Y == ip.Y &&
|
||||
newNode.Polygon[k].X < ip.X))
|
||||
{
|
||||
lowest = new ClipperIntPoint(polyNodes.ChildCount - 1, k);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void AddPaths(List<List<ClipperIntPoint>> paths, ClipperJoinType joinType, ClipperEndType endType)
|
||||
{
|
||||
foreach (var p in paths)
|
||||
{
|
||||
AddPath(p, joinType, endType);
|
||||
}
|
||||
}
|
||||
|
||||
public static long Round(double value) => value < 0 ? (long)(value - 0.5) : (long)(value + 0.5);
|
||||
|
||||
public static ClipperDoublePoint GetUnitNormal(ClipperIntPoint pt1, ClipperIntPoint pt2)
|
||||
{
|
||||
double dx = (pt2.X - pt1.X);
|
||||
double dy = (pt2.Y - pt1.Y);
|
||||
if ((dx == 0) && (dy == 0))
|
||||
{
|
||||
return new ClipperDoublePoint();
|
||||
}
|
||||
|
||||
var f = 1 * 1.0 / Math.Sqrt(dx * dx + dy * dy);
|
||||
dx *= f;
|
||||
dy *= f;
|
||||
|
||||
return new ClipperDoublePoint(dy, -dx);
|
||||
}
|
||||
}
|
||||
}
|
||||
81
src/UglyToad.PdfPig/Geometry/ClipperLibrary/ClipperOutPt.cs
Normal file
81
src/UglyToad.PdfPig/Geometry/ClipperLibrary/ClipperOutPt.cs
Normal file
@@ -0,0 +1,81 @@
|
||||
/*******************************************************************************
|
||||
* *
|
||||
* 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. *
|
||||
* *
|
||||
*******************************************************************************/
|
||||
|
||||
/*******************************************************************************
|
||||
* Boost Software License - Version 1.0 - August 17th, 2003 *
|
||||
* *
|
||||
* Permission is hereby granted, free of charge, to any person or organization *
|
||||
* obtaining a copy of the software and accompanying documentation covered by *
|
||||
* this license (the "Software") to use, reproduce, display, distribute, *
|
||||
* execute, and transmit the Software, and to prepare derivative works of the *
|
||||
* Software, and to permit third-parties to whom the Software is furnished to *
|
||||
* do so, all subject to the following: *
|
||||
* *
|
||||
* The copyright notices in the Software and this entire statement, including *
|
||||
* the above license grant, this restriction and the following disclaimer, *
|
||||
* must be included in all copies of the Software, in whole or in part, and *
|
||||
* all derivative works of the Software, unless such copies or derivative *
|
||||
* works are solely in the form of machine-executable object code generated by *
|
||||
* a source language processor. *
|
||||
* *
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
|
||||
* FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT *
|
||||
* SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE *
|
||||
* FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, *
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *
|
||||
* DEALINGS IN THE SOFTWARE. *
|
||||
*******************************************************************************/
|
||||
|
||||
/*******************************************************************************
|
||||
* *
|
||||
* Code modified for PdfPig *
|
||||
* *
|
||||
*******************************************************************************/
|
||||
namespace UglyToad.PdfPig.Geometry.ClipperLibrary
|
||||
{
|
||||
internal class ClipperOutPt
|
||||
{
|
||||
public int Index;
|
||||
public ClipperIntPoint Pt;
|
||||
public ClipperOutPt Next;
|
||||
public ClipperOutPt Prev;
|
||||
}
|
||||
}
|
||||
88
src/UglyToad.PdfPig/Geometry/ClipperLibrary/ClipperOutRec.cs
Normal file
88
src/UglyToad.PdfPig/Geometry/ClipperLibrary/ClipperOutRec.cs
Normal file
@@ -0,0 +1,88 @@
|
||||
/*******************************************************************************
|
||||
* *
|
||||
* 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. *
|
||||
* *
|
||||
*******************************************************************************/
|
||||
|
||||
/*******************************************************************************
|
||||
* Boost Software License - Version 1.0 - August 17th, 2003 *
|
||||
* *
|
||||
* Permission is hereby granted, free of charge, to any person or organization *
|
||||
* obtaining a copy of the software and accompanying documentation covered by *
|
||||
* this license (the "Software") to use, reproduce, display, distribute, *
|
||||
* execute, and transmit the Software, and to prepare derivative works of the *
|
||||
* Software, and to permit third-parties to whom the Software is furnished to *
|
||||
* do so, all subject to the following: *
|
||||
* *
|
||||
* The copyright notices in the Software and this entire statement, including *
|
||||
* the above license grant, this restriction and the following disclaimer, *
|
||||
* must be included in all copies of the Software, in whole or in part, and *
|
||||
* all derivative works of the Software, unless such copies or derivative *
|
||||
* works are solely in the form of machine-executable object code generated by *
|
||||
* a source language processor. *
|
||||
* *
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
|
||||
* FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT *
|
||||
* SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE *
|
||||
* FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, *
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *
|
||||
* DEALINGS IN THE SOFTWARE. *
|
||||
*******************************************************************************/
|
||||
|
||||
/*******************************************************************************
|
||||
* *
|
||||
* Code modified for PdfPig *
|
||||
* *
|
||||
*******************************************************************************/
|
||||
namespace UglyToad.PdfPig.Geometry.ClipperLibrary
|
||||
{
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
internal class ClipperOutRec
|
||||
{
|
||||
public int Idx;
|
||||
public bool IsHole;
|
||||
public bool IsOpen;
|
||||
public ClipperOutRec FirstLeft; //see comments in clipper.pas
|
||||
public ClipperOutPt Pts;
|
||||
public ClipperOutPt BottomPt;
|
||||
public ClipperPolyNode PolyNode;
|
||||
}
|
||||
}
|
||||
141
src/UglyToad.PdfPig/Geometry/ClipperLibrary/ClipperPoints.cs
Normal file
141
src/UglyToad.PdfPig/Geometry/ClipperLibrary/ClipperPoints.cs
Normal file
@@ -0,0 +1,141 @@
|
||||
/*******************************************************************************
|
||||
* *
|
||||
* 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. *
|
||||
* *
|
||||
*******************************************************************************/
|
||||
|
||||
/*******************************************************************************
|
||||
* Boost Software License - Version 1.0 - August 17th, 2003 *
|
||||
* *
|
||||
* Permission is hereby granted, free of charge, to any person or organization *
|
||||
* obtaining a copy of the software and accompanying documentation covered by *
|
||||
* this license (the "Software") to use, reproduce, display, distribute, *
|
||||
* execute, and transmit the Software, and to prepare derivative works of the *
|
||||
* Software, and to permit third-parties to whom the Software is furnished to *
|
||||
* do so, all subject to the following: *
|
||||
* *
|
||||
* The copyright notices in the Software and this entire statement, including *
|
||||
* the above license grant, this restriction and the following disclaimer, *
|
||||
* must be included in all copies of the Software, in whole or in part, and *
|
||||
* all derivative works of the Software, unless such copies or derivative *
|
||||
* works are solely in the form of machine-executable object code generated by *
|
||||
* a source language processor. *
|
||||
* *
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
|
||||
* FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT *
|
||||
* SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE *
|
||||
* FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, *
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *
|
||||
* DEALINGS IN THE SOFTWARE. *
|
||||
*******************************************************************************/
|
||||
|
||||
/*******************************************************************************
|
||||
* *
|
||||
* Code modified for PdfPig *
|
||||
* *
|
||||
*******************************************************************************/
|
||||
|
||||
namespace UglyToad.PdfPig.Geometry.ClipperLibrary
|
||||
{
|
||||
internal struct ClipperDoublePoint
|
||||
{
|
||||
public double X;
|
||||
|
||||
public double Y;
|
||||
|
||||
public ClipperDoublePoint(double x, double y)
|
||||
{
|
||||
X = x;
|
||||
Y = y;
|
||||
}
|
||||
|
||||
public ClipperDoublePoint(ClipperDoublePoint dp) : this(dp.X, dp.Y)
|
||||
{
|
||||
}
|
||||
|
||||
public ClipperDoublePoint(ClipperIntPoint ip) : this(ip.X, ip.Y)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
internal struct ClipperIntPoint
|
||||
{
|
||||
public long X;
|
||||
|
||||
public long Y;
|
||||
|
||||
public ClipperIntPoint(long x, long y)
|
||||
{
|
||||
X = x;
|
||||
Y = y;
|
||||
}
|
||||
|
||||
public ClipperIntPoint(double x, double y) : this((long)x, (long)y)
|
||||
{
|
||||
}
|
||||
|
||||
public ClipperIntPoint(ClipperIntPoint pt) : this(pt.X, pt.Y)
|
||||
{
|
||||
}
|
||||
|
||||
public static bool operator ==(ClipperIntPoint a, ClipperIntPoint b) => a.X == b.X && a.Y == b.Y;
|
||||
|
||||
public static bool operator !=(ClipperIntPoint a, ClipperIntPoint b) => a.X != b.X || a.Y != b.Y;
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
if (obj == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (obj is ClipperIntPoint a)
|
||||
{
|
||||
return (X == a.X) && (Y == a.Y);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return base.GetHashCode();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
179
src/UglyToad.PdfPig/Geometry/ClipperLibrary/ClipperPolyNode.cs
Normal file
179
src/UglyToad.PdfPig/Geometry/ClipperLibrary/ClipperPolyNode.cs
Normal file
@@ -0,0 +1,179 @@
|
||||
/*******************************************************************************
|
||||
* *
|
||||
* 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. *
|
||||
* *
|
||||
*******************************************************************************/
|
||||
|
||||
/*******************************************************************************
|
||||
* Boost Software License - Version 1.0 - August 17th, 2003 *
|
||||
* *
|
||||
* Permission is hereby granted, free of charge, to any person or organization *
|
||||
* obtaining a copy of the software and accompanying documentation covered by *
|
||||
* this license (the "Software") to use, reproduce, display, distribute, *
|
||||
* execute, and transmit the Software, and to prepare derivative works of the *
|
||||
* Software, and to permit third-parties to whom the Software is furnished to *
|
||||
* do so, all subject to the following: *
|
||||
* *
|
||||
* The copyright notices in the Software and this entire statement, including *
|
||||
* the above license grant, this restriction and the following disclaimer, *
|
||||
* must be included in all copies of the Software, in whole or in part, and *
|
||||
* all derivative works of the Software, unless such copies or derivative *
|
||||
* works are solely in the form of machine-executable object code generated by *
|
||||
* a source language processor. *
|
||||
* *
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
|
||||
* FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT *
|
||||
* SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE *
|
||||
* FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, *
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *
|
||||
* DEALINGS IN THE SOFTWARE. *
|
||||
*******************************************************************************/
|
||||
|
||||
/*******************************************************************************
|
||||
* *
|
||||
* Code modified for PdfPig *
|
||||
* *
|
||||
*******************************************************************************/
|
||||
namespace UglyToad.PdfPig.Geometry.ClipperLibrary
|
||||
{
|
||||
using System.Collections.Generic;
|
||||
|
||||
internal class ClipperPolyTree : ClipperPolyNode
|
||||
{
|
||||
internal List<ClipperPolyNode> AllPolys = new List<ClipperPolyNode>();
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
for (var i = 0; i < AllPolys.Count; i++)
|
||||
{
|
||||
AllPolys[i] = null;
|
||||
}
|
||||
|
||||
AllPolys.Clear();
|
||||
Children.Clear();
|
||||
}
|
||||
|
||||
public ClipperPolyNode GetFirst()
|
||||
{
|
||||
if (Children.Count > 0)
|
||||
{
|
||||
return Children[0];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public int Total
|
||||
{
|
||||
get
|
||||
{
|
||||
int result = AllPolys.Count;
|
||||
//with negative offsets, ignore the hidden outer polygon ...
|
||||
if (result > 0 && Children[0] != AllPolys[0])
|
||||
{
|
||||
result--;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal class ClipperPolyNode
|
||||
{
|
||||
public ClipperPolyNode Parent { get; set; }
|
||||
internal List<ClipperIntPoint> Polygon = new List<ClipperIntPoint>();
|
||||
internal int Index;
|
||||
internal ClipperJoinType JoinType;
|
||||
internal ClipperEndType EndType;
|
||||
internal List<ClipperPolyNode> Children = new List<ClipperPolyNode>();
|
||||
|
||||
public bool IsHole => IsHoleNode();
|
||||
|
||||
public bool IsOpen { get; set; }
|
||||
|
||||
private bool IsHoleNode()
|
||||
{
|
||||
bool result = true;
|
||||
ClipperPolyNode node = Parent;
|
||||
while (node != null)
|
||||
{
|
||||
result = !result;
|
||||
node = node.Parent;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public int ChildCount => Children.Count;
|
||||
|
||||
public List<ClipperIntPoint> Contour => Polygon;
|
||||
|
||||
internal void AddChild(ClipperPolyNode child)
|
||||
{
|
||||
int cnt = Children.Count;
|
||||
Children.Add(child);
|
||||
child.Parent = this;
|
||||
child.Index = cnt;
|
||||
}
|
||||
|
||||
public ClipperPolyNode GetNext()
|
||||
{
|
||||
if (Children.Count > 0)
|
||||
{
|
||||
return Children[0];
|
||||
}
|
||||
|
||||
return GetNextSiblingUp();
|
||||
}
|
||||
|
||||
internal ClipperPolyNode GetNextSiblingUp()
|
||||
{
|
||||
if (Parent == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (Index == Parent.Children.Count - 1)
|
||||
{
|
||||
return Parent.GetNextSiblingUp();
|
||||
}
|
||||
|
||||
return Parent.Children[Index + 1];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
/*******************************************************************************
|
||||
* *
|
||||
* 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. *
|
||||
* *
|
||||
*******************************************************************************/
|
||||
|
||||
/*******************************************************************************
|
||||
* Boost Software License - Version 1.0 - August 17th, 2003 *
|
||||
* *
|
||||
* Permission is hereby granted, free of charge, to any person or organization *
|
||||
* obtaining a copy of the software and accompanying documentation covered by *
|
||||
* this license (the "Software") to use, reproduce, display, distribute, *
|
||||
* execute, and transmit the Software, and to prepare derivative works of the *
|
||||
* Software, and to permit third-parties to whom the Software is furnished to *
|
||||
* do so, all subject to the following: *
|
||||
* *
|
||||
* The copyright notices in the Software and this entire statement, including *
|
||||
* the above license grant, this restriction and the following disclaimer, *
|
||||
* must be included in all copies of the Software, in whole or in part, and *
|
||||
* all derivative works of the Software, unless such copies or derivative *
|
||||
* works are solely in the form of machine-executable object code generated by *
|
||||
* a source language processor. *
|
||||
* *
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
|
||||
* FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT *
|
||||
* SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE *
|
||||
* FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, *
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *
|
||||
* DEALINGS IN THE SOFTWARE. *
|
||||
*******************************************************************************/
|
||||
|
||||
/*******************************************************************************
|
||||
* *
|
||||
* Code modified for PdfPig *
|
||||
* *
|
||||
*******************************************************************************/
|
||||
namespace UglyToad.PdfPig.Geometry.ClipperLibrary
|
||||
{
|
||||
internal class ClipperScanbeam
|
||||
{
|
||||
public long Y;
|
||||
public ClipperScanbeam Next;
|
||||
}
|
||||
}
|
||||
95
src/UglyToad.PdfPig/Geometry/ClipperLibrary/ClipperTEdge.cs
Normal file
95
src/UglyToad.PdfPig/Geometry/ClipperLibrary/ClipperTEdge.cs
Normal file
@@ -0,0 +1,95 @@
|
||||
/*******************************************************************************
|
||||
* *
|
||||
* 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. *
|
||||
* *
|
||||
*******************************************************************************/
|
||||
|
||||
/*******************************************************************************
|
||||
* Boost Software License - Version 1.0 - August 17th, 2003 *
|
||||
* *
|
||||
* Permission is hereby granted, free of charge, to any person or organization *
|
||||
* obtaining a copy of the software and accompanying documentation covered by *
|
||||
* this license (the "Software") to use, reproduce, display, distribute, *
|
||||
* execute, and transmit the Software, and to prepare derivative works of the *
|
||||
* Software, and to permit third-parties to whom the Software is furnished to *
|
||||
* do so, all subject to the following: *
|
||||
* *
|
||||
* The copyright notices in the Software and this entire statement, including *
|
||||
* the above license grant, this restriction and the following disclaimer, *
|
||||
* must be included in all copies of the Software, in whole or in part, and *
|
||||
* all derivative works of the Software, unless such copies or derivative *
|
||||
* works are solely in the form of machine-executable object code generated by *
|
||||
* a source language processor. *
|
||||
* *
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
|
||||
* FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT *
|
||||
* SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE *
|
||||
* FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, *
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *
|
||||
* DEALINGS IN THE SOFTWARE. *
|
||||
*******************************************************************************/
|
||||
|
||||
/*******************************************************************************
|
||||
* *
|
||||
* Code modified for PdfPig *
|
||||
* *
|
||||
*******************************************************************************/
|
||||
namespace UglyToad.PdfPig.Geometry.ClipperLibrary
|
||||
{
|
||||
internal class ClipperTEdge
|
||||
{
|
||||
internal ClipperIntPoint Bot;
|
||||
internal ClipperIntPoint Curr; //current (updated for every new scanbeam)
|
||||
internal ClipperIntPoint Top;
|
||||
internal ClipperIntPoint Delta;
|
||||
internal double Dx;
|
||||
internal ClipperPolyType PolyTyp;
|
||||
internal ClipperEdgeSide 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 ClipperTEdge Next;
|
||||
internal ClipperTEdge Prev;
|
||||
internal ClipperTEdge NextInLML;
|
||||
internal ClipperTEdge NextInAEL;
|
||||
internal ClipperTEdge PrevInAEL;
|
||||
internal ClipperTEdge NextInSEL;
|
||||
internal ClipperTEdge PrevInSEL;
|
||||
}
|
||||
}
|
||||
@@ -3,33 +3,41 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UglyToad.PdfPig.Core;
|
||||
using UglyToad.PdfPig.Graphics;
|
||||
using static UglyToad.PdfPig.Core.PdfSubpath;
|
||||
using ClipperLibrary;
|
||||
using Core;
|
||||
using Graphics;
|
||||
using static Core.PdfSubpath;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// Applies clipping from a clipping path to another path.
|
||||
/// </summary>
|
||||
internal static class Clipping
|
||||
internal static class ClippingExtensions
|
||||
{
|
||||
const double factor = 10_000.0;
|
||||
const int linesInCurve = 10; // number of lines to use when transforming bezier curve to polyline.
|
||||
private const double Factor = 10_000.0;
|
||||
|
||||
/// <summary>
|
||||
/// Number of lines to use when transforming bezier curve to polyline.
|
||||
/// </summary>
|
||||
private const int LinesInCurve = 10;
|
||||
|
||||
/// <summary>
|
||||
/// Generates the result of applying a clipping path to another path.
|
||||
/// </summary>
|
||||
public static PdfPath Clip(this PdfPath clipping, PdfPath subject)
|
||||
{
|
||||
if (clipping == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(clipping), "Clip(): the clipping path cannot be null.");
|
||||
throw new ArgumentNullException(nameof(clipping), $"{nameof(Clip)}: the clipping path cannot be null.");
|
||||
}
|
||||
|
||||
if (!clipping.IsClipping)
|
||||
{
|
||||
throw new ArgumentException("Clip(): the clipping path does not have the IsClipping flag set to true.", nameof(clipping));
|
||||
throw new ArgumentException($"{nameof(Clip)}: the clipping path does not have the IsClipping flag set to true.", nameof(clipping));
|
||||
}
|
||||
|
||||
if (subject == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(subject), "Clip(): the subject path cannot be null.");
|
||||
throw new ArgumentNullException(nameof(subject), $"{nameof(Clip)}: the subject path cannot be null.");
|
||||
}
|
||||
|
||||
if (subject.Count == 0)
|
||||
@@ -37,7 +45,7 @@
|
||||
return subject;
|
||||
}
|
||||
|
||||
Clipper clipper = new Clipper();
|
||||
var clipper = new Clipper();
|
||||
|
||||
// Clipping path
|
||||
foreach (var subPathClipping in clipping)
|
||||
@@ -53,7 +61,7 @@
|
||||
subPathClipping.CloseSubpath();
|
||||
}
|
||||
|
||||
clipper.AddPath(subPathClipping.ToClipperPolygon().ToList(), PolyType.ptClip, true);
|
||||
clipper.AddPath(subPathClipping.ToClipperPolygon().ToList(), ClipperPolyType.Clip, true);
|
||||
}
|
||||
|
||||
// Subject path
|
||||
@@ -72,36 +80,41 @@
|
||||
subPathSubject.CloseSubpath();
|
||||
}
|
||||
|
||||
clipper.AddPath(subPathSubject.ToClipperPolygon().ToList(), PolyType.ptSubject, subjectClose);
|
||||
clipper.AddPath(subPathSubject.ToClipperPolygon().ToList(), ClipperPolyType.Subject, subjectClose);
|
||||
}
|
||||
|
||||
var clippingFillType = clipping.FillingRule == FillingRule.NonZeroWinding ? PolyFillType.pftNonZero : PolyFillType.pftEvenOdd;
|
||||
var subjectFillType = subject.FillingRule == FillingRule.NonZeroWinding ? PolyFillType.pftNonZero : PolyFillType.pftEvenOdd;
|
||||
var clippingFillType = clipping.FillingRule == FillingRule.NonZeroWinding ? ClipperPolyFillType.NonZero : ClipperPolyFillType.EvenOdd;
|
||||
var subjectFillType = subject.FillingRule == FillingRule.NonZeroWinding ? ClipperPolyFillType.NonZero : ClipperPolyFillType.EvenOdd;
|
||||
|
||||
if (!subjectClose)
|
||||
{
|
||||
PdfPath clippedPath = subject.CloneEmpty();
|
||||
|
||||
// Case where subject is not closed
|
||||
var solutions = new PolyTree();
|
||||
if (clipper.Execute(ClipType.ctIntersection, solutions, subjectFillType, clippingFillType))
|
||||
var solutions = new ClipperPolyTree();
|
||||
if (clipper.Execute(ClipperClipType.Intersection, solutions, subjectFillType, clippingFillType))
|
||||
{
|
||||
foreach (var solution in solutions.Childs)
|
||||
foreach (var solution in solutions.Children)
|
||||
{
|
||||
if (solution.Contour.Count > 0)
|
||||
{
|
||||
PdfSubpath clippedSubpath = new PdfSubpath();
|
||||
clippedSubpath.MoveTo(solution.Contour[0].X / factor, solution.Contour[0].Y / factor);
|
||||
clippedSubpath.MoveTo(solution.Contour[0].X / Factor, solution.Contour[0].Y / Factor);
|
||||
|
||||
for (int i = 1; i < solution.Contour.Count; i++)
|
||||
{
|
||||
clippedSubpath.LineTo(solution.Contour[i].X / factor, solution.Contour[i].Y / factor);
|
||||
clippedSubpath.LineTo(solution.Contour[i].X / Factor, solution.Contour[i].Y / Factor);
|
||||
}
|
||||
clippedPath.Add(clippedSubpath);
|
||||
}
|
||||
}
|
||||
if (clippedPath.Count > 0) return clippedPath;
|
||||
|
||||
if (clippedPath.Count > 0)
|
||||
{
|
||||
return clippedPath;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
else
|
||||
@@ -109,34 +122,42 @@
|
||||
PdfPath clippedPath = subject.CloneEmpty();
|
||||
|
||||
// Case where subject is closed
|
||||
var solutions = new List<List<IntPoint>>();
|
||||
if (clipper.Execute(ClipType.ctIntersection, solutions, subjectFillType, clippingFillType))
|
||||
var solutions = new List<List<ClipperIntPoint>>();
|
||||
if (!clipper.Execute(ClipperClipType.Intersection, solutions, subjectFillType, clippingFillType))
|
||||
{
|
||||
foreach (var solution in solutions)
|
||||
{
|
||||
if (solution.Count > 0)
|
||||
{
|
||||
PdfSubpath clippedSubpath = new PdfSubpath();
|
||||
clippedSubpath.MoveTo(solution[0].X / factor, solution[0].Y / factor);
|
||||
|
||||
for (int i = 1; i < solution.Count; i++)
|
||||
{
|
||||
clippedSubpath.LineTo(solution[i].X / factor, solution[i].Y / factor);
|
||||
}
|
||||
clippedSubpath.CloseSubpath();
|
||||
clippedPath.Add(clippedSubpath);
|
||||
}
|
||||
}
|
||||
if (clippedPath.Count > 0) return clippedPath;
|
||||
return null;
|
||||
}
|
||||
|
||||
foreach (var solution in solutions)
|
||||
{
|
||||
if (solution.Count > 0)
|
||||
{
|
||||
PdfSubpath clippedSubpath = new PdfSubpath();
|
||||
clippedSubpath.MoveTo(solution[0].X / Factor, solution[0].Y / Factor);
|
||||
|
||||
for (int i = 1; i < solution.Count; i++)
|
||||
{
|
||||
clippedSubpath.LineTo(solution[i].X / Factor, solution[i].Y / Factor);
|
||||
}
|
||||
clippedSubpath.CloseSubpath();
|
||||
clippedPath.Add(clippedSubpath);
|
||||
}
|
||||
}
|
||||
|
||||
if (clippedPath.Count > 0)
|
||||
{
|
||||
return clippedPath;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a path to a set of points for the Clipper algorithm to use.
|
||||
/// Allows duplicate points as they will be removed by Clipper.
|
||||
/// </summary>
|
||||
private static IEnumerable<IntPoint> ToClipperPolygon(this PdfSubpath pdfPath)
|
||||
private static IEnumerable<ClipperIntPoint> ToClipperPolygon(this PdfSubpath pdfPath)
|
||||
{
|
||||
if (pdfPath.Commands.Count == 0)
|
||||
{
|
||||
@@ -145,38 +166,44 @@
|
||||
|
||||
if (pdfPath.Commands[0] is Move currentMove)
|
||||
{
|
||||
var previous = new IntPoint(currentMove.Location.X * factor, currentMove.Location.Y * factor);
|
||||
var previous = new ClipperIntPoint(currentMove.Location.X * Factor, currentMove.Location.Y * Factor);
|
||||
|
||||
yield return previous;
|
||||
if (pdfPath.Commands.Count == 1) yield break;
|
||||
|
||||
if (pdfPath.Commands.Count == 1)
|
||||
{
|
||||
yield break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ArgumentException("ToClipperPolygon(): First command is not a Move command. Type is '" + pdfPath.Commands[0].GetType().ToString() + "'.", nameof(pdfPath));
|
||||
throw new ArgumentException($"ToClipperPolygon(): First command is not a Move command. Type is '{pdfPath.Commands[0].GetType()}'.", nameof(pdfPath));
|
||||
}
|
||||
|
||||
for (int i = 1; i < pdfPath.Commands.Count; i++)
|
||||
for (var i = 1; i < pdfPath.Commands.Count; i++)
|
||||
{
|
||||
var command = pdfPath.Commands[i];
|
||||
if (command is Move move)
|
||||
if (command is Move)
|
||||
{
|
||||
throw new ArgumentException("ToClipperPolygon():only one move allowed per subpath.", nameof(pdfPath));
|
||||
}
|
||||
else if (command is Line line)
|
||||
|
||||
if (command is Line line)
|
||||
{
|
||||
yield return new IntPoint(line.From.X * factor, line.From.Y * factor);
|
||||
yield return new IntPoint(line.To.X * factor, line.To.Y * factor);
|
||||
yield return new ClipperIntPoint(line.From.X * Factor, line.From.Y * Factor);
|
||||
yield return new ClipperIntPoint(line.To.X * Factor, line.To.Y * Factor);
|
||||
}
|
||||
else if (command is BezierCurve curve)
|
||||
{
|
||||
foreach (var lineB in curve.ToLines(linesInCurve))
|
||||
foreach (var lineB in curve.ToLines(LinesInCurve))
|
||||
{
|
||||
yield return new IntPoint(lineB.From.X * factor, lineB.From.Y * factor);
|
||||
yield return new IntPoint(lineB.To.X * factor, lineB.To.Y * factor);
|
||||
yield return new ClipperIntPoint(lineB.From.X * Factor, lineB.From.Y * Factor);
|
||||
yield return new ClipperIntPoint(lineB.To.X * Factor, lineB.To.Y * Factor);
|
||||
}
|
||||
}
|
||||
else if (command is Close)
|
||||
{
|
||||
yield return new IntPoint(currentMove.Location.X * factor, currentMove.Location.Y * factor);
|
||||
yield return new ClipperIntPoint(currentMove.Location.X * Factor, currentMove.Location.Y * Factor);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user