Browse Source

Port Clipper.cs into ImageSharp style

All the classes from Clipper.cs have been moved into there own folder/namespace.
Added README.md to preserve the original Attribution.
I've ported the code to use Vector2 instead of its own point classes.
I've removed all the unused clipping options, and polygon styles that are not required and thus removed a lot of branching logic.
pull/52/head
Scott Williams 9 years ago
parent
commit
c39a633fbf
  1. 4924
      src/ImageSharp/Drawing/Shapes/Clipper.cs
  2. 165
      src/ImageSharp/Drawing/Shapes/ComplexPolygon.cs
  3. 3860
      src/ImageSharp/Drawing/Shapes/PolygonClipper/Clipper.cs
  4. 31
      src/ImageSharp/Drawing/Shapes/PolygonClipper/ClipperException.cs
  5. 31
      src/ImageSharp/Drawing/Shapes/PolygonClipper/Direction.cs
  6. 31
      src/ImageSharp/Drawing/Shapes/PolygonClipper/EdgeSide.cs
  7. 38
      src/ImageSharp/Drawing/Shapes/PolygonClipper/IntersectNode.cs
  8. 48
      src/ImageSharp/Drawing/Shapes/PolygonClipper/IntersectNodeSort.cs
  9. 38
      src/ImageSharp/Drawing/Shapes/PolygonClipper/Join.cs
  10. 44
      src/ImageSharp/Drawing/Shapes/PolygonClipper/LocalMinima.cs
  11. 38
      src/ImageSharp/Drawing/Shapes/PolygonClipper/Maxima.cs
  12. 43
      src/ImageSharp/Drawing/Shapes/PolygonClipper/OutPt.cs
  13. 64
      src/ImageSharp/Drawing/Shapes/PolygonClipper/OutRec.cs
  14. 179
      src/ImageSharp/Drawing/Shapes/PolygonClipper/PolyNode.cs
  15. 81
      src/ImageSharp/Drawing/Shapes/PolygonClipper/PolyTree.cs
  16. 31
      src/ImageSharp/Drawing/Shapes/PolygonClipper/PolyType.cs
  17. 40
      src/ImageSharp/Drawing/Shapes/PolygonClipper/README.md
  18. 33
      src/ImageSharp/Drawing/Shapes/PolygonClipper/Scanbeam.cs
  19. 118
      src/ImageSharp/Drawing/Shapes/PolygonClipper/TEdge.cs

4924
src/ImageSharp/Drawing/Shapes/Clipper.cs

File diff suppressed because it is too large

165
src/ImageSharp/Drawing/Shapes/ComplexPolygon.cs

