Working on rotating images.

So far only 90 degree rotation is supported.
Only the image is currently being rotated.
Overlays, debugger, and the navigator still need to be updated to support rotation.
This commit is contained in:
Robert Hickman 2013-08-13 15:39:22 -06:00
parent 26ad522f59
commit b9583c43ac
6 changed files with 187 additions and 8 deletions

View File

@ -505,6 +505,7 @@ function updateViewport( drawer ) {
Math.log( 2 )
))
),
degrees = drawer.viewport.degrees,
renderPixelRatioC,
renderPixelRatioT,
zeroRatioT,
@ -529,7 +530,14 @@ function updateViewport( drawer ) {
drawer.context.clearRect( 0, 0, viewportSize.x, viewportSize.y );
}
//TODO
//Change bounds for rotation
if (degrees === 90 || degrees === 270) {
var rotatedBounds = viewportBounds.rotate( degrees );
viewportTL = rotatedBounds.getTopLeft();
viewportBR = rotatedBounds.getBottomRight();
}
//Don't draw if completely outside of the viewport
if ( !drawer.wrapHorizontal &&
( viewportBR.x < 0 || viewportTL.x > 1 ) ) {
return;
@ -571,6 +579,7 @@ function updateViewport( drawer ) {
continue;
}
//Perform calculations for draw if we haven't drawn this
renderPixelRatioT = drawer.viewport.deltaPixelsFromPoints(
drawer.source.getPixelRatio( level ),
false
@ -1192,7 +1201,11 @@ function drawTiles( drawer, lastDrawn ){
} else {
if ( USE_CANVAS ) {
// TODO do this in a more performant way
// specifically, don't save,rotate,restore every time we draw a tile
offsetForRotation( tile, drawer.canvas, drawer.context, drawer.viewport.degrees );
tile.drawCanvas( drawer.context );
restoreRotationChanges( tile, drawer.canvas, drawer.context );
} else {
tile.drawHTML( drawer.canvas );
}
@ -1218,6 +1231,32 @@ function drawTiles( drawer, lastDrawn ){
}
}
function offsetForRotation( tile, canvas, context, degrees ){
var cx = canvas.width / 2,
cy = canvas.height / 2,
px = tile.position.x - cx,
py = tile.position.y - cy;
context.save();
context.translate(cx, cy);
context.rotate( Math.PI / 180 * degrees);
tile.position.x = px;
tile.position.y = py;
}
function restoreRotationChanges( tile, canvas, context ){
var cx = canvas.width / 2,
cy = canvas.height / 2,
px = tile.position.x + cx,
py = tile.position.y + cy;
tile.position.x = px;
tile.position.y = py;
context.restore();
}
function drawDebugInfo( drawer, tile, count, i ){

View File

@ -533,6 +533,9 @@ window.OpenSeadragon = window.OpenSeadragon || function( options ){
navigatorPosition: null,
navigatorSizeRatio: 0.2,
// INITIAL ROTATION
degrees: 0,
//REFERENCE STRIP SETTINGS
showReferenceStrip: false,
referenceStripScroll: 'horizontal',
@ -1924,4 +1927,23 @@ window.OpenSeadragon = window.OpenSeadragon || function( options ){
throw new Error(message);
};
/**
* http://stackoverflow.com/questions/246193
* /how-do-i-round-a-number-in-javascript
* @private
* @inner
* @function
* @param {Number} num
* @param {Number} decimals
* @return {Number}
*/
$._round = function ( num, decimals ) {
var coefficient;
decimals = decimals || 10;
coefficient = Math.pow( 10, decimals );
return Math.round( num * coefficient ) / coefficient;
};
}( OpenSeadragon ));

View File

@ -160,6 +160,27 @@ $.Point.prototype = {
);
},
/**
* Rotates the point around the specified pivot
* 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.
* @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 = $._round(
Math.cos( angle ) * ( this.x - pivot.x ) -
Math.sin( angle ) * ( this.y - pivot.y ) + pivot.x
),
y = $._round(
Math.sin( angle ) * ( this.x - pivot.x ) +
Math.cos( angle ) * ( this.y - pivot.y ) + pivot.y
);
return new $.Point( x, y );
},
/**
* Add another Point to this point and return a new Point.
* @function

View File

@ -69,14 +69,17 @@ $.Rect.prototype = {
},
/**
* Provides the coordinates of the upper-left corner of the rectanglea s a
* Provides the coordinates of the upper-left corner of the rectangle as a
* point.
* @function
* @returns {OpenSeadragon.Point} The coordinate of the upper-left corner of
* the rectangle.
*/
getTopLeft: function() {
return new $.Point( this.x, this.y );
return new $.Point(
this.x,
this.y
);
},
/**
@ -93,10 +96,38 @@ $.Rect.prototype = {
);
},
/**
* Provides the coordinates of the top-right corner of the rectangle as a
* point.
* @function
* @returns {OpenSeadragon.Point} The coordinate of the top-right corner of
* the rectangle.
*/
getTopRight: function() {
return new $.Point(
this.x + this.width,
this.y
);
},
/**
* Provides the coordinates of the bottom-left corner of the rectangle as a
* point.
* @function
* @returns {OpenSeadragon.Point} The coordinate of the bottom-left corner of
* the rectangle.
*/
getBottomLeft: function() {
return new $.Point(
this.x,
this.y + this.height
);
},
/**
* Computes the center of the rectangle.
* @function
* @returns {OpenSeadragon.Point} The center of the rectangle as represnted
* @returns {OpenSeadragon.Point} The center of the rectangle as represented
* as represented by a 2-dimensional vector (x,y)
*/
getCenter: function() {
@ -109,7 +140,7 @@ $.Rect.prototype = {
/**
* Returns the width and height component as a vector OpenSeadragon.Point
* @function
* @returns {OpenSeadragon.Point} The 2 dimensional vector represnting the
* @returns {OpenSeadragon.Point} The 2 dimensional vector representing the
* the width and height of the rectangle.
*/
getSize: function() {
@ -117,7 +148,7 @@ $.Rect.prototype = {
},
/**
* Determines if two Rectanlges have equivalent components.
* Determines if two Rectangles have equivalent components.
* @function
* @param {OpenSeadragon.Rect} rectangle The Rectangle to compare to.
* @return {Boolean} 'true' if all components are equal, otherwise 'false'.
@ -131,7 +162,48 @@ $.Rect.prototype = {
},
/**
* Provides a string representation of the retangle which is useful for
* Rotates a rectangle around a point. Currently only 90, 180, and 270
* degrees are supported.
* @function
* @param {Number} degrees The angle in degrees to rotate.
* @param {OpenSeadragon.Point} pivot The point about which to rotate.
* Defaults to the center of the rectangle.
* @return {OpenSeadragon.Rect}
*/
rotate: function( degrees, pivot ) {
// TODO support arbitrary rotation
var width = this.width,
height = this.height,
newTopLeft;
pivot = pivot || this.getCenter();
switch ( degrees ) {
case 90:
newTopLeft = this.getBottomLeft();
width = this.height;
height = this.width;
break;
case 180:
newTopLeft = this.getBottomRight();
break;
case 270:
newTopLeft = this.getTopRight();
width = this.height;
height = this.width;
break;
default:
newTopLeft = this.getTopLeft();
break;
}
newTopLeft = newTopLeft.rotate(degrees, pivot);
return new $.Rect(newTopLeft.x, newTopLeft.y, width, height);
},
/**
* Provides a string representation of the rectangle which is useful for
* debugging.
* @function
* @returns {String} A string representation of the rectangle.

View File

@ -1074,6 +1074,19 @@ $.extend( $.Viewer.prototype, $.EventHandler.prototype, $.ControlDock.prototype,
return this;
},
/**
* @function
* @name OpenSeadragon.Viewer.prototype.rotate
* @return {OpenSeadragon.Viewer} Chainable.
*/
rotate: function(clockwise){
clockwise = clockwise || true;
this.viewport.degrees = ( this.viewport.degrees + (clockwise ? 90 : -90 ) + 360 ) % 360;
//this.raiseEvent( 'rotate', { viewer: this } );
this.drawer.update();
return this;
},
/**
* Display a message in the viewport
* @function
@ -1696,5 +1709,9 @@ function onNext(){
this.goToPage( next );
}
function onRotate(){
this.rotate();
}
}( OpenSeadragon ));

View File

@ -79,7 +79,8 @@ $.Viewport = function( options ) {
wrapVertical: $.DEFAULT_SETTINGS.wrapVertical,
defaultZoomLevel: $.DEFAULT_SETTINGS.defaultZoomLevel,
minZoomLevel: $.DEFAULT_SETTINGS.minZoomLevel,
maxZoomLevel: $.DEFAULT_SETTINGS.maxZoomLevel
maxZoomLevel: $.DEFAULT_SETTINGS.maxZoomLevel,
degrees: $.DEFAULT_SETTINGS.degrees
}, options );
@ -497,6 +498,7 @@ $.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 );
},
@ -531,6 +533,12 @@ $.Viewport.prototype = {
* @return {OpenSeadragon.Viewport} Chainable.
*/
zoomBy: function( factor, refPoint, immediately ) {
if( typeof refPoint != 'undefined' ) {
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 );
},