Skip to content

Commit 6c6ff30

Browse files
committed
First draft of PolygonOffsette
First draft of implementing PolygonOffsetter Also added back the IntersectionRule to GenerateClippedShapes. It is not implemented yet
1 parent 2e76417 commit 6c6ff30

File tree

5 files changed

+65
-20
lines changed

5 files changed

+65
-20
lines changed

src/ImageSharp.Drawing/Shapes/ClipPathExtensions.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ public static IPath Clip(
6363
clipper.AddPath(subjectPath, ClippingType.Subject);
6464
clipper.AddPaths(clipPaths, ClippingType.Clip);
6565

66-
IPath[] result = clipper.GenerateClippedShapes(options.ClippingOperation);
66+
IPath[] result = clipper.GenerateClippedShapes(options.ClippingOperation, options.IntersectionRule);
6767

6868
return new ComplexPolygon(result);
6969
}

src/ImageSharp.Drawing/Shapes/ISimplePath.cs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
// Copyright (c) Six Labors.
22
// Licensed under the Six Labors Split License.
33

4+
using System.Runtime.CompilerServices;
5+
using System.Runtime.InteropServices.ComTypes;
6+
using SixLabors.ImageSharp.Drawing.Shapes.PolygonClipper;
7+
using SixLabors.PolygonClipper;
8+
49
namespace SixLabors.ImageSharp.Drawing;
510

611
/// <summary>
@@ -17,4 +22,22 @@ public interface ISimplePath
1722
/// Gets the points that make this up as a simple linear path.
1823
/// </summary>
1924
ReadOnlyMemory<PointF> Points { get; }
25+
26+
/// <summary>
27+
/// Converts to <see cref="SixLabors.PolygonClipper.Polygon"/>
28+
/// </summary>
29+
/// <returns>The converted polygon.</returns>
30+
internal SixLabors.PolygonClipper.Polygon ToPolygon()
31+
{
32+
SixLabors.PolygonClipper.Polygon polygon = [];
33+
Contour contour = new();
34+
polygon.Add(contour);
35+
36+
foreach (PointF point in this.Points.Span)
37+
{
38+
contour.AddVertex(new Vertex(point.X, point.Y));
39+
}
40+
41+
return polygon;
42+
}
2043
}

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

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ internal class Clipper
1919
/// <param name="operation">The clipping operation.</param>
2020
/// <param name="rule">The intersection rule.</param>
2121
/// <returns>The <see cref="T:IPath[]"/>.</returns>
22-
public IPath[] GenerateClippedShapes(BooleanOperation operation)
22+
public IPath[] GenerateClippedShapes(BooleanOperation operation, IntersectionRule rule)
2323
{
2424
ArgumentNullException.ThrowIfNull(this.subject);
2525
ArgumentNullException.ThrowIfNull(this.clip);
@@ -28,7 +28,6 @@ public IPath[] GenerateClippedShapes(BooleanOperation operation)
2828

2929
SixLabors.PolygonClipper.Polygon result = polygonClipper.Run();
3030

31-
3231
IPath[] shapes = new IPath[result.Count];
3332

3433
int index = 0;
@@ -86,15 +85,7 @@ public void AddPath(IPath path, ClippingType clippingType)
8685
/// <param name="clippingType">Type of the poly.</param>
8786
internal void AddPath(ISimplePath path, ClippingType clippingType)
8887
{
89-
ReadOnlySpan<PointF> vectors = path.Points.Span;
90-
SixLabors.PolygonClipper.Polygon polygon = [];
91-
Contour contour = new();
92-
polygon.Add(contour);
93-
94-
foreach (PointF point in vectors)
95-
{
96-
contour.AddVertex(new Vertex(point.X, point.Y));
97-
}
88+
SixLabors.PolygonClipper.Polygon polygon = path.ToPolygon();
9889

9990
switch (clippingType)
10091
{

src/ImageSharp.Drawing/Shapes/PolygonClipper/PolygonOffsetter.cs

Lines changed: 38 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
using System.Numerics;
55
using System.Runtime.CompilerServices;
6+
using SixLabors.PolygonClipper;
67

78
namespace SixLabors.ImageSharp.Drawing.Shapes.PolygonClipper;
89

@@ -101,13 +102,25 @@ public void Execute(float delta, PathsF solution)
101102
//
102103
// // PolygonClipper will throw for unhandled exceptions but if a result is empty
103104
// // we should just return the original path.
104-
// if (solution.Count == 0)
105-
// {
106-
// foreach (PathF path in this.solution)
107-
// {
108-
// solution.Add(path);
109-
// }
110-
// }
105+
SixLabors.PolygonClipper.Polygon result = SixLabors.PolygonClipper.PolygonClipper.Union(this.solution.ToPolygon(), solution.ToPolygon());
106+
107+
if (result.Count == 0)
108+
{
109+
foreach (PathF path in this.solution)
110+
{
111+
solution.Add(path);
112+
}
113+
}
114+
115+
foreach (Contour contour in result)
116+
{
117+
PathF path = new(contour.Count);
118+
solution.Add(path);
119+
foreach (Vertex vertex in contour)
120+
{
121+
path.Add(new Vector2((float)vertex.X, (float)vertex.Y));
122+
}
123+
}
111124
}
112125

113126
private void ExecuteInternal(float delta)
@@ -680,6 +693,24 @@ public PathsF(int capacity)
680693
: base(capacity)
681694
{
682695
}
696+
697+
internal SixLabors.PolygonClipper.Polygon ToPolygon()
698+
{
699+
SixLabors.PolygonClipper.Polygon polygon = [];
700+
701+
foreach (PathF pathF in this)
702+
{
703+
Contour contour = new();
704+
polygon.Add(contour);
705+
706+
foreach (Vector2 point in pathF)
707+
{
708+
contour.AddVertex(new Vertex(point.X, point.Y));
709+
}
710+
}
711+
712+
return polygon;
713+
}
683714
}
684715

685716
internal class PathF : List<Vector2>

tests/ImageSharp.Drawing.Tests/Shapes/PolygonClipper/ClipperTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ private IEnumerable<IPath> Clip(IPath shape, params IPath[] hole)
3939
}
4040
}
4141

42-
return clipper.GenerateClippedShapes(BooleanOperation.Difference);
42+
return clipper.GenerateClippedShapes(BooleanOperation.Difference, IntersectionRule.EvenOdd);
4343
}
4444

4545
[Fact]

0 commit comments

Comments
 (0)