@ -11,6 +11,7 @@ namespace ImageSharp.Drawing.Shapes
using System.Numerics;
using Paths;
using PolygonClipper;
/// <summary>
/// Represents a complex polygon made up of one or more outline
@ -124,156 +125,78 @@ namespace ImageSharp.Drawing.Shapes
return this.GetEnumerator();
}
private void AddPoints(ClipperLib.Clipper clipper, IShape shape, ClipperLib.PolyType polyType)
private void AddPoints(Clipper clipper, IShape shape, PolyType polyType)
{
foreach (var path in shape)
// if the path is already the shape use it directly and skip the path loop.
if (shape is IPath)
{
var points = path.AsSimpleLinearPath();
var clipperPoints = new List<ClipperLib.IntPoint>();
foreach (var point in points)
{
var p = point * ClipperScaleFactor;
clipperPoints.Add(new ClipperLib.IntPoint((long)p.X, (long)p.Y));
}
clipper.AddPath(
clipperPoints,
polyType,
path.IsClosed);
(IPath)shape,
polyType);
}
}
private void AddPoints(ClipperLib.Clipper clipper, IShape[] shapes, bool[] shouldInclude, ClipperLib.PolyType polyType)
{
for (var i = 0; i < shapes.Length; i++)
else
{
if (shouldInclude[i])
foreach (var path in shape)
{
this.AddPoints(clipper, shapes[i], polyType);
clipper.AddPath(
path,
polyType);
}
}
}
private void ExtractOutlines(ClipperLib.PolyNode tree, List<IShape> shapes)
private void AddPoints(Clipper clipper, IEnumerable<IShape> shapes, PolyType polyType)
{
if (tree.Contour.Any())
foreach (var shape in shapes)
{
// convert the Clipper Contour from scaled ints back down to the origional size (this is going to be lossy but not significantly)
var pointCount = tree.Contour.Count;
var vectors = new Vector2[pointCount];
for (var i = 0; i < pointCount; i++)
{
var p = tree.Contour[i];
vectors[i] = new Vector2(p.X, p.Y) / ClipperScaleFactor;
}
var polygon = new Polygon(new LinearLineSegment(vectors));
shapes.Add(polygon);
}
foreach (var c in tree.Childs)
{
this.ExtractOutlines(c, shapes);
this.AddPoints(clipper, shape, polyType);
}
}
/// <summary>
/// Determines if the <see cref="IShape"/>s bounding boxes overlap.
/// </summary>
/// <param name="source">The source.</param>
/// <param name="target">The target.</param>
/// <returns>true if the 2 shapes bounding boxes overlap.</returns>
private bool OverlappingBoundingBoxes(IShape source, IShape target)
{
return source.Bounds.Intersects(target.Bounds);
}
private void FixAndSetShapes(IShape[] outlines, IShape[] holes)
private void ExtractOutlines(PolyNode tree, List<IShape> shapes, List<IPath> paths)
{
// if any outline doesn't overlap another shape then we don't have to bother with sending them through clipper
// as sending then though clipper will turn them into generic polygons and loose thier shape specific optimisations
int outlineLength = outlines.Length;
int holesLength = holes?.Length ?? 0;
bool[] overlappingOutlines = new bool[outlineLength];
bool[] overlappingHoles = new bool[holesLength];
bool anyOutlinesOverlapping = false;
bool anyHolesOverlapping = false;
for (int i = 0; i < outlineLength; i++)
if (tree.Contour.Any())
{
for (int j = i + 1; j < outlineLength; j++)
// if the source path is set then we clipper retained the full path intact thus we can freely
// use it and get any shape optimisations that are availible.
if (tree.SourcePath != null)
{
// skip the bounds check if they are already tested
if (overlappingOutlines[i] == false || overlappingOutlines[j] == false)
{
if (this.OverlappingBoundingBoxes(outlines[i], outlines[j]))
{
overlappingOutlines[i] = true;
overlappingOutlines[j] = true;
anyOutlinesOverlapping = true;
}
}
shapes.Add((IShape)tree.SourcePath);
paths.Add(tree.SourcePath);
}
for (int k = 0; k < holesLength; k++)
else
{
if (overlappingOutlines[i] == false || overlappingHoles[k] == false)
{
if (this.OverlappingBoundingBoxes(outlines[i], holes[k]))
{
overlappingOutlines[i] = true;
overlappingHoles[k] = true;
anyOutlinesOverlapping = true;
anyHolesOverlapping = true;
}
}
// convert the Clipper Contour from scaled ints back down to the origional size (this is going to be lossy but not significantly)
var polygon = new Polygon(new Paths.LinearLineSegment(tree.Contour.ToArray()));
shapes.Add(polygon);
paths.Add(polygon);
}
}
if (anyOutlinesOverlapping)
foreach (var c in tree.Children)
{
var clipper = new ClipperLib.Clipper();
// add the outlines and the holes to clipper, scaling up from the float source to the int based system clipper uses
this.AddPoints(clipper, outlines, overlappingOutlines, ClipperLib.PolyType.ptSubject);
if (anyHolesOverlapping)
{
this.AddPoints(clipper, holes, overlappingHoles, ClipperLib.PolyType.ptClip);
}
var tree = new ClipperLib.PolyTree();
clipper.Execute(ClipperLib.ClipType.ctDifference, tree);
List<IShape> newShapes = new List<IShape>();
this.ExtractOutlines(c, shapes, paths);
}
}
// convert the 'tree' back to shapes
this.ExtractOutlines(tree, newShapes);
private void FixAndSetShapes(IEnumerable<IShape> outlines, IEnumerable<IShape> holes)
{
var clipper = new Clipper();
// add the origional outlines that where not overlapping
for (int i = 0; i < outlineLength - 1; i++)
{
if (!overlappingOutlines[i])
{
newShapes.Add(outlines[i]);
}
}
// add the outlines and the holes to clipper, scaling up from the float source to the int based system clipper uses
this.AddPoints(clipper, outlines, PolyType.Subject);
this.AddPoints(clipper, holes, PolyType.Clip);
this.shapes = newShapes.ToArray();
}
else
{
this.shapes = outlines;
}
var tree = clipper.Execute();
var paths = new List<IPath>();
foreach (var o in this.shapes)
{
paths.AddRange(o);
}
List<IShape> shapes = new List<IShape>();
List<IPath> paths = new List<IPath>();
this.paths = paths;
// convert the 'tree' back to paths
this.ExtractOutlines(tree, shapes, paths);
this.shapes = shapes.ToArray();
this.paths = paths.ToArray();
}
}
}

