From 791ecfae7547262934ae324ec80a23af33923358 Mon Sep 17 00:00:00 2001
From: Antoine Vandecreme <ant.vand@gmail.com>
Date: Thu, 3 Oct 2013 17:26:44 -0400
Subject: [PATCH 1/2] Add coordinates conversion methods to viewport.

---
 src/viewport.js      | 106 ++++++++++++++++++++++++++++++++++++++-
 test/demo/basic.html |  44 +++++++++++++++++
 test/test.css        |   4 ++
 test/test.html       |   1 +
 test/units.js        | 115 +++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 269 insertions(+), 1 deletion(-)
 create mode 100644 test/units.js

diff --git a/src/viewport.js b/src/viewport.js
index 691851c4..916c05f5 100644
--- a/src/viewport.js
+++ b/src/viewport.js
@@ -600,7 +600,7 @@ $.Viewport.prototype = {
     /**
      * Gets the current rotation in degrees.
      * @function
-     * @name OpenSeadragon.Viewport.prototype.setRotation
+     * @name OpenSeadragon.Viewport.prototype.getRotation
      * @return {Number} The current rotation in degrees.
      */
     getRotation: function() {
@@ -676,6 +676,7 @@ $.Viewport.prototype = {
 
 
     /**
+     * Convert a delta (translation vector) from image pixels coordinates to viewport coordinates
      * @function
      * @param {Boolean} current - Pass true for the current location; defaults to false (target location).
      */
@@ -686,6 +687,7 @@ $.Viewport.prototype = {
     },
 
     /**
+     * Convert a delta (translation vector) from viewport coordinates to image pixels coordinates.
      * @function
      * @param {Boolean} current - Pass true for the current location; defaults to false (target location).
      */
@@ -696,6 +698,7 @@ $.Viewport.prototype = {
     },
 
     /**
+     * Convert image pixel coordinates to viewport coordinates.
      * @function
      * @param {Boolean} current - Pass true for the current location; defaults to false (target location).
      */
@@ -709,6 +712,7 @@ $.Viewport.prototype = {
     },
 
     /**
+     * Convert viewport coordinates to image pixel coordinates.
      * @function
      * @param {Boolean} current - Pass true for the current location; defaults to false (target location).
      */
@@ -829,6 +833,106 @@ $.Viewport.prototype = {
             coordB.x,
             coordB.y
         );
+    },
+
+    /**
+     * Convert a pixel coordinates relative to the viewer element to image
+     * coordinates.
+     * @param {OpenSeadragon.Point} pixel
+     * @returns {OpenSeadragon.Point}
+     */
+    viewerElementToImageCoordinates: function( pixel ) {
+        var point = this.pointFromPixel( pixel, true );
+        return this.viewportToImageCoordinates( point );
+    },
+
+    /**
+     * Convert a pixel coordinates relative to the image to
+     * viewer element coordinates.
+     * @param {OpenSeadragon.Point} point
+     * @returns {OpenSeadragon.Point}
+     */
+    imageToViewerElementCoordinates: function( point ) {
+        var pixel = this.pixelFromPoint( point, true );
+        return this.imageToViewportCoordinates( pixel );
+    },
+
+    /**
+     * Convert a 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 an 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 pixel coordinates relative to the viewer element to viewport
+     * coordinates.
+     * @param {OpenSeadragon.Point} pixel
+     * @returns {OpenSeadragon.Point}
+     */
+    viewerElementToViewportCoordinates: function( pixel ) {
+        return this.pointFromPixel( pixel, true );
+    },
+
+    /**
+     * Convert viewport coordinates to a pixel coordinates relative to the
+     * viewer element.
+     * @param {OpenSeadragon.Point} point
+     * @returns {OpenSeadragon.Point}
+     */
+    viewportToViewerElementCoordinates: function( point ) {
+        return this.pixelFromPoint( point, true );
+    },
+
+    /**
+     * Convert a pixel coordinates relative to the window to viewport coordinates.
+     * @param {OpenSeadragon.Point} pixel
+     * @returns {OpenSeadragon.Point}
+     */
+    windowToViewportCoordinates: function( pixel ) {
+        var viewerCoordinates = pixel.minus(
+                OpenSeadragon.getElementPosition( this.viewer.element ));
+        return this.viewerElementToViewportCoordinates( viewerCoordinates );
+    },
+
+    /**
+     * Convert viewport coordinates to a pixel coordinates relative to the window.
+     * @param {OpenSeadragon.Point} point
+     * @returns {OpenSeadragon.Point}
+     */
+    viewportToWindowCoordinates: function( point ) {
+        var viewerCoordinates = this.viewportToViewerElementCoordinates( point );
+        return viewerCoordinates.plus(
+                OpenSeadragon.getElementPosition( this.viewer.element ));
+    },
+
+    /**
+     * Get the zoom ratio of the image. 1 means original image size, 0.5 half size...
+     * @function
+     * @param {Boolean} current If true gives the current zoom otherwise gives the
+     * target zoom.
+     * @returns {Number}
+     */
+    getImageZoomRatio: function( current ) {
+        var imageWidth = this.viewer.source.dimensions.x;
+        var containerWidth = this.getContainerSize().x;
+        var zoomToZoomLevelRatio = containerWidth / imageWidth;
+        return this.getZoom( current ) * zoomToZoomLevelRatio;
     }
 };
 
diff --git a/test/demo/basic.html b/test/demo/basic.html
index 19572b86..be8cbb4c 100644
--- a/test/demo/basic.html
+++ b/test/demo/basic.html
@@ -18,6 +18,24 @@
         Simple demo page to show a default OpenSeadragon viewer.
     </div>
     <div id="contentDiv" class="openseadragon1"></div>
+    <div>
+        <table border="1">
+            <tr>
+                <th></th>
+                <th>Window (pixel)</th>
+                <th>Container (pixel)</th>
+                <th>Image (pixel)</th>
+                <th>Viewport (point)</th>
+            </tr>
+            <tr>
+                <th>Cursor position</th>
+                <td id="windowPosition"></td>
+                <td id="containerPosition"></td>
+                <td id="imagePosition"></td>
+                <td id="viewportPosition"></td>
+            <tr>
+        </table>
+    </div>
     <script type="text/javascript">
 
         var viewer = OpenSeadragon({
@@ -28,6 +46,32 @@
             showNavigator:true
         });
 
+        function pointToString(point) {
+            return point.x.toPrecision(4) + "," + point.y.toPrecision(4);
+        }
+
+        var onMouseTrackerMove = function(eventSender, eventData) {
+            var viewerX = eventData.position.x;
+            var viewerY = eventData.position.y;
+            var windowPoint = new OpenSeadragon.Point(viewerX, viewerY);
+            $("#windowPosition").text( pointToString(windowPoint));
+
+            var containerPoint = windowPoint.minus(
+                    OpenSeadragon.getElementPosition(viewer.element));
+            $("#containerPosition").text( pointToString(containerPoint));
+
+            var imagePoint = viewer.viewport.windowToImageCoordinates(windowPoint);
+            $("#imagePosition").text( pointToString(imagePoint));
+
+            var viewportPoint = viewer.viewport.windowToViewportCoordinates(windowPoint);
+            $("#viewportPosition").text( pointToString(viewportPoint));
+        };
+
+        mouseTracker = new OpenSeadragon.MouseTracker({
+            element: document,
+            moveHandler: onMouseTrackerMove
+        }).setTracking(true);
+
     </script>
 </body>
 </html>
diff --git a/test/test.css b/test/test.css
index 3b1617bc..a7693328 100644
--- a/test/test.css
+++ b/test/test.css
@@ -13,3 +13,7 @@
     width: 300px;
 }
 
