feat(CAD): 337-3a 나-1 그리기 8 — 오토캐드 물음 차례 · 옵션 · 기본값 · 빈 Enter · Esc · 끝난 뒤
- LINE: 「첫 번째 점 지정」 빈 Enter = 마지막 끝점에서 이음 · U = 마지막 토막(되돌림 한 칸) · 둘째 토막부터 C · Enter · Esc = 끝(토막 남음) - PLINE(새 pline-tool): 호(A) 접선 호 · 길이(L) · 닫기(C · 호 모드 CL) · 명령 취소(U) · 선(L) · Esc · Enter = 그린 데까지 남김 - RECTANG: 치수(D) 길이 · 폭 기억(RECT.L · RECT.W) → 누른 쪽 사분면 · 없는 옵션 안내 - CIRCLE: 3P · 2P · 지름(D) <2r> · 반지름 기억(CIRCLERAD · 처음 <> 없음) · 한 번 뒤 끝 - POLYGON(새 polygon-tool): 변 수 기억 <4> · 3~1024 정수 · 모서리(E) · 내접/외접 기억 · 숫자 = 아래 변 수평 - ARC(새 arc-tool): 세 점 · 중심(C) · 각도(A) · 끝(E) · 반지름(R) - ELLIPSE(새 ellipse-tool): 축 두 끝 · 중심(C) · 회전(R) · 다른 축 숫자 = 중심에서 반 길이(N10) - SPLINE: 다음 점 입력 · U · 넷째 점부터 C · Esc 버림 · DONUT 중심 되풀이(loopFrom) - 시험 draw-acad 22 · keyboard-chain 옛 선 · 폴리선 줄 두 곳 새 동작으로 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VmC34fsxxbweEG3RUjs3Mn
This commit is contained in:
@@ -1,114 +1,65 @@
|
||||
/** 그리기 명령 — 폴리선·호·다각형·타원·스플라인·점 (조사표 1절) */
|
||||
/** 그리기 명령 — 스플라인·점·도넛 + 폴리선·호·다각형·타원 다시 내보냄 (조사표 1절 · 337 설계 1-1) */
|
||||
import { CircleEntity } from '../../entities/CircleEntity';
|
||||
import type { Entity } from '../../entities/Entity';
|
||||
import {
|
||||
arcThroughThreePoints,
|
||||
ellipsePoints,
|
||||
regularPolygonPoints,
|
||||
splinePoints,
|
||||
} from '../../helpers/geometry/shape-points';
|
||||
import type { Point } from '@flatten-js/core';
|
||||
import { OPT } from '../../commands/prompt';
|
||||
import { splinePoints } from '../../helpers/geometry/shape-points';
|
||||
import { addEntities, getActiveLayerId } from '../../state';
|
||||
import { Tool } from '../../tools';
|
||||
import {
|
||||
arcEntity,
|
||||
lineEntity,
|
||||
pointEntity,
|
||||
polyLineEntity,
|
||||
styled,
|
||||
} from '../factories/entity-factory';
|
||||
import { pointEntity, polyLineEntity, styled } from '../factories/entity-factory';
|
||||
import { createSequenceTool } from '../factories/sequence-tool';
|
||||
import { option } from './draw-steps';
|
||||
|
||||
export const plineToolStateMachine = createSequenceTool({
|
||||
tool: Tool.PLINE,
|
||||
steps: [
|
||||
{ kind: 'point', instructions: '폴리선의 시작점을 지정하십시오.' },
|
||||
{ kind: 'point', instructions: '다음 점을 지정하십시오. ENTER로 종료합니다.' },
|
||||
],
|
||||
repeatLastStep: true,
|
||||
preview: (input) => {
|
||||
const preview = polyLineEntity([...input.points(), input.cursor]);
|
||||
return preview ? [preview] : [];
|
||||
},
|
||||
commit: (input) => {
|
||||
const polyline = polyLineEntity(input.points());
|
||||
if (polyline) addEntities([polyline], true);
|
||||
},
|
||||
});
|
||||
export { arcToolStateMachine } from './arc-tool';
|
||||
export { ellipseToolStateMachine } from './ellipse-tool';
|
||||
export { plineToolStateMachine } from './pline-tool';
|
||||
export { polygonToolStateMachine } from './polygon-tool';
|
||||
|
||||
export const arcToolStateMachine = createSequenceTool({
|
||||
tool: Tool.ARC,
|
||||
steps: [
|
||||
{ kind: 'point', instructions: '호의 시작점을 지정하십시오.' },
|
||||
{ kind: 'point', instructions: '호가 지나갈 두 번째 점을 지정하십시오.' },
|
||||
{ kind: 'point', instructions: '호의 끝점을 지정하십시오.' },
|
||||
],
|
||||
preview: (input) => {
|
||||
const points = input.points();
|
||||
if (points.length === 1) return [lineEntity(points[0], input.cursor)];
|
||||
if (points.length === 2) {
|
||||
const definition = arcThroughThreePoints(points[0], points[1], input.cursor);
|
||||
return definition ? [arcEntity(definition)] : [lineEntity(points[0], input.cursor)];
|
||||
}
|
||||
return [];
|
||||
},
|
||||
commit: (input) => {
|
||||
const [start, through, end] = input.points();
|
||||
const definition = arcThroughThreePoints(start, through, end);
|
||||
// 세 점이 일직선이면 호가 성립하지 않으므로 선으로 대체한다
|
||||
addEntities([definition ? arcEntity(definition) : lineEntity(start, end)], true);
|
||||
},
|
||||
});
|
||||
/** 닫힌 스플라인 — 끝 둘레 이웃을 이어 붙여 그린 뒤 이음 구간만 남김 */
|
||||
function closedSplinePoints(points: Point[]): Point[] {
|
||||
const spans = 12;
|
||||
const wrapped = splinePoints([points[points.length - 1], ...points, points[0], points[1]], spans);
|
||||
const loop = wrapped.slice(spans, spans * (points.length + 1));
|
||||
return [...loop, loop[0]];
|
||||
}
|
||||
|
||||
export const polygonToolStateMachine = createSequenceTool({
|
||||
tool: Tool.POLYGON,
|
||||
steps: [
|
||||
{ kind: 'number', instructions: '면의 수를 입력하십시오 <6>.', defaultValue: 6 },
|
||||
{ kind: 'point', instructions: '다각형의 중심을 지정하십시오.' },
|
||||
{ kind: 'point', instructions: '꼭짓점을 지정하십시오 (중심에서의 반지름).' },
|
||||
],
|
||||
preview: (input) => {
|
||||
const points = input.points();
|
||||
if (points.length !== 1) return [];
|
||||
const polygon = polyLineEntity(regularPolygonPoints(points[0], input.cursor, input.number(0)));
|
||||
return polygon ? [polygon] : [];
|
||||
},
|
||||
commit: (input) => {
|
||||
const [center, vertex] = input.points();
|
||||
const polygon = polyLineEntity(regularPolygonPoints(center, vertex, input.number(0)));
|
||||
if (polygon) addEntities([polygon], true);
|
||||
},
|
||||
});
|
||||
|
||||
export const ellipseToolStateMachine = createSequenceTool({
|
||||
tool: Tool.ELLIPSE,
|
||||
steps: [
|
||||
{ kind: 'point', instructions: '타원의 중심을 지정하십시오.' },
|
||||
{ kind: 'point', instructions: '장축의 끝점을 지정하십시오.' },
|
||||
{ kind: 'point', instructions: '단축 거리를 지정하십시오.' },
|
||||
],
|
||||
preview: (input) => {
|
||||
const points = input.points();
|
||||
if (points.length === 1) return [lineEntity(points[0], input.cursor)];
|
||||
if (points.length === 2) {
|
||||
const minor = points[0].distanceTo(input.cursor)[0];
|
||||
const ellipse = polyLineEntity(ellipsePoints(points[0], points[1], minor));
|
||||
return ellipse ? [ellipse] : [];
|
||||
}
|
||||
return [];
|
||||
},
|
||||
commit: (input) => {
|
||||
const [center, majorPoint, minorPoint] = input.points();
|
||||
const minorRadius = center.distanceTo(minorPoint)[0];
|
||||
const ellipse = polyLineEntity(ellipsePoints(center, majorPoint, minorRadius));
|
||||
if (ellipse) addEntities([ellipse], true);
|
||||
},
|
||||
});
|
||||
const NEXT_POINT = '다음 점 입력';
|
||||
const TOLERANCE = option('TOLERANCE', 'L', '공차');
|
||||
|
||||
/**
|
||||
* 스플라인(SPLINE) — 337 설계 1-1. 「첫 번째 점 지정:」 → 「다음 점 입력:」 → 「다음 점 입력 또는 [명령 취소(U)]:」 →
|
||||
* 넷째 점부터 [명령 취소(U)/닫기(C)] 되풀이 · 빈 Enter = 확정 · C = 닫고 끝 · Esc = 버림.
|
||||
*/
|
||||
export const splineToolStateMachine = createSequenceTool({
|
||||
tool: Tool.SPLINE,
|
||||
steps: [
|
||||
{ kind: 'point', instructions: '스플라인의 첫 점을 지정하십시오.' },
|
||||
{ kind: 'point', instructions: '다음 점을 지정하십시오. ENTER로 종료합니다.' },
|
||||
{
|
||||
kind: 'point',
|
||||
prompt: {
|
||||
text: '첫 번째 점 지정',
|
||||
absent: [
|
||||
option('METHOD', 'M', '방법'),
|
||||
option('KNOTS', 'K', '매듭'),
|
||||
option('OBJECT', 'O', '객체'),
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
kind: 'point',
|
||||
prompt: {
|
||||
text: NEXT_POINT,
|
||||
absent: [option('TANGENT', 'T', '시작 접촉부'), TOLERANCE],
|
||||
},
|
||||
},
|
||||
{
|
||||
kind: 'point',
|
||||
prompt: (input) => ({
|
||||
text: NEXT_POINT,
|
||||
options: input.points().length >= 3 ? [OPT.UNDO, OPT.CLOSE] : [OPT.UNDO],
|
||||
absent: [option('TANGENT', 'T', '끝 접촉부'), TOLERANCE],
|
||||
}),
|
||||
options: { UNDO: 'undo', CLOSE: 'close' },
|
||||
},
|
||||
],
|
||||
repeatLastStep: true,
|
||||
preview: (input) => {
|
||||
@@ -116,7 +67,8 @@ export const splineToolStateMachine = createSequenceTool({
|
||||
return preview ? [preview] : [];
|
||||
},
|
||||
commit: (input) => {
|
||||
const spline = polyLineEntity(splinePoints(input.points()));
|
||||
const points = input.points();
|
||||
const spline = polyLineEntity(input.closed ? closedSplinePoints(points) : splinePoints(points));
|
||||
if (spline) addEntities([spline], true);
|
||||
},
|
||||
});
|
||||
@@ -138,6 +90,7 @@ export const donutToolStateMachine = createSequenceTool({
|
||||
{ kind: 'number', instructions: '도넛의 외부 지름을 입력하십시오 <2>.', defaultValue: 2 },
|
||||
{ kind: 'point', instructions: '도넛의 중심을 지정하십시오.' },
|
||||
],
|
||||
loopFrom: 2, // 오토캐드 — 중심 되풀이 · 빈 Enter 끝
|
||||
preview: (input) => donutEntities(input.number(0), input.number(1), input.cursor),
|
||||
commit: (input) => {
|
||||
addEntities(donutEntities(input.number(0), input.number(1), input.point(2)), true);
|
||||
|
||||
Reference in New Issue
Block a user