Sprint 35 — 뷰어 IFC 익스포트 연결 + Pset_BeamCommon

## 뷰어 통합
- `cimery-viewer` → `cimery-ifc` 의존성 추가.
- `project_file::scene_params_to_ifc()` 변환 함수:
  SceneParams 의 모든 파라미터(경간 수·교각 형식·skew·헌치·단면 종류·신축이음)
  를 BridgeExportParams 로 전부 매핑.
- egui 프로젝트 섹션에 "📤 IFC4X3 익스포트" 버튼.
  현재 파라미터 상태로 즉시 `projects/bridge.ifc` 생성.
- `project_file::default_ifc_path()` 헬퍼.

## Pset_BeamCommon (IFC Phase 3a)
- `write_pset_beam_common()`: 4개 속성
  · Reference (IFCIDENTIFIER) — 거더 라벨
  · Span (IFCLENGTHMEASURE) — mm
  · LoadBearing (IFCBOOLEAN) — .T.
  · IsExternal (IFCBOOLEAN) — .F.
- IFCRELDEFINESBYPROPERTIES 로 각 IFCBEAM 에 연결.
- `IfcSectionKind` public re-export (viewer 에서 직접 참조).

## 테스트
- pset_beam_common_attached_to_girders 추가. 17개 전체 통과.
- cargo check --workspace --features occt: 0 errors.

Phase 3 남은 로드맵:
- IfcAlignment + IfcLinearPlacement
- Camber 반영 (현재 직선 girder 만)
- Pset_BearingCommon, Pset_SlabCommon
- IfcElementAssembly 로 Pier(column+capbeam) 그룹화

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
minsung
2026-04-15 19:31:36 +09:00
parent 567345e933
commit 693c95dc6f
6 changed files with 107 additions and 2 deletions

View File

@@ -19,6 +19,7 @@ path = "src/main.rs"
[dependencies]
cimery-kernel = { workspace = true }
cimery-ifc = { workspace = true }
log = { workspace = true }
env_logger = { workspace = true }
wgpu = "22"

View File

@@ -764,6 +764,18 @@ impl RenderState {
}
}
});
// Sprint 35: IFC4X3 Add2 익스포트 (현재 파라미터 기준).
if ui.button("📤 IFC4X3 익스포트").clicked() {
let params = project_file::scene_params_to_ifc(&p, "bridge");
let ifc = cimery_ifc::export_bridge(&params);
let path = project_file::default_ifc_path("bridge");
match std::fs::write(&path, &ifc) {
Ok(_) => log::info!(
"IFC exported: {:?} ({} bytes)", path, ifc.len()
),
Err(e) => log::error!("IFC export failed: {e}"),
}
}
});
ui.separator();

View File

@@ -131,3 +131,37 @@ pub fn default_save_path(name: &str) -> std::path::PathBuf {
p.push(format!("{}.cimery.json", name));
p
}
/// IFC 파일 기본 저장 경로.
pub fn default_ifc_path(name: &str) -> std::path::PathBuf {
let mut p = std::path::PathBuf::from("projects");
std::fs::create_dir_all(&p).ok();
p.push(format!("{}.ifc", name));
p
}
/// SceneParams → cimery-ifc::BridgeExportParams 변환.
///
/// viewer 의 SceneParams 에 있는 모든 파라미터를 IFC 익스포터 입력으로 매핑.
/// 선형(alignment)·camber 는 IFC Phase 3 로드맵(미반영).
pub fn scene_params_to_ifc(p: &SceneParams, name: &str) -> cimery_ifc::BridgeExportParams {
use cimery_ifc::{BridgeExportParams, IfcSectionKind};
BridgeExportParams {
name: name.to_owned(),
span_m: p.span_m,
span_count: p.span_count,
girder_count: p.girder_count,
girder_spacing: p.girder_spacing as f64,
girder_height: p.girder_height as f64,
slab_thickness: p.slab_thickness as f64,
bearing_height: 60.0,
section_kind: match p.section_type {
GirderSectionType::PscI => IfcSectionKind::PscI,
GirderSectionType::SteelBox => IfcSectionKind::SteelBox,
},
skew_deg: p.skew_deg as f64,
haunch_depth: p.haunch_depth as f64,
show_parapets: true,
show_joints: p.show_expansion_joints,
}
}