diff --git a/src/overlay.js b/src/overlay.js index d104e8cd..7465d573 100644 --- a/src/overlay.js +++ b/src/overlay.js @@ -417,7 +417,7 @@ * @returns {OpenSeadragon.Rect} overlay bounds */ getBounds: function(viewport) { - $.console.assert(!viewport, 'Calling Overlay.getBounds withouth ' + + $.console.assert(viewport, 'Calling Overlay.getBounds withouth ' + 'specifying a viewport is deprecated.'); var width = this.width; var height = this.height; @@ -442,11 +442,22 @@ this.rotationMode === $.OverlayRotationMode.EXACT) { return bounds; } - // If overlay not fully scalable, BOUNDING_BOX falls back to EXACT - if (this.rotationMode === $.OverlayRotationMode.BOUNDING_BOX && - (this.width === null || this.height === null)) { - return bounds; + if (this.rotationMode === $.OverlayRotationMode.BOUNDING_BOX) { + // If overlay not fully scalable, BOUNDING_BOX falls back to EXACT + if (this.width === null || this.height === null) { + return bounds; + } + // It is easier to just compute the position and size and + // convert to viewport coordinates. + var positionAndSize = this._getOverlayPositionAndSize(viewport); + return viewport.viewerElementToViewportRectangle(new $.Rect( + positionAndSize.position.x, + positionAndSize.position.y, + positionAndSize.size.x, + positionAndSize.size.y)); } + + // NO_ROTATION case return bounds.rotate(-viewport.degrees, this._getPlacementPoint(bounds)); } diff --git a/src/viewport.js b/src/viewport.js index 821d8075..13841da7 100644 --- a/src/viewport.js +++ b/src/viewport.js @@ -1262,6 +1262,20 @@ $.Viewport.prototype = { return this.pixelFromPoint( point, true ); }, + /** + * Convert a rectangle in pixel coordinates relative to the viewer element + * to viewport coordinates. + * @param {OpenSeadragon.Rect} rectangle the rectangle to convert + * @returns {OpenSeadragon.Rect} the converted rectangle + */ + viewerElementToViewportRectangle: function(rectangle) { + return $.Rect.fromSummits( + this.pointFromPixel(rectangle.getTopLeft(), true), + this.pointFromPixel(rectangle.getTopRight(), true), + this.pointFromPixel(rectangle.getBottomLeft(), true) + ); + }, + /** * Convert a rectangle in viewport coordinates to pixel coordinates relative * to the viewer element. diff --git a/test/modules/overlays.js b/test/modules/overlays.js index 0183d61f..49eb0c4f 100644 --- a/test/modules/overlays.js +++ b/test/modules/overlays.js @@ -982,4 +982,63 @@ start(); }); }); + + // ---------- + asyncTest('Fully scaled overlay rotation mode BOUNDING_BOX', function() { + viewer = OpenSeadragon({ + id: 'example-overlays', + prefixUrl: '/build/openseadragon/images/', + tileSources: '/test/data/testpattern.dzi', + springStiffness: 100, // Faster animation = faster tests + degrees: 45, + overlays: [{ + id: "fully-scaled-overlay", + x: 1, + y: 1, + width: 1, + height: 1, + placement: OpenSeadragon.Placement.BOTTOM_RIGHT, + rotationMode: OpenSeadragon.OverlayRotationMode.BOUNDING_BOX + }] + }); + + viewer.addOnceHandler('open', function() { + var viewport = viewer.viewport; + + var $overlay = $("#fully-scaled-overlay"); + var expectedRect = viewport.viewportToViewerElementRectangle( + new OpenSeadragon.Rect(0, 0, 1, 1)).getBoundingBox(); + var actualPosition = $overlay.position(); + Util.assessNumericValue(actualPosition.left, expectedRect.x, epsilon, + "Scaled overlay position.x should adjust to rotation."); + Util.assessNumericValue(actualPosition.top, expectedRect.y, epsilon, + "Scaled overlay position.y should adjust to rotation."); + + var actualWidth = $overlay.width(); + var actualHeight = $overlay.height(); + Util.assessNumericValue(actualWidth, expectedRect.width, epsilon, + "Scaled overlay width should not adjust to rotation."); + Util.assessNumericValue(actualHeight, expectedRect.height, epsilon, + "Scaled overlay height should not adjust to rotation."); + + var actualBounds = viewer.getOverlayById("fully-scaled-overlay") + .getBounds(viewport); + var expectedBounds = new OpenSeadragon.Rect( + 0.5, -0.5, Math.sqrt(2), Math.sqrt(2), 45); + var boundsEpsilon = 0.000001; + Util.assessNumericValue(actualBounds.x, expectedBounds.x, boundsEpsilon, + "The fully scaled overlay should have adjusted bounds.x"); + Util.assessNumericValue(actualBounds.y, expectedBounds.y, boundsEpsilon, + "The fully scaled overlay should have adjusted bounds.y"); + Util.assessNumericValue(actualBounds.width, expectedBounds.width, boundsEpsilon, + "The fully scaled overlay should have adjusted bounds.width"); + Util.assessNumericValue(actualBounds.height, expectedBounds.height, boundsEpsilon, + "The fully scaled overlay should have adjusted bounds.height"); + Util.assessNumericValue(actualBounds.degrees, expectedBounds.degrees, boundsEpsilon, + "The fully scaled overlay should have adjusted bounds.degrees"); + + start(); + }); + }); + })();