mirror of
https://github.com/Matysh/houseplan-card
synced 2026-09-29 03:09:36 +00:00
feat: junction limits refuse the write in every editing surface (#329)
П3 measures the WALL, not the catalogue atom: a short filler segment that compensates a thickness step (owner's fixture, 5 cm = (30-20)/2) is a legal continuation of a long same-thickness wall, so the rule walks the maximal collinear run through the shared nodes before judging the length. Resize stops at the last allowed position and names the broken rule instead of the generic "geometry cannot be saved"; the Thickness dialog refuses through its own toast. Both channels are pinned by demo/smoke_junction_limits plus three mutants (angle threshold, write barrier, degenerate apex bevel). Issue: #329 User-Visible: yes
This commit is contained in:
@@ -185,3 +185,34 @@ test('§4: у вырожденной вершины грани прямые —
|
||||
assert.ok(side > cm(7.5), `сторона ${index} не вырождена: ${side}`);
|
||||
}
|
||||
});
|
||||
|
||||
test('П3 меряет стену, а не атом: компенсация перепада толщин законна', async () => {
|
||||
const { collinearRunLengthUnits } = await import('../test-build/junction-limits.js');
|
||||
// Репорт владельца 2026-08-27: на стыке 30 см и 20 см атомизация оставляет
|
||||
// кусок (30−20)/2 = 5 см — коллинеарное продолжение той же стены.
|
||||
const run = [
|
||||
{ id: 'long', a: [0, 0], b: [0, cm(349)], cm: 30 },
|
||||
{ id: 'step', a: [0, cm(349)], b: [0, cm(354)], cm: 30 },
|
||||
{ id: 'cross', a: [0, cm(354)], b: [cm(482), cm(354)], cm: 20 },
|
||||
];
|
||||
assert.deepEqual(checkSegmentLengths(run, CELL, PITCH), [],
|
||||
'короткий атом внутри прямого прогона не нарушение');
|
||||
const runLength = collinearRunLengthUnits(run[1], run);
|
||||
assert.ok(Math.abs((runLength / PITCH) * CELL - 354) < 1e-6, 'меряется весь прогон');
|
||||
|
||||
// Одинокая короткая стена по-прежнему отклоняется: коллинеарного
|
||||
// продолжения нет.
|
||||
const lonely = [
|
||||
{ id: 'a', a: [0, 0], b: [cm(10), 0], cm: 15 },
|
||||
{ id: 'b', a: [cm(10), 0], b: [cm(10), cm(10)], cm: 15 },
|
||||
];
|
||||
assert.equal(checkSegmentLengths(lonely, CELL, PITCH).length, 2);
|
||||
|
||||
// Продолжение ДРУГОЙ толщины прогоном не считается.
|
||||
const mixed = [
|
||||
{ id: 'thin', a: [0, 0], b: [0, cm(10)], cm: 15 },
|
||||
{ id: 'thick', a: [0, cm(10)], b: [0, cm(400)], cm: 40 },
|
||||
];
|
||||
assert.ok(checkSegmentLengths(mixed, CELL, PITCH)
|
||||
.some((item) => item.subject === 'thin'));
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user