diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 9fd92dd0f..9973ccb53 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -10,6 +10,7 @@ * `rugnux` writes the unmerged MTZ by default, and a P1 merge beside it, so a wrong space group can be re-merged without reprocessing. * Significant improvements to symmetry handling in `rugnux`: the lattice, the point group, the setting and the systematic absences. * The `rugnux` report gives the resolution the CC1/2 fit reached, beside the range the reflections were written to. +* The `jfjoch_viewer` grid scan view draws the cells in the proportion of the scan steps, so the map has the shape of the scanned area. ### 1.0.0-rc.165 This is an UNSTABLE release. It includes many experimental features, as well as many AI generated fixes. We recommend using rc.152 for production use. diff --git a/viewer/image_viewer/JFJochGridScanImage.cpp b/viewer/image_viewer/JFJochGridScanImage.cpp index c4bfc1bda..ea6601f90 100644 --- a/viewer/image_viewer/JFJochGridScanImage.cpp +++ b/viewer/image_viewer/JFJochGridScanImage.cpp @@ -25,6 +25,9 @@ void JFJochGridScanImage::loadData(const std::vector &data, const GridSca W = settings.GetGridSizeX_step(); H = settings.GetGridSizeY_step(); + // Draw a cell in the proportion of the area it covers, so a scan with a coarse x step and a + // fine y step looks like the sample region it was taken over, not like a square grid. + pixel_aspect_ = std::fabs(settings.GetGridStepY_um() / settings.GetGridStepX_um()); image_fp = settings.Rearrange(data, NAN); std::vector indices(image_fp.size()); diff --git a/viewer/image_viewer/JFJochImage.cpp b/viewer/image_viewer/JFJochImage.cpp index 39e4c21ad..72941a010 100644 --- a/viewer/image_viewer/JFJochImage.cpp +++ b/viewer/image_viewer/JFJochImage.cpp @@ -954,7 +954,7 @@ void JFJochImage::fitToView() { } void JFJochImage::fitToViewShorterSideOnce() { - if (initial_fit_done_ && prev_H == H && prev_W == W) + if (initial_fit_done_ && prev_H == H && prev_W == W && prev_aspect_ == pixel_aspect_) return; @@ -963,6 +963,7 @@ void JFJochImage::fitToViewShorterSideOnce() { prev_H = H; prev_W = W; + prev_aspect_ = pixel_aspect_; // Guard against tiny or zero viewport (happens before layout settles) const QSize vp = viewport()->size(); @@ -976,7 +977,11 @@ void JFJochImage::fitToViewShorterSideOnce() { setTransformationAnchor(QGraphicsView::AnchorViewCenter); setTransform(QTransform()); - fitInView(QRectF(0, 0, static_cast(W), static_cast(H)), Qt::KeepAspectRatio); + // Non-square pixels are fitted as if the image were as tall as they draw it, and the extra + // height is then put back into the transform: the image still fits, and the uniform zooms + // that follow keep the proportion. + fitInView(QRectF(0, 0, static_cast(W), static_cast(H) * pixel_aspect_), Qt::KeepAspectRatio); + scale(1.0, pixel_aspect_); scale_factor = transform().m11(); centerOn(QPointF(static_cast(W) * 0.5, static_cast(H) * 0.5)); @@ -998,7 +1003,7 @@ void JFJochImage::setZoom(double input) { scale_factor = input; if (!scene()) return; - setTransform(QTransform::fromScale(input, input)); + setTransform(QTransform::fromScale(input, input * pixel_aspect_)); updateOverlay(); emitViewportChanged(); } diff --git a/viewer/image_viewer/JFJochImage.h b/viewer/image_viewer/JFJochImage.h index b8cb6ea67..afeb7a92c 100644 --- a/viewer/image_viewer/JFJochImage.h +++ b/viewer/image_viewer/JFJochImage.h @@ -109,6 +109,13 @@ protected: size_t W = 0, H = 0; size_t prev_W = 0, prev_H = 0; + // Height of one pixel as it is drawn, in units of its width. 1.0 for a detector image, where + // pixels are square; a grid scan whose x and y steps differ sets it so that a cell is drawn + // in the proportion of the area it covers. Only the view transform is anisotropic - scene + // coordinates stay one unit per pixel everywhere. + qreal pixel_aspect_ = 1.0; + qreal prev_aspect_ = 1.0; + // Track initial fit state and last image size bool initial_fit_done_ = false;