Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 45 additions & 4 deletions Sources/SwiftPlot/PlotStyleHelpers.swift
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ public struct Coordinate {
}

public protocol CoordinateResolver {
func resolve(_ coordinate: Coordinate) -> Point
func resolve(_ coordinate: Coordinate) -> Point
}

public protocol Annotation {
Expand All @@ -69,7 +69,7 @@ public enum Direction {
case west
}

public protocol AnchorableAnnotation : Annotation {
public protocol AnchorableAnnotation: Annotation {
var direction: Direction { get set }
var margin: Float { get set }
mutating func resolve(renderer: Renderer, center: Point)
Expand Down Expand Up @@ -107,7 +107,7 @@ struct Box: Annotation, AnchorableAnnotation {
}
}

struct Text : Annotation, AnchorableAnnotation {
struct Text: Annotation, AnchorableAnnotation {
public var text = ""
public var color = Color.black
public var size: Float = 15
Expand Down Expand Up @@ -157,7 +157,7 @@ struct Text : Annotation, AnchorableAnnotation {
}
}

struct Arrow : Annotation {
struct Arrow: Annotation {
public var color = Color.black
public var start = Point(0.0, 0.0)
public var end = Point(0.0, 0.0)
Expand Down Expand Up @@ -277,3 +277,44 @@ struct Arrow : Annotation {
self.overrideAnchor = overrideAnchor
}
}

struct Bracket: Annotation {
public var color = Color.black
public var start = Coordinate()
public var end = Coordinate()
public var strokeWidth: Float = 3
public var isDashed: Bool = false
public var legLength: Float = 15
public var anchorableAnnotation: AnchorableAnnotation?
public mutating func draw(resolver: CoordinateResolver, renderer: Renderer) {
// Calculate leg points.
let startPoint = resolver.resolve(start), endPoint = resolver.resolve(end)
var startLegPoint = startPoint + Point(0.0, -strokeWidth/2-legLength)
let startLegRotateAngle = -atan2(endPoint.x - startPoint.x, endPoint.y - startPoint.y)
startLegPoint = rotatePoint(point: startLegPoint, center: startPoint, angleRadians: startLegRotateAngle + 0.5 * Float.pi)
var endLegPoint = endPoint + Point(0.0, -strokeWidth/2-legLength)
endLegPoint = rotatePoint(point: endLegPoint, center: endPoint, angleRadians: startLegRotateAngle + 0.5 * Float.pi)

// Draws bracket.
renderer.drawPolyline(Polyline(startLegPoint, startPoint, endPoint, endLegPoint)!,
strokeWidth: strokeWidth,
strokeColor: color,
isDashed: isDashed)

// Calculate anchor point.
let anchorPoint = Point((startPoint.x + endPoint.x)/2, (startPoint.y + endPoint.y)/2)

// Draws AnchorableAnnotation if specified.
anchorableAnnotation?.resolve(renderer: renderer, center: anchorPoint)
anchorableAnnotation?.draw(resolver: resolver, renderer: renderer)
}
public init(color: Color = .black, start: Coordinate = Coordinate(), end: Coordinate = Coordinate(), strokeWidth: Float = 5, isDashed: Bool = false, legLength: Float = 15, anchorableAnnotation: AnchorableAnnotation? = nil) {
self.color = color
self.start = start
self.end = end
self.strokeWidth = strokeWidth
self.isDashed = isDashed
self.legLength = legLength
self.anchorableAnnotation = anchorableAnnotation
}
}
52 changes: 52 additions & 0 deletions Tests/SwiftPlotTests/Annotation/annotation-bracket.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
@testable import SwiftPlot
import Foundation
import SVGRenderer
#if canImport(AGGRenderer)
import AGGRenderer
#endif
#if canImport(QuartzRenderer)
import QuartzRenderer
#endif

@available(tvOS 13, watchOS 13, *)
extension AnnotationTests {

func testAnnotationBracket() throws {

let fileName = "_35_bracket_annotation"

var lineGraph = LineGraph<Float, Float>(enablePrimaryAxisGrid: true)
lineGraph.addFunction(sin, minX: -5.0, maxX: 5.0, label: "sin(x)", color: .lightBlue)
lineGraph.plotTitle.title = "FUNCTION"
lineGraph.plotLabel.xLabel = "X-AXIS"
lineGraph.plotLabel.yLabel = "Y-AXIS"
lineGraph.plotLineThickness = 3.0

lineGraph.addAnnotation(annotation: Bracket(start: Coordinate(point: Point(150.0, 607.0)),
end: Coordinate(point: Point(630.0, 607.0)),
anchorableAnnotation: Text(text: "Period",
direction: .south)))
lineGraph.addAnnotation(annotation: Bracket(start: Coordinate(point: Point(900, 585.0)),
end: Coordinate(point: Point(900, 340.0)),
anchorableAnnotation: Text(text: "Amplitude",
direction: .east)))
let svg_renderer = SVGRenderer()
try lineGraph.drawGraphAndOutput(fileName: svgOutputDirectory+fileName,
renderer: svg_renderer)
verifyImage(name: fileName, renderer: .svg)
#if canImport(AGGRenderer)
let agg_renderer = AGGRenderer()
try lineGraph.drawGraphAndOutput(fileName: aggOutputDirectory+fileName,
renderer: agg_renderer)
verifyImage(name: fileName, renderer: .agg)
#endif
/*
#if canImport(QuartzRenderer)
let quartz_renderer = QuartzRenderer()
try lineGraph.drawGraphAndOutput(fileName: coreGraphicsOutputDirectory+fileName,
renderer: quartz_renderer)
verifyImage(name: fileName, renderer: .coreGraphics)
#endif
*/
}
}
38 changes: 19 additions & 19 deletions Tests/SwiftPlotTests/LineChart/linechart-regressiontests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import SwiftPlot
import Foundation

extension LineChartTests {

func testLineChart_positiveYOrigin() throws {
let x:[Float] = [0, 1, 2, 3]
let y:[Float] = [70, 80, 95, 100]
Expand All @@ -16,7 +16,7 @@ extension LineChartTests {

try renderAndVerify(lineGraph, size: Size(width: 300, height: 300))
}

func testLineChart_positiveYOrigin_secondary() throws {
let x:[Float] = [0, 1, 2, 3]
let y:[Float] = [70, 80, 95, 100]
Expand All @@ -32,10 +32,10 @@ extension LineChartTests {
lineGraph.plotLineThickness = 3.0
lineGraph.enablePrimaryAxisGrid = true
lineGraph.enableSecondaryAxisGrid = true

try renderAndVerify(lineGraph, size: Size(width: 400, height: 400))
}

func testLineChart_negativeYOrigin() throws {
let x:[Float] = [0, 1, 2, 3]
let y:[Float] = [-70, -80, -95, -100]
Expand All @@ -49,7 +49,7 @@ extension LineChartTests {

try renderAndVerify(lineGraph, size: Size(width: 300, height: 300))
}

func testLineChart_positiveXOrigin() throws {
let x:[Float] = [5, 6, 7, 8]
let y:[Float] = [70, 80, 95, 100]
Expand All @@ -63,7 +63,7 @@ extension LineChartTests {

try renderAndVerify(lineGraph, size: Size(width: 300, height: 300))
}

func testLineChart_negativeXOrigin() throws {
let x:[Float] = [-5, -6, -7, -8]
let y:[Float] = [-70, -80, -95, -100]
Expand All @@ -77,7 +77,7 @@ extension LineChartTests {

try renderAndVerify(lineGraph, size: Size(width: 300, height: 300))
}

func testLineChart_positiveXOrigin_secondary() throws {
let x:[Float] = [0, 1, 2, 3]
let y:[Float] = [70, 80, 95, 100]
Expand All @@ -94,10 +94,10 @@ extension LineChartTests {
lineGraph.plotLineThickness = 3.0
lineGraph.enablePrimaryAxisGrid = true
lineGraph.enableSecondaryAxisGrid = true

try renderAndVerify(lineGraph, size: Size(width: 400, height: 400))
}

func testLineChart_negativeXOrigin_unsorted() throws {
let x:[Float] = [-8, -7, -6, -5]
let y:[Float] = [70, 80, 95, 100]
Expand All @@ -111,7 +111,7 @@ extension LineChartTests {

try renderAndVerify(lineGraph, size: Size(width: 300, height: 300))
}

func testLineChart_crossX() throws {
func someFunction(_ x: Float) -> Float { (x * x) + 10 }
var lineGraph_func = LineGraph<Float,Float>(enablePrimaryAxisGrid: true)
Expand All @@ -126,7 +126,7 @@ extension LineChartTests {
lineGraph_func.plotLabel.yLabel = "Y-AXIS"
try renderAndVerify(lineGraph_func, size: Size(width: 400, height: 400))
}

func testLineChart_crossY() throws {
func someFunction(_ x: Float) -> Float { 5 * cos(2 * x * x) / x }
var lineGraph_func = LineGraph<Float,Float>(enablePrimaryAxisGrid: true)
Expand All @@ -141,22 +141,22 @@ extension LineChartTests {
lineGraph_func.plotLabel.yLabel = "Y-AXIS"
try renderAndVerify(lineGraph_func, size: Size(width: 400, height: 400))
}

func testLineChart_crossBothAxes() throws {
var lineGraph = LineGraph<Float,Float>(enablePrimaryAxisGrid: true,
enableSecondaryAxisGrid: false)
let clamp: ClosedRange<Float>? = -150...150
lineGraph.addFunction({ pow($0, 2) }, minX: -5, maxX: 5, clampY: clamp, label: "2", color: .lightBlue)
lineGraph.addFunction({ pow($0, 3) }, minX: -5, maxX: 5, clampY: clamp, label: "3", color: .orange)
lineGraph.addFunction({ pow($0, 4) }, minX: -5, maxX: 5, clampY: clamp, label: "4", color: .red)
lineGraph.addFunction({ pow($0, 5) }, minX: -5, maxX: 5, clampY: clamp, label: "5", color: .brown)
lineGraph.addFunction({ pow($0 , 6) }, minX: -5, maxX: 5, clampY: clamp, label: "6", color: .purple)
lineGraph.addFunction({ pow($0 , 7) }, minX: -5, maxX: 5, clampY: clamp, label: "7", color: .green)
lineGraph.addFunction({ Float(truncating: pow(Decimal(Double($0)), Int(2)) as NSNumber) }, minX: -5, maxX: 5, clampY: clamp, label: "2", color: .lightBlue)
lineGraph.addFunction({ Float(truncating: pow(Decimal(Double($0)), Int(3)) as NSNumber) }, minX: -5, maxX: 5, clampY: clamp, label: "3", color: .orange)
lineGraph.addFunction({ Float(truncating: pow(Decimal(Double($0)), Int(4)) as NSNumber) }, minX: -5, maxX: 5, clampY: clamp, label: "4", color: .red)
lineGraph.addFunction({ Float(truncating: pow(Decimal(Double($0)), Int(5)) as NSNumber) }, minX: -5, maxX: 5, clampY: clamp, label: "5", color: .brown)
lineGraph.addFunction({ Float(truncating: pow(Decimal(Double($0)), Int(6)) as NSNumber) }, minX: -5, maxX: 5, clampY: clamp, label: "6", color: .purple)
lineGraph.addFunction({ Float(truncating: pow(Decimal(Double($0)), Int(7)) as NSNumber) }, minX: -5, maxX: 5, clampY: clamp, label: "7", color: .green)
lineGraph.plotTitle.title = "y = x^n"
lineGraph.plotLabel.xLabel = "x"
lineGraph.plotLabel.yLabel = "y"
lineGraph.backgroundColor = .transparent

try renderAndVerify(lineGraph, size: Size(width: 800, height: 400))
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading