1 /* 2 Copyright 2008,2009 3 Matthias Ehmann, 4 Michael Gerhaeuser, 5 Carsten Miller, 6 Bianca Valentin, 7 Alfred Wassermann, 8 Peter Wilfahrt 9 10 This file is part of JSXGraph. 11 12 JSXGraph is free software: you can redistribute it and/or modify 13 it under the terms of the GNU Lesser General Public License as published by 14 the Free Software Foundation, either version 3 of the License, or 15 (at your option) any later version. 16 17 JSXGraph is distributed in the hope that it will be useful, 18 but WITHOUT ANY WARRANTY; without even the implied warranty of 19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 GNU Lesser General Public License for more details. 21 22 You should have received a copy of the GNU Lesser General Public License 23 along with JSXGraph. If not, see <http://www.gnu.org/licenses/>. 24 */ 25 26 /** 27 * @fileoverview In this file the Coords object is defined, a class to manage all 28 * properties and methods coordinates usually have. 29 * @author graphjs 30 * @version 0.1 31 */ 32 33 JXG.COORDS_BY_USER = 0x0001; 34 JXG.COORDS_BY_SCREEN = 0x0002; 35 36 /** 37 * Constructs a new Coordinates object. 38 * @class This is the Coordinates class. 39 * All members a coordinate has to provide 40 * are defined here. 41 * @param {int} method The type of coordinates given by the user. Accepted values are <b>COORDS_BY_SCREEN</b> and <b>COORDS_BY_USER</b>. 42 * @param {Array} coordinates An array of affine coordinates. 43 * @param {JXG.AbstractRenderer} renderer A reference to a Renderer. 44 * @borrows JXG.EventEmitter#on as this.on 45 * @borrows JXG.EventEmitter#off as this.off 46 * @borrows JXG.EventEmitter#triggerEventHandlers as this.triggerEventHandlers 47 * @borrows JXG.EventEmitter#eventHandlers as this.eventHandlers 48 * @constructor 49 */ 50 JXG.Coords = function (method, coordinates, board) { 51 /** 52 * Stores the board the object is used on. 53 * @type JXG.Board 54 */ 55 this.board = board; 56 57 /** 58 * Stores coordinates for user view as homogeneous coordinates. 59 * @type Array 60 */ 61 this.usrCoords = []; 62 /** 63 * Stores coordinates for screen view as homogeneous coordinates. 64 * @type Array 65 */ 66 this.scrCoords = []; 67 68 JXG.EventEmitter.eventify(this); 69 this.setCoordinates(method, coordinates); 70 }; 71 72 JXG.extend(JXG.Coords.prototype, /** @lends JXG.Coords.prototype */ { 73 /** 74 * Normalize homogeneous coordinates 75 * @private 76 */ 77 normalizeUsrCoords: function () { 78 var eps = JXG.Math.eps; 79 if (Math.abs(this.usrCoords[0]) > eps) { 80 this.usrCoords[1] /= this.usrCoords[0]; 81 this.usrCoords[2] /= this.usrCoords[0]; 82 this.usrCoords[0] = 1.0; 83 } 84 }, 85 86 /** 87 * Compute screen coordinates out of given user coordinates. 88 * @private 89 */ 90 usr2screen: function (doRound) { 91 var mround = Math.round, // Is faster on IE, maybe slower with JIT compilers 92 b = this.board, 93 uc = this.usrCoords, 94 oc = b.origin.scrCoords; 95 96 if (doRound === null || doRound) { 97 this.scrCoords[0] = mround(uc[0]); 98 this.scrCoords[1] = mround(uc[0]*oc[1] + uc[1]*b.unitX); 99 this.scrCoords[2] = mround(uc[0]*oc[2] - uc[2]*b.unitY); 100 } else { 101 this.scrCoords[0] = uc[0]; 102 this.scrCoords[1] = uc[0]*oc[1] + uc[1]*b.unitX; 103 this.scrCoords[2] = uc[0]*oc[2] - uc[2]*b.unitY; 104 } 105 }, 106 107 /** 108 * Compute user coordinates out of given screen coordinates. 109 * @private 110 */ 111 screen2usr: function () { 112 var o = this.board.origin.scrCoords, 113 sc = this.scrCoords, 114 b = this.board; 115 this.usrCoords[0] = 1.0; 116 this.usrCoords[1] = (sc[1] - o[1])/b.unitX; 117 this.usrCoords[2] = (o[2] - sc[2])/b.unitY; 118 }, 119 120 /** 121 * Calculate distance of one point to another. 122 * @param {Number} coord_type The type of coordinates used here. Possible values are <b>JXG.COORDS_BY_USER</b> and <b>JXG.COORDS_BY_SCREEN</b>. 123 * @param {JXG.Coords} coordinates The Coords object to which the distance is calculated. 124 * @returns {Number} The distance 125 */ 126 distance: function (coord_type, coordinates) { 127 var sum = 0, 128 c, 129 ucr = this.usrCoords, 130 scr = this.scrCoords, 131 f; 132 133 if (coord_type === JXG.COORDS_BY_USER) { 134 c = coordinates.usrCoords; 135 f = ucr[0]-c[0]; 136 sum = f*f; 137 if (sum>JXG.Math.eps) { 138 return Number.POSITIVE_INFINITY; 139 } 140 f = ucr[1]-c[1]; 141 sum += f*f; 142 f = ucr[2]-c[2]; 143 sum += f*f; 144 } else { 145 c = coordinates.scrCoords; 146 //f = scr[0]-c[0]; 147 //sum = f*f; 148 f = scr[1]-c[1]; 149 sum += f*f; 150 f = scr[2]-c[2]; 151 sum += f*f; 152 } 153 154 return Math.sqrt(sum); 155 }, 156 157 /** 158 * Set coordinates by either user coordinates or screen coordinates and recalculate the other one. 159 * @param {Number} coord_type The type of coordinates used here. Possible values are <b>COORDS_BY_USER</b> and <b>COORDS_BY_SCREEN</b>. 160 * @param {Array} coordinates An array of affine coordinates the Coords object is set to. 161 * @param {Boolean} [doRound=true] flag If true or null round the coordinates in usr2screen. This is used in smooth curve plotting. 162 * The IE needs rounded coordinates. Id doRound==false we have to round in updatePathString. 163 * @returns {JXG.Coords} Reference to the coords object. 164 */ 165 setCoordinates: function (coord_type, coordinates, doRound) { 166 var uc = this.usrCoords, 167 sc = this.scrCoords, 168 ou = this.usrCoords.slice(0), os = this.scrCoords.slice(0); 169 170 if (coord_type === JXG.COORDS_BY_USER) { 171 if (coordinates.length === 2) { // Euclidean coordinates 172 uc[0] = 1.0; 173 uc[1] = coordinates[0]; 174 uc[2] = coordinates[1]; 175 } else { // Homogeneous coordinates (normalized) 176 uc[0] = coordinates[0]; 177 uc[1] = coordinates[1]; 178 uc[2] = coordinates[2]; 179 this.normalizeUsrCoords(); 180 } 181 this.usr2screen(doRound); 182 } else { 183 sc[1] = coordinates[0]; 184 sc[2] = coordinates[1]; 185 this.screen2usr(); 186 } 187 188 this.triggerEventHandlers('update', ou, os); 189 190 return this; 191 }, 192 193 /** 194 * Triggered whenever the coordinates change. 195 * @name JXG.Coords#update 196 * @param {Array} ou Old user coordinates 197 * @param {Array} os Old screen coordinates 198 * @event 199 */ 200 __evt__: function (ou, os) { }, 201 202 /** 203 * @ignore 204 */ 205 __evt__: function () {} 206 }); 207