@@ -28,47 +28,32 @@ private TessellatedMultipolygon(Ring[] rings)
2828 this . TotalVertexCount = rings . Sum ( r => r . VertexCount ) ;
2929 }
3030
31- private enum RingType
32- {
33- Contour ,
34- Hole
35- }
36-
3731 public int TotalVertexCount { get ; }
3832
3933 public int Count => this . rings . Length ;
4034
4135 public Ring this [ int index ] => this . rings [ index ] ;
4236
43- public static TessellatedMultipolygon Create (
44- IPath path ,
45- MemoryAllocator memoryAllocator ,
46- OrientationHandling orientationHandling = OrientationHandling . ForcePositiveOrientationOnSimplePolygons )
37+ public static TessellatedMultipolygon Create ( IPath path , MemoryAllocator memoryAllocator )
4738 {
48- RingType ? firstRingType = orientationHandling == OrientationHandling . FirstRingIsContourFollowedByHoles ? RingType . Contour : ( RingType ? ) null ;
49- RingType ? followUpRingType = orientationHandling == OrientationHandling . FirstRingIsContourFollowedByHoles ? RingType . Hole : ( RingType ? ) null ;
50-
51- // For now let's go with the assumption that first loop is always an external contour,
52- // and the rests are loops.
5339 if ( path is IInternalPathOwner ipo )
5440 {
5541 IReadOnlyList < InternalPath > internalPaths = ipo . GetRingsAsInternalPath ( ) ;
5642
57- // If we have only one ring, we may want to orient it as a contour
58- if ( internalPaths . Count == 1 && orientationHandling != OrientationHandling . KeepOriginal )
59- {
60- firstRingType = RingType . Contour ;
61- }
43+ // If we have only one ring, we can change it's orientation without negative side-effects.
44+ // Since the algorithm works best with positively-oriented polygons,
45+ // we enforce the orientation for best output quality.
46+ bool enforcePositiveOrientationOnFirstRing = internalPaths . Count == 1 ;
6247
63- Ring [ ] rings = new Ring [ internalPaths . Count ] ;
48+ var rings = new Ring [ internalPaths . Count ] ;
6449 IMemoryOwner < PointF > pointBuffer = internalPaths [ 0 ] . ExtractVertices ( memoryAllocator ) ;
65- RepeateFirstVertexAndEnsureOrientation ( pointBuffer . Memory . Span , firstRingType ) ;
50+ RepeateFirstVertexAndEnsureOrientation ( pointBuffer . Memory . Span , enforcePositiveOrientationOnFirstRing ) ;
6651 rings [ 0 ] = new Ring ( pointBuffer ) ;
6752
6853 for ( int i = 1 ; i < internalPaths . Count ; i ++ )
6954 {
7055 pointBuffer = internalPaths [ i ] . ExtractVertices ( memoryAllocator ) ;
71- RepeateFirstVertexAndEnsureOrientation ( pointBuffer . Memory . Span , followUpRingType ) ;
56+ RepeateFirstVertexAndEnsureOrientation ( pointBuffer . Memory . Span , false ) ;
7257 rings [ i ] = new Ring ( pointBuffer ) ;
7358 }
7459
@@ -78,40 +63,38 @@ public static TessellatedMultipolygon Create(
7863 {
7964 ReadOnlyMemory < PointF > [ ] points = path . Flatten ( ) . Select ( sp => sp . Points ) . ToArray ( ) ;
8065
81- // If we have only one ring, we may want to orient it as a contour
82- if ( points . Length == 1 && orientationHandling != OrientationHandling . KeepOriginal )
83- {
84- firstRingType = RingType . Contour ;
85- }
66+ // If we have only one ring, we can change it's orientation without negative side-effects.
67+ // Since the algorithm works best with positively-oriented polygons,
68+ // we enforce the orientation for best output quality.
69+ bool enforcePositiveOrientationOnFirstRing = points . Length == 1 ;
8670
87- Ring [ ] rings = new Ring [ points . Length ] ;
88- rings [ 0 ] = MakeRing ( points [ 0 ] , firstRingType , memoryAllocator ) ;
71+ var rings = new Ring [ points . Length ] ;
72+ rings [ 0 ] = MakeRing ( points [ 0 ] , enforcePositiveOrientationOnFirstRing , memoryAllocator ) ;
8973 for ( int i = 1 ; i < points . Length ; i ++ )
9074 {
91- rings [ i ] = MakeRing ( points [ i ] , followUpRingType , memoryAllocator ) ;
75+ rings [ i ] = MakeRing ( points [ i ] , false , memoryAllocator ) ;
9276 }
9377
9478 return new TessellatedMultipolygon ( rings ) ;
9579 }
9680
97- static Ring MakeRing ( ReadOnlyMemory < PointF > points , RingType ? ringType , MemoryAllocator allocator )
81+ static Ring MakeRing ( ReadOnlyMemory < PointF > points , bool enforcePositiveOrientation , MemoryAllocator allocator )
9882 {
9983 IMemoryOwner < PointF > buffer = allocator . Allocate < PointF > ( points . Length + 1 ) ;
10084 Span < PointF > span = buffer . Memory . Span ;
10185 points . Span . CopyTo ( span ) ;
102- RepeateFirstVertexAndEnsureOrientation ( span , ringType ) ;
86+ RepeateFirstVertexAndEnsureOrientation ( span , enforcePositiveOrientation ) ;
10387 return new Ring ( buffer ) ;
10488 }
10589
106- static void RepeateFirstVertexAndEnsureOrientation ( Span < PointF > span , RingType ? ringType )
90+ static void RepeateFirstVertexAndEnsureOrientation ( Span < PointF > span , bool enforcePositiveOrientation )
10791 {
10892 // Repeat first vertex for perf:
10993 span [ span . Length - 1 ] = span [ 0 ] ;
11094
111- if ( ringType . HasValue )
95+ if ( enforcePositiveOrientation )
11296 {
113- int orientation = ringType . Value == RingType . Contour ? 1 : - 1 ;
114- TopologyUtilities . EnsureOrientation ( span , orientation ) ;
97+ TopologyUtilities . EnsureOrientation ( span , 1 ) ;
11598 }
11699 }
117100 }
@@ -158,4 +141,4 @@ public void Dispose()
158141 }
159142 }
160143 }
161- }
144+ }
0 commit comments