Skip to content

Commit c0bf874

Browse files
committed
rfac: drawPlotLines now takes a new struct Polyline instead of an array of points.
This has the same advantage as the `Polygon` of making the user handle the fact that it needs at least 3 points, as early as possible and preserving that fact in the type itself.
1 parent ad7883d commit c0bf874

File tree

6 files changed

+97
-30
lines changed

6 files changed

+97
-30
lines changed

Sources/AGGRenderer/AGGRenderer/AGGRenderer.swift

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -185,21 +185,21 @@ public class AGGRenderer: Renderer{
185185
agg_object)
186186
}
187187

188-
public func drawPlotLines(points p: [Point],
188+
public func drawPlotLines(polyline: Polyline,
189189
strokeWidth thickness: Float,
190190
strokeColor: Color,
191191
isDashed: Bool) {
192192
var x = [Float]()
193193
var y = [Float]()
194-
195-
for index in 0..<p.count {
196-
x.append(p[index].x + xOffset)
197-
y.append(p[index].y + yOffset)
194+
195+
for point in polyline {
196+
x.append(point.x + xOffset)
197+
y.append(point.y + yOffset)
198198
}
199199

200200
draw_plot_lines(x,
201201
y,
202-
Int32(p.count),
202+
Int32(x.count),
203203
thickness,
204204
strokeColor.r,
205205
strokeColor.g,

Sources/QuartzRenderer/QuartzRenderer.swift

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -401,19 +401,20 @@ public class QuartzRenderer: Renderer {
401401
context.setLineDash(phase: 1, lengths: [])
402402
}
403403

404-
public func drawPlotLines(points p: [Point],
404+
public func drawPlotLines(polyline: Polyline,
405405
strokeWidth thickness: Float,
406406
strokeColor: Color,
407407
isDashed: Bool) {
408-
guard !p.isEmpty else { return }
409-
let line = CGMutablePath()
410-
line.move(to: CGPoint(x: CGFloat(p[0].x + xOffset), y: CGFloat(p[0].y + yOffset)))
411-
for point in p[1...] {
412-
line.addLine(to: CGPoint(x: CGFloat(point.x + xOffset), y: CGFloat(point.y + yOffset)))
408+
409+
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)))
413414
}
414415
context.setStrokeColor(strokeColor.cgColor)
415416
context.setLineWidth(CGFloat(thickness))
416-
context.addPath(line)
417+
context.addPath(linePath)
417418
if(isDashed) {
418419
let dashes: [ CGFloat ] = [ CGFloat(thickness + 1), CGFloat(thickness + 1) ]
419420
context.setLineDash(phase: 1, lengths: dashes)

Sources/SVGRenderer/SVGRenderer.swift

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -186,13 +186,11 @@ public class SVGRenderer: Renderer{
186186
lines.append(line)
187187
}
188188

189-
public func drawPlotLines(points p: [Point],
189+
public func drawPlotLines(polyline: Polyline,
190190
strokeWidth thickness: Float,
191191
strokeColor: Color,
192192
isDashed: Bool) {
193-
guard p.count > 1 else { return }
194-
195-
let pointsString = p.lazy.map { point in
193+
let pointsString = polyline.lazy.map { point in
196194
let convertedPoint = self.convertToSVGCoordinates(point)
197195
return "\(convertedPoint.x),\(convertedPoint.y)"
198196
}.joined(separator: " ")

Sources/SwiftPlot/Histogram.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -329,7 +329,9 @@ extension Histogram: HasGraphLayout {
329329
for ((backRightBinHeight, frontRightBinHeight), x) in zip(zip(backHeightsSlice, frontHeightsSlice), xValues) {
330330

331331
func endLine() {
332-
renderer.drawPlotLines(points: line, strokeWidth: strokeWidth,
332+
// This algorithm should never produce lines with less than 2 points
333+
guard let polyline = Polyline(points: line) else { fatalError("drawData: Expecting 2 or more points, got \(line.count) instead") }
334+
renderer.drawPlotLines(polyline: polyline, strokeWidth: strokeWidth,
333335
strokeColor: series.color, isDashed: false)
334336
line.removeAll(keepingCapacity: true)
335337
}

Sources/SwiftPlot/LineChart.swift

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -419,22 +419,21 @@ extension LineGraph: HasGraphLayout {
419419
//functions to draw the plot
420420
public func drawData(markers: PlotMarkers, size: Size, renderer: Renderer) {
421421
for s in primaryAxis.series {
422-
var points = [Point]()
423-
for p in s.scaledValues {
424-
points.append(Point(Float(p.x),Float(p.y)))
425-
}
426-
renderer.drawPlotLines(points: points,
422+
let p1 = s.scaledValues[0]
423+
let p2 = s.scaledValues[1]
424+
let tail = s.scaledValues[2...].map { Point(Float($0.x), Float($0.y)) }
425+
426+
renderer.drawPlotLines(polyline: Polyline(Point(Float(p1.x),Float(p1.y)), Point(Float(p2.x), Float(p2.y)), tail: tail),
427427
strokeWidth: plotLineThickness,
428428
strokeColor: s.color,
429429
isDashed: false)
430430
}
431431
if (secondaryAxis != nil) {
432432
for s in secondaryAxis!.series {
433-
var points = [Point]()
434-
for p in s.scaledValues {
435-
points.append(Point(Float(p.x),Float(p.y)))
436-
}
437-
renderer.drawPlotLines(points: points,
433+
let p1 = s.scaledValues[0]
434+
let p2 = s.scaledValues[1]
435+
let tail = s.scaledValues[2...].map { Point(Float($0.x), Float($0.y)) }
436+
renderer.drawPlotLines(polyline: Polyline(Point(Float(p1.x),Float(p1.y)), Point(Float(p2.x), Float(p2.y)), tail: tail),
438437
strokeWidth: plotLineThickness,
439438
strokeColor: s.color,
440439
isDashed: true)

Sources/SwiftPlot/Renderer.swift

Lines changed: 69 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,14 +67,14 @@ public protocol Renderer: AnyObject{
6767
strokeColor: Color, isDashed: Bool)
6868

6969
/*drawPlotLines()
70-
*params: points p: [Point],
70+
*params: polyline: Polyline,
7171
* strokeWidth thickness: Float,
7272
* strokeColor: Color,
7373
* isDashed: Bool
7474
*description: Draws all the line segments in a single data series for a Line Graph.
7575
* This function always operates in the coordinate system with the shifted origin.
7676
*/
77-
func drawPlotLines(points p: [Point],
77+
func drawPlotLines(polyline: Polyline,
7878
strokeWidth thickness: Float,
7979
strokeColor: Color, isDashed: Bool)
8080

@@ -263,3 +263,70 @@ extension Polygon.Iterator: IteratorProtocol {
263263
}
264264

265265
extension Polygon.Iterator: Sequence {}
266+
267+
/// Polyline structure definition and sequence extension, along with its iterator.
268+
public struct Polyline {
269+
public var p1: Point, p2: Point
270+
public var tail: [Point]
271+
272+
public init(_ p1: Point, _ p2: Point, tail: [Point] = []) {
273+
(self.p1, self.p2) = (p1, p2)
274+
self.tail = tail
275+
}
276+
277+
public init(_ p1: Point, _ p2: Point, tail: ArraySlice<Point>) {
278+
self.init(p1, p2, tail: Array(tail))
279+
}
280+
281+
public init() {
282+
self.init(.zero, .zero)
283+
}
284+
285+
public init?(points: [Point]) {
286+
guard points.count >= 2 else { return nil }
287+
288+
self = Polyline(points[0], points[1], tail: points[2...])
289+
}
290+
}
291+
292+
extension Polyline: Sequence {
293+
public struct Iterator {
294+
private var state: State
295+
private var tailIterator: Array<Point>.Iterator
296+
private let polyline: Polyline
297+
298+
private enum State {
299+
case p1, p2
300+
case tail
301+
}
302+
303+
public init(polyline: Polyline) {
304+
state = .p1
305+
tailIterator = polyline.tail.makeIterator()
306+
self.polyline = polyline
307+
}
308+
}
309+
310+
public func makeIterator() -> Polyline.Iterator {
311+
return Iterator(polyline: self)
312+
}
313+
}
314+
315+
extension Polyline.Iterator: IteratorProtocol {
316+
public typealias Element = Point
317+
318+
public mutating func next() -> Point? {
319+
switch state {
320+
case .p1:
321+
state = .p2
322+
return polyline.p1
323+
case .p2:
324+
state = .tail
325+
return polyline.p2
326+
case .tail:
327+
return tailIterator.next()
328+
}
329+
}
330+
}
331+
332+
extension Polyline.Iterator: Sequence {}

0 commit comments

Comments
 (0)