3860
src/ImageSharp/Drawing/Shapes/PolygonClipper/Clipper.cs

File diff suppressed because it is too large

31
src/ImageSharp/Drawing/Shapes/PolygonClipper/ClipperException.cs

@ -0,0 +1,31 @@
// <copyright file="ClipperException.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp.Drawing.Shapes.PolygonClipper
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using System.Runtime.CompilerServices;
using Paths;
/// <summary>
/// Clipper Exception
/// </summary>
/// <seealso cref="System.Exception" />
internal class ClipperException : Exception
{
/// <summary>
/// Initializes a new instance of the <see cref="ClipperException"/> class.
/// </summary>
/// <param name="description">The description.</param>
public ClipperException(string description)
: base(description)
{
}
}
}

31
src/ImageSharp/Drawing/Shapes/PolygonClipper/Direction.cs

@ -0,0 +1,31 @@
// <copyright file="Direction.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp.Drawing.Shapes.PolygonClipper
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using System.Runtime.CompilerServices;
using Paths;
/// <summary>
/// ???
/// </summary>
internal enum Direction
{
/// <summary>
/// The right to left
/// </summary>
RightToLeft,
/// <summary>
/// The left to right
/// </summary>
LeftToRight
}
}

31
src/ImageSharp/Drawing/Shapes/PolygonClipper/EdgeSide.cs

@ -0,0 +1,31 @@
// <copyright file="EdgeSide.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp.Drawing.Shapes.PolygonClipper
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using System.Runtime.CompilerServices;
using Paths;
/// <summary>
/// ??
/// </summary>
internal enum EdgeSide
{
/// <summary>
/// The left
/// </summary>
Left,
/// <summary>
/// The right
/// </summary>
Right
}
}

38
src/ImageSharp/Drawing/Shapes/PolygonClipper/IntersectNode.cs

@ -0,0 +1,38 @@
// <copyright file="IntersectNode.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp.Drawing.Shapes.PolygonClipper
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using System.Runtime.CompilerServices;
using Paths;
/// <summary>
/// ??
/// </summary>
internal class IntersectNode
{
#pragma warning disable SA1401 // Field must be private
/// <summary>
/// The edge1
/// </summary>
internal TEdge Edge1;
/// <summary>
/// The edge2
/// </summary>
internal TEdge Edge2;
/// <summary>
/// The pt
/// </summary>
internal System.Numerics.Vector2 Pt;
#pragma warning restore SA1401 // Field must be private
}
}

48
src/ImageSharp/Drawing/Shapes/PolygonClipper/IntersectNodeSort.cs

@ -0,0 +1,48 @@
// <copyright file="IntersectNodeSort.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp.Drawing.Shapes.PolygonClipper
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using System.Runtime.CompilerServices;
using Paths;
/// <summary>
/// Compares <see cref="IntersectNode"/>s
/// </summary>
internal class IntersectNodeSort : IComparer<IntersectNode>
{
/// <summary>
/// Compares the specified node1.
/// </summary>
/// <param name="node1">The node1.</param>
/// <param name="node2">The node2.</param>
/// <returns>
/// 1 if node2 %gt; node1
/// -1 if node2 $lt; node1
/// 0 if same
/// </returns>
public int Compare(IntersectNode node1, IntersectNode node2)
{
float i = node2.Pt.Y - node1.Pt.Y;
if (i > 0)
{
return 1;
}
else if (i < 0)
{
return -1;
}
else
{
return 0;
}
}
}
}

38
src/ImageSharp/Drawing/Shapes/PolygonClipper/Join.cs

