feat(view): colour the ③ 3D rebar by diameter or by member, with a legend
Role colours stay the default (spec §6.7). A control on ③ switches to diameter (nominal size, H and S of one size share a colour, Okabe–Ito palette) or member (받침블럭 · 코핑 · 기둥 · 확대기초). The legend lists only the items the model has. Highlighting and the state colours are unchanged. Approved 2026-10-23. Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
5d5ad7e997
commit
d35e27e7de
6 files changed
+176
-3
No files matched your search
@@ -0,0 +1,56 @@
|
||||
import { describe, expect, it } from 'vitest';
|
||||
import * as THREE from 'three';
|
||||
import { buildPier } from '../src/core/geometry';
|
||||
import { DIAMETER_GROUPS, diameterGroupIndex, memberOfBar } from '../src/core/rebar/color';
|
||||
import { buildRebar3D } from '../src/view/rebar3d';
|
||||
import { loadP1 } from './helpers';
|
||||
|
||||
const rb = buildRebar3D(buildPier(loadP1()));
|
||||
const colorOf = (name: string) => (rb.byName.get(name)![0].material as THREE.MeshStandardMaterial).color.getHex();
|
||||
|
||||
describe('③ 3D 색 기준 (spec §6.7 승인 2026-10-23)', () => {
|
||||
it('every bar of P1 belongs to a known member (none falls into 기타)', () => {
|
||||
const names = [...rb.byName.keys()];
|
||||
expect(names.filter((n) => memberOfBar(n) === 'other')).toEqual([]);
|
||||
});
|
||||
|
||||
it('H and S of the same size share one diameter group; a non-rebar diameter has none', () => {
|
||||
expect(DIAMETER_GROUPS[diameterGroupIndex(15.9)].label).toBe('H16 · S16');
|
||||
expect(DIAMETER_GROUPS[diameterGroupIndex(25.4)].label).toBe('H25 · S25');
|
||||
expect(DIAMETER_GROUPS).toHaveLength(8);
|
||||
expect(diameterGroupIndex(60)).toBe(-1);
|
||||
});
|
||||
|
||||
it('role is the default colour; diameter and member modes recolour every bar and can switch back', () => {
|
||||
const role = colorOf('C1');
|
||||
rb.setColorMode('member');
|
||||
expect(colorOf('C1')).not.toBe(role);
|
||||
rb.setColorMode('diameter');
|
||||
expect(colorOf('C1')).not.toBe(role);
|
||||
rb.setColorMode('role');
|
||||
expect(colorOf('C1')).toBe(role);
|
||||
});
|
||||
|
||||
it('member mode: all bars of one member share one colour', () => {
|
||||
rb.setColorMode('member');
|
||||
expect(colorOf('C1')).toBe(colorOf('C14'));
|
||||
expect(colorOf('P1')).toBe(colorOf('P6'));
|
||||
expect(colorOf('C1')).not.toBe(colorOf('P1'));
|
||||
rb.setColorMode('role');
|
||||
});
|
||||
|
||||
it('diameter mode: bars of one size share a colour, a different size does not (C1 and C7 are H29, C9 is H25)', () => {
|
||||
rb.setColorMode('diameter');
|
||||
expect(colorOf('C1')).toBe(colorOf('C7'));
|
||||
expect(colorOf('C1')).not.toBe(colorOf('C9'));
|
||||
rb.setColorMode('role');
|
||||
});
|
||||
|
||||
it('legend lists only the items the model has; role mode has none', () => {
|
||||
expect(rb.legend('role')).toEqual([]);
|
||||
expect(rb.legend('member').map((i) => i.label)).toEqual(['받침블럭', '코핑', '기둥', '확대기초']);
|
||||
const sizes = rb.legend('diameter').map((i) => i.label);
|
||||
expect(sizes.length).toBeGreaterThan(0);
|
||||
expect(sizes.length).toBeLessThanOrEqual(8);
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user