68 lines
2.3 KiB
Swift
68 lines
2.3 KiB
Swift
//
|
|
// UIBezierPath+Helpers.swift
|
|
// Tusker
|
|
//
|
|
// Created by Shadowfacts on 6/25/20.
|
|
// Copyright © 2020 Shadowfacts. All rights reserved.
|
|
//
|
|
|
|
import UIKit
|
|
|
|
// TODO: write unit tests for this
|
|
extension UIBezierPath {
|
|
|
|
/// Create a new UIBezierPath that wraps around the given array of rectangles.
|
|
/// This is not a convex hull aglorithm. What this does is it takes a set of rectangles
|
|
/// and draws a line around the outer borders of the combined shape.
|
|
convenience init(wrappingAround rects: [CGRect]) {
|
|
precondition(rects.count > 0)
|
|
|
|
if rects.count == 1 {
|
|
self.init(rect: rects.first!)
|
|
return
|
|
}
|
|
|
|
let rects = rects.sorted { $0.minY < $1.minY }
|
|
|
|
self.init()
|
|
|
|
// start at the top left corner
|
|
self.move(to: CGPoint(x: rects.first!.minX, y: rects.first!.minY))
|
|
|
|
// walk down the left side
|
|
var prevLeft = rects.first!.minX
|
|
for rect in rects where !rect.minX.isEqual(to: prevLeft) {
|
|
self.addLine(to: CGPoint(x: prevLeft, y: rect.minY))
|
|
self.addLine(to: CGPoint(x: rect.minX, y: rect.minY))
|
|
prevLeft = rect.minX
|
|
}
|
|
|
|
// ensure at the bottom left if not already
|
|
let bottomLeft = CGPoint(x: rects.last!.minX, y: rects.last!.maxY)
|
|
if !self.currentPoint.equalTo(bottomLeft) {
|
|
self.addLine(to: bottomLeft)
|
|
}
|
|
|
|
// across the bottom of the last rect
|
|
self.addLine(to: CGPoint(x: rects.last!.maxX, y: rects.last!.maxY))
|
|
|
|
// walk up the right side
|
|
var prevRight = rects.last!.maxX
|
|
for rect in rects.reversed() where !rect.maxX.isEqual(to: prevRight) {
|
|
self.addLine(to: CGPoint(x: prevRight, y: rect.maxY))
|
|
self.addLine(to: CGPoint(x: rect.maxX, y: rect.maxY))
|
|
prevRight = rect.maxX
|
|
}
|
|
|
|
// ensure at the top right if not already
|
|
let topRight = CGPoint(x: rects.first!.maxX, y: rects.first!.minY)
|
|
if !self.currentPoint.equalTo(topRight) {
|
|
self.addLine(to: topRight)
|
|
}
|
|
|
|
// across the top of the first rect
|
|
self.addLine(to: CGPoint(x: rects.first!.minX, y: rects.first!.minY))
|
|
}
|
|
|
|
}
|