feat(b07): 횡단 원지반 층 잠금 풂 · 측점 한 벌 groupId(180-1)
- 장 · 측점 한 장 원지반 층 잠금 지움(종단 그대로) - 장의 측점마다 그림 · 표 · 글 groupId 하나 · cross_placements group_id - 화면 덧그림(설계선 · 구조물)도 같은 groupId - 새 시험 test_180_b07_cross_group Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TNMXVCZXMpHpVvqmFkeChL
This commit is contained in:
@@ -19,7 +19,7 @@ from uuid import UUID, uuid5
|
||||
|
||||
from config.config_system import DRAWING_SCALE_CROSS
|
||||
|
||||
# 레이어 정의 — 지표면선은 상세설계 제어 대상에서 제외하므로 잠금한다(N-1-3).
|
||||
# 레이어 정의 — 지표면선은 종단에서 잠금(N-1-3) · 횡단은 장에서 옮기므로 풂(180-1).
|
||||
GROUND_LAYER_ID = "b08-ground"
|
||||
GROUND_COLOR = "#f5f7fa"
|
||||
DESIGN_LAYER_ID = "b08-design"
|
||||
@@ -622,7 +622,7 @@ def build_cross_drawing(
|
||||
}
|
||||
],
|
||||
"layers": [
|
||||
_layer(GROUND_LAYER_ID, "원지반", locked=True),
|
||||
_layer(GROUND_LAYER_ID, "원지반"),
|
||||
_layer(DESIGN_LAYER_ID, "계획선"),
|
||||
_layer(STRUCTURE_LAYER_ID, "구조물"),
|
||||
_layer(ROCK_LAYER_ID, "암 경계선"),
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
|
||||
import re
|
||||
from typing import Any
|
||||
from uuid import uuid5
|
||||
|
||||
from B05_Profile.B05_Profile_Engine_Sections import cross_key
|
||||
from B07_DesignDetail.B07_DesignDetail_Engine_Cad import (
|
||||
@@ -22,6 +23,7 @@ from B07_DesignDetail.B07_DesignDetail_Engine_Cad import (
|
||||
ROCK_LAYER_ID,
|
||||
STRUCTURE_LAYER_ID,
|
||||
TABLE_LINE_COLOR,
|
||||
_ENTITY_NS,
|
||||
_clip_polyline,
|
||||
_layer,
|
||||
_section_window,
|
||||
@@ -211,6 +213,12 @@ def build_cross_sheet(sheet: dict[str, Any], sections: list[dict[str, Any]]) ->
|
||||
left, _bottom, right, top = frames[0] if frames and frames[0] else cell
|
||||
if left < cell[0] - 1e-6 or right > cell[2] + 1e-6 or top > cell[3] + 1e-6:
|
||||
overflow.append(cell)
|
||||
# 측점 한 벌 = groupId 하나 — 한 번 클릭에 그림 · 표 · 글 함께(180-1)
|
||||
group_id = str(uuid5(_ENTITY_NS, f"{seed_id}:group"))
|
||||
for entity in placed["entities"]:
|
||||
entity["groupId"] = group_id
|
||||
for placement in placed.get("cross_placements") or []:
|
||||
placement["group_id"] = group_id
|
||||
entities.extend(placed["entities"])
|
||||
placements.extend(placed.get("cross_placements") or [])
|
||||
|
||||
@@ -233,7 +241,7 @@ def build_cross_sheet(sheet: dict[str, Any], sections: list[dict[str, Any]]) ->
|
||||
# 칸보다 큰 단면의 칸 [x0, y0, x1, y1] — 라우터가 CAD 가이드 붉은 틀로 보냄(169-2)
|
||||
"overflow_cells": overflow,
|
||||
"layers": [
|
||||
_layer(GROUND_LAYER_ID, "원지반", locked=True),
|
||||
_layer(GROUND_LAYER_ID, "원지반"),
|
||||
_layer(DESIGN_LAYER_ID, "계획선"),
|
||||
_layer(STRUCTURE_LAYER_ID, "구조물"),
|
||||
_layer(ROCK_LAYER_ID, "암 경계선"),
|
||||
|
||||
@@ -32,6 +32,8 @@ export interface CrossPlacement {
|
||||
x1: number;
|
||||
/** 블록 테두리(종이 mm) [x0, y0, x1, y1] — 그림을 이 안으로 자른다. */
|
||||
frame?: number[];
|
||||
/** 측점 한 벌 묶음(180-1) — 덧그림도 같은 묶음으로 함께 골라짐. */
|
||||
group_id?: string;
|
||||
}
|
||||
|
||||
/** 측점과 도면 배치를 같은 자리로 볼 허용 오차(m). 정본이 누가거리를 0.01m로 끊어 쓴다. */
|
||||
@@ -78,6 +80,7 @@ export async function appendStructureEntities(
|
||||
continue; // 한 측점의 기하 실패가 도면 전체를 막으면 안 된다.
|
||||
}
|
||||
if (!entities.length) continue;
|
||||
if (placement.group_id) for (const entity of entities) entity.groupId = placement.group_id;
|
||||
// 이 블록 설계선은 우리가 다시 그렸다 — 서버가 낸 트림 전 설계선은 걷어낸다.
|
||||
replaced.push(frame);
|
||||
fresh.push(...entities);
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""180-1 B07 횡단 장 — 원지반선 고르기 · 측점 한 벌 groupId.
|
||||
|
||||
못박는 것
|
||||
- 횡단 장 · 측점 한 장의 원지반 층은 안 잠김(종단은 그대로 잠김).
|
||||
- 측점마다 groupId 하나(원지반 · 계획선 · 표 · 글 전부) · 측점끼리 다름.
|
||||
- 칸 격자선 · 도각엔 groupId 없음.
|
||||
- cross_placements 의 group_id = 그 측점 엔티티 값(화면 덧그림이 같은 묶음).
|
||||
"""
|
||||
|
||||
from B07_DesignDetail.B07_DesignDetail_Engine_Cad import (
|
||||
FRAME_LAYER_ID,
|
||||
GROUND_LAYER_ID,
|
||||
build_cross_drawing,
|
||||
)
|
||||
from B07_DesignDetail.B07_DesignDetail_Engine_Cad_Sheet import (
|
||||
build_cross_sheet,
|
||||
plan_cross_sheets,
|
||||
)
|
||||
from B07_DesignDetail.B07_DesignDetail_Engine_Template import use_project_templates
|
||||
|
||||
|
||||
def _source(chainage: float) -> dict:
|
||||
return {
|
||||
"chainage_m": chainage,
|
||||
"samples": [
|
||||
{"valid": True, "offset_m": float(x), "elevation_m": 100.0 + 0.1 * x}
|
||||
for x in range(-5, 6)
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
def _design_line() -> list[dict]:
|
||||
return [{"offset_m": x, "elevation_m": 100.0} for x in (-3.0, 0.0, 3.0)]
|
||||
|
||||
|
||||
def _drawing() -> dict:
|
||||
use_project_templates(None)
|
||||
chainages = [0.0, 20.0, 40.0, 60.0]
|
||||
sheet = plan_cross_sheets(chainages, {"default": [2, 2]})[0]
|
||||
sections = [
|
||||
{
|
||||
"chainage": c,
|
||||
"source": _source(c),
|
||||
"design_line": _design_line(),
|
||||
"design": {"structure_note": "L형 측구"},
|
||||
"quantity_table": {"ground": 1.0, "planned": 0.5},
|
||||
"title": f"No.{int(c // 20)}",
|
||||
}
|
||||
for c in chainages
|
||||
]
|
||||
return build_cross_sheet(sheet, sections)
|
||||
|
||||
|
||||
def _ground_locked(drawing: dict) -> bool:
|
||||
return next(layer for layer in drawing["layers"] if layer["id"] == GROUND_LAYER_ID)["isLocked"]
|
||||
|
||||
|
||||
def test_원지반_층_안_잠김() -> None:
|
||||
assert _ground_locked(_drawing()) is False
|
||||
single = build_cross_drawing(_source(0.0), "cross_00000m", _design_line(), None, None, "")
|
||||
assert _ground_locked(single) is False
|
||||
|
||||
|
||||
def test_측점마다_groupId_하나() -> None:
|
||||
drawing = _drawing()
|
||||
placements = drawing["cross_placements"]
|
||||
assert len(placements) == 4
|
||||
group_ids = [p["group_id"] for p in placements]
|
||||
assert len(set(group_ids)) == 4 # 측점끼리 다름
|
||||
grouped = [e for e in drawing["entities"] if "groupId" in e]
|
||||
assert {e["groupId"] for e in grouped} == set(group_ids)
|
||||
for group_id in group_ids:
|
||||
members = [e for e in grouped if e["groupId"] == group_id]
|
||||
layers = {e["layerId"] for e in members}
|
||||
types = {e["type"] for e in members}
|
||||
assert GROUND_LAYER_ID in layers and "Table" in types and "Text" in types
|
||||
# 격자선 · 도각은 묶지 않음
|
||||
assert all("groupId" not in e for e in drawing["entities"] if e["layerId"] == FRAME_LAYER_ID)
|
||||
assert all(e["layerId"] != FRAME_LAYER_ID for e in grouped)
|
||||
|
||||
|
||||
def test_groupId_결정적() -> None:
|
||||
first = [p["group_id"] for p in _drawing()["cross_placements"]]
|
||||
assert first == [p["group_id"] for p in _drawing()["cross_placements"]]
|
||||
Reference in New Issue
Block a user