1 /* 2 Copyright 2010 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 * @param {String} string A string containing construction(s) in JSXGraph Construction Syntax. 27 * @param {String} mode Possible values seem are "normal" or "macro" 28 * @param {Array} params Parameters, only used in macro mode 29 * @param {Array} paraIn Parameters, only used in macro mode 30 * @param {String} macroName Name of the macro, only used in macro mode 31 * @type object 32 * @return An object consisting of several arrays (lines, circles, points, angles, ...) where the created elements are stored. 33 */ 34 JXG.Board.prototype.construct = function(string, mode, params, paraIn, macroName) { 35 var splitted, i, j, output = {}, objName, defElements, obj, type, possibleNames, tmp, noMacro, k,l, pattern, createdNames, found, 36 mac, prop, propName, propValue, attributes; 37 if(!JXG.exists(mode)) { 38 mode = "normal"; 39 } 40 else { // mode = 'macro' 41 createdNames = []; 42 } 43 output.lines = []; 44 output.circles = []; 45 output.points = []; 46 output.intersections = []; 47 output.angles = []; 48 output.macros = []; 49 output.functions = []; 50 output.texts = []; 51 output.polygons = []; 52 if(string.search(/\{/) != -1) { // Macros finden! Innerhalb der {} darf nicht am ; getrennt werden. Noch nicht getestet: mehrere Makros hintereinander in einem construct. 53 tmp = string.match(/\{/); 54 tmp = tmp.length; 55 l=0; 56 for(j=0; j<tmp; j++) { 57 k = string.slice(l).search(/\{/); 58 mac = string.slice(k); 59 mac = mac.slice(0,mac.search(/\}/)+1); 60 mac = mac.replace(/;/g,'?'); // Achtung! Fragezeichen duerfen daher nicht im Code eines Macros vorkommen! 61 string = string.slice(0,k) + mac + string.slice(k+mac.length); 62 l=k+1; 63 } 64 } 65 splitted = string.split(';'); 66 for(i=0; i< splitted.length; i++) { 67 // Leerzeichen am Anfang und am Ende entfernen 68 splitted[i] = splitted[i].replace (/^\s+/, '').replace (/\s+$/, ''); 69 if(splitted[i].search(/\{/) != -1) { 70 splitted[i] = splitted[i].replace(/\?/g,';'); 71 } 72 if(splitted[i].search(/Macro/) != -1) { 73 this.addMacro(splitted[i]); 74 } 75 else { 76 if(splitted[i].length > 0) { 77 prop = false; 78 if(splitted[i].search(/=/) != -1) { 79 objName = splitted[i].split('='); 80 propValue = objName[1]; 81 propValue = propValue.replace (/^\s+/, '').replace (/\s+$/, ''); 82 if(objName[0].search(/\./) != -1) { 83 prop = true; 84 85 objName = objName[0].split('.'); 86 propName = objName[objName.length-1]; 87 propName = propName.replace (/^\s+/, '').replace (/\s+$/, ''); 88 objName.pop(); 89 objName = objName.join("."); 90 if(mode == 'macro') { 91 for(j=0; j<params.length; j++) { 92 if(objName == params[j]) { 93 objName = paraIn[j]; 94 } 95 } 96 } 97 //alert("_"+objName+"_"+propName+"_"+propValue+"_"); 98 //alert(JXG.getReference(this,objName).name); 99 JXG.getReference(this,objName).setProperty(propName+":"+propValue); 100 101 } 102 } 103 if(!prop) { // nicht nur eine Eigenschaft setzen, sondern neues Element konstruieren 104 if(splitted[i].search(/=/) != -1) { 105 objName = splitted[i].split('='); 106 splitted[i] = objName[1].replace (/^\s+/, ''); // Leerzeichen am Anfang entfernen 107 objName = objName[0].replace (/\s+$/, ''); // Leerzeichen am Ende entfernen 108 } 109 else { 110 objName = ''; 111 } 112 attributes = {}; 113 found = true; 114 while(found) { 115 if(splitted[i].search(/(.*)draft$/) != -1) { 116 attributes.draft = true; 117 splitted[i] = RegExp.$1; 118 splitted[i] = splitted[i].replace (/\s+$/, ''); // Leerzeichen am Ende entfernen 119 } 120 if(splitted[i].search(/(.*)invisible$/) != -1) { 121 attributes.visible = false; 122 splitted[i] = RegExp.$1; 123 splitted[i] = splitted[i].replace (/\s+$/, ''); // Leerzeichen am Ende entfernen 124 } 125 if(splitted[i].search(/(.*)nolabel$/) != -1) { 126 attributes.withLabel = false; 127 splitted[i] = RegExp.$1; 128 splitted[i] = splitted[i].replace (/\s+$/, ''); // Leerzeichen am Ende entfernen 129 } 130 if(splitted[i].search(/nolabel|invisible|draft/) == -1) { 131 found = false; 132 } 133 } 134 noMacro = true; 135 if(this.definedMacros) { 136 for(j=0; j<this.definedMacros.macros.length; j++) { 137 pattern = new RegExp("^"+this.definedMacros.macros[j][0]+"\\s*\\("); 138 if(splitted[i].search(pattern) != -1) { // TODO: testen, was mit den Macros xxx und yxxx passiert 139 //alert("MACRO!"+splitted[i]+"_"+this.definedMacros.macros[j][2]); 140 noMacro = false; 141 // Parameter aufdroeseln 142 splitted[i].match(/\((.*)\)/); 143 tmp = RegExp.$1; 144 tmp = tmp.split(','); 145 for(k=0; k < tmp.length; k++) { 146 tmp[k].match(/\s*(\S*)\s*/); 147 tmp[k] = RegExp.$1; 148 } 149 output[objName] = this.construct(this.definedMacros.macros[j][2],'macro',this.definedMacros.macros[j][1], tmp, objName); 150 output.macros.push(output[objName]); 151 break; 152 } 153 } 154 } 155 if(noMacro) { // splitted[i] war kein Macro-Aufruf 156 if(splitted[i].search(/^[\[\]].*[\[\]]$/) != -1) { // Gerade, Halbgerade oder Segment 157 splitted[i].match(/([\[\]])(.*)([\[\]])/); 158 attributes.straightFirst = (RegExp.$1 != '['); 159 attributes.straightLast = (RegExp.$3 == '['); 160 defElements = (RegExp.$2).replace (/^\s+/, '').replace (/\s+$/, ''); 161 if(defElements.search(/ /) != -1) { 162 defElements.match(/(\S*) +(\S*)/); 163 defElements = []; 164 defElements[0] = RegExp.$1; 165 defElements[1] = RegExp.$2; 166 } // sonst wird die Gerade durch zwei Punkte definiert, die einen Namen haben, der aus nur jeweils einem Buchstaben besteht 167 if(objName != '') { 168 if(!JXG.exists(attributes.withLabel)) { 169 attributes.withLabel = true; 170 } 171 attributes.name = objName; 172 if(mode == 'macro') { 173 createdNames.push(objName); 174 } 175 } 176 if(mode == 'macro') { 177 if(macroName != '') { 178 for(j=0; j<createdNames.length; j++) { // vorher oder nachher? 179 if(defElements[0] == createdNames[j]) { 180 defElements[0] = macroName+"."+defElements[0]; 181 } 182 if(defElements[1] == createdNames[j]) { 183 defElements[1] = macroName+"."+defElements[1]; 184 } 185 } 186 } 187 for(j=0; j<params.length; j++) { 188 if(defElements[0] == params[j]) { 189 defElements = [paraIn[j], defElements[1]]; 190 } 191 if(defElements[1] == params[j]) { 192 defElements = [defElements[0], paraIn[j]]; 193 } 194 } 195 if(macroName != '') { 196 attributes.id = macroName+"."+objName; 197 } 198 } 199 if(typeof defElements == 'string') { 200 defElements = [JXG.getReference(this,defElements.charAt(0)), JXG.getReference(this,defElements.charAt(1))]; 201 } 202 else { 203 defElements = [JXG.getReference(this,defElements[0]), JXG.getReference(this,defElements[1])]; 204 } 205 output.lines.push(this.create('line', 206 defElements, 207 attributes)); 208 if(objName != '') { 209 output[objName] = output.lines[output.lines.length-1]; 210 } 211 } 212 else if(splitted[i].search(/k\s*\(.*/) != -1) { // Kreis 213 splitted[i].match(/k\s*\(\s*(\S.*\S|\S)\s*,\s*(\S.*\S|\S)\s*\)/); 214 defElements = []; 215 defElements[0] = RegExp.$1; 216 defElements[1] = RegExp.$2; 217 for(j=0; j<=1; j++) { 218 if(defElements[j].search(/[\[\]]/) != -1) { // Linie, definiert durch [P_1 P_2] , ist bei den Parametern dabei 219 defElements[j].match(/^[\[\]]\s*(\S.*\S)\s*[\[\]]$/); 220 defElements[j] = RegExp.$1; 221 if(defElements[j].search(/ /) != -1) { 222 defElements[j].match(/(\S*) +(\S*)/); 223 defElements[j] = []; 224 defElements[j][0] = RegExp.$1; 225 defElements[j][1] = RegExp.$2; 226 } // sonst wird die Gerade durch zwei Punkte definiert, die einen Namen haben, der aus nur jeweils einem Buchstaben besteht 227 if(mode == 'macro') { 228 if(macroName != '') { 229 for(k=0; k<createdNames.length; k++) { // vorher oder nachher? 230 if(defElements[j][0] == createdNames[k]) { 231 defElements[j][0] = macroName+"."+defElements[j][0]; 232 } 233 if(defElements[j][1] == createdNames[k]) { 234 defElements[j][1] = macroName+"."+defElements[j][1]; 235 } 236 } 237 } 238 for(k=0; k<params.length; k++) { 239 if(defElements[j][0] == params[k]) { 240 defElements[j] = [paraIn[k], defElements[j][1]]; 241 } 242 if(defElements[j][1] == params[k]) { 243 defElements[j] = [defElements[j][0], paraIn[k]]; 244 } 245 } 246 } 247 if(typeof defElements[j] == 'string') { 248 defElements[j] = (function(el, board) { return function() { 249 return JXG.getReference(board,el.charAt(0)).Dist(JXG.getReference(board,el.charAt(1))); // TODO 250 }} 251 )(defElements[j], this); 252 } 253 else { 254 defElements[j] = (function(el, board) { return function() { 255 return JXG.getReference(board,el[0]).Dist(JXG.getReference(board,el[1])); // TODO 256 }} 257 )(defElements[j], this); 258 } 259 260 } 261 else if(defElements[j].search(/[0-9\.\s]+/) != -1){ // Radius als Zahl 262 defElements[j] = 1.0*defElements[j]; 263 } 264 else { // Element mit Name 265 if(mode == 'macro') { 266 if(macroName != '') { 267 for(k=0; k<createdNames.length; k++) { // vorher oder nachher? 268 if(defElements[j] == createdNames[k]) { 269 defElements[j] = macroName+"."+createdNames[k]; 270 } 271 } 272 } 273 for(k=0; k<params.length; k++) { 274 if(defElements[j] == params[k]) { 275 defElements[j] = paraIn[k]; 276 } 277 } 278 } 279 defElements[j] = JXG.getReference(this,defElements[j]); 280 } 281 } 282 if(objName != '') { 283 if(!JXG.exists(attributes.withLabel)) { 284 attributes.withLabel = true; 285 } 286 attributes.name = objName; 287 if(mode == 'macro') { 288 if(macroName != '') { 289 attributes.id = macroName+"."+objName; 290 } 291 createdNames.push(objName); 292 } 293 } 294 output.circles.push(this.create('circle',defElements,attributes)); 295 if(objName != '') { 296 output[objName] = output.circles[output.circles.length-1]; 297 } 298 } 299 else if(splitted[i].search(/^[A-Z]+.*\(\s*[0-9\.\-]+\s*[,\|]\s*[0-9\.\-]+\s*\)/) != -1 300 && splitted[i].search(/Macro\((.*)\)/) == -1) { // Punkt, startet mit einem Grossbuchstaben! (definiert durch Koordinaten) 301 splitted[i].match(/^([A-Z]+\S*)\s*\(\s*(.*)\s*[,\|]\s*(.*)\s*\)$/); 302 objName = RegExp.$1; // Name 303 attributes.name = objName; 304 if(mode == 'macro') { 305 if(macroName != '') { 306 attributes.id = macroName+"."+objName; 307 } 308 createdNames.push(objName); 309 } 310 output.points.push(this.create('point',[1.0*RegExp.$2,1.0*RegExp.$3],attributes)); 311 output[objName] = output.points[output.points.length-1]; 312 } 313 else if(splitted[i].search(/^[A-Z]+.*\(.+(([,\|]\s*[0-9\.\-]+\s*){2})?/) != -1 314 && splitted[i].search(/Macro\((.*)\)/) == -1) { // Gleiter, mit oder ohne Koordinaten 315 splitted[i].match(/([A-Z]+.*)\((.*)\)/); 316 objName = RegExp.$1; 317 defElements = RegExp.$2; 318 objName = objName.replace (/^\s+/, '').replace (/\s+$/, ''); 319 defElements = defElements.replace (/^\s+/, '').replace (/\s+$/, ''); 320 if(defElements.search(/[,\|]/) != -1) { // Koordinaten angegeben 321 defElements.match(/(\S*)\s*[,\|]\s*([0-9\.]+)\s*[,\|]\s*([0-9\.]+)\s*/); 322 defElements = []; 323 defElements[0] = RegExp.$1; 324 defElements[1] = 1.0*RegExp.$2; 325 defElements[2] = 1.0*RegExp.$3; 326 } 327 else { // keine Koordinaten 328 obj = defElements; 329 defElements = []; 330 defElements[0] = obj; // Name des definierenden Elements 331 defElements[1] = 0; // (0,0) als Gleiterkoordinaten vorgeben... 332 defElements[2] = 0; 333 } 334 attributes.name = objName; 335 if(mode == 'macro') { 336 if(macroName != '') { 337 for(k=0; k<createdNames.length; k++) { // vorher oder nachher? 338 if(defElements[0] == createdNames[k]) { 339 defElements[0] = macroName+"."+createdNames[k]; 340 } 341 } 342 } 343 for(k=0; k<params.length; k++) { 344 if(defElements[0] == params[k]) { 345 defElements[0] = paraIn[k]; 346 } 347 } 348 if(macroName != '') { 349 attributes.id = macroName+"."+objName; 350 } 351 createdNames.push(objName); 352 } 353 output.points.push(this.create('glider', 354 [defElements[1],defElements[2],JXG.getReference(this,defElements[0])], 355 attributes)); 356 output[objName] = output.points[output.points.length-1]; 357 } 358 else if(splitted[i].search(/&/) != -1) { // Schnittpunkt 359 splitted[i].match(/(.*)&(.*)/); 360 defElements = []; 361 defElements[0] = RegExp.$1; 362 defElements[1] = RegExp.$2; 363 defElements[0] = defElements[0].replace(/\s+$/, ''); // Leerzeichen am Ende entfernen 364 defElements[1] = defElements[1].replace (/^\s+/, ''); // Leerzeichen am Anfang entfernen 365 if(mode == 'macro') { 366 for(j=0; j<=1; j++) { 367 if(macroName != '') { 368 for(k=0; k<createdNames.length; k++) { // vorher oder nachher? 369 if(defElements[j] == createdNames[k]) { 370 defElements[j] = macroName+"."+createdNames[k]; 371 } 372 } 373 } 374 for(k=0; k<params.length; k++) { 375 if(defElements[j] == params[k]) { 376 defElements[j] = paraIn[k]; 377 } 378 } 379 } 380 } 381 defElements[0] = JXG.getReference(this,defElements[0]); 382 defElements[1] = JXG.getReference(this,defElements[1]); 383 if ((defElements[0].elementClass==JXG.OBJECT_CLASS_LINE || defElements[0].elementClass==JXG.OBJECT_CLASS_CURVE) && 384 (defElements[1].elementClass==JXG.OBJECT_CLASS_LINE || defElements[1].elementClass==JXG.OBJECT_CLASS_CURVE)) { 385 if(objName != '') { 386 attributes.name = objName; 387 if(mode == 'macro') { 388 if(macroName != '') { 389 attributes.id = macroName+"."+objName; 390 } 391 createdNames.push(objName); 392 } 393 } 394 obj = this.create('intersection',[defElements[0],defElements[1],0],attributes); 395 output.intersections.push(obj); 396 if(objName != '') { 397 output[attributes.name] = obj; 398 } 399 } 400 else { 401 if(objName != '') { 402 attributes.name = objName+"_1"; 403 if(mode == 'macro') { 404 if(macroName != '') { 405 attributes.id = macroName+"."+objName+"_1"; 406 } 407 createdNames.push(objName+"_1"); 408 } 409 } 410 obj = this.create('intersection',[defElements[0],defElements[1],0],attributes); 411 output.intersections.push(obj); 412 if(objName != '') { 413 output[attributes.name] = obj; 414 } 415 if(objName != '') { 416 attributes.name = objName+"_2"; 417 if(mode == 'macro') { 418 if(macroName != '') { 419 attributes.id = macroName+"."+objName+"_2"; 420 } 421 createdNames.push(objName+"_2"); 422 } 423 } 424 obj = this.create('intersection',[defElements[0],defElements[1],1],attributes); 425 output.intersections.push(obj); 426 if(objName != '') { 427 output[attributes.name] = obj; 428 } 429 } 430 } 431 else if(splitted[i].search(/\|[\|_]\s*\(/) != -1) { // Parallele oder Senkrechte 432 splitted[i].match(/\|([\|_])\s*\(\s*(\S*)\s*,\s*(\S*)\s*\)/); 433 type = RegExp.$1; 434 if(type == '|') { 435 type = 'parallel'; 436 } 437 else { // type == '_' 438 type = 'normal'; 439 } 440 defElements = []; 441 defElements[0] = RegExp.$2; 442 defElements[1] = RegExp.$3; 443 if(mode == 'macro') { 444 for(j=0; j<=1; j++) { 445 if(macroName != '') { 446 for(k=0; k<createdNames.length; k++) { // vorher oder nachher? 447 if(defElements[j] == createdNames[k]) { 448 defElements[j] = macroName+"."+createdNames[k]; 449 } 450 } 451 } 452 for(k=0; k<params.length; k++) { 453 if(defElements[j] == params[k]) { 454 defElements[j] = paraIn[k]; 455 } 456 } 457 } 458 } 459 if(objName != '') { 460 attributes.name = objName; 461 if(!JXG.exists(attributes.withLabel)) { 462 attributes.withLabel = true; 463 } 464 if(mode == 'macro') { 465 if(macroName != '') { 466 attributes.id = macroName+"."+objName; 467 } 468 createdNames.push(objName); 469 } 470 } 471 output.lines.push(this.create(type, 472 [JXG.getReference(this,defElements[0]),JXG.getReference(this,defElements[1])], 473 attributes)); 474 475 if(objName != '') { 476 output[objName] = output.lines[output.lines.length-1]; 477 } 478 } 479 else if(splitted[i].search(/^</) != -1) { // Winkel 480 splitted[i].match(/<\s*\(\s*(\S*)\s*,\s*(\S*)\s*,\s*(\S*)\s*\)/); 481 defElements = []; 482 defElements[0] = RegExp.$1; 483 defElements[1] = RegExp.$2; 484 defElements[2] = RegExp.$3; 485 if(mode == 'macro') { 486 for(j=0; j<=2; j++) { 487 if(macroName != '') { 488 for(k=0; k<createdNames.length; k++) { // vorher oder nachher? 489 if(defElements[j] == createdNames[k]) { 490 defElements[j] = macroName+"."+createdNames[k]; 491 } 492 } 493 } 494 for(k=0; k<params.length; k++) { 495 if(defElements[j] == params[k]) { 496 defElements[j] = paraIn[k]; 497 } 498 } 499 } 500 } 501 if(objName == '') { 502 output.lines.push(this.create('angle', 503 [JXG.getReference(this,defElements[0]), 504 JXG.getReference(this,defElements[1]), 505 JXG.getReference(this,defElements[2])], 506 attributes)); 507 } 508 else { 509 possibleNames = ['alpha', 'beta', 'gamma', 'delta', 'epsilon', 'zeta', 'eta', 'theta', 510 'iota', 'kappa', 'lambda', 'mu', 'nu', 'xi', 'omicron', 'pi', 'rho', 511 'sigmaf', 'sigma', 'tau', 'upsilon', 'phi', 'chi', 'psi', 'omega']; 512 type = ''; 513 for(j=0; j<possibleNames.length;j++) { 514 if(objName == possibleNames[j]) { 515 attributes.text = '&'+objName+';'; 516 attributes.name = '&'+objName+';'; 517 type = 'greek'; 518 break; 519 } 520 else { 521 if(j == possibleNames.length -1) { 522 attributes.text = objName; 523 attributes.name = objName; 524 } 525 } 526 } 527 if(!JXG.exists(attributes.withLabel)) { 528 attributes.withLabel = true; 529 } 530 if(mode == 'macro') { 531 if(macroName != '') { 532 attributes.id = macroName+"."+objName; 533 } 534 createdNames.push(objName); 535 } 536 output.angles.push(this.create('angle', 537 [JXG.getReference(this,defElements[0]), 538 JXG.getReference(this,defElements[1]), 539 JXG.getReference(this,defElements[2])], 540 attributes)); 541 output[objName] = output.angles[output.angles.length-1]; 542 } 543 } 544 else if(splitted[i].search(/([0-9]+)\/([0-9]+)\(\s*(\S*)\s*,\s*(\S*)\s*\)/) != -1) { // Punkt mit Teilverhaeltnis, z.B. Mittelpunkt 545 defElements = []; 546 defElements[0] = 1.0*(RegExp.$1)/(1.0*(RegExp.$2)); 547 defElements[1] = RegExp.$3; 548 defElements[2] = RegExp.$4; 549 if(mode == 'macro') { 550 for(j=1; j<=2; j++) { 551 if(macroName != '') { 552 for(k=0; k<createdNames.length; k++) { // vorher oder nachher? 553 if(defElements[j] == createdNames[k]) { 554 defElements[j] = macroName+"."+createdNames[k]; 555 } 556 } 557 } 558 for(k=0; k<params.length; k++) { 559 if(defElements[j] == params[k]) { 560 defElements[j] = paraIn[k]; 561 } 562 } 563 } 564 } 565 defElements[1] = JXG.getReference(this,RegExp.$3); 566 defElements[2] = JXG.getReference(this,RegExp.$4); 567 obj = []; 568 obj[0] = (function(el, board) { return function() { 569 return (1-el[0])*el[1].coords.usrCoords[1]+el[0]*el[2].coords.usrCoords[1]; 570 }} 571 )(defElements, this); 572 obj[1] = (function(el, board) { return function() { 573 return (1-el[0])*el[1].coords.usrCoords[2]+el[0]*el[2].coords.usrCoords[2]; 574 }} 575 )(defElements, this); 576 if(objName != '') { 577 attributes.name = objName; 578 if(mode == 'macro') { 579 if(macroName != '') { 580 attributes.id = macroName+"."+objName; 581 } 582 createdNames.push(objName); 583 } 584 } 585 output.points.push(this.create('point',[obj[0],obj[1]],attributes)); 586 if(objName != '') { 587 output[objName] = output.points[output.points.length-1]; 588 } 589 } 590 else if(splitted[i].search(/(\S*)\s*:\s*(.*)/) != -1) { // Funktionsgraph 591 objName = RegExp.$1; 592 tmp = JXG.GeonextParser.geonext2JS(RegExp.$2, this); 593 defElements = [new Function('x','var y = '+tmp+'; return y;')]; 594 attributes.name = objName; 595 output.functions.push(this.create('functiongraph',defElements,attributes)); 596 output[objName] = output.functions[output.functions.length-1]; 597 } 598 else if(splitted[i].search(/#(.*)\(\s*([0-9])\s*[,|]\s*([0-9])\s*\)/) != -1) { // Text element 599 defElements = []; // [0-9\.\-]+ 600 defElements[0] = RegExp.$1; 601 defElements[1] = 1.0*RegExp.$2; 602 defElements[2] = 1.0*RegExp.$3; 603 defElements[0] = defElements[0].replace (/^\s+/, '').replace (/\s+$/, ''); // trim 604 output.texts.push(this.create('text',[defElements[1],defElements[2],defElements[0]], attributes)); 605 } 606 else if(splitted[i].search(/(\S*)\s*\[(.*)\]/) != -1) { // Polygon 607 attributes.name = RegExp.$1; 608 if(!JXG.exists(attributes.withLabel)) { 609 attributes.withLabel = true; 610 } 611 defElements = RegExp.$2; 612 defElements = defElements.split(','); 613 for(j=0; j<defElements.length; j++) { 614 defElements[j] = defElements[j].replace (/^\s+/, '').replace (/\s+$/, ''); // trim 615 if(mode == 'macro') { 616 if(macroName != '') { 617 for(k=0; k<createdNames.length; k++) { // vorher oder nachher? 618 if(defElements[j] == createdNames[k]) { 619 defElements[j] = macroName+"."+createdNames[k]; 620 } 621 } 622 } 623 for(k=0; k<params.length; k++) { 624 if(defElements[j] == params[k]) { 625 defElements[j] = paraIn[k]; 626 } 627 } 628 } 629 defElements[j] = JXG.getReference(this,defElements[j]); 630 } 631 output.polygons.push(this.create('polygon',defElements,attributes)); 632 output[attributes.name] = output.polygons[output.polygons.length-1]; 633 } 634 } 635 } 636 } 637 } 638 } 639 this.update(); 640 return output; 641 }; 642 643 /** 644 * Parses a string like<br /> 645 * <tt><macro-name> = Macro(A, B, C) { <Command in JSXGraph Construction syntax>; ...<Command in JXG-Construct syntax>; }</tt><br /> 646 * and adds it as a macro so it can be used in the JSXGraph Construction Syntax. 647 * @param {String} string A string like the one in the methods description. 648 * @see #construct 649 */ 650 JXG.Board.prototype.addMacro = function(string) { 651 var defHead, defBody, defName = '', i; 652 string.match(/(.*)\{(.*)\}/); 653 defHead = RegExp.$1; 654 defBody = RegExp.$2; 655 if(defHead.search(/=/) != -1) { 656 defHead.match(/\s*(\S*)\s*=.*/); 657 defName = RegExp.$1; 658 defHead = (defHead.split('='))[1]; 659 } 660 defHead.match(/Macro\((.*)\)/); 661 defHead = RegExp.$1; 662 defHead = defHead.split(','); 663 for(i=0; i < defHead.length; i++) { 664 defHead[i].match(/\s*(\S*)\s*/); 665 defHead[i] = RegExp.$1; 666 } 667 668 if(this.definedMacros == null) { 669 this.definedMacros = {}; 670 this.definedMacros.macros = []; 671 } 672 673 this.definedMacros.macros.push([defName, defHead, defBody]); 674 if(defName != '') { 675 this.definedMacros.defName = this.definedMacros.macros[this.definedMacros.macros.length-1]; 676 } 677 }; 678