Last active
June 21, 2017 09:11
-
-
Save yusuke024/fc54e822b9e8c6ce592d5937a22b759a to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) | |
} | |
} | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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