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 * @constructor 45 */ 46 JXG.Coords = function (method, coordinates, board) { 47 /** 48 * Stores the board the object is used on. 49 * @type JXG.Board 50 */ 51 this.board = board; 52 53 /** 54 * Stores coordinates for user view as homogeneous coordinates. 55 * @type Array 56 */ 57 this.usrCoords = []; 58 /** 59 * Stores coordinates for screen view as homogeneous coordinates. 60 * @type Array 61 */ 62 this.scrCoords = []; 63 64 if(method == JXG.COORDS_BY_USER) { 65 if (coordinates.length<=2) { 66 this.usrCoords[0] = 1.0; 67 this.usrCoords[1] = coordinates[0]; 68 this.usrCoords[2] = coordinates[1]; 69 } else { // homogeneous coordinates 70 this.usrCoords[0] = coordinates[0]; 71 this.usrCoords[1] = coordinates[1]; 72 this.usrCoords[2] = coordinates[2]; 73 this.normalizeUsrCoords(); 74 } 75 this.usr2screen(); 76 } else { 77 this.scrCoords[0] = 1.0; 78 this.scrCoords[1] = coordinates[0]; 79 this.scrCoords[2] = coordinates[1]; 80 this.screen2usr(); 81 } 82 }; 83 84 /** 85 * Normalize homogeneous coordinates 86 * @private 87 */ 88 JXG.Coords.prototype.normalizeUsrCoords = function() { 89 var eps = 0.000001; 90 if (Math.abs(this.usrCoords[0])>eps) { 91 this.usrCoords[1] /= this.usrCoords[0]; 92 this.usrCoords[2] /= this.usrCoords[0]; 93 this.usrCoords[0] = 1.0; 94 } 95 }; 96 97 /** 98 * Compute screen coordinates out of given user coordinates. 99 * @private 100 */ 101 JXG.Coords.prototype.usr2screen = function(doRound) { 102 var mround = Math.round, // Is faster on IE, maybe slower with JIT compilers 103 b = this.board, 104 uc = this.usrCoords, 105 oc = b.origin.scrCoords; 106 107 if (doRound==null || doRound) { 108 this.scrCoords[0] = mround(uc[0]); 109 this.scrCoords[1] = mround(uc[0]*oc[1] + uc[1]*b.stretchX); 110 this.scrCoords[2] = mround(uc[0]*oc[2] - uc[2]*b.stretchY); 111 } else { 112 this.scrCoords[0] = uc[0]; 113 this.scrCoords[1] = uc[0]*oc[1] + uc[1]*b.stretchX; 114 this.scrCoords[2] = uc[0]*oc[2] - uc[2]*b.stretchY; 115 } 116 }; 117 118 /** 119 * Compute user coordinates out of given screen coordinates. 120 * @private 121 */ 122 JXG.Coords.prototype.screen2usr = function() { 123 var o = this.board.origin.scrCoords, 124 sc = this.scrCoords, 125 b = this.board; 126 this.usrCoords[0] = 1.0; 127 this.usrCoords[1] = (sc[1] - o[1])/b.stretchX; 128 this.usrCoords[2] = (o[2] - sc[2])/b.stretchY; 129 }; 130 131 /** 132 * Calculate distance of one point to another. 133 * @param {int} method The type of coordinates used here. Possible values are <b>JXG.COORDS_BY_USER</b> and <b>JXG.COORDS_BY_SCREEN</b>. 134 * @param {JXG.Coords} coordinates The Coords object to which the distance is calculated. 135 */ 136 JXG.Coords.prototype.distance = function(meth, crd) { 137 var sum = 0, 138 c, 139 ucr = this.usrCoords, 140 scr = this.scrCoords, 141 f; 142 143 if (meth == JXG.COORDS_BY_USER) { 144 c = crd.usrCoords; 145 f = ucr[0]-c[0]; 146 sum = f*f; 147 f = ucr[1]-c[1]; 148 sum += f*f; 149 f = ucr[2]-c[2]; 150 sum += f*f; 151 } else { 152 c = crd.scrCoords; 153 f = scr[0]-c[0]; 154 sum = f*f; 155 f = scr[1]-c[1]; 156 sum += f*f; 157 f = scr[2]-c[2]; 158 sum += f*f; 159 } 160 161 return Math.sqrt(sum); 162 }; 163 164 /** 165 * Set coordinates by method 166 * @param {int} method The type of coordinates used here. Possible values are <b>COORDS_BY_USER</b> and <b>COORDS_BY_SCREEN</b>. 167 * @param {Array} coordinates An array of affine coordinates the Coords object is set to. 168 * @param {boolean} optional flag If true or null round the coordinates in usr2screen. This is used in smooth curve plotting. 169 * The IE needs rounded coordinates. Id doRound==false we have to round in updatePathString. 170 */ 171 JXG.Coords.prototype.setCoordinates = function(method, crd, doRound) { 172 var uc = this.usrCoords, 173 sc = this.scrCoords; 174 175 if (method == JXG.COORDS_BY_USER) { 176 if (crd.length==2) { // Euclidean coordinates 177 uc[0] = 1.0; 178 uc[1] = crd[0]; 179 uc[2] = crd[1]; 180 } else { // Homogeneous coordinates (normalized) 181 uc[0] = crd[0]; 182 uc[1] = crd[1]; 183 uc[2] = crd[2]; 184 this.normalizeUsrCoords(); 185 } 186 this.usr2screen(doRound); 187 } else { 188 sc[1] = crd[0]; 189 sc[2] = crd[1]; 190 this.screen2usr(); 191 } 192 }; 193