@ -0,0 +1,38 @@
// <copyright file="Join.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp.Drawing.Shapes.PolygonClipper
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using System.Runtime.CompilerServices;
using Paths;
/// <summary>
/// ??
/// </summary>
internal class Join
{
#pragma warning disable SA1401 // Field must be private
/// <summary>
/// The out PT1
/// </summary>
internal OutPt OutPt1;
/// <summary>
/// The out PT2
/// </summary>
internal OutPt OutPt2;
/// <summary>
/// The off pt
/// </summary>
internal System.Numerics.Vector2 OffPt;
#pragma warning restore SA1401 // Field must be private
}
}

44
src/ImageSharp/Drawing/Shapes/PolygonClipper/LocalMinima.cs

@ -0,0 +1,44 @@
// <copyright file="LocalMinima.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp.Drawing.Shapes.PolygonClipper
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using System.Runtime.CompilerServices;
using Paths;
/// <summary>
/// ??
/// </summary>
internal class LocalMinima
{
#pragma warning disable SA1401 // Field must be private
/// <summary>
/// The y
/// </summary>
internal float Y;
/// <summary>
/// The left bound
/// </summary>
internal TEdge LeftBound;
/// <summary>
/// The right bound
/// </summary>
internal TEdge RightBound;
/// <summary>
/// The next
/// </summary>
internal LocalMinima Next;
#pragma warning restore SA1401 // Field must be private
}
}

38
src/ImageSharp/Drawing/Shapes/PolygonClipper/Maxima.cs

@ -0,0 +1,38 @@
// <copyright file="Maxima.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp.Drawing.Shapes.PolygonClipper
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using System.Runtime.CompilerServices;
using Paths;
/// <summary>
/// ??
/// </summary>
internal class Maxima
{
#pragma warning disable SA1401 // Field must be private
/// <summary>
/// The x
/// </summary>
internal float X;
/// <summary>
/// The next
/// </summary>
internal Maxima Next;
/// <summary>
/// The previous
/// </summary>
internal Maxima Prev;
#pragma warning restore SA1401 // Field must be private
}
}

43
src/ImageSharp/Drawing/Shapes/PolygonClipper/OutPt.cs

@ -0,0 +1,43 @@
// <copyright file="OutPt.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp.Drawing.Shapes.PolygonClipper
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using System.Runtime.CompilerServices;
using Paths;
/// <summary>
/// ??
/// </summary>
internal class OutPt
{
#pragma warning disable SA1401 // Field must be private
/// <summary>
/// The index
/// </summary>
internal int Idx;
/// <summary>
/// The pt
/// </summary>
internal System.Numerics.Vector2 Pt;
/// <summary>
/// The next
/// </summary>
internal OutPt Next;
/// <summary>
/// The previous
/// </summary>
internal OutPt Prev;
#pragma warning restore SA1401 // Field must be private
}
}

64
src/ImageSharp/Drawing/Shapes/PolygonClipper/OutRec.cs

@ -0,0 +1,64 @@
// <copyright file="OutRec.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp.Drawing.Shapes.PolygonClipper
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using System.Runtime.CompilerServices;
using Paths;
/// <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 OutRec
{
#pragma warning disable SA1401 // Field must be private
/// <summary>
/// The source path
/// </summary>
internal IPath SourcePath;
/// <summary>
/// The index
/// </summary>
internal int Idx;
/// <summary>
/// The is hole
/// </summary>
internal bool IsHole;
/// <summary>
/// The is open
/// </summary>
internal bool IsOpen;
/// <summary>
/// The first left
/// </summary>
internal OutRec FirstLeft;
/// <summary>
/// The PTS
/// </summary>
internal OutPt Pts;
/// <summary>
/// The bottom pt
/// </summary>
internal OutPt BottomPt;
/// <summary>
/// The poly node
/// </summary>
internal PolyNode PolyNode;
#pragma warning restore SA1401 // Field must be private
}
}

179
src/ImageSharp/Drawing/Shapes/PolygonClipper/PolyNode.cs

