@reekon-tools/boldr-cad 1.6.0 → 1.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +12 -1
- package/dist/data/provider.d.ts +2 -1
- package/dist/data/sync.js +4 -1
- package/dist/data/sync.js.map +1 -1
- package/dist/editor/actions.js +26 -2
- package/dist/editor/actions.js.map +1 -1
- package/dist/editor/advance.d.ts +2 -0
- package/dist/editor/advance.js +23 -0
- package/dist/editor/advance.js.map +1 -0
- package/dist/editor/dimSize.d.ts +13 -0
- package/dist/editor/dimSize.js +50 -0
- package/dist/editor/dimSize.js.map +1 -0
- package/dist/editor/gestures.js +30 -7
- package/dist/editor/gestures.js.map +1 -1
- package/dist/editor/keypad.d.ts +8 -0
- package/dist/editor/keypad.js +15 -1
- package/dist/editor/keypad.js.map +1 -1
- package/dist/editor/laser.d.ts +9 -0
- package/dist/editor/laser.js +38 -12
- package/dist/editor/laser.js.map +1 -1
- package/dist/editor/linkActions.d.ts +5 -1
- package/dist/editor/linkActions.js +27 -5
- package/dist/editor/linkActions.js.map +1 -1
- package/dist/editor/ports.d.ts +9 -0
- package/dist/editor/ports.js +2 -0
- package/dist/editor/ports.js.map +1 -1
- package/dist/editor/refDim.d.ts +17 -0
- package/dist/editor/refDim.js +62 -0
- package/dist/editor/refDim.js.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/model/clockwise.d.ts +11 -0
- package/dist/model/clockwise.js +123 -0
- package/dist/model/clockwise.js.map +1 -0
- package/dist/model/settings.d.ts +2 -0
- package/dist/model/settings.js +1 -1
- package/dist/model/settings.js.map +1 -1
- package/dist/model/types.d.ts +5 -0
- package/dist/react/BottomBar.js +43 -3
- package/dist/react/BottomBar.js.map +1 -1
- package/dist/react/PlanCanvas.native.js +15 -9
- package/dist/react/PlanCanvas.native.js.map +1 -1
- package/dist/react/host.d.ts +6 -0
- package/dist/react/host.js +11 -1
- package/dist/react/host.js.map +1 -1
- package/dist/react/ports.js +2 -1
- package/dist/react/ports.js.map +1 -1
- package/dist/react/store.d.ts +1 -1
- package/dist/react/store.js.map +1 -1
- package/dist/render/draw.d.ts +8 -0
- package/dist/render/draw.js +164 -92
- package/dist/render/draw.js.map +1 -1
- package/dist/render/navigate.d.ts +11 -6
- package/dist/render/navigate.js +34 -20
- package/dist/render/navigate.js.map +1 -1
- package/dist/tools/dim.d.ts +15 -0
- package/dist/tools/dim.js +171 -45
- package/dist/tools/dim.js.map +1 -1
- package/dist/tools/line.js +5 -0
- package/dist/tools/line.js.map +1 -1
- package/package.json +1 -1
- package/src/data/provider.ts +2 -2
- package/src/data/sync.ts +4 -1
- package/src/editor/actions.ts +20 -2
- package/src/editor/advance.ts +23 -0
- package/src/editor/dimSize.ts +53 -0
- package/src/editor/gestures.ts +31 -9
- package/src/editor/keypad.ts +17 -1
- package/src/editor/laser.ts +38 -10
- package/src/editor/linkActions.ts +25 -6
- package/src/editor/ports.ts +10 -0
- package/src/editor/refDim.ts +61 -0
- package/src/index.ts +1 -2
- package/src/model/clockwise.ts +121 -0
- package/src/model/settings.ts +3 -1
- package/src/model/types.ts +5 -0
- package/src/react/BottomBar.tsx +46 -2
- package/src/react/PlanCanvas.native.tsx +25 -12
- package/src/react/host.ts +11 -1
- package/src/react/ports.ts +3 -2
- package/src/react/store.ts +1 -1
- package/src/render/draw.ts +131 -71
- package/src/render/navigate.ts +31 -20
- package/src/tools/dim.ts +168 -35
- package/src/tools/line.ts +4 -0
- package/src/ui/domPorts.ts +2 -0
package/dist/render/navigate.js
CHANGED
|
@@ -46,43 +46,57 @@ export function shiftTo(s, ox, oy, to, W, H) {
|
|
|
46
46
|
export const NAV_DOWN = 0, NAV_MOVE = 1, NAV_UP = 2, NAV_CANCEL = 3;
|
|
47
47
|
/**
|
|
48
48
|
* One touch event, as the UI thread sees it: the fingers after it, and the view (moved if `moved`). Fingers navigate —
|
|
49
|
-
* pan, and zoom about their middle — once two are down, or
|
|
50
|
-
* view only (editor/gestures.ts decides the same on its side), until the last one lifts. A
|
|
51
|
-
*
|
|
52
|
-
*
|
|
49
|
+
* pan, and zoom about their middle — once two are down, or a finger lands while a Pencil is down or when the drawing is
|
|
50
|
+
* view only (editor/gestures.ts decides the same on its side), until the last one lifts. A finger already down and not
|
|
51
|
+
* navigating when a Pencil lands is set aside until it lifts. A pen or a mouse never navigates. `type` is NAV_DOWN… ;
|
|
52
|
+
* `kind` is the event's pointer, for a touch that doesn't say what it is itself; `allIds`, every pointer still down (on
|
|
53
|
+
* a down event: a finger that went without a word, a lost touch-up, is dropped so it can't hold a gesture open).
|
|
53
54
|
*/
|
|
54
55
|
export function navTouch(st, type, kind, changed, allIds, readOnly, view, drawn) {
|
|
55
56
|
'worklet';
|
|
56
|
-
const
|
|
57
|
-
if (kind !== 'touch')
|
|
58
|
-
return { st: { ...st, pen }, view, moved: false };
|
|
57
|
+
const lost = (id) => type === NAV_DOWN && !!allIds && !allIds.includes(id);
|
|
59
58
|
const fingers = {};
|
|
60
|
-
for (const k in st.fingers)
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
}
|
|
59
|
+
for (const k in st.fingers)
|
|
60
|
+
if (!lost(Number(k)))
|
|
61
|
+
fingers[Number(k)] = st.fingers[Number(k)];
|
|
62
|
+
let pens = st.pens.filter(id => !lost(id)), landed = false, moved = false;
|
|
65
63
|
for (const t of changed) {
|
|
66
|
-
|
|
64
|
+
const k = t.kind ?? kind;
|
|
65
|
+
if (type === NAV_UP || type === NAV_CANCEL) {
|
|
67
66
|
delete fingers[t.id];
|
|
68
|
-
|
|
67
|
+
pens = pens.filter(id => id !== t.id);
|
|
68
|
+
}
|
|
69
|
+
else if (type === NAV_DOWN && k === 'pen') {
|
|
70
|
+
if (!pens.includes(t.id))
|
|
71
|
+
pens = [...pens, t.id];
|
|
72
|
+
// (fingers down and not navigating are let go of: their moves and lifts are no finger's from here)
|
|
73
|
+
if (!st.navigating)
|
|
74
|
+
for (const f in fingers)
|
|
75
|
+
delete fingers[f];
|
|
76
|
+
}
|
|
77
|
+
else if (type === NAV_DOWN ? k === 'touch' : t.id in fingers) {
|
|
69
78
|
fingers[t.id] = { x: t.x, y: t.y };
|
|
79
|
+
if (type === NAV_DOWN)
|
|
80
|
+
landed = true;
|
|
81
|
+
else
|
|
82
|
+
moved = true;
|
|
83
|
+
}
|
|
70
84
|
}
|
|
71
85
|
const pts = Object.keys(fingers).map(k => fingers[Number(k)]);
|
|
72
86
|
if (!pts.length)
|
|
73
|
-
return { st: { fingers, navigating: false, last: null,
|
|
87
|
+
return { st: { fingers, navigating: false, last: null, pens }, view, moved: false };
|
|
74
88
|
let navigating = st.navigating, v = view;
|
|
75
89
|
if (!navigating) {
|
|
76
|
-
if (pts.length < 2 && !(
|
|
77
|
-
return { st: { fingers, navigating: false, last: null,
|
|
90
|
+
if (pts.length < 2 && !(landed && (pens.length > 0 || readOnly)))
|
|
91
|
+
return { st: { fingers, navigating: false, last: null, pens }, view, moved: false };
|
|
78
92
|
navigating = true;
|
|
79
93
|
// start from the view the drawing on screen was drawn at, unless the fingers' own is newer
|
|
80
94
|
if (drawn && v.seq <= drawn.seq)
|
|
81
95
|
v = { s: drawn.view.s, cx: drawn.view.cx, cy: drawn.view.cy, seq: drawn.seq };
|
|
82
96
|
}
|
|
83
|
-
const now = pinchOf(pts), was = st.last, next = { fingers, navigating, last: now,
|
|
84
|
-
// a finger came or went: carry on from here, no jump
|
|
85
|
-
if (type !== NAV_MOVE || !now || !was || was.n !== now.n || !drawn)
|
|
97
|
+
const now = pinchOf(pts), was = st.last, next = { fingers, navigating, last: now, pens };
|
|
98
|
+
// a finger came or went: carry on from here, no jump (and a Pencil's move alone moves no view)
|
|
99
|
+
if (type !== NAV_MOVE || !moved || !now || !was || was.n !== now.n || !drawn)
|
|
86
100
|
return { st: next, view: v, moved: false };
|
|
87
101
|
const to = navStep(v, was, now, drawn.W, drawn.H);
|
|
88
102
|
return { st: next, view: { s: to.s, cx: to.cx, cy: to.cy, seq: v.seq + 1 }, moved: true };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"navigate.js","sourceRoot":"","sources":["../../src/render/navigate.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"navigate.js","sourceRoot":"","sources":["../../src/render/navigate.ts"],"names":[],"mappings":"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"}
|
package/dist/tools/dim.d.ts
CHANGED
|
@@ -26,6 +26,12 @@ export declare const dimTool: {
|
|
|
26
26
|
* along its centerline where there's no space; the keypad can switch it.
|
|
27
27
|
*/
|
|
28
28
|
export declare function dimLine(lid: string, side?: 1 | -1): void;
|
|
29
|
+
/**
|
|
30
|
+
* Whether giving dimension `c` the value `v` replaces a value measured there: a driving one, entered (not a default
|
|
31
|
+
* nobody measured), changed by it. Not one linked to a measurement of the job: that's asked about anyway
|
|
32
|
+
* (askLinkedChange). What a host warns about before a reading overwrites (laserReadingOverwrites).
|
|
33
|
+
*/
|
|
34
|
+
export declare const replacesMeasured: (c: Constraint | undefined, v: number) => boolean;
|
|
29
35
|
/** Why a measurement of the job can't drive a line the drawing already sets the length of. */
|
|
30
36
|
export declare const LENGTH_SET_ALREADY = "The drawing already sets that line\u2019s length. Free it first (make one of its dimensions a reference), then pick the measurement.";
|
|
31
37
|
/** Why a measurement of the job can't drive an angle the drawing already sets. */
|
|
@@ -52,6 +58,15 @@ export declare function onChoice(c: Constraint, ch: FaceChoice): boolean;
|
|
|
52
58
|
export declare function setDimFace(id: string, ch: FaceChoice): void;
|
|
53
59
|
/** From a wall's edge to a point: square to the wall, from that face. */
|
|
54
60
|
export declare function dimEdgePoint(lid: string, side: 1 | -1, p: string): void;
|
|
61
|
+
/**
|
|
62
|
+
* What the yellow + measures for the selection, as the dimension it would make (`c`, its value unset), with the one
|
|
63
|
+
* already there for it (`existing`), which the + edits instead. Null where it makes no dimension of the plan: nothing it
|
|
64
|
+
* measures, a door's or window's sizes (their own dimensions), a wall's thickness, the wall view (wallPlus).
|
|
65
|
+
*/
|
|
66
|
+
export declare function selectionDim(): {
|
|
67
|
+
c: Constraint;
|
|
68
|
+
existing?: string;
|
|
69
|
+
} | null;
|
|
55
70
|
/**
|
|
56
71
|
* Two things picked, at least one a wall's edge: the distance between them — two edges of one wall, its thickness
|
|
57
72
|
* (`thickness` opens it); of two walls, face to face; an edge and a line, from that face; an edge and a point, from it.
|
package/dist/tools/dim.js
CHANGED
|
@@ -20,7 +20,8 @@ import { solver } from '../solver';
|
|
|
20
20
|
import { fmtAng, fmtLen } from '../units';
|
|
21
21
|
import { addOpeningDim } from './openings';
|
|
22
22
|
import { keypadFresh, keypadOpen, keypadSetReading } from '../editor/keypad';
|
|
23
|
-
import {
|
|
23
|
+
import { advanceAfterReading } from '../editor/advance';
|
|
24
|
+
import { cornerLines, edgePair, selInfo } from '../editor/selection';
|
|
24
25
|
import { closeKeypad, kpTyped, openKeypad, showConflict, toast, updateCtx, updateHint } from '../editor/ports';
|
|
25
26
|
import { noScaleYet, pendingLabel, startingValue } from '../editor/scaleGate';
|
|
26
27
|
export const dimTool = {
|
|
@@ -237,7 +238,7 @@ export function dimLine(lid, side) {
|
|
|
237
238
|
editDim(ex, undefined, false, wall && side ? { face: side } : undefined);
|
|
238
239
|
return;
|
|
239
240
|
}
|
|
240
|
-
let face = wall ?
|
|
241
|
+
let face = wall ? firstFace(sk, lid, side) : 0;
|
|
241
242
|
const len = () => (face ? faceLength(sk, lid, face) : lineLen(sk, l));
|
|
242
243
|
// (while it's being entered, what it measures is what's highlighted: the edge, or the wall)
|
|
243
244
|
const was = ed.sel;
|
|
@@ -251,8 +252,13 @@ export function dimLine(lid, side) {
|
|
|
251
252
|
keypadSetReading(len()); },
|
|
252
253
|
})) : undefined,
|
|
253
254
|
onClose: () => { ed.sel = was; updateCtx(); requestDraw(); },
|
|
254
|
-
onDone: (v, capture) => {
|
|
255
|
-
|
|
255
|
+
onDone: (v, capture) => {
|
|
256
|
+
if (!(v > 0))
|
|
257
|
+
return;
|
|
258
|
+
// a laser reading's (it comes with its record) moves on to the next line clockwise; a typed one stays
|
|
259
|
+
if (addLength(v, capture !== undefined ? { capture } : {}) && capture !== undefined)
|
|
260
|
+
advanceAfterReading(lid, side);
|
|
261
|
+
},
|
|
256
262
|
// (or a length of the job's, from its list: the line takes it, linked to it)
|
|
257
263
|
measurements: offersJobMeasurements() ? {
|
|
258
264
|
kind: 'length', pick: t => {
|
|
@@ -264,22 +270,31 @@ export function dimLine(lid, side) {
|
|
|
264
270
|
},
|
|
265
271
|
} : undefined,
|
|
266
272
|
};
|
|
267
|
-
/** The line's length dimension, driving, measured where the keypad says (`extra`: what it's from). */
|
|
273
|
+
/** The line's length dimension, driving, measured where the keypad says (`extra`: what it's from). Whether it took. */
|
|
268
274
|
function addLength(v, extra) {
|
|
269
275
|
pushHistory();
|
|
270
|
-
const r = tryAddConstraint({
|
|
276
|
+
const r = tryAddConstraint({ ...lengthDim(sk, lid, face), value: v, ...extra });
|
|
271
277
|
// a measurement of the job drives a line, or nothing: not one whose length the drawing already sets
|
|
278
|
+
let took = r.ok;
|
|
272
279
|
if (r.ok && r.ref && extra.measurementRef) {
|
|
273
280
|
delete SK().cons[r.id];
|
|
274
281
|
dropHistory();
|
|
275
282
|
toast(LENGTH_SET_ALREADY, { warn: true });
|
|
283
|
+
took = false;
|
|
276
284
|
}
|
|
277
285
|
else if (!r.ok)
|
|
278
286
|
dropHistory();
|
|
279
287
|
afterEdit();
|
|
288
|
+
return took;
|
|
280
289
|
}
|
|
281
290
|
openKeypad(spec);
|
|
282
291
|
}
|
|
292
|
+
/**
|
|
293
|
+
* Whether giving dimension `c` the value `v` replaces a value measured there: a driving one, entered (not a default
|
|
294
|
+
* nobody measured), changed by it. Not one linked to a measurement of the job: that's asked about anyway
|
|
295
|
+
* (askLinkedChange). What a host warns about before a reading overwrites (laserReadingOverwrites).
|
|
296
|
+
*/
|
|
297
|
+
export const replacesMeasured = (c, v) => !!c && c.driving !== false && !c.auto && !c.measurementRef && changesValue(c, v);
|
|
283
298
|
/** Why a measurement of the job can't drive a line the drawing already sets the length of. */
|
|
284
299
|
export const LENGTH_SET_ALREADY = 'The drawing already sets that line’s length. Free it first (make one of its dimensions a reference), then pick the measurement.';
|
|
285
300
|
/** Why a measurement of the job can't drive an angle the drawing already sets. */
|
|
@@ -452,8 +467,96 @@ export function dimEdgePoint(lid, side, p) {
|
|
|
452
467
|
toast('Pick a point off the wall to measure from its edge.', { warn: true });
|
|
453
468
|
return;
|
|
454
469
|
}
|
|
455
|
-
dimPointLine(p, lid, { faces:
|
|
470
|
+
dimPointLine(p, lid, { faces: edgePointFaces(sk, lid, side, p), title: 'Distance from the edge' });
|
|
471
|
+
}
|
|
472
|
+
/** From a wall's edge to a point: measured from that face of the wall. */
|
|
473
|
+
const edgePointFaces = (sk, lid, side, p) => [faceToward(sk, lid, sk.points[p], side), 0];
|
|
474
|
+
/* What the + measures, as a dimension not made yet: the builders above make these, and the grey number shows them. */
|
|
475
|
+
/**
|
|
476
|
+
* The face a wall's length (a curved wall's diameter) is first measured on: `side`, the edge picked; picked whole, the
|
|
477
|
+
* side a space is on (the side it was tapped on, between two); its centreline with no space beside it.
|
|
478
|
+
*/
|
|
479
|
+
const firstFace = (sk, id, side) => side ?? defaultFace(sk, id, ed.wallTap?.id === id ? ed.wallTap.side : undefined) ?? 0;
|
|
480
|
+
/** Line `lid`'s length, measured on `face` (a wall's; 0 along the line). Its label sits off the side it's measured on. */
|
|
481
|
+
function lengthDim(sk, lid, face) {
|
|
482
|
+
const l = sk.lines[lid];
|
|
483
|
+
return { type: 'dist', a: l.a, b: l.b, kind: 'al', line: lid, driving: true, off: face ? (face * 30) / V().s : 0, ...(face ? { face } : {}) };
|
|
484
|
+
}
|
|
485
|
+
/** A circle's or arc's diameter, across `face` (a curved wall's; 0 its centreline). */
|
|
486
|
+
const diamDim = (id, face) => ({ type: 'diam', c: id, driving: true, ...(face ? { face } : {}) });
|
|
487
|
+
/** A circle's or arc's diameter dimension, if it has one. */
|
|
488
|
+
const diamDimOf = (sk, id) => Object.keys(sk.cons).find(k => sk.cons[k].type === 'diam' && sk.cons[k].c === id);
|
|
489
|
+
/** The angle between two lines. */
|
|
490
|
+
const angleDim = (l1, l2) => ({ type: 'angle', l1, l2, value: 0, driving: true });
|
|
491
|
+
/** The straight distance between two points. */
|
|
492
|
+
const pointsDim = (a, b) => ({ type: 'dist', a, b, kind: 'al', driving: true, off: 0 });
|
|
493
|
+
/**
|
|
494
|
+
* Point `p`'s distance from line `lid`, square to it, on its side of it. On a wall, from `faces[0]` (see dimPointLine) —
|
|
495
|
+
* by default the face toward the point where a space is against it; `l2`, the wall the point is the end of.
|
|
496
|
+
*/
|
|
497
|
+
function pointLineDim(sk, p, lid, opts = {}) {
|
|
498
|
+
const l = sk.lines[lid], P = sk.points[p], A = sk.points[l.a], B = sk.points[l.b];
|
|
499
|
+
const sd = ((B.x - A.x) * (P.y - A.y) - (B.y - A.y) * (P.x - A.x)) / (hyp(B.x - A.x, B.y - A.y) || 1);
|
|
500
|
+
const c = { type: 'pldist', p, l: lid, value: 0, sign: sd < 0 ? -1 : 1, driving: true, ...(opts.l2 ? { l2: opts.l2 } : {}) };
|
|
501
|
+
applyFace(c, { faces: opts.faces ?? [faceToward(sk, lid, P), 0] });
|
|
502
|
+
return c;
|
|
503
|
+
}
|
|
504
|
+
/**
|
|
505
|
+
* What the yellow + measures for the selection, as the dimension it would make (`c`, its value unset), with the one
|
|
506
|
+
* already there for it (`existing`), which the + edits instead. Null where it makes no dimension of the plan: nothing it
|
|
507
|
+
* measures, a door's or window's sizes (their own dimensions), a wall's thickness, the wall view (wallPlus).
|
|
508
|
+
*/
|
|
509
|
+
export function selectionDim() {
|
|
510
|
+
const sk = SK(), s = selInfo();
|
|
511
|
+
if (s.dims.length || s.odims.length || s.openings.length || s.oanchors.length)
|
|
512
|
+
return null;
|
|
513
|
+
if (s.wfaces.length === 1 && s.n === 1) {
|
|
514
|
+
const [id, side] = edgeOf(s.wfaces[0]);
|
|
515
|
+
if (sk.lines[id])
|
|
516
|
+
return { c: lengthDim(sk, id, side), existing: lengthDimOf(sk, id) ?? undefined };
|
|
517
|
+
return { c: diamDim(id, side), existing: diamDimOf(sk, id) };
|
|
518
|
+
}
|
|
519
|
+
if (edgePair(s)) {
|
|
520
|
+
const edges = s.wfaces.map(edgeOf), other = ed.sel.find(x => x.type !== 'wface');
|
|
521
|
+
if (edges.length === 2) {
|
|
522
|
+
const [[a, sa], [b, sb]] = edges;
|
|
523
|
+
return a !== b && sk.lines[a] && sk.lines[b] ? twoLinesDim(sk, a, b, { [a]: sa, [b]: sb }) : null;
|
|
524
|
+
}
|
|
525
|
+
const [lid, side] = edges[0], l = sk.lines[lid];
|
|
526
|
+
if (other?.type === 'line')
|
|
527
|
+
return twoLinesDim(sk, lid, other.id, { [lid]: side });
|
|
528
|
+
if (other?.type !== 'point' || !l || other.id === l.a || other.id === l.b)
|
|
529
|
+
return null;
|
|
530
|
+
return { c: pointLineDim(sk, other.id, lid, { faces: edgePointFaces(sk, lid, side, other.id) }), existing: pointLineDimOf(sk, other.id, lid) };
|
|
531
|
+
}
|
|
532
|
+
if (s.lines.length === 1 && s.n === 1) {
|
|
533
|
+
const lid = s.lines[0];
|
|
534
|
+
return { c: lengthDim(sk, lid, faced(sk, lid) ? firstFace(sk, lid) : 0), existing: lengthDimOf(sk, lid) ?? undefined };
|
|
535
|
+
}
|
|
536
|
+
if (s.curves.length === 1 && s.n === 1) {
|
|
537
|
+
const id = s.curves[0];
|
|
538
|
+
return { c: diamDim(id, wallOf(sk, id) ? firstFace(sk, id) : 0), existing: diamDimOf(sk, id) };
|
|
539
|
+
}
|
|
540
|
+
if (s.points.length === 1 && s.n === 1)
|
|
541
|
+
return cornerDim(sk, s.points[0]);
|
|
542
|
+
if (s.n === 2 && s.lines.length === 2)
|
|
543
|
+
return twoLinesDim(sk, s.lines[0], s.lines[1]);
|
|
544
|
+
if (s.n === 2 && s.points.length === 2) {
|
|
545
|
+
const [a, b] = s.points;
|
|
546
|
+
const existing = Object.keys(sk.cons).find(id => { const c = sk.cons[id]; return c.type === 'dist' && !c.line && ((c.a === a && c.b === b) || (c.a === b && c.b === a)); });
|
|
547
|
+
return { c: pointsDim(a, b), existing };
|
|
548
|
+
}
|
|
549
|
+
if (s.n === 2 && s.points.length === 1 && s.lines.length === 1) {
|
|
550
|
+
const [p] = s.points, [lid] = s.lines, l = sk.lines[lid];
|
|
551
|
+
// (one of the line's own ends is no distance from it)
|
|
552
|
+
if (!l || p === l.a || p === l.b)
|
|
553
|
+
return null;
|
|
554
|
+
return { c: pointLineDim(sk, p, lid), existing: pointLineDimOf(sk, p, lid) };
|
|
555
|
+
}
|
|
556
|
+
return null;
|
|
456
557
|
}
|
|
558
|
+
/** A distance from point `p` to line `lid` already in the drawing. */
|
|
559
|
+
const pointLineDimOf = (sk, p, lid) => Object.keys(sk.cons).find(id => sk.cons[id].type === 'pldist' && sk.cons[id].p === p && sk.cons[id].l === lid);
|
|
457
560
|
/**
|
|
458
561
|
* Two things picked, at least one a wall's edge: the distance between them — two edges of one wall, its thickness
|
|
459
562
|
* (`thickness` opens it); of two walls, face to face; an edge and a line, from that face; an edge and a point, from it.
|
|
@@ -491,7 +594,7 @@ export function dimPoints(a, b) {
|
|
|
491
594
|
title: 'Distance', ...startingValue(L), selectAll: true, laser: true,
|
|
492
595
|
onDone: (v, capture) => {
|
|
493
596
|
pushHistory();
|
|
494
|
-
const r = tryAddConstraint({
|
|
597
|
+
const r = tryAddConstraint({ ...pointsDim(a, b), value: v, ...(capture !== undefined ? { capture } : {}) });
|
|
495
598
|
if (!r.ok)
|
|
496
599
|
dropHistory();
|
|
497
600
|
ed.sel = [];
|
|
@@ -506,9 +609,32 @@ export function dimPoints(a, b) {
|
|
|
506
609
|
* or, picked whole, each wall's room side (see faceToward).
|
|
507
610
|
*/
|
|
508
611
|
export function dimTwoLines(l1, l2, sides = {}) {
|
|
509
|
-
const sk = SK(),
|
|
510
|
-
if (!
|
|
612
|
+
const sk = SK(), d = twoLinesDim(sk, l1, l2, sides);
|
|
613
|
+
if (!d)
|
|
511
614
|
return;
|
|
615
|
+
if (d.existing) {
|
|
616
|
+
const c = sk.cons[d.existing];
|
|
617
|
+
// (the edges picked: it's measured between them now)
|
|
618
|
+
editDim(d.existing, undefined, false, c.type === 'pldist' && Object.keys(sides).length ? d.facesFrom(c.l, c.p) : undefined);
|
|
619
|
+
return;
|
|
620
|
+
}
|
|
621
|
+
if (d.c.type === 'angle') {
|
|
622
|
+
dimAngle(l1, l2);
|
|
623
|
+
return;
|
|
624
|
+
}
|
|
625
|
+
const f = d.facesFrom(l1, d.c.p);
|
|
626
|
+
dimPointLine(d.c.p, l1, { keepParallel: l2, title: 'Distance between lines', faces: f.faces, l2: f.l2 });
|
|
627
|
+
}
|
|
628
|
+
/**
|
|
629
|
+
* What the + measures between two lines: their distance if they're parallel — square to the first, from the end of the
|
|
630
|
+
* second that sits most squarely across from it, between the faces `sides` says (see dimTwoLines) — otherwise the angle
|
|
631
|
+
* between them. `existing`: a dimension already between them; `facesFrom`: the faces between line `l` and the other,
|
|
632
|
+
* from point `p` on the other.
|
|
633
|
+
*/
|
|
634
|
+
function twoLinesDim(sk, l1, l2, sides = {}) {
|
|
635
|
+
const L1 = sk.lines[l1], L2 = sk.lines[l2];
|
|
636
|
+
if (!L1 || !L2)
|
|
637
|
+
return null;
|
|
512
638
|
const [ax, ay] = norm2(sk.points[L1.b].x - sk.points[L1.a].x, sk.points[L1.b].y - sk.points[L1.a].y);
|
|
513
639
|
const [bx, by] = norm2(sk.points[L2.b].x - sk.points[L2.a].x, sk.points[L2.b].y - sk.points[L2.a].y);
|
|
514
640
|
const parallel = Math.abs(ax * by - ay * bx) < 0.02; // within about a degree
|
|
@@ -521,27 +647,17 @@ export function dimTwoLines(l1, l2, sides = {}) {
|
|
|
521
647
|
return (c.l1 === l1 && c.l2 === l2) || (c.l1 === l2 && c.l2 === l1);
|
|
522
648
|
return (c.l === l1 && (c.p === L2.a || c.p === L2.b)) || (c.l === l2 && (c.p === L1.a || c.p === L1.b));
|
|
523
649
|
});
|
|
524
|
-
/** The faces between line `l` (the one measured square to) and the other, from point `p` on the other. */
|
|
525
650
|
const facesFrom = (l, p) => {
|
|
526
651
|
const o = l === l1 ? l2 : l1, ol = sk.lines[o], on = sk.lines[l];
|
|
527
652
|
return { faces: [faceToward(sk, l, sk.points[p], sides[l], true), faceToward(sk, o, sk.points[on.a], sides[o], true)], ...(faced(sk, o) && ol ? { l2: o } : {}) };
|
|
528
653
|
};
|
|
529
|
-
if (
|
|
530
|
-
|
|
531
|
-
// (the edges picked: it's measured between them now)
|
|
532
|
-
editDim(existing, undefined, false, c.type === 'pldist' && Object.keys(sides).length ? facesFrom(c.l, c.p) : undefined);
|
|
533
|
-
return;
|
|
534
|
-
}
|
|
535
|
-
if (!parallel) {
|
|
536
|
-
dimAngle(l1, l2);
|
|
537
|
-
return;
|
|
538
|
-
}
|
|
539
|
-
// measure from the end of the second line that sits most squarely across from the first
|
|
654
|
+
if (!parallel)
|
|
655
|
+
return { c: angleDim(l1, l2), existing, facesFrom };
|
|
540
656
|
const A = sk.points[L1.a], B = sk.points[L1.b], len2 = (B.x - A.x) ** 2 + (B.y - A.y) ** 2 || 1;
|
|
541
657
|
const t = (pid) => { const P = sk.points[pid]; return ((P.x - A.x) * (B.x - A.x) + (P.y - A.y) * (B.y - A.y)) / len2; };
|
|
542
658
|
const p = Math.abs(t(L2.a) - 0.5) <= Math.abs(t(L2.b) - 0.5) ? L2.a : L2.b;
|
|
543
659
|
const f = facesFrom(l1, p);
|
|
544
|
-
|
|
660
|
+
return { c: pointLineDim(sk, p, l1, { faces: f.faces, l2: f.l2 }), existing, facesFrom };
|
|
545
661
|
}
|
|
546
662
|
/**
|
|
547
663
|
* The distance from point `p` to line `lid`, square to it. On a wall it's measured from `faces[0]`, its face toward
|
|
@@ -550,11 +666,7 @@ export function dimTwoLines(l1, l2, sides = {}) {
|
|
|
550
666
|
* switch them.
|
|
551
667
|
*/
|
|
552
668
|
export function dimPointLine(p, lid, opts = {}) {
|
|
553
|
-
const sk = SK(),
|
|
554
|
-
const sd = ((B.x - A.x) * (P.y - A.y) - (B.y - A.y) * (P.x - A.x)) / (hyp(B.x - A.x, B.y - A.y) || 1);
|
|
555
|
-
const sign = sd < 0 ? -1 : 1;
|
|
556
|
-
const c = { type: 'pldist', p, l: lid, value: 0, sign, driving: true, ...(opts.l2 ? { l2: opts.l2 } : {}) };
|
|
557
|
-
applyFace(c, { faces: opts.faces ?? [faceToward(sk, lid, P), 0] });
|
|
669
|
+
const sk = SK(), c = pointLineDim(sk, p, lid, opts);
|
|
558
670
|
const choices = faceChoices(sk, c);
|
|
559
671
|
ed.sel = [];
|
|
560
672
|
ed.preview = (cx, T) => { const e = dimEnds(sk, c); if (e)
|
|
@@ -590,15 +702,13 @@ export function dimPointLine(p, lid, opts = {}) {
|
|
|
590
702
|
*/
|
|
591
703
|
export function dimCurve(id, side) {
|
|
592
704
|
const sk = SK(), wall = !!wallOf(sk, id);
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
return;
|
|
598
|
-
}
|
|
705
|
+
const ex = diamDimOf(sk, id);
|
|
706
|
+
if (ex) {
|
|
707
|
+
editDim(ex, undefined, false, wall && side ? { face: side } : undefined);
|
|
708
|
+
return;
|
|
599
709
|
}
|
|
600
|
-
let face = wall ?
|
|
601
|
-
const now = () => measure(sk,
|
|
710
|
+
let face = wall ? firstFace(sk, id, side) : 0;
|
|
711
|
+
const now = () => measure(sk, diamDim(id, face));
|
|
602
712
|
// (while it's being entered, what it measures across is what's highlighted: the edge, or the wall)
|
|
603
713
|
const was = ed.sel, type = sk.circles[id] ? 'circle' : 'arc';
|
|
604
714
|
const show = () => { ed.sel = face ? [{ type: 'wface', id: edgeId(id, face) }] : [{ type, id }]; requestDraw(); };
|
|
@@ -615,7 +725,7 @@ export function dimCurve(id, side) {
|
|
|
615
725
|
if (v <= 0)
|
|
616
726
|
return;
|
|
617
727
|
pushHistory();
|
|
618
|
-
const r = tryAddConstraint({
|
|
728
|
+
const r = tryAddConstraint({ ...diamDim(id, face), value: v });
|
|
619
729
|
if (!r.ok)
|
|
620
730
|
dropHistory();
|
|
621
731
|
// (as a length: the dimension made, nothing left highlighted)
|
|
@@ -627,19 +737,26 @@ export function dimCurve(id, side) {
|
|
|
627
737
|
}
|
|
628
738
|
/** A corner's angle (two lines meeting at `pid`): its angle dimension's keypad, or a new one's. False if it isn't a corner. */
|
|
629
739
|
export function cornerAngle(pid, done, modeless = false) {
|
|
630
|
-
const sk = SK(),
|
|
631
|
-
if (!
|
|
740
|
+
const sk = SK(), d = cornerDim(sk, pid);
|
|
741
|
+
if (!d)
|
|
632
742
|
return false;
|
|
633
743
|
// edit the corner's existing angle dimension rather than stacking a second one
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
editDim(ex, done, modeless);
|
|
744
|
+
if (d.existing)
|
|
745
|
+
editDim(d.existing, done, modeless);
|
|
637
746
|
else
|
|
638
|
-
dimAngle(
|
|
747
|
+
dimAngle(d.c.l1, d.c.l2, done, modeless);
|
|
639
748
|
return true;
|
|
640
749
|
}
|
|
750
|
+
/** A corner's angle (two lines meeting at `pid`), as the + measures it; `existing`, its angle dimension. Null if it isn't a corner. */
|
|
751
|
+
function cornerDim(sk, pid) {
|
|
752
|
+
const pair = cornerLines(sk, pid);
|
|
753
|
+
if (!pair)
|
|
754
|
+
return null;
|
|
755
|
+
const existing = Object.keys(sk.cons).find(id => { const c = sk.cons[id]; return c.type === 'angle' && ((c.l1 === pair[0] && c.l2 === pair[1]) || (c.l1 === pair[1] && c.l2 === pair[0])); });
|
|
756
|
+
return { c: angleDim(pair[0], pair[1]), existing };
|
|
757
|
+
}
|
|
641
758
|
export function dimAngle(l1, l2, done, modeless = false) {
|
|
642
|
-
const c =
|
|
759
|
+
const c = angleDim(l1, l2);
|
|
643
760
|
const cur = measure(SK(), c);
|
|
644
761
|
/** The angle dimension, driving, at `v` degrees (`extra`: what it's from). */
|
|
645
762
|
const addAngle = (v, extra) => {
|
|
@@ -700,7 +817,16 @@ export function editDim(id, done, modeless = false, pick) {
|
|
|
700
817
|
onPress: () => { face = onChoice(c, ch) ? null : { ...ch, l2: face?.l2 ?? ch.l2 }; if (keypadFresh())
|
|
701
818
|
keypadSetReading(now()); },
|
|
702
819
|
})),
|
|
703
|
-
onDone: (v, capture) => {
|
|
820
|
+
onDone: (v, capture) => {
|
|
821
|
+
const took = setDimValue(id, v * k, face ?? undefined, { capture });
|
|
822
|
+
done?.();
|
|
823
|
+
// a laser reading's (it comes with its record) on a line's length or a curve's diameter moves on to the next
|
|
824
|
+
// line clockwise; a typed one, or one the drawing refused or asked about, stays
|
|
825
|
+
const of = c.type === 'dist' ? c.line : c.type === 'diam' ? c.c : undefined;
|
|
826
|
+
if (took && capture !== undefined && of)
|
|
827
|
+
advanceAfterReading(of, pick?.face || undefined);
|
|
828
|
+
},
|
|
829
|
+
overwrites: v => replacesMeasured(SK().cons[id], v * k),
|
|
704
830
|
// a line's length or an angle: or one of the job's, from its list — the dimension takes it, linked to it (a
|
|
705
831
|
// dimension already linked to another, re-linked)
|
|
706
832
|
measurements: ((c.type === 'dist' && c.line) || isAng) && offersJobMeasurements() ? {
|