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