@ -0,0 +1,179 @@
// <copyright file="PolyNode.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp.Drawing.Shapes.PolygonClipper
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using System.Runtime.CompilerServices;
using Paths;
/// <summary>
/// Poly Node
/// </summary>
internal class PolyNode
{
#pragma warning disable SA1401 // Field must be private
/// <summary>
/// The polygon
/// </summary>
internal List<Vector2> Polygon = new List<Vector2>();
/// <summary>
/// The index
/// </summary>
internal int Index;
/// <summary>
/// The childs
/// </summary>
protected List<PolyNode> children = new List<PolyNode>();
private PolyNode parent;
#pragma warning restore SA1401 // Field must be private
/// <summary>
/// Gets the child count.
/// </summary>
/// <value>
/// The child count.
/// </value>
public int ChildCount
{
get { return this.children.Count; }
}
/// <summary>
/// Gets the contour.
/// </summary>
/// <value>
/// The contour.
/// </value>
public List<Vector2> Contour
{
get { return this.Polygon; }
}
/// <summary>
/// Gets the childs.
/// </summary>
/// <value>
/// The childs.
/// </value>
public List<PolyNode> Children
{
get { return this.children; }
}
/// <summary>
/// Gets or sets the parent.
/// </summary>
/// <value>
/// The parent.
/// </value>
public PolyNode Parent
{
get { return this.parent; }
internal set { this.parent = value; }
}
/// <summary>
/// Gets a value indicating whether this instance is hole.
/// </summary>
/// <value>
/// <c>true</c> if this instance is hole; otherwise, <c>false</c>.
/// </value>
public bool IsHole
{
get { return this.IsHoleNode(); }
}
/// <summary>
/// Gets or sets a value indicating whether this instance is open.
/// </summary>
/// <value>
/// <c>true</c> if this instance is open; otherwise, <c>false</c>.
/// </value>
public bool IsOpen { get; set; }
/// <summary>
/// Gets or sets the source path.
/// </summary>
/// <value>
/// The source path.
/// </value>
public IPath SourcePath { get; internal set; }
/// <summary>
/// Gets the next.
/// </summary>
/// <returns>The next node</returns>
public PolyNode GetNext()
{
if (this.children.Count > 0)
{
return this.children[0];
}
else
{
return this.GetNextSiblingUp();
}
}
/// <summary>
/// Adds the child.
/// </summary>
/// <param name="child">The child.</param>
internal void AddChild(PolyNode child)
{
int cnt = this.children.Count;
this.children.Add(child);
child.parent = this;
child.Index = cnt;
}
/// <summary>
/// Gets the next sibling up.
/// </summary>
/// <returns>The next sibling up</returns>
internal PolyNode GetNextSiblingUp()
{
if (this.parent == null)
{
return null;
}
else if (this.Index == this.parent.children.Count - 1)
{
return this.parent.GetNextSiblingUp();
}
else
{
return this.parent.Children[this.Index + 1];
}
}
/// <summary>
/// Determines whether [is hole node].
/// </summary>
/// <returns>
/// <c>true</c> if [is hole node]; otherwise, <c>false</c>.
/// </returns>
private bool IsHoleNode()
{
bool result = true;
PolyNode node = this.parent;
while (node != null)
{
result = !result;
node = node.parent;
}
return result;
}
}
}

81
src/ImageSharp/Drawing/Shapes/PolygonClipper/PolyTree.cs

@ -0,0 +1,81 @@
// <copyright file="PolyTree.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp.Drawing.Shapes.PolygonClipper
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using System.Runtime.CompilerServices;
using Paths;
/// <summary>
/// Poly Tree
/// </summary>
/// <seealso cref="ImageSharp.Drawing.Shapes.PolygonClipper.PolyNode" />
internal class PolyTree : PolyNode
{
#pragma warning disable SA1401 // Field must be private
/// <summary>
/// All polys
/// </summary>
internal List<PolyNode> AllPolys = new List<PolyNode>();
#pragma warning restore SA1401 // Field must be private
/// <summary>
/// Gets the total.
/// </summary>
/// <value>
/// The total.
/// </value>
public int Total
{
get
{
int result = this.AllPolys.Count;
// with negative offsets, ignore the hidden outer polygon ...
if (result > 0 && this.Children[0] != this.AllPolys[0])
{
result--;
}
return result;
}
}
/// <summary>
/// Clears this instance.
/// </summary>
public void Clear()
{
for (int i = 0; i < this.AllPolys.Count; i++)
{
this.AllPolys[i] = null;
}
this.AllPolys.Clear();
this.Children.Clear();
}
/// <summary>
/// Gets the first.
/// </summary>
/// <returns>the first node</returns>
public PolyNode GetFirst()
{
if (this.Children.Count > 0)
{
return this.Children[0];
}
else
{
return null;
}
}
}
}

