chore(요구): 요구 241 분석(6장 · B07 구조물 도면 · 전개도 · ☰ 서랍 · B06 · B05 평면 · R 제약 · 한 페이지 방법)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01C6BNBFXFndbqYxu6sZuknK
This commit is contained in:
2026-10-17 14:33:58 +09:00
co-authored by Claude Opus 5.5
parent 940a1c3f5b
commit 7329065c3b
@@ -0,0 +1,106 @@
# 요구 241 분석 (10-17 · PLAN 376~385 근거)
원문 = `docs/raw/요구_1017/사용자요구_1017.md` 요구 241 · 그림 = 같은 폴더 `그림_241_*.png` · 조사 = Explore 여섯(읽기만) + 브레인 직접 확인(부품 처음값 = 종류 정의 「반영」 없을 때 코드 값 · 우측 판 법선 폭 = 「횡단 반폭」 세션값 · 노선 무관) · 줄 번호는 10-17 기준.
## 1장 B07 구조물 도면 · 전개도 (241-1 · 2 · 3)
### (a) 좌측 패널 · 도면 열기
- 컨테이너: B07_DesignDetail/B07_DesignDetail_UI_Panels.ts:26-40 DRAWING_GROUPS(표지 · 평면도 · 종단도 · 횡단도 · 토적도) → buildDrawingSidePanel(:56) · createPanelCard/attachCollapsible(ui_template/ui_template_collapsible.ts:15,26) · 기본 접힘 FOLDED_KINDS(:43) · 단추 drawingButton(:95-107 data-drawing-id) · 1장 이하 = 카드 없이 단추(:132 → 새 둘은 늘 카드로) · 평면도만 buildPlanSection(UI_PlanKinds.ts:256-285 · groupPlanSheets :233-253 plan_kind/plan_kind_name).
- 클릭 → UI_Page.ts:407 selectDrawing → openTab(:404) → loadDrawing(:339) → requestDrawing(:285 캐시) → fetchDesignDrawing(Api_Fetch.ts:156) → GET /api/projects/{id}/design-drawings/{drawing_id}(Router.py:296) → cad.load(:357) · 목록 GET .../design-drawings(Router.py:273) → _drawing_list(Router_Support.py:185-247 · 도면번호 _store_drawing_numbers :250) · 단건 _read_drawing(:456-616 id 모양 분기 · 확정본 kind 다시 정함 :479-484 — 새 id 접두 안 넣으면 kind cross 로 잘못) · 확정 PUT confirm(Router.py:390) · 내보내기 POST /drawing-export(Api_Fetch.ts:328).
- 도각 frame_entities(Engine_Template.py:509 · :492 · 양식 resources/master_template/drawing/00_template_A1.json · 프로젝트 templates/drawing 우선 :55-114) · 표제란 title_block_fields(Router.py:147) · add_title_fields(Router_Support.py:469-472) · 반환 {format, entities, layers}(Engine_Cad_MassHaul.py:581-599) · kind 목록 B07_DesignDetail_Schema.py:13-25,54-66 · Api_Fetch.ts:9-19,105-115.
### (b) 구조물 조합 도면
- 연결: structures.json summary_item + group_items{gid}(B05_Profile_Structures_Schema.py:197-199) · pipe_points.json 같음(common_util_drainage_pipes.py:101-103) · 항목 {layer, owner, key, name}(common_util_summary_item.py:3-4) · gid 관 grv6lny · 유입 gnbf9m9 · 유출 g9lq9uk(design_structure_pipe.ts:41,58,92) · BOX gboxbody/gboxin/gboxout · 세월교 gford/gfordin/gfordout · 흙막이 gsoiladd{n} · 도수로 gchuteadd{n}(B08_Quantity_Router_Summary.py:67-74).
- M02 저장: structure/<열id>.json = {양식:"구조물도면", 열, 도면:{format,entities,layers}, 더한장:[{장id,이름,도면}], 도번}(M02_MasterTemplete_Store.py:355-361 · M02_Template_Layers.py:196-197) · 모두 openwebcad JSON(DXF/DWG 는 업로드 때 /api/m02/drawing-import 변환).
- 프로젝트 사본: [저장] 뒤 templates/structures/{구조물id | pipe@측점}[__gid]/도면.json(M02_Item_Snapshot.py:1-18 · M02_Item_Source.py:133-155) · linked_snapshots(root)(:417-440 · assignments :158-176) · 읽기 GET /api/projects/{id}/items/{폴더}/도면(M02_Project_Items_Router.py:147 · B08_Quantity_UI_Drawing.ts:1-14,60-85 가 씀).
- 권장: 서버 linked_snapshots 중 "도면" 부분 · 조합 키 snapshot_folder_name(common_util_summary_item.py:99-106)로 중복 없앰 · id structure_{키}[_{장}] · 도각 structure_frame(도번)(M02_MasterTemplete_Router_Drawing.py:108-131) + 도면명 인자.
- 충돌: 09-13 「표준도(구조물도)를 B07 에서 B08 로 이관」(Router_Support.py:245 · Schema.py:23) — 이번 요구로 B07 에 다시 들임(B08 모달 그대로).
### (c) 전개도 자료(B08 재사용)
- 관보호공 유입·유출: pipe_points pipe · {side}_type=="기슭막이"(B08 :579) · {side}_revet_before_m/after_m(둘 다 비면 length_m/2 · B06_Section_Engine_Culvert.py:211-243) · 시점 at−전 · 종점 at+후 · 거리 = 전+후(_revet_length B08 :169-175) · H {side}_revet_height_m(빈칸 pipe_wall_height_m · Culvert.py:83-110 · B08 :583-596) · 형태 {side}_revet_form(정의 json :155-169,:218-233).
- 추가 흙막이 n(배관 · BOX · 세월교): soil_add_{n}_form/length/height/before/after(design_structure_guard.ts:33-120) · 선 단 수까지 soil_tiers_from_designs + container_rows(M02_Table_Fill_Spec.py:46-108).
- 박스암거: wing_in/out=="흙막이" 때 {side}_revet_*(design_structure_box.ts:10-12 · _guard B08 :155-166) · 본체 length_m 은 계류 방향(종단 아님).
- 세월교: inlet/outlet_type=="흙막이"(design_structure_ford.ts:7-9).
- 흙막이(C군): structures soil_guard start_m/end_m(Schema.py:233-245) · wall_specs_from(B06_Section_Engine_Structures_Wall.py:82-121) · height_m + tier_{n}_*(:56-67) · form(빈칸 통나무·목재틀 json :1478-1493).
- 옹벽: retaining_wall · wall_form = 콘크리트(json :929-938 · form 은 형식(중력식) — wall_specs_from :103 이 form 을 씀 주의).
- 콘크리트 포장 · 쇄석 포설: pavement_concrete · gravel_surfacing(enabled false) · pavement_specs_from(common_util_structure_pavement.py:46-73) · B = width_m(빈칸 B06 노폭 carriageway_width_m 구간 평균 · B06_Section_Engine_Design.py:460 · config_system_design.py:334).
- 같이 씀: collect_items(M02_Table_Fill.py:86-145) · load_note_sources(Engine_Cad_CulvertNote.py:273-289) · 쓰면 안 됨 structure_lengths(겹친 구간 합침).
- 측점: 기준 정수 m · 흙막이 전후 0.5 단위 → 소수 · 간격 infer_station_interval(Engine_Cad.py:288) · 기존 표기 No.22+5.0 · NO.22+5 · NO.12+5.5 → 그림 No.22+05 꼴 헬퍼 새로.
- 그림 검산: No.22+00~No.26+05 = 85 m · 3.5 × 85 = 297.5 ㎡ → 거리 = 종점 − 시점 · 면적 = 거리 × H(B).
### (d) 채움 · 표
- CAD Hatch 선 무늬뿐(HatchEntity.ts:17-28) · DXF 내보내면 Hatch 채움 사라짐(Engine_Frame_Export.py:210-213) → 파이썬 기본 도형(polyline_entity · _circle_entity Engine_Cad.py:57-148)으로 무늬 직접(돌 = 흔든 격자 원/폴리선 · 찰 작은 돌+줄눈 · 메 큰 돌 · 콘크리트·쇄석 = 점 · 돌망태 = 격자+돌 · 통나무 = 원 한 줄 · uuid5 씨앗) · 형태→무늬 hatchOfForm(B06_Section_UI_Cross_Wall_Hatch.ts:36-44) 뜻만 빌림.
- 표 table_entity(Engine_Cad.py:183-219 병합 칸 · DXF 선+글 Frame_Export.py:170-172 · 예 Engine_Cad_Table.py:129-275) · 기울인 라벨 _text_entity(direction)(:151-180) · 축척 auto_scale_h(MassHaul.py:55-66).
### (e) 최소 구조
- 새: B07_DesignDetail_Engine_Cad_Development.py(development_rows · development_items · build_development_drawing — 줄바꿈 배치 · 채움 · 양 끝 측점·H 라벨 · L= · 우하단 표 · 도각) · B07_DesignDetail_Router_Support_Structure.py(linked_snapshots + structure_frame) · test_241_development.py.
- 고침: Router_Support.py(666줄) _drawing_list 맨 뒤 두 목록(도면번호 안 밀리게) · _read_drawing 분기 둘 + 확정본 kind(:479-484) · Router.py(:311-353) 전개도 id 면 source_design=_designs_by_chainage(:261) · Schema.py Literal "structure" · "development" · Api_Fetch.ts union · UI_Panels.ts DRAWING_GROUPS 「구조물 도면」 「전개도」 · :132 늘 카드 · 하위 묶음 groupPlanSheets 재사용 · config_system.py:155-195 축척 후보(선택).
- id development_{type_id}_{FORMS 순번}[_{n}] · 그룹 (구조물 종류, 형태)마다 한 장 · 넘치면 _2 · 제목 「{구조물} {형태} 전개도」 · 포장 「콘크리트포장 전개도」 · 「쇄석포설 전개도」.
### 물음(권장): 두께 = 벽 H · 포장 B · 거리 = 종점−시점 · 길이 없는 것 빼고 「길이 미입력 N곳」 · 높이 빈칸 = 박스 + H=미입력 · 관보호공 그룹(배관 유입·유출 + 흙막이 n) · BOX·세월교 흙막이 = 각 그룹 · 바자 포함 · 숨김 종류 = 흙막이 그룹 · 추가 단 = 별도 박스 · 축척 자동 · 측점 No.04+08 · 구조물 도면 = 조합 키 중복 없앰 · 더한장 장마다 단추 · 확정 가능 · 쇄석 = 배치 있을 때만.
## 2장 ☰ 서랍 (241-4)
- 파일: A00_Common/app_shell.ts buildDrawer :150-224(☰ :151-156 · 열기/닫기 :165-175 · 안 단추 누르면 닫힘 :177-185 · CSS :427-499 · 프로젝트 화면 :538-548) · ui_template/ui_template_overlay.css · ui_template_theme.css · A00_Common/device_context.css · 시험 resources/tester/test_device_drawer.py.
- 묶음: ① 로고 :189 ② 진행 단계 :163-172(workflow_layout.ts:203 · B01 :241 · m_settings_nav.ts:91 에서 빌림) ③ 메뉴 nav.app-drawer__nav :191-193(NAV_ITEMS :128-134 프로그램 · 회사소개 · 소식 · 교육 · 기술지원 · 하위 없음 · 단추 높이 44 × 5 ≈ 236 px) ④ 설정 :219-221(언어 · 테마 · [설정] · 계정 :264-313 · 터치 모드 :226-261).
- 구분 안 됨 까닭: 폭 min(320px,100vw)(:461) = 패널 320(overlay:25 · theme:207) · 자리 top 0 · left 0(프로젝트 --app-header-h 0 · device_context.css:96 · :458 · :539) = 패널 · 바탕 둘 다 --color-surface-raised(:464 · overlay:15) · 그림자 둘 다 --shadow-lg(알파 6 % 이하) · 위 줄 z 201(:510) · 패널 200 → 서랍이 패널을 정확히 덮어 「패널 내용이 바뀐 것」처럼 보임.
- 고침: 폭 :461 min(240px,100vw)(어두운 패널 80 px 보임) · 바탕 :464 var(--color-surface)(밝음 #f6f7fa · 어두움 #1e1930 ≠ 패널) · 프로젝트 규칙 :542 border-right 2px solid var(--color-accent) · 메뉴 = 네이티브 details(open 없음 = 접힘 기본 · summary 는 버튼 아님 → 서랍 안 닫힘 · 키보드 됨) + summary 글 새 키 App_Nav_Site · CSS 한 줄 · 열림 기억 안 함(셸 다시 그림마다 접힘 = 기본) · 공개 화면(폭 900 이하)도 접힘(펼칠 거면 is-bm-route 판단 한 줄).
- 시험: test_device_drawer.py:78-83 묶음 순서 ["brand","steps","site","settings"] · :119-120 그대로 · 접힘 · summary 누름 = 펼침 + 서랍 유지 · 폭 < 패널 · 바탕 ≠ 패널 확인 더함.
## 3장 B06 횡단 — 교차점 · 좌상 표 · 표고 상자 · 사토장/토취장 (241-5 · 6 · 7 · 8)
### 5 교차점 = 사면처럼
- 370-2: 쪽마다 설계선∩원지반 원 · 늘 보임 · 키 toe:left|right(B06_Section_UI_Cross_Design_Pick.ts:472-477,498-505 · logic/B06_Section_UI_Cross_Fit.ts:62-71 · toeOffsets 37-59 · CSS B06_Section_UI_Style_Cross_Areas.css:196-206) · 멈춤 Fit.ts:81-113(Design_Pick.ts:559-566) · 멈춘 자리 = 성토 판정(common_util_cross_design_geometry.ts:196-199) · 0.02 m 보다 짧은 조각 버림(Design_Pick.ts:62,259) → 사면 키 사라짐 → 같은 쪽 toe: 이어받음(:298-306) · 교차점 누름 = 공용 칸 「교차점 이동 (좌/우)」 ◀↺▶ + ◀▶ 키(:640-645,662-673).
- 빠짐: hover 반응 없음(카드 고름 대상 :hover 규칙 0 · 커서만 Areas.css:183-188 · 상세 모달만 hover Style_Cross_Detail.css:212-230) · 제목 「교차점 이동」 ≠ 「사면 이동」 · 정확히 0 자리 시험 없음(helper_370_2_toe_stop.cjs:248-303) · 판정 원 5 px(Center.ts:17 기본 8 을 Design_Pick.ts:503 이 덮음).
- 고침: Areas.css:196-206 .b06-chart__toe-hit:hover(고른 모양) · design-hit:hover(164-176) · Design_Pick.ts:640-645 제목 「사면 이동 {쪽}」 · 사면 조각 없으면 값 앞 「절·성토 없음 · 」 · 원 8 px · 시험 test_370_2_toe_stop.py:66,79 · helper 에 section(stop) 경우.
- 물음(권장): 올리기만 해도 고름 = 아니오(올리면 강조 · 누르면 고름 — 지나가다 고름 뺏김 · 키 대상 흔들림 · 터치 hover 없음).
### 6 카드 좌상단 면적표 걷기
- B06_Section_UI_Cross_Areas.ts:320-416 buildAreaReadout(사토장 줄 378-392) · View.ts:652-654 만듦 · :687 붙임 · CSS Areas.css:10-115 · 모달은 SVG 만 떼 감(Section_View.ts:617) · 모달 표 = B07_DesignDetail_Engine_Cad_Table.py:40-59.
- 고침: View.ts 652-654 · 687 readout.root · setChipActive(195,229,248,265,309,322,691) 지움 · Areas.ts:250-416 지움 · Areas.css :18 · 21-115 지움(:17 --b06-areas-font 남김) · Style_Cross_Controls.css:7-15 조정창 top → var(--spacing-8) · locale_b2:427,432-439,442-443 지움 · Cross_Design.ts:446 주석 · test_173_areas_detail.py:46-72.
### 7 Y축 표고 상자 둘
- 지금 상자 하나 = section.center_z(중심 원지반고 · Engine_Sections_Core.py:470,503) · 소수 1 · B06_Section_UI_Cross_Axes.ts:29-31,120-147,151-173 · 색 --color-accent(Style_Cross.css:398-409 · 이미 보라) · 계획고는 십자선만(View_Frame.ts:39-59).
- 고침: Axes.ts designZ 옵션 · 상자 둘(원지반 먼저 · 계획 나중 = 위) · y 차 16 px 미만이면 원지반 상자만 밀어냄(위아래 관계 따라 · 칸 밖이면 반대) · --ground(--color-chart-1 = 원지반선 Style_Cross.css:430-433) · --design(--color-royal-amethyst = 설계선 Areas.css:151-155) · 배선 카드 View.ts:381-390 designZ(356) · 모달 Section_View.ts:621-630 cardDesignElevation(341-348) · 시험 test_318_cross_card.py:71-88,105-111,123-131 · helper_318 겹침 경우.
### 8 사토장 · 토취장
- 정의 구조물정의.json:2827-2848 spoil_bank(site · capacity_m3 · 켜짐) · 2849-2871 borrow_pit(꺼짐) · 부품 처음값 common_util/common_util_structure_parts.json:464-470 spoil_bank 횡단도 none · 형상 spoil · 3D surface(종류 정의 「반영」 없을 때 쓰는 코드 처음값) · borrow_pit 모두 none.
- 새 측점 안 심음(횡단도 none → common_util_structure_station.ts:152-160 빈 목록) · 사토 단면은 가까운 기존 측점(B06_Section_Engine_SpoilFill.py:46-65) · 입력은 아무 정수 m(Fields.ts:205 · Structures_Snap.ts:24-26 · Panel.ts:647-648,683).
- 카드 그림: spoil_sites(Engine_SpoilFill.py:103-113 ↔ logic/B06_Section_Cross_Enforce.ts:108-110) 폭 이분법 · 단면 다시 셈(Engine_Design.py:356-361,507-521 ↔ common_util_cross_design.ts:420-428,575-586 · Cross_Stage.ts:172-196 · Server_Calc_Prebuild.py:221-233) · 그림 View.ts:531-533 → Cross_SpoilFill.ts:59-95 · CSS Areas.css:569-587 · 면적표 줄 · 모달 띠(Detail_Table.ts:165-171 등) · B07 표 칸(Cad_Table.py:53-57,83).
- CAD 글 이미 됨: Detail_Cad.ts:237-280 측점 ±0.51 m 안 · 종류 이름 줄 + 「상세 내용: 사토장 부피 150㎥」(164-181 · Balloon.ts:195-206) ↔ CulvertNote.py:104-106,208-238 · 조건 = 기준 측점이 측점과 0.51 m 안 · 그 측점 CAD 칸 아직 저장 안 됨.
- 고침: parts.json:468-469 형상 none · 3D none(처음값) → spoil_sites 빈 목록 · 남은 사토 값 정리 로직(Engine_SpoilFill.py:232-268 · Cross_Stage.ts:125-127) · 죽은 코드(SpoilFill.ts · Engine_SpoilFill.py 등) 정리 · 기존 측점만 고르기 = common_util_structure_station.ts 「가장 가까운 기존 측점」 맞춤 → Fields.ts:205 · Snap.ts:25-26 · Panel.ts:648 · 방향키 Panel_Tools.ts:245 · 시험 test_322_1_catalog_mirror.py:84 · test_349_0n · test_b06_spoil_fill_allocation.py · test_spoil_fill_mirror.py · test_150 · test_179_4.
- 물음(권장): 사토 단면 계산(폭 · 용량 · 「사토장」 수량 칸)까지 지움 = 예 · 맞춤 방식 = 가까운 측점 · 대상 = 일반+구조물+추가 측점 · 저장된 CAD 칸 덧붙임 안 함 · 토취장은 사용자가 M02 에서 켬.
## 4장 B05 평면 — 아이콘 · 절성토선 · 측점/기울기 · 우측 판 · 교각점 · 연동 · 방향키 (241-9 · 10 · 11 · 12 · 14 · 15 · 16)
공통: RouteEdit.ts 697줄(700 한도 test_345_5b:139) → 새 배선은 Pointer · Cross · Render · Footprint · 새 파일 · Chrome/Render/Pointer/Cross/Input = B05_Profile_UI_RouteEdit_*.ts.
- 9 되돌리기 아이콘: Chrome:67-70 ↶ ↷ 글자 · 회전 Chrome:25-32 HALF_TURN_ICON(반원 화살표) → 둘 다 반원처럼 · 종단 도구줄 ↶↷(Profile_Tools.ts:173-176) · 고침 HISTORY_ICON SVG(곧은 꼬리 + 갈고리 ↩ ↪) · test_b05_routeedit_chrome_modal.py:41-43 · 물음(권장) 종단 도구줄도 같이(innerHTML).
- 10 절/성토선: 굵기 Footprint.ts:27 STROKE_WIDTH 1.4 · 색 Footprint.css:2-20(밝음 절토 #dc2626 · 성토 #2563eb = 하천선 같음 · 어두움 성토 #60a5fa ≈ 등고선) · 고침 갈래별 굵기(도로 끝 1.8 · 비탈 끝 2.6) · 색(권장 절토 밝음 #e11d48/어두움 #ff6b6b · 성토 밝음 #0d9488/어두움 #2dd4bf) · test_346_2_footprint_draw.py:108-114.
- 11 [측점] [기울기]: 측점 Render:309 drawStationMarks(B04 MapOverlays.ts:227) · 기울기 Render:310 overStations → RouteEdit:347-356 → Slope.ts:174-181(/route/elevations) · 켬끔 본보기 Footprint.ts:29,50-61 · 고침 Chrome:81 앞 두 단추 · 켬끔 모듈 · Render:309-310 · 함정: 측점 끄면 Pointer:188-205 눈금 집기도 끔(Input:329-331 라벨 0개면 전부 집힘) · 물음(권장) 기본 둘 다 켬 · 페이지 동안 기억 · 시점·종점 이름표 남김 · 기울기 끄면 높이 요청 멈춤.
- 12 횡단 우측 판: 양식 = ui_template_side_panels.ts · .css(createSidePanels :68 · createWorkflowPanelHandle · 폭 끌기 · aislo:pref 기억 · M02_Labor_Detail.ts:155 · M02_AreaPanel.ts:107 · M01_LogicLab_Side.ts:41 · 배수유역 판 Drainage_Chrome.ts:66) · 지금 자체 틀(Chrome:121-140 aside side-wrap · [횡단] 유리 단추 · RouteEdit.css:190-245 덮개 · --b05-side-open) · 고침 createSidePanels({prefKey:"b05-routeedit-cross", panels:[{id:"cross",title:"횡단",body:side}], follow:false, defaultWidth:460}) · 물음: 양식대로면 지도를 밀어 좁힘(352-1 덮개와 다름) · test_b05_routeedit_chrome_modal.py:46,56-58.
- 14 교각점: NODE_R 4(+2 고름 Render:36-37) · 그리는 차례 노드(249-305) 위에 반폭선 · 눈금 · 라벨 · 기울기 · 재기 · 등고 라벨(308-314) → 라벨이 덮음 · 집기 문턱 Pointer:35-42(노드 9 · 손잡이 11 · 눈금 11 · 호 8 · 등고 6) · 집는 차례 노드 먼저(158-236) · 하이라이트 없음(pointermove 커서만 298-309) · 고침 노드 블록을 314 뒤로 · NODE_R 6 · 문턱 12 · 맴돔 pickAt(노드 중심 6 px 안 = 노드 · 밖 = 가까운 쪽) · 이길 쪽만 밝힘 · Input stationAtScreen {chainage, distance} · test_b05_routeedit_pick.py.
- 15 연동 · 법선: 평면은 고름 한 칸 안 들음(design_selection.ts:135,150 · design_pick_profile.ts:134-160 · design_view_profile.ts:380-389) · 평면 눈금 클릭(Pointer:188-205)도 안 적음 · 파란 법선 = Render:392-430 drawCrossWidth(#0ea5e9) 뜬 측점 하나 · 길이 = Cross:253-260 B06 「횡단 반폭」 세션값 또는 원지반 표본 범위(:176,184) → 노선 · 설계 무관(안 바뀜 유력 원인) · 기준점 처음 누른 누가거리 붙듦(Cross:241) · 스냅 때 MC 측점 옮김(Frame.ts:158-176) → 선 눈금에서 벗어남 · pipelineCrossAt(Cross:172-174) 종류 안 가림 · 자료 = 가게 footprint.records(PlanFootprint.ts:43-57 · 일반측점 key grid:) · 고침(Cross 한 곳): subscribeSelection 구독 → 일반측점이면 open · 평면 open 하면 selectDesign(from b05-plan) · 측점 key 로 들고 차례마다 다시 짚음 · 폭 = footprint 비탈 끝 좌우 · 절성토 색 · test_b05_routeedit_cross_width.py · 물음(권장) 구조물 고름 = 그 자리 마름모 · 법선 = 고른 측점 하나 · 평면 눈금 클릭 = 공용 고름에 적음.
- 16 방향키: 평면 키 처리 없음 · 고른 점 RouteEdit:162 picked · 충돌 Profile_Panel_Tools.ts:317-364(▲▼ :226-233 arrowsBelongToProfile 안 봄 · ◀▶ :236 · :348 defaultPrevented 비킴) · 스냅(366-3) 놓을 때만 맞춤 → 0.1 m 밀어도 같은 측점이면 되돌아옴 · 반 간격 넘으면 수 m 튐 · 뒤 IP 도 · 고침 Pointer: window keydown capture(마지막 누름 .b05-routeedit 안 · picked ≥ 0 · 고정 아님 · 입력칸 아님) · unrotate + toMetric 화면 위 = 위 · 0.1 m · 하한 Pointer:271-291 · 누르는 동안 옮김만 · 뗄 때 commit(스냅이면 맞춤) · 반복 Profile_Edit.ts:32-33 · lastPointerWithin(Panel_Base.ts:77-96) · 물음(권장) 화면 축 · Shift ×10 · 스냅 때 상태줄 「실제 이동 m · 함께 밀린 IP 수」 · 제자리면 「같은 측점 — 스냅 끄고 미세 조정」 · IP 안 고른 채 평면 누른 뒤 ▲▼ = 평면이 삼킴.
## 5장 R = 일반측점 기본 제약 · 노선 추천 · [재계산] (241-13 · 18)
약칭: Station=B05_Profile/B05_Profile_Engine_RouteInitial_Station.py · RI=B05_Profile_Engine_RouteInitial.py · Pool/Search/Store=B05_Profile_Engine_RouteInitial_{Pool,Search,Store}.py · Rec=B05_Profile_UI_RouteEdit_Recommend.ts · Fit=logic/B05_Profile_RouteEdit_StationFit.ts · RE=B05_Profile_UI_RouteEdit.ts(697줄) · Replan=B05_Profile_Router_Replan.py(682줄) · CSS=B05_Profile_UI_Style_RouteRecommend.css
### 351 추천 지금
- 갈래 고른 뒤 그 선만 맞춤(RI:398-417 · 고르기 · 비중 쓸기는 맞추기 전 선 test_route_initial.py:124) · 응답 = 맞춘 선 + unsnapped + off_station_curves(RI:431-446).
- 셈(Station:465-491 깊이 우선 · 되돌림 30번 :443-462): IP 들어오는 접선 ±20 m(:199-232) · R 후보 9(:300-303) · 목표 = MC 아래/위 일반측점 · 앞 MC + 20 m 이상(:304-308 → 곡선 수 ≤ 측점 수 · MC 간격 ≥ 20 m) · 원래 선 6 m 넘게 벗어나거나 더 가파르면 버림(:277-281 · config:44) · 못 놓으면 뒤 꺾임 3개까지 합침(_absorb_next :235-257) · 안 되면 내각 ≥ 155° 일 때만 곡선 끔(:356-364) · 20 m 안 다투는 쌍 = 덜 꺾인 IP 지움/꺾임만(_crowded :369-418) · 그래도 = 그 자리(_kept :420-441) 「측점 밖 곡선 N개」(Rec:428-431).
- 모달 「측점 맞춤」 기본 켬 · 저장 안 됨(Rec:151-154,310-316) · [적용] = 보이는 쪽(Rec:578-581) · 실측 측점 밖 16 → 3/166.
- 생성 중 넣을 자리: ① _turn_steps(Search:227-235) IP 간격 ≥ 20 m(그래프 ×1.75 · 비추천) ② _trace(Pool:116-131) 후보마다 맞춤 → 고르기 · 쓸기 · 거름(Pool:176-178,201,223) 맞춘 선 기준 · 측점 밖 0 후보 앞세움 · excess(RI:337-346) · ALGO_VERSION 5(Store:35) · 후보 ~30 만큼 시간 더.
### 366-3 손 편집
- Fit = 351 줄인 꼴(±간격/2 :109 · 하한 깨면 버림 :157-165 · 합침 · 끔 · 되돌림 없음) · 24/50 실패 까닭 = 앞 곡선이 측점 차지 → 다음 곡선 빈 측점 10 m 넘게 멀어 건너뜀(:151-156).
- 부르는 자리 RE:267-271 · 452-456 · 540-541 · 상태줄 RE:419 · 깃발 = 편집 창 기본 끔(RE:164) → 열 때 plan.station_snap(RE:618-619) ← Replan:535 ← load_station_snap(칸 없으면 끔 Engine_Sections.py:88-90) ← [저장] 때만(Replan:253-277,585) · 같은 깃발 = 224-2 「호 안 일반측점을 MC 로」(Sections_Core.py:291-313,377 · Engine_Sections.py:460,575 · design_pipeline_page.ts:608) → 옛 프로젝트 기본 켬이면 측점 · 수량 말없이 바뀜 · 추천 [적용] = 편집 창 깃발 저장(RouteEdit_Apply.ts:174).
### 18 재계산
- 이미 있음 data-act="rerun"(Rec:201) · 토글을 그 앞에 끼움(Rec:316) · 안 보이는 까닭 = 옵션 칸 세로 쌓임(CSS:276-294,408-410) + dirty 일 때만(Rec:400) · 경로 Rec:577 → run()(:445-517) → POST /route/initial(Router_RouteInitial.py:29-38 → compute_initial :41-180 · 같은 입력 저장본 :128-131 · 아니면 비중 탐색만 RI:376-392 → Pool:270-287).
- 고침: Rec:201 버튼을 .b05-routerec__row 로 감쌈(토글 왼쪽 같은 줄) · CSS 한 줄 flex · 늘 보이게 Rec:400-401(hidden = logic !== "weighted" && !dirty 또는 늘 보임 + disabled).
### 지식DB: 곡선 최소 간격 기준 없음(grep 0) · 곡선설치_계산.md:34 TL₁+TL₂ ≤ IP 거리(기하) · 평면선형.md:26 내각 155° 이상 곡선 생략 가능 · 설계제원_총괄.md:114 측점 20 m · 노선측량.md:144 원전 MC = 보조측점(사용자 규칙과 다름) → 「MC = 서로 다른 일반측점」 = 사용자 규칙으로 기록.
### 최소 설계(권장): 새 초기 노선 서버 맞춤 + 깃발 켬(_ensure_planned_initial Replan:287-309 · 도우미는 Station) · 편집 창 깃발 = 저장값(새 프로젝트 켬 · 옛 칸 없음 = 끔) · 못 맞춘 곡선 그대로 + 개수 · 추천 [적용] = 깃발 켬 저장(Apply.ts:174) · 추천 셈 기본 켬 · 남은 측점 밖 곡선 = 「못 지킨 구간」에 · 고르기 단계부터 맞춘 선(a②)은 2단계.
### 물음: Q1 옛 프로젝트 기본 켬(권장 아니오) · Q2 못 맞춘 곡선(그대로 + 경고) · Q3 추천 「측점 맞춤」 끔 갈래 남김 · Q4 고르기 단계부터 맞춘 선(a②) · Q5 224-2 옛 규칙 남김 · Q6 재계산 늘 보임 vs 바꾼 뒤.
## 6장 B05 · B06 한 페이지 · 캐시 공유 — 방법 제시 (241-17)
약칭(A00_Common/design/): DP=design_page · DSh=design_shared · DSt=design_store · DSv=design_save · DL=design_leave · DPr=design_profile · PP=design_pipeline_page · PC=design_pipeline_cross · VP=design_view_profile · VPS=design_view_profile_sections · VC=design_view_cross · BPS=A00_Common/b_page_state · B05 PS=UI_Page_Structures · PA=UI_Page_Actions · PT=UI_Profile_Panel_Tools · PH=UI_Profile_History · PE=UI_Profile_Edit · RE=UI_RouteEdit · RH=UI_RouteEdit_History · RA=UI_RouteEdit_Apply · RC=UI_RouteEdit_Cross · B06 SS=Section_Store · SD=Section_Drafts · SK=Station_Keys · SW=UI_Page_Station_Swap · SVP=UI_Section_View_Profile · DS=UI_Page_Design_Sync · LS=UI_Page_Link_Session · FC=UI_Page_Ford_Controls · SP=UI_Page_Structures_Panel · PER=UI_Page_Persist · CV=UI_Cross_View · CR=Cross_Refresh
### (a) 같은 자료를 여러 벌 듦
- 노선 초안 3벌(세션 route-draft · 편집기 클로저 RE:137-160 · 편집기 사진 100단 RH:94 · 등록표 RA:64) · 계획고 초안 2벌(alignment-draft · PE shared Map PE:150 · 노선 0 상수 두 곳 PP:113 · DSv:113) · 관 5벌(초안 · b05:pipes 세션 직접 PT:44,94,100 · shared.lastPipes DSh:100,180 · VP:113-129 · B06 SP:169 · 배수 판) · 구조물 6벌 · 저장분 관·구조물·종류 6곳 따로 fetch(PP:614-617 · SD:48,80-91 · PS:283-284 · SP:383-385 · 배수 판 · DSv:168-183 · 종류 목록 켜진 것만 vs 전부) · 횡단 상세(SS cache · 세션 1.5 MB · PC storedText 재파싱 · 묶음 canon/shown · hold · 고치는 쪽 넷 — 카드 그리기가 면적 씀 CV:512-520) · 조정창 9칸 = 누가거리 글 열쇠 · 세션 직접(LS:84,99 · FC:139,154,340,357) · 노선 id 출처 다섯(PA:46 · VC:618 · DPr:210 · PP:246 · RC:76-88) · 고름 · 사진첩(draft 만) · 떠남 지문 메모리만.
### (b) 아직 두 페이지처럼
- 기능이 보기 마운트에 달림(DP:84-87,208-216 · 숨긴 채 세움 셋 DSh:344 · VP:234 · DP:145) · 진입 길 둘(VP:487-550 vs VC:589-682 · 대시보드 돌려보냄 조건 둘) · 마운트가 모듈 싱글턴 덮어씀(setPipeSectionsSource VP:232 · VC:111) · 묶음 재료를 보기가 넣음(VPS:85,91 · SVP:188,295 · 종류 갈래 PS:286 · SP:387 · 365-5 덧대기 baseMoved PP:311,678 = 증거) · 화면이 공유 자료 고침(CV:512-520 · 다시 셈 창구 셋 · 면적 얹기 다섯) · 보일 때마다 다시 받기(VP:441-445 · VC:563-571) · 알림 콜백 표(DSh:146-165) · 저장 길이 마운트에 달림(DSh:271-273 · PA:81-84 vs PER:521-541 · 뒤처리 둘) · 다시 세우기 다섯 길 · 키 · 떠남(PT:364-370 · setActive 부르는 곳 0 · RH listen 빈 함수 · DL:109-112 꼼수).
### (c) 목표 원칙 일곱
1 상태 한 곳 = design_store(값마다 칸 하나 · 보기는 구독) 2 자료 읽기 한 줄 = 페이지(저장분 한 번 · 노선 id = 서버 context 한 칸 · 보기 전환 요청 0) 3 계산 한 벌 = 묶음(입력 = 가게 칸 · 파생 = 묶음 출력 · 횡단 다시 셈 창구 하나 · 지문 고리) 4 보기 = 그리는 쪽(구독해 그리기만 · 공유 객체 안 고침 · 숨으면 그림만 멈춤) 5 되돌리기 한 줄(사진 = draft 칸만) 6 열쇠 한 규칙(aislo:{통}:{이름}:{프로젝트}[:{노선}] · 측점 값 = 측점 열쇠 · 세션 직접 0) 7 3층 그대로(CLAUDE.md 5장 · [저장] 본문 = 칸에서 모음).
### 옮기는 차례(0~7 · 단계마다 확인)
0 기준 잼(전환당 요청 수 · switchMs DP:251-254 · 열 때 바퀴 · test_365) → 1 죽은 갈래 · 열쇠 정리(세션 직접 접근 → 등록부 · grep 0) → 2 페이지 자료 줄(새 design_page_data.ts · 저장분 한 번 · 노선 id 한 칸 · 종류 한 벌 · 새로고침 fetchStructures 1회 · 전환 요청 0) → 3 묶음 입력 = 가게만(보기 render/setIrregularStations 지움 · 어느 쪽 먼저든 열 때 1바퀴 · baseMoved 0) → 4 횡단 다시 셈 창구 하나(refreshCrossDesigns 부르는 곳 1 · ▲ = cross 1회 · 카드 안 그려도 면적 같음) → 5 보기 = 그리는 쪽(toView/toAll → 가게 구독 · setPipe* → shared 서비스 · onShow fetch 지움) → 6 저장 한 줄 보기 무관(B05 만 연 [저장] 몸 = B06 다녀온 뒤 몸 · B06 안 열고 [확정]) → 7 결과 층 정리(세션 section-detail = 저장 정본만 · JSON.parse 횟수 · 세션 크기).
- 주의: 700줄 근처 DPr 700 · PP 698 · RE 697 · VC 688 → 새 파일 · SS · B05_Profile_Api_Structures 는 B07 · B08 · B09 도 부름(2 · 7 단계 그쪽 시험 같이).