+#unitsexample {
+    height: 500px;
+    width: 500px;
+}
\ No newline at end of file
diff --git a/test/test.html b/test/test.html
index fe42bec6..3bd6f919 100644
--- a/test/test.html
+++ b/test/test.html
@@ -22,5 +22,6 @@
     <script src="/test/formats.js"></script>
     <script src="/test/utils.js"></script>
     <script src="/test/events.js"></script>
+    <script src="/test/units.js"></script>
 </body>
 </html>
diff --git a/test/units.js b/test/units.js
new file mode 100644
index 00000000..eb2b70ac
--- /dev/null
+++ b/test/units.js
@@ -0,0 +1,115 @@
+/* global module, asyncTest, $, ok, equal, notEqual, start, test, Util, testLog */
+
+(function() {
+    var viewer;
+
+    module('Units', {
+        setup: function () {
+            var example = $('<div id="unitsexample"></div>').appendTo("#qunit-fixture");
+
+            testLog.reset();
+
+            viewer = OpenSeadragon({
+                id:            'unitsexample',
+                prefixUrl:     '/build/openseadragon/images/',
+                springStiffness: 100 // Faster animation = faster tests
+            });
+        },
+        teardown: function () {
+            if (viewer && viewer.close) {
+                viewer.close();
+            }
+
+            viewer = null;
+        }
+    });
+
+
+    function pointEqual(a, b, message) {
+        ok(a.x === b.x && a.y === b.y, message);
+    }
+
+    // ----------
+    asyncTest('Coordinates conversions', function() {
+
+        viewer.addHandler("open", function () {
+            var viewport = viewer.viewport;
+
+            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 pixel = viewport.viewerElementToImageCoordinates(point0_0);
+            pointEqual(pixel, point0_0, 'When opening, viewer coordinate 0,0 is also pixel 0,0');
+
+            var viewerWidth = $(viewer.element).width();
+            var imageWidth = viewer.source.dimensions.x;
+            var point1_0 = new OpenSeadragon.Point(1, 0);
+            var viewerTopRight = new OpenSeadragon.Point(viewerWidth, 0);
+            var imageTopRight = new OpenSeadragon.Point(imageWidth, 0);
+
+            var point = viewport.viewerElementToViewportCoordinates(viewerTopRight);
+            pointEqual(point, point1_0, 'Viewer top right has viewport coordinates 1,0.');
+            var pixel = viewport.viewerElementToImageCoordinates(viewerTopRight);
+            pointEqual(pixel, imageTopRight, 'Viewer top right has viewport coordinates imageWidth,0.');
+
+            var point = new OpenSeadragon.Point(15, 12);
+            var result = viewport.viewerElementToImageCoordinates(
+                viewport.imageToViewerElementCoordinates(point));
+            pointEqual(result, point, 'viewerElement and image');
+
+            var result = viewport.windowToImageCoordinates(
+                viewport.imageToWindowCoordinates(point));
+            pointEqual(result, point, 'window and image');
+
+            var result = viewport.viewerElementToViewportCoordinates(
+                viewport.viewportToViewerElementCoordinates(point));
+            pointEqual(result, point, 'viewerElement and viewport');
+
+            var result = viewport.windowToViewportCoordinates(
+                viewport.viewportToWindowCoordinates(point));
+            pointEqual(result, point, 'window and viewport');
+
+            start();
+        });
+        viewer.open('/test/data/testpattern.dzi');
+    });
+
+    // ----------
+    asyncTest('ZoomRatio', function() {
+        viewer.addHandler("open", function () {
+
+            var viewport = viewer.viewport;
+
+            var imageWidth = 1000;
+
+            function getCurrentImageWidth() {
+                return viewport.viewportToViewerElementCoordinates(
+                    new OpenSeadragon.Point(1, 0)).minus(
+                        viewport.viewportToViewerElementCoordinates(
+                            new OpenSeadragon.Point(0, 0))).x;
+            }
+
+            function checkZoom() {
+                var currentImageWidth = getCurrentImageWidth();
+                var expected = currentImageWidth / imageWidth;
+                var actual = viewport.getImageZoomRatio(true);
+                equal(actual, expected);
+            }
+
+            checkZoom();
+
+            var zoomHandler = function() {
+                viewer.removeHandler('animationfinish', zoomHandler);
+                checkZoom();
+                start();
+            };
+
+            viewer.addHandler('animationfinish', zoomHandler);
+            viewport.zoomTo(2);
+        });
+
+        viewer.open('/test/data/testpattern.dzi');
+    });
+
+
+})();