31
src/ImageSharp/Drawing/Shapes/PolygonClipper/PolyType.cs

@ -0,0 +1,31 @@
// <copyright file="PolyType.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp.Drawing.Shapes.PolygonClipper
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using System.Runtime.CompilerServices;
using Paths;
/// <summary>
/// Poly Type
/// </summary>
internal enum PolyType
{
/// <summary>
/// The subject
/// </summary>
Subject,
/// <summary>
/// The clip
/// </summary>
Clip
}
}

40
src/ImageSharp/Drawing/Shapes/PolygonClipper/README.md

@ -0,0 +1,40 @@
# Clipper
License details for code in this folder, this is code original written by **Angus Johnson**
The license header onthe original file which has now be split across multiple files in this folder.
```
/*******************************************************************************
* *
* Author : Angus Johnson *
* Version : 6.4.0 *
* Date : 2 July 2015 *
* Website : http://www.angusj.com *
* Copyright : Angus Johnson 2010-2015 *
* *
* 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 *
* *
*******************************************************************************/
```

33
src/ImageSharp/Drawing/Shapes/PolygonClipper/Scanbeam.cs

@ -0,0 +1,33 @@
// <copyright file="Scanbeam.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp.Drawing.Shapes.PolygonClipper
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using System.Runtime.CompilerServices;
using Paths;
/// <summary>
/// Scanbeam
/// </summary>
internal class Scanbeam // would this work as a struct?
{
#pragma warning disable SA1401 // Field must be private
/// <summary>
/// The y
/// </summary>
internal float Y;
/// <summary>
/// The next
/// </summary>
internal Scanbeam Next;
#pragma warning restore SA1401 // Field must be private
}
}

118
src/ImageSharp/Drawing/Shapes/PolygonClipper/TEdge.cs

@ -0,0 +1,118 @@
// <copyright file="TEdge.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp.Drawing.Shapes.PolygonClipper
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using System.Runtime.CompilerServices;
using Paths;
/// <summary>
/// TEdge
/// </summary>
internal class TEdge
{
#pragma warning disable SA1401 // Field must be private
/// <summary>
/// The source path, see if we can link this back later
/// </summary>
internal IPath SourcePath;
/// <summary>
/// The bot
/// </summary>
internal System.Numerics.Vector2 Bot;
/// <summary>
/// The current (updated for every new scanbeam)
/// </summary>
internal System.Numerics.Vector2 Curr;
/// <summary>
/// The top
/// </summary>
internal System.Numerics.Vector2 Top;
/// <summary>
/// The delta
/// </summary>
internal System.Numerics.Vector2 Delta;
/// <summary>
/// The dx
/// </summary>
internal double Dx;
/// <summary>
/// The poly type
/// </summary>
internal PolyType PolyTyp;
/// <summary>
/// Side only refers to current side of solution poly
/// </summary>
internal EdgeSide Side;
/// <summary>
/// 1 or -1 depending on winding direction
/// </summary>
internal int WindDelta;
/// <summary>
/// The winding count
/// </summary>
internal int WindCnt;
/// <summary>
/// The winding count of the opposite polytype
/// </summary>
internal int WindCnt2;
/// <summary>
/// The out index
/// </summary>
internal int OutIdx;
/// <summary>
/// The next
/// </summary>
internal TEdge Next;
/// <summary>
/// The previous
/// </summary>
internal TEdge Prev;
/// <summary>
/// The next in LML
/// </summary>
internal TEdge NextInLML;
/// <summary>
/// The next in ael
/// </summary>
internal TEdge NextInAEL;
/// <summary>
/// The previous in ael
/// </summary>
internal TEdge PrevInAEL;
/// <summary>
/// The next in sel
/// </summary>
internal TEdge NextInSEL;
/// <summary>
/// The previous in sel
/// </summary>
internal TEdge PrevInSEL;
#pragma warning restore SA1401 // Field must be
}
}
Loading…
Cancel
Save