123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173 |
- import Foundation
- import AVFoundation
- public struct Quadrilateral: Transformable {
-
-
- var topLeft: CGPoint
-
-
- var topRight: CGPoint
-
-
- var bottomRight: CGPoint
-
- var bottomLeft: CGPoint
-
- init(rectangleFeature: CIRectangleFeature) {
- self.topLeft = rectangleFeature.topLeft
- self.topRight = rectangleFeature.topRight
- self.bottomLeft = rectangleFeature.bottomLeft
- self.bottomRight = rectangleFeature.bottomRight
- }
-
- init(topLeft: CGPoint, topRight: CGPoint, bottomRight: CGPoint, bottomLeft: CGPoint) {
- self.topLeft = topLeft
- self.topRight = topRight
- self.bottomRight = bottomRight
- self.bottomLeft = bottomLeft
- }
-
-
- func path() -> UIBezierPath {
- let path = UIBezierPath()
- path.move(to: topLeft)
- path.addLine(to: topRight)
- path.addLine(to: bottomRight)
- path.addLine(to: bottomLeft)
- path.close()
-
- return path
- }
-
-
-
-
-
-
- func applying(_ transform: CGAffineTransform) -> Quadrilateral {
- let quadrilateral = Quadrilateral(topLeft: topLeft.applying(transform), topRight: topRight.applying(transform), bottomRight: bottomRight.applying(transform), bottomLeft: bottomLeft.applying(transform))
-
- return quadrilateral
- }
-
-
- mutating func reorganize() {
- let points = [topLeft, topRight, bottomRight, bottomLeft]
- let ySortedPoints = sortPointsByYValue(points)
-
- guard ySortedPoints.count == 4 else {
- return
- }
-
- let topMostPoints = Array(ySortedPoints[0..<2])
- let bottomMostPoints = Array(ySortedPoints[2..<4])
- let xSortedTopMostPoints = sortPointsByXValue(topMostPoints)
- let xSortedBottomMostPoints = sortPointsByXValue(bottomMostPoints)
-
- guard xSortedTopMostPoints.count > 1,
- xSortedBottomMostPoints.count > 1 else {
- return
- }
-
- topLeft = xSortedTopMostPoints[0]
- topRight = xSortedTopMostPoints[1]
- bottomRight = xSortedBottomMostPoints[1]
- bottomLeft = xSortedBottomMostPoints[0]
- }
-
-
-
-
-
-
-
-
- func scale(_ fromSize: CGSize, _ toSize: CGSize, withRotationAngle rotationAngle: CGFloat = 0.0) -> Quadrilateral {
- var invertedfromSize = fromSize
- let rotated = rotationAngle != 0.0
-
- if rotated && rotationAngle != CGFloat.pi {
- invertedfromSize = CGSize(width: fromSize.height, height: fromSize.width)
- }
-
- var transformedQuad = self
- let invertedFromSizeWidth = invertedfromSize.width == 0 ? .leastNormalMagnitude : invertedfromSize.width
-
- let scale = toSize.width / invertedFromSizeWidth
- let scaledTransform = CGAffineTransform(scaleX: scale, y: scale)
- transformedQuad = transformedQuad.applying(scaledTransform)
-
- if rotated {
- let rotationTransform = CGAffineTransform(rotationAngle: rotationAngle)
-
- let fromImageBounds = CGRect(x: 0.0, y: 0.0, width: fromSize.width, height: fromSize.height).applying(scaledTransform).applying(rotationTransform)
-
- let toImageBounds = CGRect(x: 0.0, y: 0.0, width: toSize.width, height: toSize.height)
- let translationTransform = CGAffineTransform.translateTransform(fromCenterOfRect: fromImageBounds, toCenterOfRect: toImageBounds)
-
- transformedQuad = transformedQuad.applyTransforms([rotationTransform, translationTransform])
- }
-
- return transformedQuad
- }
-
-
-
-
-
-
-
- private func sortPointsByYValue(_ points: [CGPoint]) -> [CGPoint] {
- return points.sorted { (point1, point2) -> Bool in
- point1.y < point2.y
- }
- }
-
-
-
-
-
- private func sortPointsByXValue(_ points: [CGPoint]) -> [CGPoint] {
- return points.sorted { (point1, point2) -> Bool in
- point1.x < point2.x
- }
- }
- }
- extension Quadrilateral {
-
-
-
-
-
-
- func toCartesian(withHeight height: CGFloat) -> Quadrilateral {
- let topLeft = self.topLeft.cartesian(withHeight: height)
- let topRight = self.topRight.cartesian(withHeight: height)
- let bottomRight = self.bottomRight.cartesian(withHeight: height)
- let bottomLeft = self.bottomLeft.cartesian(withHeight: height)
-
- return Quadrilateral(topLeft: topLeft, topRight: topRight, bottomRight: bottomRight, bottomLeft: bottomLeft)
- }
-
- }
- extension Quadrilateral: Equatable {
-
- public static func == (lhs: Quadrilateral, rhs: Quadrilateral) -> Bool {
- return lhs.topLeft == rhs.topLeft && lhs.topRight == rhs.topRight && lhs.bottomRight == rhs.bottomRight && lhs.bottomLeft == rhs.bottomLeft
- }
-
- }
|