From 3e5a9b52c95defac5677ba34411fe757196b688d Mon Sep 17 00:00:00 2001
From: Antoine Vandecreme <ant.vand@gmail.com>
Date: Sat, 5 Oct 2013 10:21:12 -0400
Subject: [PATCH 2/2] Rollback basic.html and create coordinates.html. Fix unit
 tests. Fix documentation.

---
 src/viewport.js            | 20 +++++-----
 test/demo/basic.html       | 44 ----------------------
 test/demo/coordinates.html | 77 ++++++++++++++++++++++++++++++++++++++
 test/test.css              |  2 +-
 test/units.js              |  1 +
 5 files changed, 89 insertions(+), 55 deletions(-)
 create mode 100644 test/demo/coordinates.html

diff --git a/src/viewport.js b/src/viewport.js
index 916c05f5..31f658a4 100644
--- a/src/viewport.js
+++ b/src/viewport.js
@@ -676,7 +676,7 @@ $.Viewport.prototype = {
 
 
     /**
-     * Convert a delta (translation vector) from image pixels coordinates to viewport coordinates
+     * 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).
      */
@@ -687,7 +687,7 @@ $.Viewport.prototype = {
     },
 
     /**
-     * Convert a delta (translation vector) from viewport coordinates to image pixels coordinates.
+     * 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).
      */
@@ -836,7 +836,7 @@ $.Viewport.prototype = {
     },
 
     /**
-     * Convert a pixel coordinates relative to the viewer element to image
+     * Convert pixel coordinates relative to the viewer element to image
      * coordinates.
      * @param {OpenSeadragon.Point} pixel
      * @returns {OpenSeadragon.Point}
@@ -847,7 +847,7 @@ $.Viewport.prototype = {
     },
 
     /**
-     * Convert a pixel coordinates relative to the image to
+     * Convert pixel coordinates relative to the image to
      * viewer element coordinates.
      * @param {OpenSeadragon.Point} point
      * @returns {OpenSeadragon.Point}
@@ -858,7 +858,7 @@ $.Viewport.prototype = {
     },
 
     /**
-     * Convert a pixel coordinates relative to the window to image coordinates.
+     * Convert pixel coordinates relative to the window to image coordinates.
      * @param {OpenSeadragon.Point} pixel
      * @returns {OpenSeadragon.Point}
      */
@@ -869,7 +869,7 @@ $.Viewport.prototype = {
     },
 
     /**
-     * Convert an image coordinates to pixel coordinates relative to the window.
+     * Convert image coordinates to pixel coordinates relative to the window.
      * @param {OpenSeadragon.Point} pixel
      * @returns {OpenSeadragon.Point}
      */
@@ -880,7 +880,7 @@ $.Viewport.prototype = {
     },
 
     /**
-     * Convert a pixel coordinates relative to the viewer element to viewport
+     * Convert pixel coordinates relative to the viewer element to viewport
      * coordinates.
      * @param {OpenSeadragon.Point} pixel
      * @returns {OpenSeadragon.Point}
@@ -890,7 +890,7 @@ $.Viewport.prototype = {
     },
 
     /**
-     * Convert viewport coordinates to a pixel coordinates relative to the
+     * Convert viewport coordinates to pixel coordinates relative to the
      * viewer element.
      * @param {OpenSeadragon.Point} point
      * @returns {OpenSeadragon.Point}
@@ -900,7 +900,7 @@ $.Viewport.prototype = {
     },
 
     /**
-     * Convert a pixel coordinates relative to the window to viewport coordinates.
+     * Convert pixel coordinates relative to the window to viewport coordinates.
      * @param {OpenSeadragon.Point} pixel
      * @returns {OpenSeadragon.Point}
      */
@@ -911,7 +911,7 @@ $.Viewport.prototype = {
     },
 
     /**
-     * Convert viewport coordinates to a pixel coordinates relative to the window.
+     * Convert viewport coordinates to pixel coordinates relative to the window.
      * @param {OpenSeadragon.Point} point
      * @returns {OpenSeadragon.Point}
      */
diff --git a/test/demo/basic.html b/test/demo/basic.html
index be8cbb4c..19572b86 100644
--- a/test/demo/basic.html
+++ b/test/demo/basic.html
@@ -18,24 +18,6 @@
         Simple demo page to show a default OpenSeadragon viewer.
     </div>
     <div id="contentDiv" class="openseadragon1"></div>
-    <div>
-        <table border="1">
-            <tr>
-                <th></th>
-                <th>Window (pixel)</th>
-                <th>Container (pixel)</th>
-                <th>Image (pixel)</th>
-                <th>Viewport (point)</th>
-            </tr>
-            <tr>
-                <th>Cursor position</th>
-                <td id="windowPosition"></td>
-                <td id="containerPosition"></td>
-                <td id="imagePosition"></td>
-                <td id="viewportPosition"></td>
-            <tr>
-        </table>
-    </div>
     <script type="text/javascript">
 
         var viewer = OpenSeadragon({
@@ -46,32 +28,6 @@
             showNavigator:true
         });
 
-        function pointToString(point) {
-            return point.x.toPrecision(4) + "," + point.y.toPrecision(4);
-        }
-
-        var onMouseTrackerMove = function(eventSender, eventData) {
-            var viewerX = eventData.position.x;
-            var viewerY = eventData.position.y;
-            var windowPoint = new OpenSeadragon.Point(viewerX, viewerY);
-            $("#windowPosition").text( pointToString(windowPoint));
-
-            var containerPoint = windowPoint.minus(
-                    OpenSeadragon.getElementPosition(viewer.element));
-            $("#containerPosition").text( pointToString(containerPoint));
-
-            var imagePoint = viewer.viewport.windowToImageCoordinates(windowPoint);
-            $("#imagePosition").text( pointToString(imagePoint));
-
-            var viewportPoint = viewer.viewport.windowToViewportCoordinates(windowPoint);
-            $("#viewportPosition").text( pointToString(viewportPoint));
-        };
-
-        mouseTracker = new OpenSeadragon.MouseTracker({
-            element: document,
-            moveHandler: onMouseTrackerMove
-        }).setTracking(true);
-
     </script>
 </body>
 </html>
diff --git a/test/demo/coordinates.html b/test/demo/coordinates.html
new file mode 100644
index 00000000..be8cbb4c
--- /dev/null
+++ b/test/demo/coordinates.html
@@ -0,0 +1,77 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <title>OpenSeadragon Basic Demo</title>
+    <script type="text/javascript" src='../../build/openseadragon/openseadragon.js'></script>
+    <script type="text/javascript" src='../lib/jquery-1.9.1.min.js'></script>
+    <style type="text/css">
+
+      .openseadragon1 {
+          width: 800px;
+          height: 600px;
+      }
+
+    </style>
+</head>
+<body>
+    <div>
+        Simple demo page to show a default OpenSeadragon viewer.
+    </div>
+    <div id="contentDiv" class="openseadragon1"></div>
+    <div>
+        <table border="1">
+            <tr>
+                <th></th>
+                <th>Window (pixel)</th>
+                <th>Container (pixel)</th>
+                <th>Image (pixel)</th>
+                <th>Viewport (point)</th>
+            </tr>
+            <tr>
+                <th>Cursor position</th>
+                <td id="windowPosition"></td>
+                <td id="containerPosition"></td>
+                <td id="imagePosition"></td>
+                <td id="viewportPosition"></td>
+            <tr>
+        </table>
+    </div>
+    <script type="text/javascript">
+
+        var viewer = OpenSeadragon({
+            // debugMode: true,
+            id: "contentDiv",
+            prefixUrl: "../../build/openseadragon/images/",
+            tileSources: "../data/testpattern.dzi",
+            showNavigator:true
+        });
+
+        function pointToString(point) {
+            return point.x.toPrecision(4) + "," + point.y.toPrecision(4);
+        }
+
+        var onMouseTrackerMove = function(eventSender, eventData) {
+            var viewerX = eventData.position.x;
+            var viewerY = eventData.position.y;
+            var windowPoint = new OpenSeadragon.Point(viewerX, viewerY);
+            $("#windowPosition").text( pointToString(windowPoint));
+
+            var containerPoint = windowPoint.minus(
+                    OpenSeadragon.getElementPosition(viewer.element));
+            $("#containerPosition").text( pointToString(containerPoint));
+
+            var imagePoint = viewer.viewport.windowToImageCoordinates(windowPoint);
+            $("#imagePosition").text( pointToString(imagePoint));
+
+            var viewportPoint = viewer.viewport.windowToViewportCoordinates(windowPoint);
+            $("#viewportPosition").text( pointToString(viewportPoint));
+        };
+
+        mouseTracker = new OpenSeadragon.MouseTracker({
+            element: document,
+            moveHandler: onMouseTrackerMove
+        }).setTracking(true);
+
+    </script>
+</body>
+</html>
diff --git a/test/test.css b/test/test.css
index a7693328..eb651b16 100644
--- a/test/test.css
+++ b/test/test.css
@@ -16,4 +16,4 @@
 #unitsexample {
     height: 500px;
     width: 500px;
-}
\ No newline at end of file
+}
diff --git a/test/units.js b/test/units.js
index eb2b70ac..1417b801 100644
--- a/test/units.js
+++ b/test/units.js
@@ -106,6 +106,7 @@
 
             viewer.addHandler('animationfinish', zoomHandler);
             viewport.zoomTo(2);
+            start();
         });
 
         viewer.open('/test/data/testpattern.dzi');