Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- typealias GeometricValue = Numeric & Comparable
- struct GenericPoint<ValueType: GeometricValue>: Equatable {
- var x: ValueType
- var y: ValueType
- static var zero: Self { Self(x: 0, y: 0) }
- }
- extension GenericPoint {
- init(_ x: ValueType, _ y: ValueType) {
- self.init(x: x, y: y)
- }
- static func +(lhs: Self, rhs: Self) -> Self {
- Self(x: lhs.x + rhs.x, y: lhs.y + rhs.y)
- }
- static func +=(lhs: inout Self, rhs: Self) {
- lhs = lhs + rhs
- }
- static func -(lhs: Self, rhs: Self) -> Self {
- lhs + (rhs * -1)
- }
- static func -=(lhs: inout Self, rhs: Self) {
- lhs = lhs - rhs
- }
- static func *(lhs: Self, scale: ValueType) -> Self {
- Self(x: lhs.x * scale, y: lhs.y * scale)
- }
- static func *=(lhs: inout Self, scale: ValueType) {
- lhs = lhs * scale
- }
- static prefix func - (point: Self) -> Self {
- point * -1
- }
- func offsetBy(dx: ValueType = 0, dy: ValueType = 0) -> Self {
- self + Self(x: dx, y: dy)
- }
- }
- extension GenericPoint where ValueType: FloatingPoint {
- static func /(lhs: Self, scale: ValueType) -> Self {
- lhs * (1 / scale)
- }
- static func /=(lhs: inout Self, scale: ValueType) {
- lhs *= (1 / scale)
- }
- }
- struct GenericSize<ValueType: GeometricValue>: Equatable {
- var width: ValueType
- var height: ValueType
- static var zero: Self { Self(width: 0, height: 0) }
- }
- extension GenericSize {
- init(_ w: ValueType, _ h: ValueType) {
- self.init(width: w, height: h)
- }
- }
- extension GenericSize: Sequence where ValueType: Strideable {
- typealias Element = GenericPoint<ValueType>
- func makeIterator() -> AnyIterator<Element> {
- return GenericRect(origin: .zero, size: self).makeIterator()
- }
- }
- struct GenericRect<ValueType: GeometricValue>: Equatable {
- typealias PointType = GenericPoint<ValueType>
- typealias SizeType = GenericSize<ValueType>
- var origin: PointType
- var size: SizeType
- var x: ValueType {
- get { origin.x }
- set { origin.x = newValue }
- }
- var y: ValueType {
- get { origin.y }
- set { origin.y = newValue }
- }
- var width: ValueType {
- get { size.width }
- set { size.width = newValue }
- }
- var height: ValueType {
- get { size.height }
- set { size.height = newValue }
- }
- var maxX: ValueType { Swift.max(x, x + width) }
- var maxY: ValueType { Swift.max(y, y + height) }
- var minX: ValueType { Swift.min(x, x + width) }
- var minY: ValueType { Swift.min(y, y + height) }
- var bottomLeft: PointType { PointType(x: minX, y: maxY) }
- var bottomRight: PointType { PointType(x: maxX, y: maxY) }
- var area: ValueType {
- let copy = standardized()
- return copy.width * copy.height
- }
- func contains(_ point: PointType) -> Bool {
- let test = standardized()
- return point.x >= test.x && point.y >= test.y && point.x < test.x + test.width && point.y < test.y + test.height
- }
- mutating func standardize() {
- if width < 0 {
- x += width
- width *= -1
- }
- if height < 0 {
- y += height
- height *= -1
- }
- }
- func standardized() -> Self {
- var copy = self
- copy.standardize()
- return copy
- }
- func translatedBy(_ v: PointType) -> Self {
- Self(origin: PointType(x: x + v.x, y: y + v.y), size: SizeType(width: width, height: height))
- }
- func intersection(_ r2: Self) -> Self? {
- if minX < r2.maxX, maxX > r2.minX, minY < r2.maxY, maxY > r2.minY {
- return Self(minX: Swift.max(minX, r2.minX),
- minY: Swift.max(minY, r2.minY),
- maxX: Swift.min(maxX, r2.maxX),
- maxY: Swift.min(maxY, r2.maxY))
- } else {
- return nil
- }
- }
- func inset(by insets: GenericInsets<ValueType>) -> Self {
- Self(minX: minX + insets.left,
- minY: minY + insets.top,
- maxX: maxX - insets.bottom,
- maxY: maxY - insets.right)
- }
- static var zero: Self { Self(origin: .zero, size: .zero) }
- }
- extension GenericRect {
- init(x: ValueType, y: ValueType, width: ValueType, height: ValueType) {
- self.init(origin: PointType(x: x, y: y),
- size: SizeType(width: width, height: height))
- }
- init(_ x: ValueType, _ y: ValueType, _ w: ValueType, _ h: ValueType) {
- self.init(x: x, y: y, width: w, height: h)
- }
- init(minX: ValueType, minY: ValueType, maxX: ValueType, maxY: ValueType) {
- self.init(minX, minY, maxX - minX, maxY - minY)
- }
- init(origin: PointType, bottomRight: PointType) {
- self.init(minX: origin.x, minY: origin.y, maxX: bottomRight.x, maxY: bottomRight.y)
- }
- }
- protocol Divisible {
- static func / (lhs: Self, rhs: Self) -> Self
- }
- extension Float: Divisible {}
- extension Int: Divisible {}
- extension GenericRect where ValueType: Divisible {
- var center: PointType {
- get { PointType(x: midX, y: midY) }
- set { midX = newValue.x; midY = newValue.y }
- }
- var midX: ValueType {
- get { x + (width / 2) }
- set { x = newValue - width / 2 }
- }
- var midY: ValueType {
- get { y + (height / 2) }
- set { y = newValue - height / 2 }
- }
- var bottomCenter: PointType { PointType(x: midX, y: maxY) }
- }
- extension GenericRect: Sequence where ValueType: Strideable {
- typealias Element = PointType
- func makeIterator() -> AnyIterator<PointType> {
- var at = origin
- return AnyIterator {
- if at.x == self.width {
- at.y += 1
- at.x = 0
- }
- guard at.y < self.height else { return nil }
- defer { at.x += 1 }
- return at
- }
- }
- }
- struct GenericInsets<ValueType: GeometricValue>: Equatable {
- var top: ValueType
- var left: ValueType
- var bottom: ValueType
- var right: ValueType
- static var zero: Self { Self(top: 0, left: 0, bottom: 0, right: 0) }
- }
- typealias Point = GenericPoint<Int>
- typealias Size = GenericSize<Int>
- typealias Rect = GenericRect<Int>
- typealias EdgeInsets = GenericInsets<Int>
- typealias PointF = GenericPoint<Float>
- typealias SizeF = GenericSize<Float>
- typealias RectF = GenericRect<Float>
- typealias EdgeInsetsF = GenericInsets<Float>
- extension Point {
- init(_ point: PointF) {
- self.init(Int(point.x.rounded(.down)), Int(point.y.rounded(.down)))
- }
- }
- extension PointF {
- init(_ point: Point) {
- self.init(Float(point.x), Float(point.y))
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement