Sprint 33 — IFC4X3 Add2 익스포터 Phase 1 (cimery-ifc 신설)

P2 로드맵 (Gitea #4) 첫 단계. 교량·토목 현재 표준인 IFC4X3 Add2 로 익스포트.

## cimery-ifc 크레이트 구성
- src/guid.rs: IfcGloballyUniqueId 생성.
  UUIDv4 128비트 → buildingSMART base64 22자 인코딩.
- src/writer.rs: STEP Part21 텍스트 writer.
  IfcWriter(alloc/emit/write/finish), Ref(#N), lit, real, real3, ref_list.
  HEADER 블록(FILE_DESCRIPTION/FILE_NAME/FILE_SCHEMA='IFC4X3_ADD2') + DATA 블록.
- src/bridge_export.rs: 교량 하이레벨 API.
  BridgeExportParams(span·girder·slab·bearing 치수) + export_bridge() -> String.

## 생성 엔티티 (Phase 1)
계층:
  IfcProject
    └ IfcRelAggregates → IfcSite
        └ IfcRelAggregates → IfcBridge
            └ IfcRelContainedInSpatialStructure → elements[]

원소:
- IFCBEAM × (span_count × girder_count) — 거더
- IFCSLAB × 1 — 데크 슬래브 (전 구간 연속)
- IFCCOLUMN × (span_count-1) — 피어 기둥 (내부 지점만)
- IFCFOOTING × 2 — 교대 (양 끝)
- IFCBEARING × (span_count+1)×girder_count — IFC4X3 신규 엔티티

형상 단순화(Phase 1):
- IFCEXTRUDEDAREASOLID + IFCRECTANGLEPROFILEDEF 일률.
- Phase 2 에서 IFCARBITRARYCLOSEDPROFILEDEF 로 PSC-I 14점 단면 매핑 예정.

단위: IFCSIUNIT mm (+ radian·squareMetre·cubicMetre·second·kilogram).
배치: IfcLocalPlacement 월드 원점 기준 (선형·skew·camber 는 Phase 2).

## 테스트
10개 통과:
- guid: 22자 고정, 동일 UUID 동일 GUID, 문자셋 유효성.
- writer: shell 구조, REAL 포맷, ref_list 포맷.
- bridge_export: 단경간 핵심 엔티티 포함, 다경간 피어 개수, 거더 수 일치, STEP 구조.

## 통합
- workspace Cargo.toml: crates/ifc 추가.
- cimery-app: export_ifc_default IPC 커맨드 (tauri dialog .ifc save).
- main.rs invoke_handler 등록.

Phase 2 로드맵(후속 스프린트):
- IfcAlignment + IfcLinearPlacement (선형 좌표)
- 실제 단면 profile (PSC-I · SteelBox)
- Pset_BeamCommon·Pset_BearingCommon
- IfcPile·IfcExpansionJoint·IfcKerb(방호벽)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
minsung
2026-04-15 17:02:51 +09:00
parent 94ce89093f
commit 7f14423bcd
10 changed files with 711 additions and 0 deletions

View File

@@ -19,6 +19,7 @@ cimery-kernel = { workspace = true }
cimery-incremental = { workspace = true }
cimery-evaluator = { workspace = true }
cimery-usd = { workspace = true }
cimery-ifc = { workspace = true }
serde = { workspace = true }
serde_json = { workspace = true }

View File

@@ -226,6 +226,38 @@ pub async fn export_usd_default(app: AppHandle) -> CmdResult {
}
}
// ── IFC4X3 Add2 export (Sprint 33) ────────────────────────────────────────────
/// 기본 교량 파라미터로 IFC4X3 Add2 파일(.ifc) 생성.
#[tauri::command]
pub async fn export_ifc_default(app: AppHandle) -> CmdResult {
use tauri_plugin_dialog::DialogExt;
use cimery_ifc::{BridgeExportParams, export_bridge};
let path = app
.dialog()
.file()
.add_filter("IFC4X3 Add2", &["ifc"])
.set_file_name("bridge.ifc")
.blocking_save_file();
let Some(p) = path else {
return CmdResult::err("cancelled");
};
let path_str = p.to_string();
let params = BridgeExportParams::default();
let ifc_text = export_bridge(&params);
match std::fs::write(&path_str, ifc_text) {
Ok(_) => {
log::info!("IFC exported: {path_str}");
CmdResult::ok_path(path_str)
}
Err(e) => CmdResult::err(format!("write error: {e}")),
}
}
// ── CSV template ──────────────────────────────────────────────────────────────
/// Generates a CSV parameter template for girder design.

View File

@@ -47,6 +47,7 @@ fn main() {
commands::open_project_dialog,
commands::save_project_dialog,
commands::export_usd_default,
commands::export_ifc_default,
commands::export_csv_template,
])
// ── Run ─────────────────────────────────────────────────────────────