|
@@ -416,6 +416,17 @@ open class ViewPortHandler: NSObject
|
|
return isInBoundsTop(y) && isInBoundsBottom(y)
|
|
return isInBoundsTop(y) && isInBoundsBottom(y)
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
+ A method to check whether coordinate lies within the viewport.
|
|
|
|
+
|
|
|
|
+ - Parameters:
|
|
|
|
+ - point: a coordinate.
|
|
|
|
+ */
|
|
|
|
+ @objc open func isInBounds(point: CGPoint) -> Bool
|
|
|
|
+ {
|
|
|
|
+ return isInBounds(x: point.x, y: point.y)
|
|
|
|
+ }
|
|
|
|
+
|
|
@objc open func isInBounds(x: CGFloat, y: CGFloat) -> Bool
|
|
@objc open func isInBounds(x: CGFloat, y: CGFloat) -> Bool
|
|
{
|
|
{
|
|
return isInBoundsX(x) && isInBoundsY(y)
|
|
return isInBoundsX(x) && isInBoundsY(y)
|
|
@@ -443,6 +454,52 @@ open class ViewPortHandler: NSObject
|
|
return (_contentRect.origin.y + _contentRect.size.height) >= normalizedY
|
|
return (_contentRect.origin.y + _contentRect.size.height) >= normalizedY
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
+ A method to check whether a line between two coordinates intersects with the view port by using a linear function.
|
|
|
|
+
|
|
|
|
+ Linear function (calculus): `y = ax + b`
|
|
|
|
+
|
|
|
|
+ Note: this method will not check for collision with the right edge of the view port, as we assume lines run from left
|
|
|
|
+ to right (e.g. `startPoint < endPoint`).
|
|
|
|
+
|
|
|
|
+ - Parameters:
|
|
|
|
+ - startPoint: the start coordinate of the line.
|
|
|
|
+ - endPoint: the end coordinate of the line.
|
|
|
|
+ */
|
|
|
|
+ @objc open func isIntersectingLine(from startPoint: CGPoint, to endPoint: CGPoint) -> Bool
|
|
|
|
+ {
|
|
|
|
+ // If start- and/or endpoint fall within the viewport, bail out early.
|
|
|
|
+ if isInBounds(point: startPoint) || isInBounds(point: endPoint) { return true }
|
|
|
|
+ // check if x in bound when it's a vertical line
|
|
|
|
+ if startPoint.x == endPoint.x { return isInBoundsX(startPoint.x) }
|
|
|
|
+
|
|
|
|
+ // Calculate the slope (`a`) of the line (e.g. `a = (y2 - y1) / (x2 - x1)`).
|
|
|
|
+ let a = (endPoint.y - startPoint.y) / (endPoint.x - startPoint.x)
|
|
|
|
+ // Calculate the y-correction (`b`) of the line (e.g. `b = y1 - (a * x1)`).
|
|
|
|
+ let b = startPoint.y - (a * startPoint.x)
|
|
|
|
+
|
|
|
|
+ // Check for colission with the left edge of the view port (e.g. `y = (a * minX) + b`).
|
|
|
|
+ // if a is 0, it's a horizontal line; checking b here is still valid, as b is `point.y` all the time
|
|
|
|
+ if isInBoundsY((a * contentRect.minX) + b) { return true }
|
|
|
|
+
|
|
|
|
+ // Skip unnecessary check for collision with the right edge of the view port
|
|
|
|
+ // (e.g. `y = (a * maxX) + b`), as such a line will either begin inside the view port,
|
|
|
|
+ // or intersect the left, top or bottom edges of the view port. Leaving this logic here for clarity's sake:
|
|
|
|
+ // if isInBoundsY((a * contentRect.maxX) + b) { return true }
|
|
|
|
+
|
|
|
|
+ // While slope `a` can theoretically never be `0`, we should protect against division by zero.
|
|
|
|
+ guard a != 0 else { return false }
|
|
|
|
+
|
|
|
|
+ // Check for collision with the bottom edge of the view port (e.g. `x = (maxY - b) / a`).
|
|
|
|
+ if isInBoundsX((contentRect.maxY - b) / a) { return true }
|
|
|
|
+
|
|
|
|
+ // Check for collision with the top edge of the view port (e.g. `x = (minY - b) / a`).
|
|
|
|
+ if isInBoundsX((contentRect.minY - b) / a) { return true }
|
|
|
|
+
|
|
|
|
+ // This line does not intersect the view port.
|
|
|
|
+ return false
|
|
|
|
+ }
|
|
|
|
+
|
|
/// The current x-scale factor
|
|
/// The current x-scale factor
|
|
@objc open var scaleX: CGFloat
|
|
@objc open var scaleX: CGFloat
|
|
{
|
|
{
|