Daily Research 260210 Antigravity - Web Transformation
# Daily Research Log: GD-PlanNet Web Transformation
**Date:** 2026-02-10
**Author:** Antigravity (AI Assistant)
**Project:** GD-PlanNet (AI Floor Plan to 3D)
---
## 1. Objectives & Scope
The primary goal was to modernize the local `GD-PlanNet` application, moving from a static script environment to an **interactive Web Application**.
**Key Requirements:**
- Fix persistent image loading errors (CORS).
- Enable "One-Click" server setup.
- Implement "Dynamo-like" 3D visualization controls (Solid/Surface, Thickness).
- Polish UI/UX (Progress bars, Layout, Branding).
---
## 2. Chronological Engineering Log
### Phase 1: Infrastructure & Security Architecture
**Challenge:** The user was running `index.html` directly via the file system (`file:///C:/...`).
- **Error:** `Access to fetch at '...' from origin 'null' has been blocked by CORS policy`.
- **Diagnosis:** Modern browsers strictly block local files from accessing other local files via `fetch()` (security sandbox).
- **Failed Attempt 1:** Adding `CORSMiddleware` to Python server. (Did not fix the browser's local file restriction).
- **Successful Solution:** **Full Web Server Migration**.
- **Action:** Refactored `server.py` to serve `index.html` as the root route (`/`).
- **Code Change:**
```python
@app.get("/", response_class=HTMLResponse)
async def read_root(): return FileResponse("index.html")
```
- **UX Enforcement:** Added a **Protocol Check** in `index.html`. If a user opens the file directly, a full-screen overlay blocks interaction and forces them to click a link to `http://localhost:8000`.
### Phase 2: Gallery & Image Loading System
**Challenge:** The bottom gallery refused to load images or trigger inference.
- **Error 1:** "Failed to fetch" due to absolute path handling.
- **Error 2:** `file://` path construction in JS.
- **Solution (The Proxy Pattern):**
- **Backend:** Created a dedicated endpoint `@app.get("/example-image/{filename}")` to stream image bytes safely via HTTP.
- **Frontend:** Updated `loadGallery()` to construct URLs like `/example-image/test.jpg` instead of raw file paths.
- **Bug Fix:** Fixed a **Syntax Error** in `index.html` where the `loadGallery` function was accidentally nested inside itself, causing a parser failure.
### Phase 3: Server Stability & Process Management
**Challenge:** The server refused to start with `[WinError 10048] Only one usage of each socket address is permitted`.
- **Diagnosis:** A "Ghost Process" (previous Python instance, PID 15812) was orphaned and holding port 8000.
- **Action:**
1. Trace: `netstat -ano | findstr :8000`.
2. Kill: `taskkill /F /PID 15812`.
3. **Feature:** Implemented a **Graceful Shutdown** mechanism.
- **Backend:** Added `/shutdown` endpoint using `os.kill(os.getpid(), signal.SIGTERM)`.
- **Frontend:** Added a "Stop Server" button to the UI. This prevents future "port in use" errors by ensuring the server closes cleanly.
### Phase 4: 3D Visualization Enhancements (The "Dynamo" Request)
**Requirement:** User requested capabilities similar to Autodesk Dynamo: toggling between Surface/Solid and adjusting thickness.
- **Implementation:**
1. **Controls:** Added "Solid Mode (Thicken)" Checkbox and "Thickness (Height)" Slider (1-500) to the UI.
2. **Logic Update (`visualizePolygons`):**
- **Solid (Checked):** Uses `THREE.ExtrudeGeometry` with dynamic `depth` derived from the slider.
- **Surface (Unchecked):** Uses `THREE.ShapeGeometry` with `THREE.DoubleSide` material (to ensure visibility from all angles).
3. **Reactivity:** Attached `input` and `change` event listeners to these controls. Calling `visualizePolygons()` re-renders the *existing* polygon data immediately, without needing to re-run the expensive AI inference.
### Phase 5: UI/UX Polish & Branding
- **Heatmap Display Fix:**
- **Error:** Heatmap image was broken.
- **Cause:** Double-slash URL construction (`//media/...`) caused by prepending `/` to an already absolute path.
- **Fix:** Simplified JS logic to trust the server-provided relative path.
- **"Black Screen" Fix:**
- **Cause:** `initThreeJS()` was called but not defined (as initialization logic was top-level).
- **Fix:** Removed the redundant call, unblocking the script execution.
- **Branding:**
- **Action:** Integrated `gdlab weeklydynamo.png`.
- **Technical:** Created `/logo` server endpoint to serve the local file.
- **Design:** Wrapped the logo in a dark, bordered frame (`#2a2a2a` background) to ensure the white logo contrasts correctly against the dark UI panel.
---
## 3. Technical Summary of Modified Files
### `server.py`
- **New Imports:** `HTMLResponse`, `FileResponse`, `signal`.
- **New Routes:**
- `GET /` (Serves App)
- `GET /logo` (Serves Branding)
- `GET /example-image/{filename}` (Safe Image Proxy)
- `POST /shutdown` (Process Management)
- **CORSMiddleware:** Added to allow flexible development (though less critical now with relative paths).
### `index.html`
- **Architecture:** Switched all `fetch` calls to relative paths (`/predict`, `/examples`).
- **Safety:** Added `window.location.protocol` check.
- **Features:**
- Added **Solid/Surface Toggle**.
- Added **Thickness Slider**.
- Added **Shutdown Button**.
- Added **Logo Container**.
- **Bug Fixes:**
- Removed nested function definitions.
- Fixed URL string concatenation logic.
- Fixed `initThreeJS` reference error.
- Added global state storage (`window.lastPolygons`) to support re-rendering.
---
## 4. Conclusion
The application has been successfully transformed from a fragile local script into a robust **Web Application**. It features professional-grade process management, enhanced security, and "Dynamo-like" interactive visualization capabilities, fulfilling all user requirements including the specific branding needs.
댓글
댓글 쓰기