Skip to content

Commit 6f07800

Browse files
committed
Change Polyline and Polygon to internally use just an array with a precondition on the didSet one single failable initializer.
1 parent 060258a commit 6f07800

18 files changed

+43
-153
lines changed

Sources/AGGRenderer/AGGRenderer/AGGRenderer.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ public class AGGRenderer: Renderer{
144144
fillColor: Color) {
145145
var x = [Float]()
146146
var y = [Float]()
147-
for point in polygon {
147+
for point in polygon.points {
148148
x.append(point.x + xOffset)
149149
y.append(point.y + yOffset)
150150
}
@@ -189,7 +189,7 @@ public class AGGRenderer: Renderer{
189189
var x = [Float]()
190190
var y = [Float]()
191191

192-
for point in polyline {
192+
for point in polyline.points {
193193
x.append(point.x + xOffset)
194194
y.append(point.y + yOffset)
195195
}

Sources/QuartzRenderer/QuartzRenderer.swift

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -372,10 +372,8 @@ public class QuartzRenderer: Renderer {
372372
public func drawSolidPolygon(polygon: SwiftPlot.Polygon,
373373
fillColor: Color) {
374374
let polygonPath = CGMutablePath()
375-
polygonPath.move(to: CGPoint(x: Double(polygon.p1.x + xOffset), y: Double(polygon.p1.y + yOffset)))
376-
polygonPath.addLine(to: CGPoint(x: Double(polygon.p2.x + xOffset), y: Double(polygon.p2.y + yOffset)))
377-
polygonPath.addLine(to: CGPoint(x: Double(polygon.p3.x + xOffset), y: Double(polygon.p3.y + yOffset)))
378-
polygon.tail.forEach { polygonPath.addLine(to: CGPoint(x: Double($0.x + xOffset), y: Double($0.y + yOffset)))}
375+
polygonPath.addLines(between: polygon.points.map { CGPoint(x: CGFloat($0.x), y: CGFloat($0.y)) },
376+
transform: CGAffineTransform(translationX: CGFloat(xOffset), y: CGFloat(yOffset)))
379377
polygonPath.closeSubpath()
380378
context.setFillColor(fillColor.cgColor)
381379
context.addPath(polygonPath)
@@ -407,11 +405,8 @@ public class QuartzRenderer: Renderer {
407405
isDashed: Bool) {
408406

409407
let linePath = CGMutablePath()
410-
linePath.move(to: CGPoint(x: Double(polyline.p1.x + xOffset), y: Double(polyline.p1.y + yOffset)))
411-
linePath.addLine(to: CGPoint(x: Double(polyline.p2.x + xOffset), y: Double(polyline.p2.y + yOffset)))
412-
for point in polyline.tail {
413-
linePath.addLine(to: CGPoint(x: Double(point.x + xOffset), y: Double(point.y + yOffset)))
414-
}
408+
linePath.addLines(between: polyline.points.map { CGPoint(x: CGFloat($0.x), y: CGFloat($0.y)) },
409+
transform: CGAffineTransform(translationX: CGFloat(xOffset), y: CGFloat(yOffset)))
415410
context.setStrokeColor(strokeColor.cgColor)
416411
context.setLineWidth(CGFloat(thickness))
417412
context.addPath(linePath)

Sources/SVGRenderer/SVGRenderer.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ public class SVGRenderer: Renderer{
159159
public func drawSolidPolygon(polygon: SwiftPlot.Polygon,
160160
fillColor: Color) {
161161
var pointsString = ""
162-
for point in polygon {
162+
for point in polygon.points {
163163
let convertedPoint = convertToSVGCoordinates(point)
164164
pointsString.append("\(convertedPoint.x),\(convertedPoint.y) ")
165165
}
@@ -189,7 +189,7 @@ public class SVGRenderer: Renderer{
189189
strokeWidth thickness: Float,
190190
strokeColor: Color,
191191
isDashed: Bool) {
192-
let pointsString = polyline.lazy.map { point in
192+
let pointsString = polyline.points.lazy.map { point in
193193
let convertedPoint = self.convertToSVGCoordinates(point)
194194
return "\(convertedPoint.x),\(convertedPoint.y)"
195195
}.joined(separator: " ")

Sources/SwiftPlot/Histogram.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -275,7 +275,7 @@ extension Histogram: HasGraphLayout {
275275
for ((backRightBinHeight, frontRightBinHeight), x) in zip(zip(backHeightsSlice, frontHeightsSlice), xValues) {
276276
func endLine() {
277277
// This algorithm should never produce lines with less than 2 points
278-
guard let polyline = Polyline(points: line) else { fatalError("drawData: Expecting 2 or more points, got \(line.count) instead.") }
278+
guard let polyline = Polyline(line) else { fatalError("Histogram.drawData: Expecting 2 or more points, got \(line.count) instead.") }
279279
renderer.drawPolyline(polyline, strokeWidth: strokeWidth,
280280
strokeColor: allSeriesInfo[seriesIdx].color,
281281
isDashed: false)

Sources/SwiftPlot/LineChart.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -154,8 +154,8 @@ extension LineGraph: HasGraphLayout {
154154
if let axisInfo = data.primaryAxisInfo {
155155
for dataset in primaryAxis.series {
156156
let points = dataset.values.map { axisInfo.convertCoordinate(fromData: $0) }
157-
guard let polyline = Polyline(points: points) else {
158-
fatalError("drawData: Expecting 2 or more points, got \(points.count) instead")
157+
guard let polyline = Polyline(points) else {
158+
fatalError("LineChart.drawData: Expecting 2 or more points, got \(points.count) instead")
159159
}
160160
renderer.drawPolyline(polyline,
161161
strokeWidth: plotLineThickness,
@@ -166,8 +166,8 @@ extension LineGraph: HasGraphLayout {
166166
if let secondaryAxis = secondaryAxis, let axisInfo = data.secondaryAxisInfo {
167167
for dataset in secondaryAxis.series {
168168
let points = dataset.values.map { axisInfo.convertCoordinate(fromData: $0) }
169-
guard let polyline = Polyline(points: points) else {
170-
fatalError("drawData: Expecting 2 or more points, got \(points.count) instead")
169+
guard let polyline = Polyline(points) else {
170+
fatalError("LineChart.drawData: Expecting 2 or more points, got \(points.count) instead")
171171
}
172172
renderer.drawPolyline(polyline,
173173
strokeWidth: plotLineThickness,

Sources/SwiftPlot/PlotStyleHelpers.swift

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -184,11 +184,11 @@ struct Arrow : Annotation {
184184
let wedgeRotateAngle = -atan2(end.x - start.x, end.y - start.y)
185185
p1 = rotatePoint(point: p1, center: start, angleRadians: wedgeRotateAngle + 0.5 * Float.pi)
186186
p2 = rotatePoint(point: p2, center: start, angleRadians: wedgeRotateAngle + 0.5 * Float.pi)
187-
let head = Polygon(p1, p2, end)
187+
let head = Polygon([p1, p2, end])!
188188
renderer.drawSolidPolygon(polygon: head,
189189
fillColor: color)
190190
default:
191-
renderer.drawPolyline(Polyline(start, end),
191+
renderer.drawPolyline(Polyline([start, end])!,
192192
strokeWidth: strokeWidth,
193193
strokeColor: color,
194194
isDashed: isDashed)
@@ -205,19 +205,19 @@ struct Arrow : Annotation {
205205
// Draws arrow head points.
206206
switch headStyle {
207207
case .skeletal:
208-
let head = Polyline(p1, b, tail: [p2])
208+
let head = Polyline([p1, b, p2])!
209209
renderer.drawPolyline(head,
210210
strokeWidth: strokeWidth,
211211
strokeColor: color,
212212
isDashed: isDashed)
213213
case .filled:
214-
let head = Polygon(p1, b, p2)
214+
let head = Polygon([p1, b, p2])!
215215
renderer.drawSolidPolygon(polygon: head,
216216
fillColor: color)
217217
case .dart:
218218
var p3 = end + Point(-headLength/2, 0.0)
219219
p3 = rotatePoint(point: p3, center: b, angleRadians: rotateAngle + 0.5 * Float.pi)
220-
let head = Polygon(p1, p3, p2, tail: [b])
220+
let head = Polygon([p1, p3, p2, b])!
221221
renderer.drawSolidPolygon(polygon: head,
222222
fillColor: color)
223223
default:

Sources/SwiftPlot/Renderer.swift

Lines changed: 17 additions & 122 deletions
Original file line numberDiff line numberDiff line change
@@ -195,139 +195,34 @@ extension Renderer {
195195
}
196196
}
197197

198-
/// Polygon structure definition and sequence extension, along with its iterator.
198+
/// Polygon structure definition
199199
public struct Polygon {
200-
public var p1: Point, p2: Point, p3: Point
201-
public var tail: [Point]
202-
203-
public init(_ p1: Point, _ p2: Point, _ p3: Point, tail: [Point] = []) {
204-
(self.p1, self.p2, self.p3) = (p1, p2, p3)
205-
self.tail = tail
206-
}
207-
208-
public init(_ p1: Point, _ p2: Point, _ p3: Point, tail: ArraySlice<Point>) {
209-
self.init(p1, p2, p3, tail: Array(tail))
210-
}
211-
212-
public init() {
213-
self.init(.zero, .zero, .zero)
214-
}
215-
216-
public init?(points: [Point]) {
217-
guard points.count >= 3 else { return nil }
218-
219-
self.init(points[0], points[1], points[2], tail: points[3...])
200+
public var points: [Point] {
201+
didSet {
202+
let count = points.count
203+
precondition(count >= 2, "Polygon: points array should always contain at least 3 points, it now has \(count).")
204+
}
220205
}
221-
}
222206

223-
extension Polygon: Sequence {
224-
public struct Iterator {
225-
private var state: State
226-
private var tailIterator: Array<Point>.Iterator
227-
private let polygon: Polygon
228-
229-
private enum State {
230-
case p1, p2, p3
231-
case tail
232-
}
207+
public init?(_ points: [Point]) {
208+
guard points.count >= 3 else { return nil }
233209

234-
public init(polygon: Polygon) {
235-
state = .p1
236-
tailIterator = polygon.tail.makeIterator()
237-
self.polygon = polygon
238-
}
239-
}
240-
241-
public func makeIterator() -> Polygon.Iterator {
242-
return Iterator(polygon: self)
210+
self.points = points
243211
}
244212
}
245213

246-
extension Polygon.Iterator: IteratorProtocol {
247-
public typealias Element = Point
248-
249-
public mutating func next() -> Point? {
250-
switch state {
251-
case .p1:
252-
state = .p2
253-
return polygon.p1
254-
case .p2:
255-
state = .p3
256-
return polygon.p2
257-
case .p3:
258-
state = .tail
259-
return polygon.p3
260-
case .tail:
261-
return tailIterator.next()
214+
/// Polyline structure definition
215+
public struct Polyline {
216+
public var points: [Point] {
217+
didSet {
218+
let count = points.count
219+
precondition(count >= 2, "Polyline: points array should always contain at least 2 points, it now has \(count).")
262220
}
263221
}
264-
}
265222

266-
extension Polygon.Iterator: Sequence {}
267-
268-
/// Polyline structure definition and sequence extension, along with its iterator.
269-
public struct Polyline {
270-
public var p1: Point, p2: Point
271-
public var tail: [Point]
272-
273-
public init(_ p1: Point, _ p2: Point, tail: [Point] = []) {
274-
(self.p1, self.p2) = (p1, p2)
275-
self.tail = tail
276-
}
277-
278-
public init(_ p1: Point, _ p2: Point, tail: ArraySlice<Point>) {
279-
self.init(p1, p2, tail: Array(tail))
280-
}
281-
282-
public init() {
283-
self.init(.zero, .zero)
284-
}
285-
286-
public init?(points: [Point]) {
223+
public init?(_ points: [Point]) {
287224
guard points.count >= 2 else { return nil }
288225

289-
self = Polyline(points[0], points[1], tail: points[2...])
290-
}
291-
}
292-
293-
extension Polyline: Sequence {
294-
public struct Iterator {
295-
private var state: State
296-
private var tailIterator: Array<Point>.Iterator
297-
private let polyline: Polyline
298-
299-
private enum State {
300-
case p1, p2
301-
case tail
302-
}
303-
304-
public init(polyline: Polyline) {
305-
state = .p1
306-
tailIterator = polyline.tail.makeIterator()
307-
self.polyline = polyline
308-
}
309-
}
310-
311-
public func makeIterator() -> Polyline.Iterator {
312-
return Iterator(polyline: self)
313-
}
314-
}
315-
316-
extension Polyline.Iterator: IteratorProtocol {
317-
public typealias Element = Point
318-
319-
public mutating func next() -> Point? {
320-
switch state {
321-
case .p1:
322-
state = .p2
323-
return polyline.p1
324-
case .p2:
325-
state = .tail
326-
return polyline.p2
327-
case .tail:
328-
return tailIterator.next()
329-
}
226+
self.points = points
330227
}
331228
}
332-
333-
extension Polyline.Iterator: Sequence {}

Sources/SwiftPlot/ScatterChart.swift

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -368,7 +368,7 @@ extension ScatterPlot: HasGraphLayout {
368368
tR = rotatePoint(point: tR, center: p, angleDegrees: 45.0)
369369
bL = rotatePoint(point: bL, center: p, angleDegrees: 45.0)
370370
bR = rotatePoint(point: bR, center: p, angleDegrees: 45.0)
371-
let diamond = Polygon(tL, tR, bR, tail: [bL])
371+
let diamond = Polygon([tL, tR, bR, bL])!
372372
renderer.drawSolidPolygon(polygon: diamond,
373373
fillColor: color)
374374
case .hexagon:
@@ -381,7 +381,7 @@ extension ScatterPlot: HasGraphLayout {
381381
angleDegrees: 60.0)
382382
hexagonPoints.append(hexagonPoint)
383383
}
384-
let hexagon = Polygon(hexagonPoints[0], hexagonPoints[1], hexagonPoints[2], tail: hexagonPoints[3...])
384+
let hexagon = Polygon(hexagonPoints)!
385385
renderer.drawSolidPolygon(polygon: hexagon,
386386
fillColor: color)
387387
case .pentagon:
@@ -394,7 +394,7 @@ extension ScatterPlot: HasGraphLayout {
394394
angleDegrees: 72.0)
395395
pentagonPoints.append(pentagonPoint)
396396
}
397-
let pentagon = Polygon(pentagonPoints[0], pentagonPoints[1], pentagonPoints[2], tail: pentagonPoints[3...])
397+
let pentagon = Polygon(pentagonPoints)!
398398
renderer.drawSolidPolygon(polygon: pentagon,
399399
fillColor: color)
400400

@@ -416,7 +416,7 @@ extension ScatterPlot: HasGraphLayout {
416416
starPoints.append(starOuterPoint)
417417
starPoints.append(starInnerPoint)
418418
}
419-
let star = Polygon(starPoints[0], starPoints[1], starPoints[2], tail: starPoints[3...])
419+
let star = Polygon(starPoints)!
420420
renderer.drawSolidPolygon(polygon: star,
421421
fillColor: color)
422422
}
@@ -465,7 +465,7 @@ extension ScatterPlotSeriesOptions.ScatterPattern {
465465
let p2 = rotatePoint(point: tR, center: c, angleDegrees: 45.0)
466466
let p3 = rotatePoint(point: bR, center: c, angleDegrees: 45.0)
467467
let p4 = rotatePoint(point: bL, center: c, angleDegrees: 45.0)
468-
let diamond = Polygon(p1, p2, p3, tail: [p4])
468+
let diamond = Polygon([p1, p2, p3, p4])!
469469
renderer.drawSolidPolygon(polygon: diamond,
470470
fillColor: color)
471471
case .hexagon:
@@ -480,7 +480,7 @@ extension ScatterPlotSeriesOptions.ScatterPattern {
480480
angleDegrees: 60.0)
481481
hexagonPoints.append(hexagonPoint)
482482
}
483-
let hexagon = Polygon(hexagonPoints[0], hexagonPoints[1], hexagonPoints[2], tail: hexagonPoints[3...])
483+
let hexagon = Polygon(hexagonPoints)!
484484
renderer.drawSolidPolygon(polygon: hexagon,
485485
fillColor: color)
486486
case .pentagon:
@@ -495,7 +495,7 @@ extension ScatterPlotSeriesOptions.ScatterPattern {
495495
angleDegrees: 72.0)
496496
pentagonPoints.append(pentagonPoint)
497497
}
498-
let pentagon = Polygon(pentagonPoints[0], pentagonPoints[1], pentagonPoints[2], tail: pentagonPoints[3...])
498+
let pentagon = Polygon(pentagonPoints)!
499499
renderer.drawSolidPolygon(polygon: pentagon,
500500
fillColor: color)
501501
case .star:
@@ -518,7 +518,7 @@ extension ScatterPlotSeriesOptions.ScatterPattern {
518518
starPoints.append(starOuterPoint)
519519
starPoints.append(starInnerPoint)
520520
}
521-
let star = Polygon(starPoints[0], starPoints[1], starPoints[2], tail: starPoints[3...])
521+
let star = Polygon(starPoints)!
522522
renderer.drawSolidPolygon(polygon: star,
523523
fillColor: color)
524524
}
2 Bytes
Loading
15 Bytes
Loading

0 commit comments

Comments
 (0)