diff --git a/src/drawer.js b/src/drawer.js index 9e928bb6..bad89a69 100644 --- a/src/drawer.js +++ b/src/drawer.js @@ -267,13 +267,14 @@ $.Drawer.prototype = /** @lends OpenSeadragon.Drawer.prototype */{ }, /** - * Translates from OpenSeadragon viewer rectangle to drawer rectangle. + * Scale from OpenSeadragon viewer rectangle to drawer rectangle + * (ignoring rotation) * @param {OpenSeadragon.Rect} rectangle - The rectangle in viewport coordinate system. * @return {OpenSeadragon.Rect} Rectangle in drawer coordinate system. */ viewportToDrawerRectangle: function(rectangle) { - var topLeft = this.viewport.pixelFromPoint(rectangle.getTopLeft(), true); - var size = this.viewport.deltaPixelsFromPoints(rectangle.getSize(), true); + var topLeft = this.viewport.pixelFromPointNoRotate(rectangle.getTopLeft(), true); + var size = this.viewport.deltaPixelsFromPointsNoRotate(rectangle.getSize(), true); return new $.Rect( topLeft.x * $.pixelDensityRatio, @@ -293,22 +294,14 @@ $.Drawer.prototype = /** @lends OpenSeadragon.Drawer.prototype */{ * @param {Float} [scale=1] - Apply a scale to tile position and size. Defaults to 1. * @param {OpenSeadragon.Point} [translate] A translation vector to offset tile position */ - drawTile: function( tile, drawingHandler, useSketch, scale, translate ) { + drawTile: function(tile, drawingHandler, useSketch, scale, translate) { $.console.assert(tile, '[Drawer.drawTile] tile is required'); $.console.assert(drawingHandler, '[Drawer.drawTile] drawingHandler is required'); - if ( this.useCanvas ) { - var context = this._getContext( useSketch ); + if (this.useCanvas) { + var context = this._getContext(useSketch); scale = scale || 1; - // TODO do this in a more performant way - // specifically, don't save,rotate,restore every time we draw a tile - if( this.viewport.degrees !== 0 ) { - this._offsetForRotation( tile, this.viewport.degrees, useSketch ); - tile.drawCanvas( context, drawingHandler, scale, translate ); - this._restoreRotationChanges( tile, useSketch ); - } else { - tile.drawCanvas( context, drawingHandler, scale, translate ); - } + tile.drawCanvas(context, drawingHandler, scale, translate); } else { tile.drawHTML( this.canvas ); } @@ -418,7 +411,7 @@ $.Drawer.prototype = /** @lends OpenSeadragon.Drawer.prototype */{ context.fillStyle = this.debugGridColor; if ( this.viewport.degrees !== 0 ) { - this._offsetForRotation( tile, this.viewport.degrees ); + this._offsetForRotation(this.viewport.degrees); } context.strokeRect( @@ -480,7 +473,7 @@ $.Drawer.prototype = /** @lends OpenSeadragon.Drawer.prototype */{ ); if ( this.viewport.degrees !== 0 ) { - this._restoreRotationChanges( tile ); + this._restoreRotationChanges(); } context.restore(); }, @@ -506,21 +499,21 @@ $.Drawer.prototype = /** @lends OpenSeadragon.Drawer.prototype */{ }, // private - _offsetForRotation: function( tile, degrees, useSketch ){ - var cx = this.canvas.width / 2, - cy = this.canvas.height / 2; + _offsetForRotation: function(degrees, useSketch) { + var cx = this.canvas.width / 2; + var cy = this.canvas.height / 2; - var context = this._getContext( useSketch ); + var context = this._getContext(useSketch); context.save(); context.translate(cx, cy); - context.rotate( Math.PI / 180 * degrees); + context.rotate(Math.PI / 180 * degrees); context.translate(-cx, -cy); }, // private - _restoreRotationChanges: function( tile, useSketch ){ - var context = this._getContext( useSketch ); + _restoreRotationChanges: function(useSketch) { + var context = this._getContext(useSketch); context.restore(); }, diff --git a/src/navigator.js b/src/navigator.js index 40cfa64e..2bd80f44 100644 --- a/src/navigator.js +++ b/src/navigator.js @@ -301,8 +301,8 @@ $.extend( $.Navigator.prototype, $.EventSource.prototype, $.Viewer.prototype, /* if( viewport && this.viewport ) { bounds = viewport.getBounds( true ); - topleft = this.viewport.pixelFromPoint( bounds.getTopLeft(), false ); - bottomright = this.viewport.pixelFromPoint( bounds.getBottomRight(), false ) + topleft = this.viewport.pixelFromPointNoRotate(bounds.getTopLeft(), false); + bottomright = this.viewport.pixelFromPointNoRotate(bounds.getBottomRight(), false) .minus( this.totalBorderWidths ); //update style for navigator-box diff --git a/src/point.js b/src/point.js index 1ceef296..ebddfffe 100644 --- a/src/point.js +++ b/src/point.js @@ -179,14 +179,46 @@ $.Point.prototype = /** @lends OpenSeadragon.Point.prototype */{ * From http://stackoverflow.com/questions/4465931/rotate-rectangle-around-a-point * @function * @param {Number} degress to rotate around the pivot. - * @param {OpenSeadragon.Point} pivot Point about which to rotate. + * @param {OpenSeadragon.Point} [pivot=(0,0)] Point around which to rotate. + * Defaults to the origin. * @returns {OpenSeadragon.Point}. A new point representing the point rotated around the specified pivot */ - rotate: function ( degrees, pivot ) { - var angle = degrees * Math.PI / 180.0, - x = Math.cos( angle ) * ( this.x - pivot.x ) - Math.sin( angle ) * ( this.y - pivot.y ) + pivot.x, - y = Math.sin( angle ) * ( this.x - pivot.x ) + Math.cos( angle ) * ( this.y - pivot.y ) + pivot.y; - return new $.Point( x, y ); + rotate: function (degrees, pivot) { + pivot = pivot || new $.Point(0, 0); + var cos; + var sin; + // Avoid float computations when possible + if (degrees % 90 === 0) { + var d = degrees % 360; + if (d < 0) { + d += 360; + } + switch (d) { + case 0: + cos = 1; + sin = 0; + break; + case 90: + cos = 0; + sin = 1; + break; + case 180: + cos = -1; + sin = 0; + break; + case 270: + cos = 0; + sin = -1; + break; + } + } else { + var angle = degrees * Math.PI / 180.0; + cos = Math.cos(angle); + sin = Math.sin(angle); + } + var x = cos * (this.x - pivot.x) - sin * (this.y - pivot.y) + pivot.x; + var y = sin * (this.x - pivot.x) + cos * (this.y - pivot.y) + pivot.y; + return new $.Point(x, y); }, /** diff --git a/src/rectangle.js b/src/rectangle.js index 35544cdf..2cfd4060 100644 --- a/src/rectangle.js +++ b/src/rectangle.js @@ -351,7 +351,7 @@ $.Rect.prototype = /** @lends OpenSeadragon.Rect.prototype */{ (Math.round(this.y * 100) / 100) + "," + (Math.round(this.width * 100) / 100) + "x" + (Math.round(this.height * 100) / 100) + "," + - (Math.round(this.degrees * 100) / 100) + "°" + + (Math.round(this.degrees * 100) / 100) + "deg" + "]"; } }; diff --git a/src/tiledimage.js b/src/tiledimage.js index b7b85995..bf61a7de 100644 --- a/src/tiledimage.js +++ b/src/tiledimage.js @@ -357,23 +357,23 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag * @return {OpenSeadragon.Rect} A rect representing the coordinates in the viewport. */ imageToViewportRectangle: function( imageX, imageY, pixelWidth, pixelHeight, current ) { - if (imageX instanceof $.Rect) { + var rect = imageX; + if (rect instanceof $.Rect) { //they passed a rect instead of individual components current = imageY; - pixelWidth = imageX.width; - pixelHeight = imageX.height; - imageY = imageX.y; - imageX = imageX.x; + } else { + rect = new $.Rect(imageX, imageY, pixelWidth, pixelHeight); } - var coordA = this.imageToViewportCoordinates(imageX, imageY, current); - var coordB = this._imageToViewportDelta(pixelWidth, pixelHeight, current); + var coordA = this.imageToViewportCoordinates(rect.getTopLeft(), current); + var coordB = this._imageToViewportDelta(rect.width, rect.height, current); return new $.Rect( coordA.x, coordA.y, coordB.x, - coordB.y + coordB.y, + rect.degrees ); }, @@ -389,23 +389,23 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag * @return {OpenSeadragon.Rect} A rect representing the coordinates in the image. */ viewportToImageRectangle: function( viewerX, viewerY, pointWidth, pointHeight, current ) { + var rect = viewerX; if (viewerX instanceof $.Rect) { //they passed a rect instead of individual components current = viewerY; - pointWidth = viewerX.width; - pointHeight = viewerX.height; - viewerY = viewerX.y; - viewerX = viewerX.x; + } else { + rect = new $.Rect(viewerX, viewerY, pointWidth, pointHeight); } - var coordA = this.viewportToImageCoordinates(viewerX, viewerY, current); - var coordB = this._viewportToImageDelta(pointWidth, pointHeight, current); + var coordA = this.viewportToImageCoordinates(rect.getTopLeft(), current); + var coordB = this._viewportToImageDelta(rect.width, rect.height, current); return new $.Rect( coordA.x, coordA.y, coordB.x, - coordB.y + coordB.y, + rect.degrees ); }, @@ -652,7 +652,7 @@ function updateViewport( tiledImage ) { haveDrawn = false, currentTime = $.now(), viewportBounds = tiledImage.viewport.getBoundsWithMargins( true ), - zeroRatioC = tiledImage.viewport.deltaPixelsFromPoints( + zeroRatioC = tiledImage.viewport.deltaPixelsFromPointsNoRotate( tiledImage.source.getPixelRatio( 0 ), true ).x * tiledImage._scaleSpring.current.value, @@ -733,7 +733,7 @@ function updateViewport( tiledImage ) { drawLevel = false; //Avoid calculations for draw if we have already drawn this - renderPixelRatioC = tiledImage.viewport.deltaPixelsFromPoints( + renderPixelRatioC = tiledImage.viewport.deltaPixelsFromPointsNoRotate( tiledImage.source.getPixelRatio( level ), true ).x * tiledImage._scaleSpring.current.value; @@ -747,12 +747,12 @@ function updateViewport( tiledImage ) { } //Perform calculations for draw if we haven't drawn this - renderPixelRatioT = tiledImage.viewport.deltaPixelsFromPoints( + renderPixelRatioT = tiledImage.viewport.deltaPixelsFromPointsNoRotate( tiledImage.source.getPixelRatio( level ), false ).x * tiledImage._scaleSpring.current.value; - zeroRatioT = tiledImage.viewport.deltaPixelsFromPoints( + zeroRatioT = tiledImage.viewport.deltaPixelsFromPointsNoRotate( tiledImage.source.getPixelRatio( Math.max( tiledImage.source.getClosestLevel( tiledImage.viewport.containerSize ) - 1, @@ -1050,12 +1050,12 @@ function onTileLoad( tiledImage, tile, time, image, errorMsg ) { * @property {string} message - The error message. */ tiledImage.viewer.raiseEvent("tile-load-failed", {tile: tile, tiledImage: tiledImage, time: time, message: errorMsg}); - if( !tiledImage.debugMode ){ - tile.loading = false; - tile.exists = false; - return; - } - } else if ( time < tiledImage.lastResetTime ) { + tile.loading = false; + tile.exists = false; + return; + } + + if ( time < tiledImage.lastResetTime ) { $.console.log( "Ignoring tile %s loaded before reset: %s", tile, tile.url ); tile.loading = false; return; @@ -1140,10 +1140,10 @@ function positionTile( tile, overlap, viewport, viewportCenter, levelVisibility, boundsSize.x *= tiledImage._scaleSpring.current.value; boundsSize.y *= tiledImage._scaleSpring.current.value; - var positionC = viewport.pixelFromPoint( boundsTL, true ), - positionT = viewport.pixelFromPoint( boundsTL, false ), - sizeC = viewport.deltaPixelsFromPoints( boundsSize, true ), - sizeT = viewport.deltaPixelsFromPoints( boundsSize, false ), + var positionC = viewport.pixelFromPointNoRotate(boundsTL, true), + positionT = viewport.pixelFromPointNoRotate(boundsTL, false), + sizeC = viewport.deltaPixelsFromPointsNoRotate(boundsSize, true), + sizeT = viewport.deltaPixelsFromPointsNoRotate(boundsSize, false), tileCenter = positionT.plus( sizeT.divide( 2 ) ), tileDistance = viewportCenter.distanceTo( tileCenter ); @@ -1331,6 +1331,10 @@ function drawTiles( tiledImage, lastDrawn ) { tiledImage._drawer._clear( true ); } + if (tiledImage.viewport.degrees !== 0) { + tiledImage._drawer._offsetForRotation(tiledImage.viewport.degrees, useSketch); + } + var usedClip = false; if ( tiledImage._clip ) { tiledImage._drawer.saveContext(useSketch); @@ -1396,6 +1400,10 @@ function drawTiles( tiledImage, lastDrawn ) { tiledImage._drawer.restoreContext( useSketch ); } + if (tiledImage.viewport.degrees !== 0) { + tiledImage._drawer._restoreRotationChanges(useSketch); + } + if ( useSketch ) { tiledImage._drawer.blendSketch( tiledImage.opacity, sketchScale, sketchTranslate ); } diff --git a/src/viewport.js b/src/viewport.js index b69ccbcb..63493371 100644 --- a/src/viewport.js +++ b/src/viewport.js @@ -704,7 +704,6 @@ $.Viewport.prototype = /** @lends OpenSeadragon.Viewport.prototype */{ this.centerSpringX.target.value, this.centerSpringY.target.value ); - delta = delta.rotate( -this.degrees, new $.Point( 0, 0 ) ); return this.panTo( center.plus( delta ), immediately ); }, @@ -750,14 +749,9 @@ $.Viewport.prototype = /** @lends OpenSeadragon.Viewport.prototype */{ * @return {OpenSeadragon.Viewport} Chainable. * @fires OpenSeadragon.Viewer.event:zoom */ - zoomBy: function( factor, refPoint, immediately ) { - if( refPoint instanceof $.Point && !isNaN( refPoint.x ) && !isNaN( refPoint.y ) ) { - refPoint = refPoint.rotate( - -this.degrees, - new $.Point( this.centerSpringX.target.value, this.centerSpringY.target.value ) - ); - } - return this.zoomTo( this.zoomSpring.target.value * factor, refPoint, immediately ); + zoomBy: function(factor, refPoint, immediately) { + return this.zoomTo( + this.zoomSpring.target.value * factor, refPoint, immediately); }, /** @@ -936,40 +930,89 @@ $.Viewport.prototype = /** @lends OpenSeadragon.Viewport.prototype */{ return changed; }, - /** - * Convert a delta (translation vector) from pixels coordinates to viewport coordinates - * @function - * @param {Boolean} current - Pass true for the current location; defaults to false (target location). + * Convert a delta (translation vector) from viewport coordinates to pixels + * coordinates. This method does not take rotation into account. + * Consider using deltaPixelsFromPoints if you need to account for rotation. + * @param {OpenSeadragon.Point} deltaPoints - The translation vector to convert. + * @param {Boolean} [current=false] - Pass true for the current location; + * defaults to false (target location). + * @returns {OpenSeadragon.Point} */ - deltaPixelsFromPoints: function( deltaPoints, current ) { + deltaPixelsFromPointsNoRotate: function(deltaPoints, current) { return deltaPoints.times( - this._containerInnerSize.x * this.getZoom( current ) + this._containerInnerSize.x * this.getZoom(current) ); }, /** - * Convert a delta (translation vector) from viewport coordinates to pixels coordinates. - * @function - * @param {Boolean} current - Pass true for the current location; defaults to false (target location). + * Convert a delta (translation vector) from viewport coordinates to pixels + * coordinates. + * @param {OpenSeadragon.Point} deltaPoints - The translation vector to convert. + * @param {Boolean} [current=false] - Pass true for the current location; + * defaults to false (target location). + * @returns {OpenSeadragon.Point} */ - deltaPointsFromPixels: function( deltaPixels, current ) { + deltaPixelsFromPoints: function(deltaPoints, current) { + return this.deltaPixelsFromPointsNoRotate( + deltaPoints.rotate(this.getRotation()), + current); + }, + + /** + * Convert a delta (translation vector) from pixels coordinates to viewport + * coordinates. This method does not take rotation into account. + * Consider using deltaPointsFromPixels if you need to account for rotation. + * @param {OpenSeadragon.Point} deltaPixels - The translation vector to convert. + * @param {Boolean} [current=false] - Pass true for the current location; + * defaults to false (target location). + * @returns {OpenSeadragon.Point} + */ + deltaPointsFromPixelsNoRotate: function(deltaPixels, current) { return deltaPixels.divide( - this._containerInnerSize.x * this.getZoom( current ) + this._containerInnerSize.x * this.getZoom(current) ); }, /** - * Convert image pixel coordinates to viewport coordinates. - * @function - * @param {Boolean} current - Pass true for the current location; defaults to false (target location). + * Convert a delta (translation vector) from pixels coordinates to viewport + * coordinates. + * @param {OpenSeadragon.Point} deltaPixels - The translation vector to convert. + * @param {Boolean} [current=false] - Pass true for the current location; + * defaults to false (target location). + * @returns {OpenSeadragon.Point} */ - pixelFromPoint: function( point, current ) { - return this._pixelFromPoint(point, this.getBounds( current )); + deltaPointsFromPixels: function(deltaPixels, current) { + return this.deltaPointsFromPixelsNoRotate(deltaPixels, current) + .rotate(-this.getRotation()); + }, + + /** + * Convert viewport coordinates to pixels coordinates. + * This method does not take rotation into account. + * Consider using pixelFromPoint if you need to account for rotation. + * @param {OpenSeadragon.Point} point the viewport coordinates + * @param {Boolean} [current=false] - Pass true for the current location; + * defaults to false (target location). + * @returns {OpenSeadragon.Point} + */ + pixelFromPointNoRotate: function(point, current) { + return this._pixelFromPointNoRotate(point, this.getBounds(current)); + }, + + /** + * Convert viewport coordinates to pixel coordinates. + * @param {OpenSeadragon.Point} point the viewport coordinates + * @param {Boolean} [current=false] - Pass true for the current location; + * defaults to false (target location). + * @returns {OpenSeadragon.Point} + */ + pixelFromPoint: function(point, current) { + return this._pixelFromPoint(point, this.getBounds(current)); }, // private - _pixelFromPoint: function( point, bounds ) { + _pixelFromPointNoRotate: function(point, bounds) { return point.minus( bounds.getTopLeft() ).times( @@ -979,12 +1022,23 @@ $.Viewport.prototype = /** @lends OpenSeadragon.Viewport.prototype */{ ); }, + // private + _pixelFromPoint: function(point, bounds) { + return this._pixelFromPointNoRotate( + point.rotate(this.getRotation(), this.getCenter(true)), + bounds); + }, + /** - * Convert viewport coordinates to image pixel coordinates. - * @function - * @param {Boolean} current - Pass true for the current location; defaults to false (target location). + * Convert pixel coordinates to viewport coordinates. + * This method does not take rotation into account. + * Consider using pointFromPixel if you need to account for rotation. + * @param {OpenSeadragon.Point} pixel Pixel coordinates + * @param {Boolean} [current=false] - Pass true for the current location; + * defaults to false (target location). + * @returns {OpenSeadragon.Point} */ - pointFromPixel: function( pixel, current ) { + pointFromPixelNoRotate: function(pixel, current) { var bounds = this.getBounds( current ); return pixel.minus( new $.Point(this._margins.left, this._margins.top) @@ -995,6 +1049,20 @@ $.Viewport.prototype = /** @lends OpenSeadragon.Viewport.prototype */{ ); }, + /** + * Convert pixel coordinates to viewport coordinates. + * @param {OpenSeadragon.Point} pixel Pixel coordinates + * @param {Boolean} [current=false] - Pass true for the current location; + * defaults to false (target location). + * @returns {OpenSeadragon.Point} + */ + pointFromPixel: function(pixel, current) { + return this.pointFromPixelNoRotate(pixel, current).rotate( + -this.getRotation(), + this.getCenter(true) + ); + }, + // private _viewportToImageDelta: function( viewerX, viewerY ) { var scale = this.homeBounds.width; @@ -1075,29 +1143,21 @@ $.Viewport.prototype = /** @lends OpenSeadragon.Viewport.prototype */{ * @param {Number} pixelWidth the width in pixel of the rectangle. * @param {Number} pixelHeight the height in pixel of the rectangle. */ - imageToViewportRectangle: function( imageX, imageY, pixelWidth, pixelHeight ) { - var coordA, - coordB, - rect; - if( arguments.length == 1 ) { - //they passed a rectangle instead of individual components - rect = imageX; - return this.imageToViewportRectangle( - rect.x, rect.y, rect.width, rect.height - ); + imageToViewportRectangle: function(imageX, imageY, pixelWidth, pixelHeight) { + var rect = imageX; + if (!(rect instanceof $.Rect)) { + //they passed individual components instead of a rectangle + rect = new $.Rect(imageX, imageY, pixelWidth, pixelHeight); } - coordA = this.imageToViewportCoordinates( - imageX, imageY - ); - coordB = this._imageToViewportDelta( - pixelWidth, pixelHeight - ); + var coordA = this.imageToViewportCoordinates(rect.x, rect.y); + var coordB = this._imageToViewportDelta(rect.width, rect.height); return new $.Rect( coordA.x, coordA.y, coordB.x, - coordB.y + coordB.y, + rect.degrees ); }, @@ -1116,25 +1176,21 @@ $.Viewport.prototype = /** @lends OpenSeadragon.Viewport.prototype */{ * @param {Number} pointWidth the width of the rectangle in viewport coordinate system. * @param {Number} pointHeight the height of the rectangle in viewport coordinate system. */ - viewportToImageRectangle: function( viewerX, viewerY, pointWidth, pointHeight ) { - var coordA, - coordB, - rect; - if ( arguments.length == 1 ) { - //they passed a rectangle instead of individual components - rect = viewerX; - return this.viewportToImageRectangle( - rect.x, rect.y, rect.width, rect.height - ); + viewportToImageRectangle: function(viewerX, viewerY, pointWidth, pointHeight) { + var rect = viewerX; + if (!(rect instanceof $.Rect)) { + //they passed individual components instead of a rectangle + rect = new $.Rect(viewerX, viewerY, pointWidth, pointHeight); } - coordA = this.viewportToImageCoordinates( viewerX, viewerY ); - coordB = this._viewportToImageDelta(pointWidth, pointHeight); + var coordA = this.viewportToImageCoordinates(rect.x, rect.y); + var coordB = this._viewportToImageDelta(rect.width, rect.height); return new $.Rect( coordA.x, coordA.y, coordB.x, - coordB.y + coordB.y, + rect.degrees ); }, diff --git a/test/demo/coordinates.html b/test/demo/coordinates.html index 188e87ee..3cf836dd 100644 --- a/test/demo/coordinates.html +++ b/test/demo/coordinates.html @@ -24,38 +24,55 @@ Window (pixel) Container (pixel) - Image 1 - top left (pixel) - Image 2 - bottom right (pixel) Viewport (point) + Big Image (pixel) + Small Image (pixel) Cursor position - - - - - + + + + + + + + Big Image top left position + + + + + + + + Small Image top left position + + + + + Zoom - - + - + diff --git a/test/modules/units.js b/test/modules/units.js index eada67b8..d4d95b08 100644 --- a/test/modules/units.js +++ b/test/modules/units.js @@ -2,6 +2,7 @@ (function () { var viewer; + var precision = 0.00000001; module('Units', { setup: function () { @@ -26,8 +27,8 @@ function pointEqual(a, b, message) { - Util.assessNumericValue(a.x, b.x, 0.00000001, message); - Util.assessNumericValue(a.y, b.y, 0.00000001, message); + Util.assessNumericValue(a.x, b.x, precision, message); + Util.assessNumericValue(a.y, b.y, precision, message); } // Check that f^-1 ( f(x) ) = x @@ -151,8 +152,6 @@ start(); }); viewer.viewport.zoomTo(0.8).panTo(new OpenSeadragon.Point(0.1, 0.2)); - - start(); }); viewer.open([{ @@ -167,6 +166,68 @@ }); + // --------- + asyncTest('Multiple images coordinates conversion with viewport rotation', function () { + + viewer.addHandler("open", function () { + var viewport = viewer.viewport; + var tiledImage1 = viewer.world.getItemAt(0); + var tiledImage2 = viewer.world.getItemAt(1); + var imageWidth = viewer.source.dimensions.x; + var imageHeight = viewer.source.dimensions.y; + + var viewerWidth = $(viewer.element).width(); + var viewerHeight = $(viewer.element).height(); + var viewerMiddleTop = new OpenSeadragon.Point(viewerWidth / 2, 0); + var viewerMiddleBottom = new OpenSeadragon.Point(viewerWidth / 2, viewerHeight); + + var point0_0 = new OpenSeadragon.Point(0, 0); + var point = viewport.viewerElementToViewportCoordinates(viewerMiddleTop); + pointEqual(point, point0_0, 'When opening, viewer middle top is also viewport 0,0'); + var image1Pixel = tiledImage1.viewerElementToImageCoordinates(viewerMiddleTop); + pointEqual(image1Pixel, point0_0, 'When opening, viewer middle top is also image 1 pixel 0,0'); + var image2Pixel = tiledImage2.viewerElementToImageCoordinates(viewerMiddleTop); + pointEqual(image2Pixel, + new OpenSeadragon.Point(-2 * imageWidth, -2 * imageHeight), + 'When opening, viewer middle top is also image 2 pixel -2*imageWidth, -2*imageHeight'); + + point = viewport.viewerElementToViewportCoordinates(viewerMiddleBottom); + pointEqual(point, new OpenSeadragon.Point(1.5, 1.5), + 'Viewer middle bottom has viewport coordinates 1.5,1.5.'); + image1Pixel = tiledImage1.viewerElementToImageCoordinates(viewerMiddleBottom); + pointEqual(image1Pixel, + new OpenSeadragon.Point(imageWidth * 1.5, imageHeight * 1.5), + 'Viewer middle bottom has image 1 pixel coordinates imageWidth * 1.5, imageHeight * 1.5'); + image2Pixel = tiledImage2.viewerElementToImageCoordinates(viewerMiddleBottom); + pointEqual(image2Pixel, + new OpenSeadragon.Point(imageWidth, imageHeight), + 'Viewer middle bottom has image 2 pixel coordinates imageWidth,imageHeight.'); + + + checkPoint(' after opening'); + viewer.addHandler('animation-finish', function animationHandler() { + viewer.removeHandler('animation-finish', animationHandler); + checkPoint(' after zoom and pan'); + + //Restore rotation + viewer.viewport.setRotation(0); + start(); + }); + viewer.viewport.zoomTo(0.8).panTo(new OpenSeadragon.Point(0.1, 0.2)); + }); + + viewer.viewport.setRotation(45); + viewer.open([{ + tileSource: "/test/data/testpattern.dzi" + }, { + tileSource: "/test/data/testpattern.dzi", + x: 1, + y: 1, + width: 0.5 + } + ]); + }); + // ---------- asyncTest('ZoomRatio 1 image', function () { viewer.addHandler("open", function () { @@ -188,10 +249,10 @@ var expectedViewportZoom = viewport.getZoom(true); var actualImageZoom = viewport.viewportToImageZoom( expectedViewportZoom); - equal(actualImageZoom, expectedImageZoom); + Util.assessNumericValue(actualImageZoom, expectedImageZoom, precision); var actualViewportZoom = viewport.imageToViewportZoom(actualImageZoom); - equal(actualViewportZoom, expectedViewportZoom); + Util.assessNumericValue(actualViewportZoom, expectedViewportZoom, precision); } checkZoom(); @@ -234,11 +295,11 @@ var actualImageZoom = image.viewportToImageZoom( expectedViewportZoom); Util.assessNumericValue(actualImageZoom, expectedImageZoom, - 0.00000001); + precision); var actualViewportImage1Zoom = image.imageToViewportZoom(actualImageZoom); Util.assessNumericValue( - actualViewportImage1Zoom, expectedViewportZoom, 0.00000001); + actualViewportImage1Zoom, expectedViewportZoom, precision); } checkZoom(image1);