1 /* 2 Copyright 2008-2022 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 dual licensed under the GNU LGPL or MIT License. 13 14 You can redistribute it and/or modify it under the terms of the 15 16 * GNU Lesser General Public License as published by 17 the Free Software Foundation, either version 3 of the License, or 18 (at your option) any later version 19 OR 20 * MIT License: https://github.com/jsxgraph/jsxgraph/blob/master/LICENSE.MIT 21 22 JSXGraph is distributed in the hope that it will be useful, 23 but WITHOUT ANY WARRANTY; without even the implied warranty of 24 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 25 GNU Lesser General Public License for more details. 26 27 You should have received a copy of the GNU Lesser General Public License and 28 the MIT License along with JSXGraph. If not, see <http://www.gnu.org/licenses/> 29 and <http://opensource.org/licenses/MIT/>. 30 */ 31 32 33 /*global JXG: true, define: true*/ 34 /*jslint nomen: true, plusplus: true*/ 35 36 /* depends: 37 jxg 38 utils/type 39 base/element 40 elements: 41 point 42 segment 43 ticks 44 */ 45 46 /** 47 * @fileoverview Geometry objects for measurements are defined in this file. This file stores all 48 * style and functional properties that are required to use a tape measure on 49 * a board. 50 */ 51 52 define([ 53 'jxg', 'utils/type', 'base/element' 54 ], function (JXG, Type, GeometryElement) { 55 56 "use strict"; 57 58 /** 59 * @class A tape measure can be used to measure distances between points. 60 * @pseudo 61 * @description 62 * @name Tapemeasure 63 * @augments Segment 64 * @constructor 65 * @type JXG.Segment 66 * @throws {Exception} If the element cannot be constructed with the given parent objects an exception is thrown. 67 * @param {Array_Array} start,end, The two arrays give the initial position where the tape measure 68 * is drawn on the board. 69 * @example 70 * // Create a tape measure 71 * var p1 = board.create('point', [0,0]); 72 * var p2 = board.create('point', [1,1]); 73 * var p3 = board.create('point', [3,1]); 74 * var tape = board.create('tapemeasure', [[1, 2], [4, 2]], {name:'dist'}); 75 * </pre><div class="jxgbox" id="JXG6d9a2cda-22fe-4cd1-9d94-34283b1bdc01" style="width: 200px; height: 200px;"></div> 76 * <script type="text/javascript"> 77 * (function () { 78 * var board = JXG.JSXGraph.initBoard('JXG6d9a2cda-22fe-4cd1-9d94-34283b1bdc01', {boundingbox: [-1, 5, 5, -1], axis: true, showcopyright: false, shownavigation: false}); 79 * var p1 = board.create('point', [0,0]); 80 * var p2 = board.create('point', [1,1]); 81 * var p3 = board.create('point', [3,1]); 82 * var tape = board.create('tapemeasure', [[1, 2], [4, 2]], {name:'dist'} ); 83 * })(); 84 * </script><pre> 85 */ 86 JXG.createTapemeasure = function (board, parents, attributes) { 87 var pos0, pos1, 88 attr, withTicks, withText, digits, 89 li, p1, p2, n, ti; 90 91 pos0 = parents[0]; 92 pos1 = parents[1]; 93 94 // start point 95 attr = Type.copyAttributes(attributes, board.options, 'tapemeasure', 'point1'); 96 p1 = board.create('point', pos0, attr); 97 98 // end point 99 attr = Type.copyAttributes(attributes, board.options, 'tapemeasure', 'point2'); 100 p2 = board.create('point', pos1, attr); 101 102 p1.setAttribute({ignoredSnapToPoints: [p2]}); 103 p2.setAttribute({ignoredSnapToPoints: [p1]}); 104 105 // tape measure line 106 attr = Type.copyAttributes(attributes, board.options, 'tapemeasure'); 107 withTicks = attr.withticks; 108 withText = attr.withlabel; 109 digits = attr.digits; 110 111 if (digits === 2 && attr.precision !== 2) { 112 // Backward compatibility 113 digits = attr.precision; 114 } 115 116 // Below, we will replace the label by the measurement function. 117 if (withText) { 118 attr.withlabel = true; 119 } 120 li = board.create('segment', [p1, p2], attr); 121 // p1, p2 are already added to li.inherits 122 123 if (withText) { 124 if (attributes.name && attributes.name !== '') { 125 n = attributes.name + ' = '; 126 } else { 127 n = ''; 128 } 129 li.label.setText(function () { 130 return n + Type.toFixed(p1.Dist(p2), digits); 131 }); 132 } 133 134 if (withTicks) { 135 attr = Type.copyAttributes(attributes, board.options, 'tapemeasure', 'ticks'); 136 //ticks = 2; 137 ti = board.create('ticks', [li, 0.1], attr); 138 li.inherits.push(ti); 139 } 140 141 // override the segments's remove method to ensure the removal of all elements 142 /** @ignore */ 143 li.remove = function () { 144 if (withTicks) { 145 li.removeTicks(ti); 146 } 147 148 board.removeObject(p2); 149 board.removeObject(p1); 150 151 GeometryElement.prototype.remove.call(this); 152 }; 153 154 /** 155 * Returns the length of the tape measure. 156 * @name Value 157 * @memberOf Tapemeasure.prototype 158 * @function 159 * @returns {Number} length of tape measure. 160 */ 161 li.Value = function () { 162 return p1.Dist(p2); 163 }; 164 165 p1.dump = false; 166 p2.dump = false; 167 168 li.elType = 'tapemeasure'; 169 li.getParents = function() { 170 return [[p1.X(), p1.Y()], [p2.X(), p2.Y()]]; 171 }; 172 173 li.subs = { 174 point1: p1, 175 point2: p2 176 }; 177 178 if (withTicks) { 179 ti.dump = false; 180 } 181 182 li.methodMap = JXG.deepCopy(li.methodMap, { 183 Value: 'Value' 184 }); 185 186 li.prepareUpdate().update(); 187 if (!board.isSuspendedUpdate) { 188 li.updateVisibility().updateRenderer(); 189 // The point updates are necessary in case of snapToGrid==true 190 li.point1.updateVisibility().updateRenderer(); 191 li.point2.updateVisibility().updateRenderer(); 192 } 193 194 return li; 195 }; 196 197 JXG.registerElement('tapemeasure', JXG.createTapemeasure); 198 199 return { 200 createTapemeasure: JXG.createTapemeasure 201 }; 202 }); 203