Skip to content

Instantly share code, notes, and snippets.

@yusuke024
Last active June 21, 2017 09:11
Show Gist options
  • Save yusuke024/fc54e822b9e8c6ce592d5937a22b759a to your computer and use it in GitHub Desktop.
Save yusuke024/fc54e822b9e8c6ce592d5937a22b759a to your computer and use it in GitHub Desktop.
import UIKit
struct Point {
let x: Double
let y: Double
}
extension Point {
static let zero = Point(x: 0, y: 0)
init(_ cgPoint: CGPoint) {
x = Double(cgPoint.x)
y = Double(cgPoint.y)
}
func distance(to: Point) -> Double {
let dx = x - to.x
let dy = y - to.y
return sqrt(dx * dx + dy * dy)
}
}
extension Point: CustomDebugStringConvertible {
var debugDescription: String {
return "(\(x), \(y))"
}
}
enum Path {
case line(begin: Point, end: Point)
case quadCurve(begin: Point, control: Point, end: Point)
case curve(begin: Point, control1: Point, control2: Point, end: Point)
}
extension Path {
func point(at: Double) -> Point {
switch self {
case .line(begin: let begin, end: let end):
return Path._point(at: at, from: begin, to: end)
case .quadCurve(begin: let begin, control: let control, end: let end):
return Path._point(at: at, points: [begin, control, end])
case .curve(begin: let begin, control1: let control1, control2: let control2, end: let end):
return Path._point(at: at, points: [begin, control1, control2, end])
}
}
private static func _point(at: Double, from: Point, to: Point) -> Point {
return Point(x: (to.x - from.x) * at + from.x, y: (to.y - from.y) * at + from.y)
}
private static func _point(at: Double, points: [Point]) -> Point {
guard points.count >= 2 else {
fatalError()
}
if points.count == 2 {
return _point(at: at, from: points[0], to: points[1])
}
var nextPoints = [Point]()
var from = points[0]
for p in points.dropFirst() {
nextPoints.append(_point(at: at, from: from, to: p))
from = p
}
return Path._point(at: at, points: nextPoints)
}
}
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let path = UIBezierPath(arcCenter: CGPoint(x: 150, y: 150), radius: 150, startAngle: 0, endAngle: CGFloat(Double.pi * 2), clockwise: true)
var paths = [Path]()
var currentPoint = CGPoint.zero
path.cgPath.applyWithBlock { (element) in
let e = element.pointee
switch (e.type) {
case .moveToPoint:
currentPoint = e.points[0]
case .addLineToPoint:
paths.append(.line(begin: Point(currentPoint),
end: Point(e.points[0])))
currentPoint = e.points[0]
case .addQuadCurveToPoint:
paths.append(.quadCurve(begin: Point(currentPoint),
control: Point(e.points[0]),
end: Point(e.points[2])))
currentPoint = e.points[1]
case .addCurveToPoint:
paths.append(.curve(begin: Point(currentPoint),
control1: Point(e.points[0]),
control2: Point(e.points[1]),
end: Point(e.points[2])))
currentPoint = e.points[2]
case .closeSubpath:
break
}
}
print(paths)
var length = 0.0
let interval = 100
for path in paths {
var lastPoint = path.point(at: 0)
for i in 0...interval {
let nextPoint = path.point(at: Double(i) / Double(interval))
length += lastPoint.distance(to: nextPoint)
lastPoint = nextPoint
}
}
let points = paths.flatMap { path in
(0...interval).map { i -> CGPoint in
let p = path.point(at: Double(i) / Double(interval))
return CGPoint(x: CGFloat(p.x), y: CGFloat(p.y))
}
}
print(length)
func plot(size: CGSize, points: [CGPoint]) -> UIImage {
let renderer = UIGraphicsImageRenderer(size: size)
return renderer.image { context in
UIColor.red.setFill()
for point in points {
let rect = CGRect(origin: point, size: .zero).insetBy(dx: -1, dy: -1)
context.fill(rect)
}
}
}
let width = 300
let imageView = UIImageView(frame: CGRect(x: 0, y: 0, width: width, height: width))
imageView.image = plot(size: CGSize(width: width, height: width), points: points)
view.addSubview(imageView)
}
}
struct Point {
let x: Double
let y: Double
}
extension Point {
static let zero = Point(x: 0, y: 0)
init(_ cgPoint: CGPoint) {
x = Double(cgPoint.x)
y = Double(cgPoint.y)
}
func distance(to: Point) -> Double {
let dx = x - to.x
let dy = y - to.y
return sqrt(dx * dx + dy * dy)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment