Move SSD view clamp math to typed Kotlin
ober
ce51755f0603742c440441897c9d4786dd76310b
--- a/templates/ssd-review.ss +++ b/templates/ssd-review.ss @@ -1136,7 +1136,9 @@ (typed-kotlin-file "com/sfb/ssdreview/SsdReviewGeometry.kt" (typed-library (com sfb ssdreview) - (export hitGroupId selectionMatchingCells cellIdsForSelection) + (export hitGroupId selectionMatchingCells cellIdsForSelection + clampInitialScale clampScale clampGroupFitScale + clampViewportOffset clampImageCoordinate) (type Float32) (type FloatArray) (def (selectionCellMatches? (rect : FloatArray) (cell : SsdCell)) : Bool @@ -1160,6 +1162,29 @@ (begin (mutable-list-add! ids (SsdCell-id (list-ref cells i))) ids))) + (def (clampFloat32 (value : Float32) + (minimum : Float32) + (maximum : Float32)) : Float32 + (if (< value minimum) + minimum + (if (> value maximum) + maximum + value))) + (def (clampInitialScale (value : Float32)) : Float32 + (clampFloat32 value (float32 0.1) (float32 8.0))) + (def (clampScale (value : Float32)) : Float32 + (clampFloat32 value (float32 0.2) (float32 8.0))) + (def (clampGroupFitScale (value : Float32)) : Float32 + (clampFloat32 value (float32 1.4) (float32 6.5))) + (def (clampViewportOffset (offset : Float32) + (viewportSize : Float32) + (scaledSize : Float32)) : Float32 + (if (<= scaledSize viewportSize) + (/ (- viewportSize scaledSize) (float32 2.0)) + (clampFloat32 offset (- viewportSize scaledSize) (float32 0.0)))) + (def (clampImageCoordinate (value : Float32) + (maximum : Float32)) : Float32 + (clampFloat32 value (float32 0.0) maximum)) (def (pointInPaddedGroup? (group : SsdGroup) (x : Float32) (y : Float32) @@ -6607,8 +6632,7 @@ " if (width <= 0 || height <= 0) return" " val displayWidth = if (rotationDegrees % 180 == 0) img.width else img.height" " val displayHeight = if (rotationDegrees % 180 == 0) img.height else img.width" - " scale = max(width.toFloat() / displayWidth.toFloat(), height.toFloat() / displayHeight.toFloat())" - " .coerceIn(0.1f, 8f)" + " scale = clampInitialScale(max(width.toFloat() / displayWidth.toFloat(), height.toFloat() / displayHeight.toFloat()))" " val scaledWidth = displayWidth * scale" " offsetX = if (scaledWidth > width) width - scaledWidth else (width - scaledWidth) / 2f" " offsetY = (height - displayHeight * scale) / 2f" @@ -6645,7 +6669,7 @@ " val groupWidth = max(16f, group.bbox[2] - group.bbox[0])" " val groupHeight = max(16f, group.bbox[3] - group.bbox[1])" " val fitScale = min(width.toFloat() / (groupWidth * 2.4f), height.toFloat() / (groupHeight * 2.4f))" - " scale = max(scale, fitScale.coerceIn(1.4f, 6.5f)).coerceIn(0.2f, 8f)" + " scale = clampScale(max(scale, clampGroupFitScale(fitScale)))" " updateMatrix()" " val center = imageToView((group.bbox[0] + group.bbox[2]) / 2f, (group.bbox[1] + group.bbox[3]) / 2f)" " offsetX += width / 2f - center[0]" @@ -6842,7 +6866,7 @@ "" " private fun zoomAt(viewX: Float, viewY: Float, factor: Float) {" " val before = viewToImage(viewX, viewY)" - " scale = (scale * factor).coerceIn(0.2f, 8f)" + " scale = clampScale(scale * factor)" " updateMatrix()" " val after = imageToView(before[0], before[1])" " offsetX += viewX - after[0]" @@ -6859,16 +6883,8 @@ " val displayHeight = if (rotationDegrees % 180 == 0) img.height.toFloat() else img.width.toFloat()" " val scaledWidth = displayWidth * scale" " val scaledHeight = displayHeight * scale" - " offsetX = if (scaledWidth <= width) {" - " (width - scaledWidth) / 2f" - " } else {" - " offsetX.coerceIn(width - scaledWidth, 0f)" - " }" - " offsetY = if (scaledHeight <= height) {" - " (height - scaledHeight) / 2f" - " } else {" - " offsetY.coerceIn(height - scaledHeight, 0f)" - " }" + " offsetX = clampViewportOffset(offsetX, width.toFloat(), scaledWidth)" + " offsetY = clampViewportOffset(offsetY, height.toFloat(), scaledHeight)" " }" "" " private fun viewToImage(x: Float, y: Float): FloatArray {" @@ -6876,8 +6892,8 @@ " inverse.mapPoints(point)" " val img = bitmap" " if (img != null) {" - " point[0] = point[0].coerceIn(0f, img.width.toFloat())" - " point[1] = point[1].coerceIn(0f, img.height.toFloat())" + " point[0] = clampImageCoordinate(point[0], img.width.toFloat())" + " point[1] = clampImageCoordinate(point[1], img.height.toFloat())" " }" " return point" " }"