Skip to content

Commit 53c1484

Browse files
committed
rfac: Change drawSolidPolygon to take a new struct Polygon instead of [Point].
- This allows us to be sure that, in each renderer, there will always be at least 3 points, avoiding having to check for that in every renderer. - This moves the problem of ensuring that there are always 3 points up the stack, making sure that the programmer ensures this as soon as possible by taking advantage of the type system, while letting the rest of the code not worry about this.
1 parent 50d0a0a commit 53c1484

File tree

5 files changed

+99
-26
lines changed

5 files changed

+99
-26
lines changed

Sources/AGGRenderer/AGGRenderer/AGGRenderer.swift

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -143,17 +143,17 @@ public class AGGRenderer: Renderer{
143143
agg_object);
144144
}
145145

146-
public func drawSolidPolygon(points: [Point],
146+
public func drawSolidPolygon(polygon: SwiftPlot.Polygon,
147147
fillColor: Color) {
148148
var x = [Float]()
149149
var y = [Float]()
150-
for index in 0..<points.count {
151-
x.append(points[index].x + xOffset)
152-
y.append(points[index].y + yOffset)
150+
for point in polygon {
151+
x.append(point.x + xOffset)
152+
y.append(point.y + yOffset)
153153
}
154154
draw_solid_polygon(x,
155155
y,
156-
Int32(points.count),
156+
Int32(x.count),
157157
fillColor.r,
158158
fillColor.g,
159159
fillColor.b,

Sources/QuartzRenderer/QuartzRenderer.swift

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -369,12 +369,14 @@ public class QuartzRenderer: Renderer {
369369
context.fillPath()
370370
}
371371

372-
public func drawSolidPolygon(points: [Point],
372+
public func drawSolidPolygon(polygon: SwiftPlot.Polygon,
373373
fillColor: Color) {
374374
let polygonPath = CGMutablePath()
375-
polygonPath.move(to: CGPoint(x: Double(points[0].x + xOffset), y: Double(points[0].y + yOffset)))
376-
for index in 1..<points.count {
377-
polygonPath.addLine(to: CGPoint(x: Double(points[index].x + xOffset), y: Double(points[index].y + yOffset)))
375+
var points = polygon.makeIterator()
376+
let p1 = points.next()!
377+
polygonPath.move(to: CGPoint(x: Double(p1.x + xOffset), y: Double(p1.y + yOffset)))
378+
for point in points {
379+
polygonPath.addLine(to: CGPoint(x: Double(point.x + xOffset), y: Double(point.y + yOffset)))
378380
}
379381
polygonPath.closeSubpath()
380382
context.setFillColor(fillColor.cgColor)

Sources/SVGRenderer/SVGRenderer.swift

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -157,15 +157,16 @@ public class SVGRenderer: Renderer{
157157
lines.append(triangle)
158158
}
159159

160-
public func drawSolidPolygon(points: [Point],
160+
public func drawSolidPolygon(polygon: SwiftPlot.Polygon,
161161
fillColor: Color) {
162-
let pts = points.map { convertToSVGCoordinates($0) }
163162
var pointsString = ""
164-
for index in 0..<pts.count {
165-
pointsString = pointsString + "\(pts[index].x),\(pts[index].y) "
163+
for point in polygon {
164+
let convertedPoint = convertToSVGCoordinates(point)
165+
pointsString.append("\(convertedPoint.x),\(convertedPoint.y) ")
166166
}
167-
let polygon = #"<polygon points="\#(pointsString)" style="fill:\#(fillColor.svgColorString);opacity:\#(fillColor.a)" />"#
168-
lines.append(polygon)
167+
168+
let polygonString = #"<polygon points="\#(pointsString)" style="fill:\#(fillColor.svgColorString);opacity:\#(fillColor.a)" />"#
169+
lines.append(polygonString)
169170
}
170171

171172
public func drawLine(startPoint p1: Point,

Sources/SwiftPlot/Renderer.swift

Lines changed: 65 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ public protocol Renderer: AnyObject{
153153
* without shifted origin.
154154
* This is decided by the boolean parameter isOriginShifted.
155155
*/
156-
func drawSolidPolygon(points: [Point],
156+
func drawSolidPolygon(polygon: Polygon,
157157
fillColor: Color)
158158

159159
/*getTextWidth()
@@ -193,3 +193,67 @@ extension Renderer {
193193
(self.xOffset, self.yOffset) = oldOffset
194194
}
195195
}
196+
197+
/// Polygon structure definition and sequence extension, along with its iterator.
198+
public struct Polygon {
199+
public var p1: Point, p2: Point, p3: Point
200+
public var tail: [Point]
201+
202+
public init() {
203+
self.init(.zero, .zero, .zero)
204+
}
205+
206+
public init(_ p1: Point, _ p2: Point, _ p3: Point, tail: [Point] = []) {
207+
(self.p1, self.p2, self.p3) = (p1, p2, p3)
208+
self.tail = tail
209+
}
210+
211+
public init(_ p1: Point, _ p2: Point, _ p3: Point, tail: ArraySlice<Point>) {
212+
self.init(p1, p2, p3, tail: Array(tail))
213+
}
214+
}
215+
216+
extension Polygon: Sequence {
217+
public struct Iterator {
218+
private var state: State
219+
private var tailIterator: Array<Point>.Iterator
220+
private let polygon: Polygon
221+
222+
private enum State {
223+
case p1, p2, p3
224+
case tail
225+
}
226+
227+
public init(polygon: Polygon) {
228+
state = .p1
229+
tailIterator = polygon.tail.makeIterator()
230+
self.polygon = polygon
231+
}
232+
}
233+
234+
public func makeIterator() -> Polygon.Iterator {
235+
return Iterator(polygon: self)
236+
}
237+
}
238+
239+
extension Polygon.Iterator: IteratorProtocol {
240+
public typealias Element = Point
241+
242+
public mutating func next() -> Point? {
243+
switch state {
244+
case .p1:
245+
state = .p2
246+
return polygon.p1
247+
case .p2:
248+
state = .p3
249+
return polygon.p2
250+
case .p3:
251+
state = .tail
252+
return polygon.p3
253+
case .tail:
254+
return tailIterator.next()
255+
}
256+
}
257+
}
258+
259+
extension Polygon.Iterator: Sequence {}

Sources/SwiftPlot/ScatterChart.swift

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -366,8 +366,8 @@ extension ScatterPlot: HasGraphLayout {
366366
tR = rotatePoint(point: tR, center: p, angleDegrees: 45.0)
367367
bL = rotatePoint(point: bL, center: p, angleDegrees: 45.0)
368368
bR = rotatePoint(point: bR, center: p, angleDegrees: 45.0)
369-
let diamondPoints: [Point] = [tL, tR, bR, bL]
370-
renderer.drawSolidPolygon(points: diamondPoints,
369+
let diamond = Polygon(tL, tR, bR, tail: [bL])
370+
renderer.drawSolidPolygon(polygon: diamond,
371371
fillColor: s.color)
372372
}
373373
case .hexagon:
@@ -387,7 +387,8 @@ extension ScatterPlot: HasGraphLayout {
387387
angleDegrees: 60.0)
388388
hexagonPoints.append(hexagonPoint)
389389
}
390-
renderer.drawSolidPolygon(points: hexagonPoints,
390+
let hexagon = Polygon(hexagonPoints[0], hexagonPoints[1], hexagonPoints[2], tail: hexagonPoints[3...])
391+
renderer.drawSolidPolygon(polygon: hexagon,
391392
fillColor: s.color)
392393
}
393394
case .pentagon:
@@ -407,7 +408,8 @@ extension ScatterPlot: HasGraphLayout {
407408
angleDegrees: 72.0)
408409
pentagonPoints.append(pentagonPoint)
409410
}
410-
renderer.drawSolidPolygon(points: pentagonPoints,
411+
let pentagon = Polygon(pentagonPoints[0], pentagonPoints[1], pentagonPoints[2], tail: pentagonPoints[3...])
412+
renderer.drawSolidPolygon(polygon: pentagon,
411413
fillColor: s.color)
412414
}
413415
case .star:
@@ -435,7 +437,8 @@ extension ScatterPlot: HasGraphLayout {
435437
starPoints.append(starOuterPoint)
436438
starPoints.append(starInnerPoint)
437439
}
438-
renderer.drawSolidPolygon(points: starPoints,
440+
let star = Polygon(starPoints[0], starPoints[1], starPoints[2], tail: starPoints[3...])
441+
renderer.drawSolidPolygon(polygon: star,
439442
fillColor: s.color)
440443
}
441444
}
@@ -485,8 +488,8 @@ extension ScatterPlotSeriesOptions.ScatterPattern {
485488
let p2 = rotatePoint(point: tR, center: c, angleDegrees: 45.0)
486489
let p3 = rotatePoint(point: bR, center: c, angleDegrees: 45.0)
487490
let p4 = rotatePoint(point: bL, center: c, angleDegrees: 45.0)
488-
let diamondPoints: [Point] = [p1, p2, p3, p4]
489-
renderer.drawSolidPolygon(points: diamondPoints,
491+
let diamond = Polygon(p1, p2, p3, tail: [p4])
492+
renderer.drawSolidPolygon(polygon: diamond,
490493
fillColor: color)
491494
case .hexagon:
492495
let c = Point((tL.x+bR.x)*Float(0.5),
@@ -500,7 +503,8 @@ extension ScatterPlotSeriesOptions.ScatterPattern {
500503
angleDegrees: 60.0)
501504
hexagonPoints.append(hexagonPoint)
502505
}
503-
renderer.drawSolidPolygon(points: hexagonPoints,
506+
let hexagon = Polygon(hexagonPoints[0], hexagonPoints[1], hexagonPoints[2], tail: hexagonPoints[3...])
507+
renderer.drawSolidPolygon(polygon: hexagon,
504508
fillColor: color)
505509
case .pentagon:
506510
let c = Point((tL.x+bR.x)*Float(0.5),
@@ -514,7 +518,8 @@ extension ScatterPlotSeriesOptions.ScatterPattern {
514518
angleDegrees: 72.0)
515519
pentagonPoints.append(pentagonPoint)
516520
}
517-
renderer.drawSolidPolygon(points: pentagonPoints,
521+
let pentagon = Polygon(pentagonPoints[0], pentagonPoints[1], pentagonPoints[2], tail: pentagonPoints[3...])
522+
renderer.drawSolidPolygon(polygon: pentagon,
518523
fillColor: color)
519524
case .star:
520525
let c = Point((tL.x+bR.x)*Float(0.5),
@@ -536,7 +541,8 @@ extension ScatterPlotSeriesOptions.ScatterPattern {
536541
starPoints.append(starOuterPoint)
537542
starPoints.append(starInnerPoint)
538543
}
539-
renderer.drawSolidPolygon(points: starPoints,
544+
let star = Polygon(starPoints[0], starPoints[1], starPoints[2], tail: starPoints[3...])
545+
renderer.drawSolidPolygon(polygon: star,
540546
fillColor: color)
541547
}
542548
}

0 commit comments

Comments
 (0)