@@ -46,6 +46,7 @@ public void OptimizeGeometry()
46
46
}
47
47
}
48
48
49
+ // This assumes all underlying geometry has been pre-optimized with OptimizeGeometry() first. Meaning there are no Box, Path, or Boundary objects remaining.
49
50
public void FlattenAndOptimize ( Transform ? trans = null , List < Element > ? targetList = null )
50
51
{
51
52
if ( Elements == null || this . IsFlattened ) { return ; }
@@ -155,7 +156,7 @@ public class Boundary : LayerElement
155
156
}
156
157
157
158
public class Path : LayerElement
158
- {
159
+ { // TODO: Path type 0 (butt) paths of 0 length are not correctly handled if optimizing
159
160
public short ? Datatype = null ;
160
161
public short PathType = 0 ;
161
162
public int Width = 0 ; // negative means not affected by magnification
@@ -165,18 +166,59 @@ public class Path : LayerElement
165
166
public override List < PointD > ? GetPolygonCoords ( )
166
167
{
167
168
if ( this . Coords == null ) { return null ; }
168
- List < List < PointD > > Input = new ( ) { new ( this . Coords ) } ;
169
169
EndType Ends = EndType . Butt ;
170
170
if ( this . PathType == 1 ) { Ends = EndType . Round ; }
171
171
if ( this . PathType == 2 ) { Ends = EndType . Square ; }
172
- if ( this . PathType == 4 )
173
- {
174
- // TODO: A whole bunch of stuff here
175
- }
172
+ if ( this . PathType == 4 ) { ConvertType4 ( ) ; } // Start and end extensions separately defined, apply them manually, then treat as butt
173
+ List < List < PointD > > Input = new ( ) { new ( this . Coords ) } ;
176
174
List < List < PointD > > Output = Clipper . InflatePaths ( Input , - Math . Abs ( this . Width ) , JoinType . Square , Ends ) ;
177
175
if ( Output . Count != 1 ) { throw new InvalidDataException ( "Trying to convert paths to polygons resulted in multiple polygons." ) ; }
178
176
return Output [ 0 ] ;
179
177
}
178
+
179
+ public void ConvertType4 ( )
180
+ {
181
+ if ( this . Coords != null && this . Coords . Length >= 2 )
182
+ {
183
+ if ( this . ExtensionStart != 0 )
184
+ {
185
+ double StartDeltaX = this . Coords [ 1 ] . x - this . Coords [ 0 ] . x ;
186
+ double StartDeltaY = this . Coords [ 1 ] . y - this . Coords [ 0 ] . y ;
187
+ if ( StartDeltaY == 0 ) { this . Coords [ 0 ] . x -= ( StartDeltaX >= 0 ) ? this . ExtensionStart : - this . ExtensionStart ; } // Horizontal
188
+ else if ( StartDeltaX == 0 ) { this . Coords [ 0 ] . y -= ( StartDeltaY >= 0 ) ? this . ExtensionStart : - this . ExtensionStart ; } // Vertical
189
+ else // Angled
190
+ {
191
+ double Slope = StartDeltaY / StartDeltaX ;
192
+ double XIncr = Math . Abs ( this . ExtensionStart ) / Math . Sqrt ( ( Slope * Slope ) + 1 ) ; // Always pos
193
+ double YIncr = Math . Abs ( Slope ) * XIncr ; // Always pos
194
+ bool XOffsetIsPos = ( StartDeltaX > 0 ) ^ ( this . ExtensionStart > 0 ) ;
195
+ bool YOffsetIsPos = ( StartDeltaY > 0 ) ^ ( this . ExtensionStart > 0 ) ;
196
+ this . Coords [ 0 ] . x += XOffsetIsPos ? XIncr : - XIncr ;
197
+ this . Coords [ 0 ] . y += YOffsetIsPos ? YIncr : - YIncr ;
198
+ }
199
+ }
200
+ if ( this . ExtensionEnd != 0 )
201
+ {
202
+ double EndDeltaX = this . Coords [ ^ 1 ] . x - this . Coords [ ^ 2 ] . x ;
203
+ double EndDeltaY = this . Coords [ ^ 1 ] . y - this . Coords [ ^ 2 ] . y ;
204
+ if ( EndDeltaY == 0 ) { this . Coords [ ^ 1 ] . x += ( EndDeltaX >= 0 ) ? this . ExtensionEnd : - this . ExtensionEnd ; } // Horizontal
205
+ else if ( EndDeltaX == 0 ) { this . Coords [ ^ 1 ] . y += ( EndDeltaY >= 0 ) ? this . ExtensionEnd : - this . ExtensionEnd ; } // Vertical
206
+ else // Angled
207
+ {
208
+ double Slope = EndDeltaY / EndDeltaX ;
209
+ double XIncr = Math . Abs ( this . ExtensionEnd ) / Math . Sqrt ( ( Slope * Slope ) + 1 ) ; // Always pos
210
+ double YIncr = Math . Abs ( Slope ) * XIncr ; // Always pos
211
+ bool XOffsetIsNeg = ( EndDeltaX > 0 ) ^ ( this . ExtensionEnd > 0 ) ; // Note inverted logic from start for these 4 lines
212
+ bool YOffsetIsNeg = ( EndDeltaY > 0 ) ^ ( this . ExtensionEnd > 0 ) ;
213
+ this . Coords [ ^ 1 ] . x += XOffsetIsNeg ? - XIncr : XIncr ;
214
+ this . Coords [ ^ 1 ] . y += YOffsetIsNeg ? - YIncr : YIncr ;
215
+ }
216
+ }
217
+ }
218
+ else { throw new InvalidDataException ( "Trying to convert type 4 path to polygon with no or too few points." ) ; }
219
+ this . PathType = 0 ;
220
+ }
221
+
180
222
public override Path Clone ( ) => new ( )
181
223
{
182
224
Coords = ( PointD [ ] ? ) this . Coords ? . Clone ( ) ,
0 commit comments