diff --git a/web/app/math/math.js b/web/app/math/math.js index a5ccbf36..bd1b3e0f 100644 --- a/web/app/math/math.js +++ b/web/app/math/math.js @@ -39,6 +39,12 @@ export function distanceSquared3(x1, y1, z1, x2, y2, z2) { return dx * dx + dy * dy + dz * dz; } +export function distanceSquared(x1, y1, x2, y2) { + const dx = x1 - x2; + const dy = y1 - y2; + return dx * dx + dy * dy; +} + export function circleFromPoints(p1, p2, p3) { var center = new Vector(); var offset = p2.x*p2.x + p2.y*p2.y; diff --git a/web/app/sketcher/shapes/dim.js b/web/app/sketcher/shapes/dim.js index f481c0fc..c089faee 100644 --- a/web/app/sketcher/shapes/dim.js +++ b/web/app/sketcher/shapes/dim.js @@ -1,7 +1,10 @@ -import * as utils from '../../utils/utils' import * as math from '../../math/math' import Vector from 'math/vector'; import {SketchObject} from './sketch-object' +import {Styles} from "../styles"; +import {_90} from "../../math/math"; +import {_270} from "../../math/math"; +import {makeAngle0_360} from "../../math/math"; class LinearDimension extends SketchObject { @@ -10,6 +13,9 @@ class LinearDimension extends SketchObject { this.a = a; this.b = b; this.flip = false; + this.offset = 15; + this.pickA = []; + this.pickB = []; } visitParams(callback) { @@ -20,6 +26,20 @@ class LinearDimension extends SketchObject { } translateImpl(dx, dy) { + + const [_ax, _ay] = this.pickA; + const [_bx, _by] = this.pickB; + + let _vx = - (_by - _ay); + let _vy = _bx - _ax; + + const d = math.distance(_ax, _ay, _bx, _by); + + //normalize + let _vxn = _vx / d; + let _vyn = _vy / d; + + this.offset += (dx * _vxn + dy * _vyn) * this.unscale; } getA() { return this.a } @@ -27,43 +47,45 @@ class LinearDimension extends SketchObject { drawImpl(ctx, scale, viewer) { + const marked = this.markers.length !== 0; + + if (marked) { + ctx.save(); + viewer.setStyle(Styles.HIGHLIGHT, ctx); + } + const dimScale = viewer.dimScale; const unscale = 1 /scale; - const off = unscale * 15; + const off = unscale * this.offset; const textOff = unscale * 3; // getTextOff(dimScale); - - var a, b, startA, startB; - if (this.flip) { - a = this.getB(); - b = this.getA(); - startA = this.b; - startB = this.a; - } else { - a = this.getA(); - b = this.getB(); - startA = this.a; - startB = this.b; - } - + + this.unscale = scale; + + let a, b, startA, startB; + a = this.getB(); + b = this.getA(); + startA = this.b; + startB = this.a; + const d = math.distanceAB(a, b); - - var _vx = - (b.y - a.y); - var _vy = b.x - a.x; + + let _vx = - (b.y - a.y); + let _vy = b.x - a.x; //normalize - var _vxn = _vx / d; - var _vyn = _vy / d; + let _vxn = _vx / d; + let _vyn = _vy / d; _vx = _vxn * off; _vy = _vyn * off; ctx.beginPath(); - - var _ax = a.x + _vx; - var _ay = a.y + _vy; - var _bx = b.x + _vx; - var _by = b.y + _vy; + + let _ax = a.x + _vx; + let _ay = a.y + _vy; + let _bx = b.x + _vx; + let _by = b.y + _vy; ctx.moveTo(_ax, _ay); ctx.lineTo(_bx, _by); @@ -98,10 +120,14 @@ class LinearDimension extends SketchObject { ctx.fill(); } - function drawExtensionLine(x, y, nx, ny, width) { + function drawExtensionLine(x, y, nx, ny, width, tip) { ctx.beginPath(); ctx.moveTo(x + ny * arrowW, y + -nx * arrowW); - ctx.lineTo(x + ny * (arrowW + width), y + -nx * (arrowW + width)); + + tip[0] = x + ny * (arrowW + width); + tip[1] = y + -nx * (arrowW + width); + + ctx.lineTo(tip[0], tip[1]); ctx.closePath(); ctx.stroke(); } @@ -119,12 +145,20 @@ class LinearDimension extends SketchObject { const innerMode = modelTextWidth <= availableArea; + let rot = makeAngle0_360(Math.atan2(-_vxn, _vyn)); + const flip = rot > _90 && rot < _270; + if (flip) { + rot += Math.PI; + } let tx, ty; if (innerMode) { drawArrow(_ax, _ay, _vxn, _vyn); drawArrow(_bx, _by, -_vxn, -_vyn); + this.pickA[0] = _ax; this.pickA[1] = _ay; + this.pickB[0] = _bx; this.pickB[1] = _by; + const h = d/2 - modelTextWidth/2; tx = (_ax + _vxn * textOff) - (- _vyn) * h; ty = (_ay + _vyn * textOff) - ( _vxn) * h; @@ -133,24 +167,59 @@ class LinearDimension extends SketchObject { drawArrow(_bx, _by, _vxn, _vyn); const outerArrowToTextPaddingPx = 6; - drawExtensionLine(_bx, _by, _vxn, _vyn, modelTextWidth + 2 * outerArrowToTextPaddingPx * unscale); - drawExtensionLine(_ax, _ay, -_vxn, -_vyn, outerArrowToTextPaddingPx * unscale); - + drawExtensionLine(_ax, _ay, -_vxn, -_vyn, outerArrowToTextPaddingPx * unscale, this.pickA); + drawExtensionLine(_bx, _by, _vxn, _vyn, modelTextWidth + 2 * outerArrowToTextPaddingPx * unscale, this.pickB); tx = (_bx + _vxn * textOff) - (- _vyn) * (arrowWpx + outerArrowToTextPaddingPx) * unscale; ty = (_by + _vyn * textOff) - ( _vxn) * (arrowWpx + outerArrowToTextPaddingPx) * unscale; } + ctx.save(); ctx.translate(tx, ty); - ctx.rotate( - Math.atan2(_vxn, _vyn)); + if (flip) { + ctx.translate(_vyn * modelTextWidth - _vxn * 2 *textOff, -_vxn * modelTextWidth - _vyn * 2*textOff); + } + + ctx.rotate(rot); ctx.scale(unscale, -unscale); ctx.fillText(txt, 0, 0); ctx.restore(); + if (marked) { + ctx.restore(); + } + } - normalDistance(aim) { - return -1; + normalDistance(aim, scale) { + + const [_ax, _ay] = this.pickA; + const [_bx, _by] = this.pickB; + + let _vx = - (_by - _ay); + let _vy = _bx - _ax; + + const d = math.distance(_ax, _ay, _bx, _by); + + //normalize + let _vxn = _vx / d; + let _vyn = _vy / d; + + let avx = aim.x - _ax; + let avy = aim.y - _ay; + + const proj = avx * _vyn + avy * (-_vxn); + + //Check if vector b lays on the vector ab + if (proj > d) { + return -1; + } + + if (proj < 0) { + return -1; + } + + return Math.abs(avx * _vxn + avy * _vyn); } } diff --git a/web/app/sketcher/tools/drag.js b/web/app/sketcher/tools/drag.js index dab5dc67..bd1f200b 100644 --- a/web/app/sketcher/tools/drag.js +++ b/web/app/sketcher/tools/drag.js @@ -14,19 +14,19 @@ export class DragTool extends Tool { } mousemove(e) { - var x = this._point.x; - var y = this._point.y; + let x = this._point.x; + let y = this._point.y; this.viewer.screenToModel2(e.offsetX, e.offsetY, this._point); - var dx = this._point.x - x; - var dy = this._point.y - y; - // for (var i = 0; i < this.lockedShifts.length; i += 2) { + let dx = this._point.x - x; + let dy = this._point.y - y; + // for (let i = 0; i < this.lockedShifts.length; i += 2) { // this.lockedValues[i] = this._point.x - this.lockedShifts[i]; // this.lockedValues[i + 1] = this._point.y - this.lockedShifts[i + 1]; // } this.obj.translate(dx, dy); // this.viewer.parametricManager.setConstantsFromGeometry(this.obj); - if (!Tool.dumbMode(e)) { + if (!Tool.dumbMode(e) || this.obj.constraints.length !== 0) { // this.viewer.parametricManager.prepare(); this.viewer.parametricManager.solve(true); } @@ -40,9 +40,10 @@ export class DragTool extends Tool { this.origin.x = e.offsetX; this.origin.y = e.offsetY; this.viewer.screenToModel2(e.offsetX, e.offsetY, this._point); - - this.viewer.parametricManager.algNumSystem.controlBounds = true; - this.viewer.parametricManager.prepare([this.obj]); + if (this.obj.constraints.length !== 0) { + this.viewer.parametricManager.algNumSystem.controlBounds = true; + this.viewer.parametricManager.prepare([this.obj]); + } } mouseup(e) { @@ -50,7 +51,7 @@ export class DragTool extends Tool { this.viewer.refresh(); this.viewer.parametricManager.algNumSystem.controlBounds = false; this.viewer.toolManager.releaseControl(); - var traveled = math.distance(this.origin.x, this.origin.y, e.offsetX, e.offsetY); + let traveled = math.distance(this.origin.x, this.origin.y, e.offsetX, e.offsetY); if (traveled >= 10) { this.viewer.historyManager.lightCheckpoint(10); } @@ -60,96 +61,4 @@ export class DragTool extends Tool { mousewheel(e) { } - solveRequest(rough) { - var paramsToUpdate = []; - this.viewer.accept(function (obj) { - if (obj.aux !== true) { - if (obj.recoverIfNecessary()){ - obj.collectParams(paramsToUpdate); - } - } - return true; - }); - - if (paramsToUpdate.length != 0) { - for (var i = 0; i < paramsToUpdate.length; i++) { - this.solver.updateParameter(paramsToUpdate[i]); - } - this.solver.solve(rough, 1); - } - } - - getParamsToLock() { - var params = []; - this.obj.accept(function (obj) { - if (obj._class === 'TCAD.TWO.EndPoint' && !obj.fullyConstrained) { - params.push(obj._x); - params.push(obj._y); - } - return true; - }); - return params; - } - - prepareSolver(extraConstraints) { - var locked = this.getParamsToLock(); - this.lockedShifts = []; - this.lockedValues = []; - for (var i = 0; i < locked.length; i += 2) { - this.lockedShifts[i] = this._point.x - locked[i].get(); - this.lockedShifts[i + 1] = this._point.y - locked[i + 1].get(); - } - this.solver = this.viewer.parametricManager.prepare(locked, extraConstraints); - //this.enableRecording(); - } - - enableRecording() { - var solver = this.solver; - DragTool.snapshots = []; - optim.DEBUG_HANDLER = () => { - DragTool.snapshots.push([]); - for (var i = 0; i < solver.solvers.length; i++) { - var sys = solver.solvers[i].system; - DragTool.snapshots[i].push(sys.params.map(function (p) { - return p.get() - })) - } - } - } - - animateSolution() { - if (DragTool.snapshots.length === 0) return; - var stepNum = 0; - var scope = this; - var then = Date.now(); - var speed = 500; - - function step() { - var now = Date.now(); - var elapsed = now - then; - - if (elapsed > speed) { - for (var i = 0; i < scope.solver.solvers.length; i++) { - var sys = scope.solver.solvers[i].system; - if (stepNum >= DragTool.snapshots[i].length) continue; - var values = DragTool.snapshots[i][stepNum]; - for (var k = 0; k < values.length; k++) { - sys.params[k]._backingParam.set(values[k]); - } - } - stepNum++; - - then = now; - scope.viewer.repaint(); - } - - if (DragTool.snapshots.length != 0 && stepNum < DragTool.snapshots[0].length) { - window.requestAnimationFrame(step); - } - } - - window.requestAnimationFrame(step); - } } - -DragTool.snapshots = []; diff --git a/web/app/sketcher/viewer2d.js b/web/app/sketcher/viewer2d.js index 232cc696..87ceb132 100644 --- a/web/app/sketcher/viewer2d.js +++ b/web/app/sketcher/viewer2d.js @@ -163,29 +163,31 @@ class Viewer { return false; } - for (var i = 0; i < this.layers.length; i++) { - var objs = this.layers[i].objects; - for (var j = 0; j < objs.length; j++) { - var l = unreachable + 1; - var before = pickResult.length; - objs[j].accept((o) => { - if (!o.visible) return true; - if (onlyPoints && !isEndPoint(o)) { + for (let layers of this._workspace) { + for (let i = 0; i < layers.length; i++) { + var objs = layers[i].objects; + for (var j = 0; j < objs.length; j++) { + var l = unreachable + 1; + var before = pickResult.length; + objs[j].accept((o) => { + if (!o.visible) return true; + if (onlyPoints && !isEndPoint(o)) { + return true; + } + l = o.normalDistance(aim, this.scale / this.retinaPxielRatio); + if (l >= 0 && l <= buffer && !isFiltered(o)) { + pickResult.push(o); + return false; + } return true; - } - l = o.normalDistance(aim, this.scale); - if (l >= 0 && l <= buffer && !isFiltered(o)) { - pickResult.push(o); - return false; - } - return true; - }); - var hit = before - pickResult.length != 0; - if (hit) { - if (!deep && pickResult.length != 0) return pickResult; - if (l >= 0 && l < heroLength) { - heroLength = l; - heroIdx = pickResult.length - 1; + }); + var hit = before - pickResult.length != 0; + if (hit) { + if (!deep && pickResult.length != 0) return pickResult; + if (l >= 0 && l < heroLength) { + heroLength = l; + heroIdx = pickResult.length - 1; + } } } }