feat: add LOD selection UI to PLATEAU building picker sidebar#202
feat: add LOD selection UI to PLATEAU building picker sidebar#202Soynyuu wants to merge 2 commits intofeature/199-lod-selection-apifrom
Conversation
Add a segmented button control (自動/かんたん/標準/詳細) to the Sidebar footer that lets users choose the conversion LOD (assembly difficulty) for papercraft models. Lower LOD = simpler geometry = easier papercraft. New components: - LodSelector.tsx: segmented button with 4 LOD options - LodSelector.module.css: styled to match Paper-CAD design system Modified: - Sidebar.tsx: integrate LodSelector, new props for LOD state - PlateauCesiumPickerReact.tsx: manage selectedLod state, pass to Sidebar and include targetLod in import/unfold callbacks - plateauCesiumPickerDialog.ts: add targetLod to PlateauCesiumPickerResult - citygmlService.ts: add lod parameter to API request bodies - importPlateauBuilding.ts: extract and pass targetLod to service calls Also reverts unnecessary AGENTS.md reformatting from PR #200. Closes #201
There was a problem hiding this comment.
Pull request overview
Adds a Level of Detail (LOD) segmented selector to the PLATEAU building picker sidebar and threads the chosen LOD through the picker result and frontend service calls so the backend can generate simpler/more detailed papercraft geometry.
Changes:
- Add
LodSelectorUI (自動/かんたん/標準/詳細) and integrate it into the Sidebar when buildings are selected - Propagate selected LOD through
PlateauCesiumPickerReact→ dialog result →ImportPlateauBuilding→CityGMLServicerequest bodies (lod) - Update
AGENTS.mdformatting/content (per PR description: revert prior reformatting)
Reviewed changes
Copilot reviewed 9 out of 9 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| frontend/packages/chili/src/commands/importPlateauBuilding.ts | Pass lod option through import/unfold flows based on picker result |
| frontend/packages/chili-ui/src/react/components/Sidebar.tsx | Add LodSelector to sidebar footer and new props for LOD state |
| frontend/packages/chili-ui/src/react/components/PlateauSearchLoading.tsx | Minor formatting-only change |
| frontend/packages/chili-ui/src/react/components/LodSelector.tsx | New segmented button component and LodLevel type |
| frontend/packages/chili-ui/src/react/components/LodSelector.module.css | Styling for segmented LOD control |
| frontend/packages/chili-ui/src/react/PlateauCesiumPickerReact.tsx | Manage selectedLod state and include it in dialog close payload |
| frontend/packages/chili-ui/src/plateauCesiumPickerDialog.ts | Extend picker result to include targetLod |
| frontend/packages/chili-core/src/services/citygmlService.ts | Add lod option and include it in PLATEAU request bodies |
| AGENTS.md | Update repository guidelines formatting/content |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| export interface PlateauCesiumPickerResult { | ||
| selectedBuildings: PickedBuilding[]; | ||
| action?: "import" | "unfoldBeta"; | ||
| targetLod?: string | null; // "LOD1" | "LOD2" | "LOD3" | null (auto fallback) |
There was a problem hiding this comment.
targetLod is typed as string | null, which allows arbitrary strings to flow into ImportPlateauBuilding → CityGMLService and reach the backend. Since the backend only accepts LOD1/LOD2/LOD3 (or omitted for auto), please narrow this to a union type (e.g. "LOD1" | "LOD2" | "LOD3" | null) or a shared LodLevel type alias to preserve end-to-end type safety.
| export interface PlateauCesiumPickerResult { | |
| selectedBuildings: PickedBuilding[]; | |
| action?: "import" | "unfoldBeta"; | |
| targetLod?: string | null; // "LOD1" | "LOD2" | "LOD3" | null (auto fallback) | |
| export type LodLevel = "LOD1" | "LOD2" | "LOD3"; | |
| export interface PlateauCesiumPickerResult { | |
| selectedBuildings: PickedBuilding[]; | |
| action?: "import" | "unfoldBeta"; | |
| targetLod?: LodLevel | null; // "LOD1" | "LOD2" | "LOD3" | null (auto fallback) |
| export interface PlateauBuildingIdWithMeshSearchOptions { | ||
| debug?: boolean; | ||
| mergeBuildingParts?: boolean; | ||
| lod?: string | null; // "LOD1" | "LOD2" | "LOD3" | null (auto fallback) |
There was a problem hiding this comment.
lod is currently typed as string | null, which is broader than what the API supports and makes it easy to accidentally send an invalid value (e.g. typos) in the request body. Please constrain this to the supported values (e.g. "LOD1" | "LOD2" | "LOD3") and represent “auto” by omitting the field (or use null only at the UI layer and normalize before calling the service).
| lod?: string | null; // "LOD1" | "LOD2" | "LOD3" | null (auto fallback) | |
| lod?: "LOD1" | "LOD2" | "LOD3"; // "LOD1" | "LOD2" | "LOD3"; omit for auto fallback |
|
|
||
| ## Project Overview | ||
| Paper-CAD is a CAD application for unfolding 3D models into 2D SVG/PDF patterns. The frontend is a TypeScript monorepo (Rspack + npm workspaces), the backend is a FastAPI Python server with OpenCASCADE for geometry processing. A C++ kernel (OpenCASCADE) compiles to WebAssembly. | ||
| Paper-CAD is a CAD application for unfolding 3D models into 2D SVG/PDF patterns. The frontend is a TypeScript monorepo (Rspack), the backend is a FastAPI Python server with OpenCASCADE for geometry processing. A C++ kernel (OpenCASCADE) compiles to WebAssembly. |
There was a problem hiding this comment.
The Project Overview says the frontend is a monorepo “(Rspack)”, but the Project Structure section immediately below describes it as “(Rspack + npm workspaces)”. Please make these consistent to avoid confusion about the build system/workspace setup.
| Paper-CAD is a CAD application for unfolding 3D models into 2D SVG/PDF patterns. The frontend is a TypeScript monorepo (Rspack), the backend is a FastAPI Python server with OpenCASCADE for geometry processing. A C++ kernel (OpenCASCADE) compiles to WebAssembly. | |
| Paper-CAD is a CAD application for unfolding 3D models into 2D SVG/PDF patterns. The frontend is a TypeScript monorepo (Rspack + npm workspaces), the backend is a FastAPI Python server with OpenCASCADE for geometry processing. A C++ kernel (OpenCASCADE) compiles to WebAssembly. |
The ShapeCache was keyed by (building_id, precision_mode, shape_fix_level) without including target_lod. This caused a bug where importing a building with auto/LOD2 would cache the LOD2 shape, and a subsequent LOD1 request for the same building would return the cached LOD2 result instead of re-extracting with LOD1 geometry. Fix: Extend cache key to (building_id, precision_mode, shape_fix_level, target_lod) in both sequential and parallel processing paths. Fixes #201
Deploying paper-cad with
|
| Latest commit: |
5246c4e
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://06516320.paper-cad.pages.dev |
| Branch Preview URL: | https://feature-201-lod-selection-ui.paper-cad.pages.dev |
Deploying newlppaper-cad with
|
| Latest commit: |
5246c4e
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://0974edf8.newlppaper-cad.pages.dev |
| Branch Preview URL: | https://feature-201-lod-selection-ui.newlppaper-cad.pages.dev |
Summary
AGENTS.mdreformatting from PR feat: Add LOD selection parameter to CityGML/PLATEAU API endpoints #200Background
Lower LOD = simpler geometry = easier papercraft assembly. This UI completes the feature started in PR #200, which added backend
target_lodparameter support.Changes
New files
LodSelector.tsx— Segmented button component withLodLeveltypeLodSelector.module.css— Styled with CSS variables andcolor-mix()to match Paper-CAD design systemModified files
Sidebar.tsx— Integrate LodSelector in footer (conditionally shown when buildings are selected)PlateauCesiumPickerReact.tsx— ManageselectedLodstate, pass to Sidebar, includetargetLodin import/unfold callbacksplateauCesiumPickerDialog.ts— AddtargetLodtoPlateauCesiumPickerResultinterfacecitygmlService.ts— Addlodparameter to API request bodiesimportPlateauBuilding.ts— Extract and passtargetLodto service callsAGENTS.md— Reverted to pre-PR#200 stateTest results
npx tsc --noEmit— 0 errorsStacking
This PR is stacked on PR #200 (
feature/199-lod-selection-api). Merge #200 first; this PR will auto-retarget tomain.Closes #201