From 963b49f15cfad86cc902e3a05c3d5a095be2321c Mon Sep 17 00:00:00 2001 From: Adrian Schoenig Date: Thu, 3 Oct 2024 17:40:47 +1000 Subject: [PATCH] Robustness, check for invalid points; ignore `zoomTo` rects of size zero. --- Sources/GeoDrawer/GeoDrawer.swift | 17 +++++++++++++++-- Sources/GeoProjector/Projection.swift | 14 ++++++++++++-- 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/Sources/GeoDrawer/GeoDrawer.swift b/Sources/GeoDrawer/GeoDrawer.swift index 8eeecc3..d6da4e3 100644 --- a/Sources/GeoDrawer/GeoDrawer.swift +++ b/Sources/GeoDrawer/GeoDrawer.swift @@ -220,8 +220,11 @@ extension GeoDrawer { // 3. Now translate the projected points into point coordinates to draw let converted = projected .map { (unproj, projected) -> (Point, Point?, Grouping) in + assert(unproj.isGood) if let projected { - return (unproj, projection.translate(projected, to: size, zoomTo: zoomTo, insets: insets), projection.willWrap(unproj) ? .wrapped : .notWrapped) + let proj = projection.translate(projected, to: size, zoomTo: zoomTo, insets: insets) + assert(proj.isGood) + return (unproj, proj, projection.willWrap(unproj) ? .wrapped : .notWrapped) } else { return (unproj, nil, .notProjected) } @@ -265,7 +268,11 @@ extension GeoDrawer { // When "resuming" the same group, connect with the previous points // in the group, but interpolate again. let interpolated = Interpolator.interpolate(from: last, to: unproj, maxDiff: 0.0025, projector: projection.project(_:)) - let translated = interpolated.map { ($0.0, projection.translate($0.1, to: size, zoomTo: zoomTo, insets: insets)) } + let translated = interpolated.map { + let translated = projection.translate($0.1, to: size, zoomTo: zoomTo, insets: insets) + assert(translated.isGood) + return ($0.0, translated) + } new.append(contentsOf: translated) } if let proj { @@ -287,3 +294,9 @@ extension GeoDrawer { return [wraps.map(\.1), unwraps.map(\.1)].filter { !$0.isEmpty } } } + +fileprivate extension Point { + var isGood: Bool { + !x.isNaN && !y.isNaN && !x.isInfinite && !y.isInfinite + } +} diff --git a/Sources/GeoProjector/Projection.swift b/Sources/GeoProjector/Projection.swift index b1e0647..cf1a121 100644 --- a/Sources/GeoProjector/Projection.swift +++ b/Sources/GeoProjector/Projection.swift @@ -91,11 +91,12 @@ extension Projection { height: size.height - insets.top - insets.bottom ) let pointInAvailable: Point - if let zoomTo { + if let zoomTo, zoomTo.size != .zero { pointInAvailable = zoomedTranslate(point, zoomTo: zoomTo, to: availableSize) } else { pointInAvailable = simpleTranslate(point, to: availableSize) } + assert(pointInAvailable.isGood) let x: Double = pointInAvailable.x + insets.left let y: Double @@ -104,7 +105,9 @@ extension Projection { #else y = (availableSize.height - pointInAvailable.y) + insets.top #endif - return Point(x: x, y: y) + let result = Point(x: x, y: y) + assert(result.isGood) + return result } private func simpleTranslate(_ point: Point, to size: Size) -> Point { @@ -137,6 +140,7 @@ extension Projection { } private func zoomedTranslate(_ point: Point, zoomTo: Rect, to size: Size) -> Point { + assert(zoomTo.size != .zero) let myRatio = zoomTo.size.aspectRatio let targetRatio = size.aspectRatio @@ -183,3 +187,9 @@ extension Size { width / height } } + +fileprivate extension Point { + var isGood: Bool { + !x.isNaN && !y.isNaN && !x.isInfinite && !y.isInfinite + } +}