Untitled
unknown
plain_text
3 years ago
3.9 kB
2
Indexable
struct LineGraphVector: VectorArithmetic { var points: [CGPoint.AnimatableData] static func + (lhs: LineGraphVector, rhs: LineGraphVector) -> LineGraphVector { return add(lhs: lhs, rhs: rhs, +) } static func - (lhs: LineGraphVector, rhs: LineGraphVector) -> LineGraphVector { return add(lhs: lhs, rhs: rhs, -) } static func add(lhs: LineGraphVector, rhs: LineGraphVector, _ sign: (CGFloat, CGFloat) -> CGFloat) -> LineGraphVector { let maxPoints = max(lhs.points.count, rhs.points.count) let leftIndices = lhs.points.indices let rightIndices = rhs.points.indices var newPoints: [CGPoint.AnimatableData] = [] (0 ..< maxPoints).forEach { index in if leftIndices.contains(index) && rightIndices.contains(index) { // Merge points let lhsPoint = lhs.points[index] let rhsPoint = rhs.points[index] newPoints.append( .init( sign(lhsPoint.first, rhsPoint.first), sign(lhsPoint.second, rhsPoint.second) ) ) } else if rightIndices.contains(index), let lastLeftPoint = lhs.points.last { // Right side has more points, collapse to last left point let rightPoint = rhs.points[index] newPoints.append( .init( sign(lastLeftPoint.first, rightPoint.first), sign(lastLeftPoint.second, rightPoint.second) ) ) } else if leftIndices.contains(index), let lastPoint = newPoints.last { // Left side has more points, collapse to last known point let leftPoint = lhs.points[index] newPoints.append( .init( sign(lastPoint.first, leftPoint.first), sign(lastPoint.second, leftPoint.second) ) ) } } return .init(points: newPoints) } mutating func scale(by rhs: Double) { points.indices.forEach { index in self.points[index].scale(by: rhs) } } var magnitudeSquared: Double { return 1.0 } static var zero: LineGraphVector { return .init(points: []) } } struct LineGraphShape: Shape { var points: [CGPoint] let closePath: Bool init(points: [CGPoint], closePath: Bool) { self.points = points self.closePath = closePath } var animatableData: LineGraphVector { get { .init(points: points.map { CGPoint.AnimatableData($0.x, $0.y) }) } set { points = newValue.points.map { CGPoint(x: $0.first, y: $0.second) } } } func path(in rect: CGRect) -> Path { Path { path in path.move(to: points.first ?? .zero) path.addLines(points) switch (closePath, points.first, points.last) { case (true, .some(let firstPoint), .some(let lastPoint)): path.addLine(to: .init(x: lastPoint.x, y: rect.height)) path.addLine(to: .init(x: 0.0, y: rect.height)) path.addLine(to: .init(x: 0.0, y: firstPoint.y)) path.closeSubpath() default: break } } } } }
Editor is loading...