From c221b81b0de5244546bf483c3e3230040d7a207e Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Fri, 20 Nov 2020 12:34:26 +0100 Subject: [PATCH] remove OrientationHandling --- .../Shapes/OrientationHandling.cs | 15 ----- .../Rasterization/ScanEdgeCollection.cs | 2 +- .../Shapes/TessellatedMultipolygon.cs | 59 +++++++------------ 3 files changed, 22 insertions(+), 54 deletions(-) delete mode 100644 src/ImageSharp.Drawing/Shapes/OrientationHandling.cs diff --git a/src/ImageSharp.Drawing/Shapes/OrientationHandling.cs b/src/ImageSharp.Drawing/Shapes/OrientationHandling.cs deleted file mode 100644 index f709f48f..00000000 --- a/src/ImageSharp.Drawing/Shapes/OrientationHandling.cs +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright (c) Six Labors. -// Licensed under the Apache License, Version 2.0. - -namespace SixLabors.ImageSharp.Drawing.Shapes -{ - /// - /// Defines polygon orientation handling mode when creating from . - /// - internal enum OrientationHandling - { - KeepOriginal, - ForcePositiveOrientationOnSimplePolygons, - FirstRingIsContourFollowedByHoles - } -} \ No newline at end of file diff --git a/src/ImageSharp.Drawing/Shapes/Rasterization/ScanEdgeCollection.cs b/src/ImageSharp.Drawing/Shapes/Rasterization/ScanEdgeCollection.cs index df7cfcdc..c0053512 100644 --- a/src/ImageSharp.Drawing/Shapes/Rasterization/ScanEdgeCollection.cs +++ b/src/ImageSharp.Drawing/Shapes/Rasterization/ScanEdgeCollection.cs @@ -42,7 +42,7 @@ public static ScanEdgeCollection Create( MemoryAllocator allocator, int subsampling) { - TessellatedMultipolygon multipolygon = TessellatedMultipolygon.Create(polygon, allocator, OrientationHandling.ForcePositiveOrientationOnSimplePolygons); + TessellatedMultipolygon multipolygon = TessellatedMultipolygon.Create(polygon, allocator); return Create(multipolygon, allocator, subsampling); } } diff --git a/src/ImageSharp.Drawing/Shapes/TessellatedMultipolygon.cs b/src/ImageSharp.Drawing/Shapes/TessellatedMultipolygon.cs index f5ef4a00..a0057723 100644 --- a/src/ImageSharp.Drawing/Shapes/TessellatedMultipolygon.cs +++ b/src/ImageSharp.Drawing/Shapes/TessellatedMultipolygon.cs @@ -28,47 +28,32 @@ private TessellatedMultipolygon(Ring[] rings) this.TotalVertexCount = rings.Sum(r => r.VertexCount); } - private enum RingType - { - Contour, - Hole - } - public int TotalVertexCount { get; } public int Count => this.rings.Length; public Ring this[int index] => this.rings[index]; - public static TessellatedMultipolygon Create( - IPath path, - MemoryAllocator memoryAllocator, - OrientationHandling orientationHandling = OrientationHandling.ForcePositiveOrientationOnSimplePolygons) + public static TessellatedMultipolygon Create(IPath path, MemoryAllocator memoryAllocator) { - RingType? firstRingType = orientationHandling == OrientationHandling.FirstRingIsContourFollowedByHoles ? RingType.Contour : (RingType?)null; - RingType? followUpRingType = orientationHandling == OrientationHandling.FirstRingIsContourFollowedByHoles ? RingType.Hole : (RingType?)null; - - // For now let's go with the assumption that first loop is always an external contour, - // and the rests are loops. if (path is IInternalPathOwner ipo) { IReadOnlyList internalPaths = ipo.GetRingsAsInternalPath(); - // If we have only one ring, we may want to orient it as a contour - if (internalPaths.Count == 1 && orientationHandling != OrientationHandling.KeepOriginal) - { - firstRingType = RingType.Contour; - } + // If we have only one ring, we can change it's orientation without negative side-effects. + // Since the algorithm works best with positively-oriented polygons, + // we enforce the orientation for best output quality. + bool enforcePositiveOrientationOnFirstRing = internalPaths.Count == 1; - Ring[] rings = new Ring[internalPaths.Count]; + var rings = new Ring[internalPaths.Count]; IMemoryOwner pointBuffer = internalPaths[0].ExtractVertices(memoryAllocator); - RepeateFirstVertexAndEnsureOrientation(pointBuffer.Memory.Span, firstRingType); + RepeateFirstVertexAndEnsureOrientation(pointBuffer.Memory.Span, enforcePositiveOrientationOnFirstRing); rings[0] = new Ring(pointBuffer); for (int i = 1; i < internalPaths.Count; i++) { pointBuffer = internalPaths[i].ExtractVertices(memoryAllocator); - RepeateFirstVertexAndEnsureOrientation(pointBuffer.Memory.Span, followUpRingType); + RepeateFirstVertexAndEnsureOrientation(pointBuffer.Memory.Span, false); rings[i] = new Ring(pointBuffer); } @@ -78,40 +63,38 @@ public static TessellatedMultipolygon Create( { ReadOnlyMemory[] points = path.Flatten().Select(sp => sp.Points).ToArray(); - // If we have only one ring, we may want to orient it as a contour - if (points.Length == 1 && orientationHandling != OrientationHandling.KeepOriginal) - { - firstRingType = RingType.Contour; - } + // If we have only one ring, we can change it's orientation without negative side-effects. + // Since the algorithm works best with positively-oriented polygons, + // we enforce the orientation for best output quality. + bool enforcePositiveOrientationOnFirstRing = points.Length == 1; - Ring[] rings = new Ring[points.Length]; - rings[0] = MakeRing(points[0], firstRingType, memoryAllocator); + var rings = new Ring[points.Length]; + rings[0] = MakeRing(points[0], enforcePositiveOrientationOnFirstRing, memoryAllocator); for (int i = 1; i < points.Length; i++) { - rings[i] = MakeRing(points[i], followUpRingType, memoryAllocator); + rings[i] = MakeRing(points[i], false, memoryAllocator); } return new TessellatedMultipolygon(rings); } - static Ring MakeRing(ReadOnlyMemory points, RingType? ringType, MemoryAllocator allocator) + static Ring MakeRing(ReadOnlyMemory points, bool enforcePositiveOrientation, MemoryAllocator allocator) { IMemoryOwner buffer = allocator.Allocate(points.Length + 1); Span span = buffer.Memory.Span; points.Span.CopyTo(span); - RepeateFirstVertexAndEnsureOrientation(span, ringType); + RepeateFirstVertexAndEnsureOrientation(span, enforcePositiveOrientation); return new Ring(buffer); } - static void RepeateFirstVertexAndEnsureOrientation(Span span, RingType? ringType) + static void RepeateFirstVertexAndEnsureOrientation(Span span, bool enforcePositiveOrientation) { // Repeat first vertex for perf: span[span.Length - 1] = span[0]; - if (ringType.HasValue) + if (enforcePositiveOrientation) { - int orientation = ringType.Value == RingType.Contour ? 1 : -1; - TopologyUtilities.EnsureOrientation(span, orientation); + TopologyUtilities.EnsureOrientation(span, 1); } } } @@ -158,4 +141,4 @@ public void Dispose() } } } -} \ No newline at end of file +}