Merge pull request #662 from avandecreme/coordinates

Add coordinates conversion methods to TiledImage.
This commit is contained in:
Ian Gilman 2015-06-19 13:13:12 -07:00
commit 6ffc81760c
3 changed files with 296 additions and 50 deletions

View File

@ -406,6 +406,83 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag
); );
}, },
/**
* Convert pixel coordinates relative to the viewer element to image
* coordinates.
* @param {OpenSeadragon.Point} pixel
* @returns {OpenSeadragon.Point}
*/
viewerElementToImageCoordinates: function( pixel ) {
var point = this.viewport.pointFromPixel( pixel, true );
return this.viewportToImageCoordinates( point );
},
/**
* Convert pixel coordinates relative to the image to
* viewer element coordinates.
* @param {OpenSeadragon.Point} pixel
* @returns {OpenSeadragon.Point}
*/
imageToViewerElementCoordinates: function( pixel ) {
var point = this.imageToViewportCoordinates( pixel );
return this.viewport.pixelFromPoint( point, true );
},
/**
* Convert pixel coordinates relative to the window to image coordinates.
* @param {OpenSeadragon.Point} pixel
* @returns {OpenSeadragon.Point}
*/
windowToImageCoordinates: function( pixel ) {
var viewerCoordinates = pixel.minus(
OpenSeadragon.getElementPosition( this.viewer.element ));
return this.viewerElementToImageCoordinates( viewerCoordinates );
},
/**
* Convert image coordinates to pixel coordinates relative to the window.
* @param {OpenSeadragon.Point} pixel
* @returns {OpenSeadragon.Point}
*/
imageToWindowCoordinates: function( pixel ) {
var viewerCoordinates = this.imageToViewerElementCoordinates( pixel );
return viewerCoordinates.plus(
OpenSeadragon.getElementPosition( this.viewer.element ));
},
/**
* Convert a viewport zoom to an image zoom.
* Image zoom: ratio of the original image size to displayed image size.
* 1 means original image size, 0.5 half size...
* Viewport zoom: ratio of the displayed image's width to viewport's width.
* 1 means identical width, 2 means image's width is twice the viewport's width...
* @function
* @param {Number} viewportZoom The viewport zoom
* @returns {Number} imageZoom The image zoom
*/
viewportToImageZoom: function( viewportZoom ) {
var ratio = this._scaleSpring.current.value *
this.viewport._containerInnerSize.x / this.source.dimensions.x;
return ratio * viewportZoom ;
},
/**
* Convert an image zoom to a viewport zoom.
* Image zoom: ratio of the original image size to displayed image size.
* 1 means original image size, 0.5 half size...
* Viewport zoom: ratio of the displayed image's width to viewport's width.
* 1 means identical width, 2 means image's width is twice the viewport's width...
* Note: not accurate with multi-image.
* @function
* @param {Number} imageZoom The image zoom
* @returns {Number} viewportZoom The viewport zoom
*/
imageToViewportZoom: function( imageZoom ) {
var ratio = this._scaleSpring.current.value *
this.viewport._containerInnerSize.x / this.source.dimensions.x;
return imageZoom / ratio;
},
/** /**
* Sets the TiledImage's position in the world. * Sets the TiledImage's position in the world.
* @param {OpenSeadragon.Point} position - The new position, in viewport coordinates. * @param {OpenSeadragon.Point} position - The new position, in viewport coordinates.

View File

@ -1,21 +1,21 @@
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<head> <head>
<title>OpenSeadragon Basic Demo</title> <title>OpenSeadragon Coordinates Demo</title>
<script type="text/javascript" src='../../build/openseadragon/openseadragon.js'></script> <script type="text/javascript" src='../../build/openseadragon/openseadragon.js'></script>
<script type="text/javascript" src='../lib/jquery-1.9.1.min.js'></script> <script type="text/javascript" src='../lib/jquery-1.9.1.min.js'></script>
<style type="text/css"> <style type="text/css">
.openseadragon1 { .openseadragon1 {
width: 800px; width: 800px;
height: 600px; height: 600px;
} }
</style> </style>
</head> </head>
<body> <body>
<div> <div>
Simple demo page to show a default OpenSeadragon viewer. Simple demo page to show OpenSeadragon coordinates system.
</div> </div>
<div id="contentDiv" class="openseadragon1"></div> <div id="contentDiv" class="openseadragon1"></div>
<div> <div>
@ -24,16 +24,26 @@
<th></th> <th></th>
<th>Window (pixel)</th> <th>Window (pixel)</th>
<th>Container (pixel)</th> <th>Container (pixel)</th>
<th>Image (pixel)</th> <th>Image 1 - top left (pixel)</th>
<th>Image 2 - bottom right (pixel)</th>
<th>Viewport (point)</th> <th>Viewport (point)</th>
</tr> </tr>
<tr> <tr>
<th>Cursor position</th> <th>Cursor position</th>
<td id="windowPosition"></td> <td id="windowPosition"></td>
<td id="containerPosition"></td> <td id="containerPosition"></td>
<td id="imagePosition"></td> <td id="image1Position"></td>
<td id="image2Position"></td>
<td id="viewportPosition"></td> <td id="viewportPosition"></td>
</tr>
<tr> <tr>
<th>Zoom</th>
<td>-</td>
<td>-</td>
<td id="image1Zoom"></td>
<td id="image2Zoom"></td>
<td id="viewportZoom"></td>
</tr>
</table> </table>
</div> </div>
<script type="text/javascript"> <script type="text/javascript">
@ -42,36 +52,57 @@
// debugMode: true, // debugMode: true,
id: "contentDiv", id: "contentDiv",
prefixUrl: "../../build/openseadragon/images/", prefixUrl: "../../build/openseadragon/images/",
tileSources: "../data/testpattern.dzi", tileSources: [{
showNavigator:true tileSource: "../data/testpattern.dzi"
},
{
tileSource: "../data/testpattern.dzi",
x: 1,
y: 1,
width: 0.5
}
],
showNavigator: true
}); });
function pointToString(point) { function pointToString(point) {
return point.x.toPrecision(4) + "," + point.y.toPrecision(4); return point.x.toPrecision(4) + "," + point.y.toPrecision(4);
} }
var onMouseTrackerMove = function(event) { var onMouseTrackerMove = function (event) {
var viewerX = event.position.x; var viewerX = event.position.x;
var viewerY = event.position.y; var viewerY = event.position.y;
var windowPoint = new OpenSeadragon.Point(viewerX, viewerY); var windowPoint = new OpenSeadragon.Point(viewerX, viewerY);
$("#windowPosition").text( pointToString(windowPoint)); $("#windowPosition").text(pointToString(windowPoint));
var containerPoint = windowPoint.minus( var containerPoint = windowPoint.minus(
OpenSeadragon.getElementPosition(viewer.element)); OpenSeadragon.getElementPosition(viewer.element));
$("#containerPosition").text( pointToString(containerPoint)); $("#containerPosition").text(pointToString(containerPoint));
var image1 = viewer.world.getItemAt(0);
var imagePoint = viewer.viewport.windowToImageCoordinates(windowPoint); var imagePoint = image1.windowToImageCoordinates(windowPoint);
$("#imagePosition").text( pointToString(imagePoint)); $("#image1Position").text(pointToString(imagePoint));
var image2 = viewer.world.getItemAt(1);
var imagePoint = image2.windowToImageCoordinates(windowPoint);
$("#image2Position").text(pointToString(imagePoint));
var viewportPoint = viewer.viewport.windowToViewportCoordinates(windowPoint); var viewportPoint = viewer.viewport.windowToViewportCoordinates(windowPoint);
$("#viewportPosition").text( pointToString(viewportPoint)); $("#viewportPosition").text(pointToString(viewportPoint));
}; };
mouseTracker = new OpenSeadragon.MouseTracker({ mouseTracker = new OpenSeadragon.MouseTracker({
element: document, element: document,
moveHandler: onMouseTrackerMove moveHandler: onMouseTrackerMove
}).setTracking(true); }).setTracking(true);
function onAnimation() {
var viewportZoom = viewer.viewport.getZoom(true);
$("#viewportZoom").text(viewportZoom.toFixed(3));
var image1 = viewer.world.getItemAt(0);
var image1Zoom = image1.viewportToImageZoom(viewportZoom);
$("#image1Zoom").text(image1Zoom.toFixed(3));
var image2 = viewer.world.getItemAt(1);
var image2Zoom = image2.viewportToImageZoom(viewportZoom);
$("#image2Zoom").text(image2Zoom.toFixed(3));
}
viewer.addHandler("animation", onAnimation);
</script> </script>
</body> </body>
</html> </html>

View File

@ -1,6 +1,6 @@
/* global module, asyncTest, $, ok, equal, notEqual, start, test, Util, testLog */ /* global module, asyncTest, $, ok, equal, notEqual, start, test, Util, testLog */
(function() { (function () {
var viewer; var viewer;
module('Units', { module('Units', {
@ -10,8 +10,8 @@
testLog.reset(); testLog.reset();
viewer = OpenSeadragon({ viewer = OpenSeadragon({
id: 'unitsexample', id: 'unitsexample',
prefixUrl: '/build/openseadragon/images/', prefixUrl: '/build/openseadragon/images/',
springStiffness: 100 // Faster animation = faster tests springStiffness: 100 // Faster animation = faster tests
}); });
}, },
@ -30,38 +30,57 @@
Util.assessNumericValue(a.y, b.y, 0.00000001, message); Util.assessNumericValue(a.y, b.y, 0.00000001, message);
} }
// ---------- // Check that f^-1 ( f(x) ) = x
asyncTest('Coordinates conversions', function() { function checkPoint(context) {
var viewport = viewer.viewport;
function checkPoint(context) { var point = new OpenSeadragon.Point(15, 12);
var viewport = viewer.viewport; var result = viewport.viewerElementToImageCoordinates(
var point = new OpenSeadragon.Point(15, 12);
var result = viewport.viewerElementToImageCoordinates(
viewport.imageToViewerElementCoordinates(point)); viewport.imageToViewerElementCoordinates(point));
pointEqual(result, point, 'viewerElement and image ' + context); pointEqual(result, point, 'viewerElement and image ' + context);
var result = viewport.windowToImageCoordinates( result = viewport.windowToImageCoordinates(
viewport.imageToWindowCoordinates(point)); viewport.imageToWindowCoordinates(point));
pointEqual(result, point, 'window and image ' + context); pointEqual(result, point, 'window and image ' + context);
var result = viewport.viewerElementToViewportCoordinates( result = viewport.viewerElementToViewportCoordinates(
viewport.viewportToViewerElementCoordinates(point)); viewport.viewportToViewerElementCoordinates(point));
pointEqual(result, point, 'viewerElement and viewport ' + context); pointEqual(result, point, 'viewerElement and viewport ' + context);
var result = viewport.windowToViewportCoordinates( result = viewport.windowToViewportCoordinates(
viewport.viewportToWindowCoordinates(point)); viewport.viewportToWindowCoordinates(point));
pointEqual(result, point, 'window and viewport ' + context); pointEqual(result, point, 'window and viewport ' + context);
for (var i = 0; i < viewer.world.getItemCount(); i++) {
var tiledImage = viewer.world.getItemAt(i);
result = tiledImage.viewportToImageCoordinates(
tiledImage.imageToViewportCoordinates(point));
pointEqual(result, point, 'viewport and tiled image ' + i + context);
result = tiledImage.viewerElementToImageCoordinates(
tiledImage.imageToViewerElementCoordinates(point));
pointEqual(result, point, 'viewerElement and tiled image ' + i + context);
result = tiledImage.windowToImageCoordinates(
tiledImage.imageToWindowCoordinates(point));
pointEqual(result, point, 'window and tiled image ' + i + context);
} }
}
// ----------
asyncTest('Single image coordinates conversions', function () {
viewer.addHandler("open", function () { viewer.addHandler("open", function () {
var viewport = viewer.viewport; var viewport = viewer.viewport;
var tiledImage = viewer.world.getItemAt(0);
var point0_0 = new OpenSeadragon.Point(0, 0); var point0_0 = new OpenSeadragon.Point(0, 0);
var point = viewport.viewerElementToViewportCoordinates(point0_0); var point = viewport.viewerElementToViewportCoordinates(point0_0);
pointEqual(point, point0_0, 'When opening, viewer coordinate 0,0 is also point 0,0'); pointEqual(point, point0_0, 'When opening, viewer coordinate 0,0 is also point 0,0');
var pixel = viewport.viewerElementToImageCoordinates(point0_0); var viewportPixel = viewport.viewerElementToImageCoordinates(point0_0);
pointEqual(pixel, point0_0, 'When opening, viewer coordinate 0,0 is also pixel 0,0'); pointEqual(viewportPixel, point0_0, 'When opening, viewer coordinate 0,0 is also viewport pixel 0,0');
var imagePixel = tiledImage.viewerElementToImageCoordinates(point0_0);
pointEqual(imagePixel, point0_0, 'When opening, viewer coordinate 0,0 is also image pixel 0,0');
var viewerWidth = $(viewer.element).width(); var viewerWidth = $(viewer.element).width();
var imageWidth = viewer.source.dimensions.x; var imageWidth = viewer.source.dimensions.x;
@ -69,15 +88,17 @@
var viewerTopRight = new OpenSeadragon.Point(viewerWidth, 0); var viewerTopRight = new OpenSeadragon.Point(viewerWidth, 0);
var imageTopRight = new OpenSeadragon.Point(imageWidth, 0); var imageTopRight = new OpenSeadragon.Point(imageWidth, 0);
var point = viewport.viewerElementToViewportCoordinates(viewerTopRight); point = viewport.viewerElementToViewportCoordinates(viewerTopRight);
pointEqual(point, point1_0, 'Viewer top right has viewport coordinates 1,0.'); pointEqual(point, point1_0, 'Viewer top right has viewport coordinates 1,0.');
var pixel = viewport.viewerElementToImageCoordinates(viewerTopRight); viewportPixel = viewport.viewerElementToImageCoordinates(viewerTopRight);
pointEqual(pixel, imageTopRight, 'Viewer top right has viewport coordinates imageWidth,0.'); pointEqual(viewportPixel, imageTopRight, 'Viewer top right has viewport pixel coordinates imageWidth,0.');
imagePixel = tiledImage.viewerElementToImageCoordinates(viewerTopRight);
pointEqual(imagePixel, imageTopRight, 'Viewer top right has image pixel coordinates imageWidth,0.');
checkPoint('after opening'); checkPoint(' after opening');
viewer.addHandler('animation-finish', function animationHandler() { viewer.addHandler('animation-finish', function animationHandler() {
viewer.removeHandler('animation-finish', animationHandler); viewer.removeHandler('animation-finish', animationHandler);
checkPoint('after zoom and pan'); checkPoint(' after zoom and pan');
start(); start();
}); });
viewer.viewport.zoomTo(0.8).panTo(new OpenSeadragon.Point(0.1, 0.2)); viewer.viewport.zoomTo(0.8).panTo(new OpenSeadragon.Point(0.1, 0.2));
@ -85,19 +106,80 @@
viewer.open('/test/data/testpattern.dzi'); viewer.open('/test/data/testpattern.dzi');
}); });
// ---------
asyncTest('Multiple images coordinates conversion', 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 point0_0 = new OpenSeadragon.Point(0, 0);
var point = viewport.viewerElementToViewportCoordinates(point0_0);
pointEqual(point, point0_0, 'When opening, viewer coordinate 0,0 is also point 0,0');
var image1Pixel = tiledImage1.viewerElementToImageCoordinates(point0_0);
pointEqual(image1Pixel, point0_0, 'When opening, viewer coordinate 0,0 is also image 1 pixel 0,0');
var image2Pixel = tiledImage2.viewerElementToImageCoordinates(point0_0);
pointEqual(image2Pixel,
new OpenSeadragon.Point(-2 * imageWidth, -2 * imageHeight),
'When opening, viewer coordinates 0,0 is also image 2 pixel -2*imageWidth, -2*imageHeight');
var viewerWidth = $(viewer.element).width();
var viewerHeight = $(viewer.element).height();
var viewerBottomRight = new OpenSeadragon.Point(viewerWidth, viewerHeight);
point = viewport.viewerElementToViewportCoordinates(viewerBottomRight);
pointEqual(point, new OpenSeadragon.Point(1.5, 1.5),
'Viewer bottom right has viewport coordinates 1.5,1.5.');
image1Pixel = tiledImage1.viewerElementToImageCoordinates(viewerBottomRight);
pointEqual(image1Pixel,
new OpenSeadragon.Point(imageWidth * 1.5, imageHeight * 1.5),
'Viewer bottom right has image 1 pixel coordinates imageWidth * 1.5, imageHeight * 1.5');
image2Pixel = tiledImage2.viewerElementToImageCoordinates(viewerBottomRight);
pointEqual(image2Pixel,
new OpenSeadragon.Point(imageWidth, imageHeight),
'Viewer bottom right 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');
start();
});
viewer.viewport.zoomTo(0.8).panTo(new OpenSeadragon.Point(0.1, 0.2));
start();
});
viewer.open([{
tileSource: "/test/data/testpattern.dzi"
}, {
tileSource: "/test/data/testpattern.dzi",
x: 1,
y: 1,
width: 0.5
}
]);
});
// ---------- // ----------
asyncTest('ZoomRatio', function() { asyncTest('ZoomRatio 1 image', function () {
viewer.addHandler("open", function () { viewer.addHandler("open", function () {
var viewport = viewer.viewport; var viewport = viewer.viewport;
var imageWidth = 1000; var imageWidth = viewer.source.dimensions.x;
function getCurrentImageWidth() { function getCurrentImageWidth() {
return viewport.viewportToViewerElementCoordinates( return viewport.viewportToViewerElementCoordinates(
new OpenSeadragon.Point(1, 0)).minus( new OpenSeadragon.Point(1, 0)).minus(
viewport.viewportToViewerElementCoordinates( viewport.viewportToViewerElementCoordinates(
new OpenSeadragon.Point(0, 0))).x; new OpenSeadragon.Point(0, 0))).x;
} }
function checkZoom() { function checkZoom() {
@ -105,7 +187,7 @@
var expectedImageZoom = currentImageWidth / imageWidth; var expectedImageZoom = currentImageWidth / imageWidth;
var expectedViewportZoom = viewport.getZoom(true); var expectedViewportZoom = viewport.getZoom(true);
var actualImageZoom = viewport.viewportToImageZoom( var actualImageZoom = viewport.viewportToImageZoom(
expectedViewportZoom); expectedViewportZoom);
equal(actualImageZoom, expectedImageZoom); equal(actualImageZoom, expectedImageZoom);
var actualViewportZoom = viewport.imageToViewportZoom(actualImageZoom); var actualViewportZoom = viewport.imageToViewportZoom(actualImageZoom);
@ -114,7 +196,7 @@
checkZoom(); checkZoom();
var zoomHandler = function() { var zoomHandler = function () {
viewer.removeHandler('animation-finish', zoomHandler); viewer.removeHandler('animation-finish', zoomHandler);
checkZoom(); checkZoom();
start(); start();
@ -127,5 +209,61 @@
viewer.open('/test/data/testpattern.dzi'); viewer.open('/test/data/testpattern.dzi');
}); });
// ----------
asyncTest('ZoomRatio 2 images', function () {
viewer.addHandler("open", function () {
var viewport = viewer.viewport;
var imageWidth = viewer.source.dimensions.x;
var image1 = viewer.world.getItemAt(0);
var image2 = viewer.world.getItemAt(1);
function getCurrentImageWidth(image) {
var bounds = image.getBounds();
return viewport.viewportToViewerElementCoordinates(
bounds.getTopRight()).minus(
viewport.viewportToViewerElementCoordinates(
bounds.getTopLeft())).x;
}
function checkZoom(image) {
var currentImageWidth = getCurrentImageWidth(image);
var expectedImageZoom = currentImageWidth / imageWidth;
var expectedViewportZoom = viewport.getZoom(true);
var actualImageZoom = image.viewportToImageZoom(
expectedViewportZoom);
Util.assessNumericValue(actualImageZoom, expectedImageZoom,
0.00000001);
var actualViewportImage1Zoom = image.imageToViewportZoom(actualImageZoom);
Util.assessNumericValue(
actualViewportImage1Zoom, expectedViewportZoom, 0.00000001);
}
checkZoom(image1);
checkZoom(image2);
var zoomHandler = function () {
viewer.removeHandler('animation-finish', zoomHandler);
checkZoom(image1);
checkZoom(image2);
start();
};
viewer.addHandler('animation-finish', zoomHandler);
viewport.zoomTo(2);
});
viewer.open([{
tileSource: "/test/data/testpattern.dzi"
}, {
tileSource: "/test/data/testpattern.dzi",
x: 1,
y: 1,
width: 0.5
}
]);
});
})(); })();