1// ---------------------------------------------------------------------------------------------------------------- 2// Dimension 3// ---------------------------------------------------------------------------------------------------------------- 4function Dimension(A, B) 5{ 6 var kAligned = 0; 7 var kHorizontal = 1; 8 var kVertical = 2; 9 var kAngle = 3; 10 11 this.scene = null; 12 this.selected = false; 13 this.A = A; 14 this.B = B; 15 this.textPoint = avg(A,B); 16 this.center = avg(A,B); // for angles 17 this.alignment = kAligned; 18 this.decimals = 2; 19 this.text = "{value.toFixed(1)}cm"; 20 this.appearance = new Appearance(); 21 this.visible = true; 22 this.frozen = false; 23 this.onChangeListeners = []; 24 this.boundsMin = new Vector(Number.MAX_VALUE,Number.MAX_VALUE); 25 this.boundsMax = new Vector(-Number.MAX_VALUE,-Number.MAX_VALUE); 26 27 this.getBoundsMin = function() 28 { 29 return this.boundsMin; 30 } 31 32 this.getBoundsMax = function() 33 { 34 return this.boundsMax; 35 } 36 37 this.saveAsJavascript = function() 38 { 39 var str = "var dim = new Dimension("; 40 41 str += "new Vector(" + this.A.x + ", " + this.A.y + ")"; 42 str += ", new Vector(" + this.B.x + ", " + this.B.y + ")"; 43 str += ");\n"; 44 45 str += this.appearance.saveAsJavascript("dim"); 46 str += "dim.textPoint = new Vector(" + this.textPoint.x + ", " + this.textPoint.y + ");\n"; 47 str += "dim.center = new Vector(" + this.center.x + ", " + this.center.y + ");\n"; 48 str += "dim.alignment = " + this.alignment + ";\n"; 49 str += "dim.lineOffset = " + this.lineOffset + ";\n"; 50 str += "dim.textOffset = " + this.textOffset + ";\n"; 51 str += "dim.text = \"" + this.text + "\";\n"; 52 str += "dim.visible = " + this.visible + ";\n"; 53 str += "dim.frozen = " + this.frozen + ";\n"; 54 55 if (this.name != undefined) 56 { 57 str += "dim.name = \"" + this.name + "\";\n"; 58 } 59 60 str += "scene.addObject(dim);\n"; 61 return str; 62 } 63 64 this.addChangeListener = function(listener) 65 { 66 this.onChangeListeners.push(listener); 67 } 68 69 this.onChange = function(changeDetails) 70 { 71 // Backwards compatibility 72 this.appearance.SetFromOldProperties(this); 73 74 var extensionLineDir; 75 76 if (this.alignment == kHorizontal) 77 { 78 extensionLineDir = new Vector(0, -1); 79 } 80 else if (this.alignment == kVertical) 81 { 82 extensionLineDir = new Vector(1, 0); 83 } 84 else 85 { 86 extensionLineDir = transpose(sub(this.B, this.A).unit()); 87 } 88 89 if (this.alignment == kAngle) 90 { 91 var radius = distance(this.textPoint, this.center); 92 93 var dirA = sub(this.A, this.center).unit(); 94 var dirB = sub(this.B, this.center).unit(); 95 96 var pA = mad(dirA, radius, this.center); 97 var pB = mad(dirB, radius, this.center); 98 var pM = mad(avg(dirA, dirB).unit(), radius, this.center); 99 100 this.boundsMin = pA; 101 this.boundsMax = pA; 102 103 this.boundsMin = min(pB, this.boundsMin); 104 this.boundsMax = max(pB, this.boundsMax); 105 106 this.boundsMin = min(pM, this.boundsMin); 107 this.boundsMax = max(pM, this.boundsMax); 108 } 109 else 110 { 111 var offsetA = dot(sub(this.textPoint, this.A), extensionLineDir); 112 var offsetB = dot(sub(this.textPoint, this.B), extensionLineDir); 113 114 var pA1 = mad(extensionLineDir, offsetA, this.A); 115 var pB1 = mad(extensionLineDir, offsetB, this.B); 116 117 var t0 = dot(sub(this.textPoint, pA1), sub(pB1, pA1)) / distanceSqr(pB1, pA1); 118 119 var pX1 = mad(sub(pB1, pA1), t0, pA1); 120 121 this.boundsMin = this.A; 122 this.boundsMax = this.A; 123 124 this.boundsMin = min(this.B, this.boundsMin); 125 this.boundsMax = max(this.B, this.boundsMax); 126 127 this.boundsMin = min(pA1, this.boundsMin); 128 this.boundsMax = max(pA1, this.boundsMax); 129 130 this.boundsMin = min(pB1, this.boundsMin); 131 this.boundsMax = max(pB1, this.boundsMax); 132 133 this.boundsMin = min(pX1, this.boundsMin); 134 this.boundsMax = max(pX1, this.boundsMax); 135 } 136 137 for (var i=0; i!=this.onChangeListeners.length; ++i) 138 { 139 this.onChangeListeners[i](this, changeDetails); 140 } 141 } 142 143 this.draw = function(camera) 144 { 145 if (this.A == undefined || this.B == undefined) 146 return; 147 148 if (this.alignment == kAngle) 149 { 150 var radius = distance(this.textPoint, this.center); 151 152 var angleA = toAngle(sub(this.A, this.center)); 153 var angleB = toAngle(sub(this.B, this.center)); 154 155 var angleMin = Math.min(angleA, angleB); 156 var angleMax = Math.max(angleA, angleB); 157 158 camera.drawArc(this.center, radius, angleMin, angleMax, this.appearance.GetLineColor(), this.appearance.GetLineWidth(this.selected), undefined, undefined, 20, 20) 159 160 var text = this.text; 161 162 var angleDeg = toDegrees(angleMax - angleMin); 163 164 var value = angleDeg; 165 166 var expr = /{(.*)}/.exec(this.text); 167
168 var valueStr = "invalid expr"; 169 170 if (expr != null && expr.length == 2) 171 { 172 valueStr = eval(expr[1]); 173 } 174 175 text = this.text.replace(/{.*}/, valueStr ); 176 177 var textDir = sub(this.textPoint, this.center).unit(); 178 179 var textAnchor = mad( textDir, camera.invScale(5), this.textPoint); 180 181 var textHAlign = (textDir.x > 0) ? "left" : "right"; 182 var textVAlign = (textDir.y > 0) ? "bottom" : "top"; 183 184 var textAngle = 0; 185 186 camera.drawText(textAnchor, text, "#000000", textHAlign, textAngle, undefined, textVAlign); 187 } 188 else 189 { 190 var extensionLineDir; 191 192 if (this.alignment == kHorizontal) 193 { 194 extensionLineDir = new Vector(0, -1); 195 } 196 else if (this.alignment == kVertical) 197 { 198 extensionLineDir = new Vector(1, 0); 199 } 200 else 201 { 202 extensionLineDir = transpose(sub(this.B, this.A).unit()); 203 } 204 205 var offsetA = dot(sub(this.textPoint, this.A), extensionLineDir); 206 var offsetB = dot(sub(this.textPoint, this.B), extensionLineDir); 207 208 var pA0 = mad(extensionLineDir, Math.sign(offsetA) * camera.invScale(5), this.A); 209 var pA1 = mad(extensionLineDir, offsetA, this.A); 210 var pA2 = mad(extensionLineDir, offsetA + Math.sign(offsetA) * camera.invScale(5), this.A); 211 212 var pB0 = mad(extensionLineDir, Math.sign(offsetB) * camera.invScale(5), this.B); 213 var pB1 = mad(extensionLineDir, offsetB, this.B); 214 var pB2 = mad(extensionLineDir, offsetB + Math.sign(offsetB) * camera.invScale(5), this.B); 215 216 var t0 = dot(sub(this.textPoint, pA1), sub(pB1, pA1)) / distanceSqr(pB1, pA1); 217 218 var pX0 = (t0>=1) ? pB1 : (t0<=0) ? pA1 : mad(sub(pB1, pA1), t0, pA1); 219 var pX1 = mad(sub(pB1, pA1), t0, pA1); 220 221 camera.drawLine(pA0, pA2, this.appearance.GetLineColor(), this.appearance.GetLineWidth(this.selected)); 222 camera.drawLine(pB0, pB2, this.appearance.GetLineColor(), this.appearance.GetLineWidth(this.selected)); 223 camera.drawLine(pX0, pX1, this.appearance.GetLineColor(), this.appearance.GetLineWidth(this.selected)); 224 225 camera.drawArrow(avg(pA1, pB1), pA1, 20, this.appearance.GetLineColor(), this.appearance.GetLineWidth(this.selected)); 226 camera.drawArrow(avg(pA1, pB1), pB1, 20, this.appearance.GetLineColor(), this.appearance.GetLineWidth(this.selected)); 227 228 var textAlign = "center"; 229 230 if (t0>1) 231 { 232 textAlign = "right"; 233 } 234 else if (t0<0) 235 { 236 textAlign = "left"; 237 } 238 239 var textAngle = toAngle(transpose(extensionLineDir)); 240 241 var factor = -1; 242 243 if (textAngle > Math.PI / 2 || textAngle <= -Math.PI / 2) 244 { 245 textAngle -= Math.PI; 246 factor = 1; 247 } 248 249 var textAnchor = this.textPoint; 250 textAnchor = mad(extensionLineDir.neg(), factor * camera.invScale(5), textAnchor); 251 252 var dist = distance(this.A, this.B); 253 254 if (this.alignment == kHorizontal) 255 dist = abs(this.A.x - this.B.x); 256 else if (this.alignment == kVertical) 257 dist = abs(this.A.y - this.B.y); 258 259 var text = this.text; 260 261 var value = dist; 262 263 var expr = /{(.*)}/.exec(this.text); 264 265 var valueStr = "invalid expr"; 266 267 if (expr != null && expr.length == 2) 268 { 269 valueStr = eval(expr[1]); 270 } 271 272 text = this.text.replace(/{.*}/, valueStr ); 273 274 camera.drawText(textAnchor, text, "#000000", textAlign, textAngle); 275 } 276 } 277 278 this.hitTest = function(a, b, camera) 279 { 280 if (this.alignment == kAngle) 281 { 282 var radius = distance(this.textPoint, this.center); 283 284 var angleA = toAngle(sub(this.A, this.center)); 285 var angleB = toAngle(sub(this.B, this.center)); 286 287 var angleMin = Math.min(angleA, angleB); 288 var angleMax = Math.max(angleA, angleB); 289 290 if (overlapRectArc(a, b, this.center, radius, angleMin, angleMax)) 291 return true; 292 } 293 else 294 { 295 var extensionLineDir; 296 297 if (this.alignment == kHorizontal) 298 { 299 extensionLineDir = new Vector(0, -1); 300 } 301 else if (this.alignment == kVertical) 302 { 303 extensionLineDir = new Vector(1, 0); 304 } 305 else 306 { 307 extensionLineDir = transpose(sub(this.B, this.A).unit()); 308 } 309 310 var offsetA = dot(sub(this.textPoint, this.A), extensionLineDir); 311 var offsetB = dot(sub(this.textPoint, this.B), extensionLineDir); 312 313 var pA1 = mad(extensionLineDir, offsetA, this.A); 314 var pB1 = mad(extensionLineDir, offsetB, this.B); 315 316 var pA2 = mad(extensionLineDir, offsetA + Math.sign(offsetA) * camera.invScale(5), this.A); 317 var pB2 = mad(extensionLineDir, offsetB + Math.sign(offsetB) * camera.invScale(5), this.B); 318
319 var t0 = dot(sub(this.textPoint, pA1), sub(pB1, pA1)) / distanceSqr(pB1, pA1); 320 321 var pX0 = (t0>=1) ? pB1 : (t0<=0) ? pA1 : mad(sub(pB1, pA1), t0, pA1); 322 var pX1 = mad(sub(pB1, pA1), t0, pA1); 323 324 if ( overlapRectLine(a, b, this.A, pA2) || 325 overlapRectLine(a, b, this.B, pB2) || 326 overlapRectLine(a, b, pA2, pB2) || 327 overlapRectLine(a, b, pX0, pX1) ) 328 return true; 329 } 330 331 return false; 332 } 333 334 this.getSnapPoints = function () 335 { 336 var points = []; 337 338 points.push( { type: "node", p: this.A} ); 339 points.push( { type: "node", p: this.B} ); 340 341 if (this.alignment == kAngle) 342 { 343 points.push( { type: "node", p: this.center } ); 344 } 345 else 346 { 347 } 348 349 return points; 350 } 351 352 this.getDragPoints = function(localSpace, camera) 353 { 354 if (this.isFrozen()) 355 return []; 356 357 var points = [ ]; 358 359 points.push( this.textPoint ); 360 points.push( this.A ); 361 points.push( this.B ); 362 363 if (this.alignment == kAngle) 364 { 365 points.push( this.center ); 366 } 367 368 return points; 369 } 370 371 this.drawDragPoint = function(camera, index, position, localSpace, alpha) 372 { 373 if (alpha == undefined) 374 alpha = 1; 375 376 camera.drawRectangle(position, camera.invScale(10), "rgba(255,0,0," + alpha + ")", 2); 377 } 378 379 this.setDragPointPos = function(index, p, localSpace, dragStartPoint, camera) 380 { 381 if (index == 0) 382 { 383 if (localSpace && this.alignment != kAngle) 384 { 385 if ( ( p.x <= Math.min(this.A.x, this.B.x) || p.x >= Math.max(this.A.x, this.B.x) ) && ( p.y >= Math.min(this.A.y, this.B.y) && p.y <= Math.max(this.A.y, this.B.y) ) ) 386 { 387 this.alignment = kVertical; 388 } 389 else if ( ( p.y <= Math.min(this.A.y, this.B.y) || p.y >= Math.max(this.A.y, this.B.y) ) && ( p.x >= Math.min(this.A.x, this.B.x) && p.x <= Math.max(this.A.x, this.B.x) ) ) 390 { 391 this.alignment = kHorizontal; 392 } 393 else 394 { 395 this.alignment = kAligned; 396 } 397 } 398 399 this.textPoint = p; 400 } 401 else if (index == 1 || index == 2) 402 { 403 var textRelPos = dot( sub(this.textPoint, this.A), sub(this.B, this.A) ) / distanceSqr(this.A, this.B); 404 var textOffset = dot( sub(this.textPoint, this.A), transpose( sub(this.B, this.A).unit() ) ); 405 406 if (this.alignment == kHorizontal) 407 textRelPos = (this.textPoint.x - this.A.x) / (this.B.x - this.A.x); 408 else if (this.alignment == kVertical) 409 textRelPos = (this.textPoint.y - this.A.y) / (this.B.y - this.A.y); 410 411 if (index == 1) 412 this.A = p; 413 else 414 this.B = p; 415 416 417 if (this.point1dir != undefined && this.point2dir != undefined) 418 { 419 var dirDot = dot(this.point1dir, this.point2dir); 420 421 if (Math.abs(dirDot) != 1) 422 { 423 var rayDir = this.point1dir; 424 425 var intersection = intersectRayRay(this.A, rayDir, this.B, this.point2dir, true); 426 427 if (intersection.hit) 428 { 429 this.alignment = kAngle; 430 this.center = intersection.P; 431 432 if (this.pointCount == 1) 433 { 434 this.text = "{value.toFixed(0)}°"; 435 this.decimals = 0; 436 } 437 } 438 } 439 } 440 441 if (this.alignment == kAligned) 442 { 443 this.textPoint = mad( sub(this.B, this.A), textRelPos, mad( transpose( sub(this.B, this.A).unit() ), textOffset, this.A ) ); 444 } 445 else if (this.alignment == kHorizontal && textRelPos>=0 && textRelPos<=1) 446 { 447 this.textPoint.x = lerp(this.A.x, this.B.x, textRelPos); 448 } 449 else if (this.alignment == kVertical && textRelPos>=0 && textRelPos<=1) 450 { 451 this.textPoint.y = lerp(this.A.y, this.B.y, textRelPos); 452 } 453 } 454 else if (index == 3) 455 { 456 this.center = p; 457 } 458 459 this.onChange(); 460 } 461 462 this.getOrigin = function() 463 { 464 return this.A; 465 } 466 467 this.setOrigin = function(p) 468 { 469 var delta = sub(p, this.A); 470 471 this.A = add(this.A, delta); 472 this.B = add(this.B, delta); 473 this.textPoint = add(this.textPoint, delta); 474 475 if (this.center !== undefined) 476 { 477 this.center = add(this.center, delta); 478 } 479 480 this.onChange(); 481 } 482 483 this.getProperties = function() 484 { 485 var appearanceControl = new PopoutContainer(undefined, "images/color_wheel.svg"); 486 { 487 appearanceControl.addControl("", new AppearanceControl(this.appearance, true, false, function(){ this.onChange(); }.bind(this)) ); 488 } 489 490 return [ 491 { name: "Appearance", control:appearanceControl }, 492 { name: "Align", control: new Dropdown(["Aligned", "Horizontal", "Vertical", "Angle"], this.alignment, function (value) { this.alignment = value; this.onChange(); }.bind(this)) }, 493 { name: "Decimals", control: new PopoutSlider(0, 5, this.decimals, 1, function (value) { this.decimals = value; this.onChange(); }.bind(this)) }, 494 { name: "Text", control: new TextBox(this.text, true, false, 64, function (value) { this.text = value; this.onChange(); }.bind(this)) }, 495 ]; 496 } 497 498 this.toggleVisibility = function(v) 499 { 500 var newVisible = (v!==undefined) ? v : !this.visible; 501 if (this.visible != newVisible) 502 { 503 this.visible = newVisible; 504 this.onChange(); 505 } 506 } 507 508 this.isVisible = function() 509 { 510 return this.visible; 511 } 512 513 this.toggleFrozen = function(f) 514 { 515 this.frozen = (f!==undefined) ? f : !this.frozen; 516 this.onChange(); 517 } 518 519 this.isFrozen = function() 520 { 521 return this.frozen; 522 } 523 524 this.setSelected = function(selected) 525 { 526 this.selected = selected; 527 } 528 529 this.isSelected = function() 530 { 531 return this.selected; 532 } 533 534 this.onChange(); 535}
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.