cropExtents: be robust to negative upper-left corner coordinates

This change fixes a bug that surfaces when an extent has been moved
partially "off screen." This can happen if an extent is translated so
that its left or top edges are outside of the rendered image. Prior to
this change, such extents would get cropped so that their upper-left
corners were always clamped to (0,0). This was wrong because it
fundamentally broke the extents' coorinate system. This change not only
preserves upper-left corner coordinates but also updates the width and
height calculations in extent-cropping to ensure that the new width and
height values still reflect the true "width" and "height" of an extent
even if some of that width or height is not visible in a rendered image.
This is essential for ensuring that mouse click detection works as
needed to translate screen-space coordinates of mouse clicks into local
(extent) coordinates for extent-matching purposes.
This commit is contained in:
Jonathan Daugherty 2022-03-31 21:58:45 -07:00
parent ec2f45f07e
commit 96f06bdfb4

View File

@ -99,25 +99,21 @@ cropExtents ctx es = catMaybes $ cropExtent <$> es
--
-- If its entirety is outside the context region, it is dropped.
--
-- Otherwise its size and upper left corner are adjusted so that
-- they are contained within the context region.
-- Otherwise its size is adjusted so that it is contained within
-- the context region.
cropExtent (Extent n (Location (c, r)) (w, h)) =
-- First, clamp the upper-left corner to at least (0, 0).
let c' = max c 0
r' = max r 0
-- Then, determine the new lower-right corner based on
-- the clamped corner.
endCol = c' + w
endRow = r' + h
-- Determine the new lower-right corner
let endCol = c + w
endRow = r + h
-- Then clamp the lower-right corner based on the
-- context
endCol' = min (ctx^.availWidthL) endCol
endRow' = min (ctx^.availHeightL) endRow
-- Then compute the new width and height from the
-- clamped lower-right corner.
w' = endCol' - c'
h' = endRow' - r'
e = Extent n (Location (c', r')) (w', h')
w' = endCol' - c
h' = endRow' - r
e = Extent n (Location (c, r)) (w', h')
in if w' < 0 || h' < 0
then Nothing
else Just e