From 5ed8a120ebc514a04557f0e58b3706ec9ee57235 Mon Sep 17 00:00:00 2001 From: DipokalLab Date: Wed, 13 May 2026 15:40:49 +0900 Subject: [PATCH 1/2] fix: update export glb --- src/three/Space.tsx | 21 +++++++++++++++------ src/ui/App.tsx | 4 ++-- 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/src/three/Space.tsx b/src/three/Space.tsx index 18bf4bb..94c99c6 100644 --- a/src/three/Space.tsx +++ b/src/three/Space.tsx @@ -43,6 +43,7 @@ function Building({ e.stopPropagation(); }} rotation={[-Math.PI / 2, 0, 0]} + userData={{ exportToGLB: true }} > @@ -353,7 +354,14 @@ function Roads({ area }: { area: any }) { const lineGeometry: any = new THREE.BufferGeometry().setFromPoints(points); - return ; + return ( + + ); })} ); @@ -391,15 +399,16 @@ export function Export() { }; const exportGLB = () => { - const sceneClone = scene.clone(true); - sceneClone.traverse((child) => { - if (child.userData && child.userData.skipExport === true) child.parent?.remove(child); - if ((child as any).isHtml === true) child.parent?.remove(child); + const exportRoot = new THREE.Group(); + scene.traverse((child) => { + if (child.userData?.exportToGLB === true) { + exportRoot.add(child.clone(true)); + } }); const exporter = new GLTFExporter(); const options = { binary: true, embedImages: true }; exporter.parse( - sceneClone, + exportRoot, (result) => { if (result instanceof ArrayBuffer) { const blob = new Blob([result], { type: "model/gltf-binary" }); diff --git a/src/ui/App.tsx b/src/ui/App.tsx index 254c20b..90766aa 100644 --- a/src/ui/App.tsx +++ b/src/ui/App.tsx @@ -203,7 +203,7 @@ function App() { GLB Download - {isFleetLogin ? ( + {/* {isFleetLogin ? ( @@ -214,7 +214,7 @@ function App() { > Fleet Login - )} + )} */} From 935067fb6d2877ccb697aea431fee5eb271e962e Mon Sep 17 00:00:00 2001 From: DipokalLab Date: Wed, 13 May 2026 15:48:34 +0900 Subject: [PATCH 2/2] fix: remove request button --- src/components/map/Processing.tsx | 90 +++++++------------------------ src/state/areaStore.ts | 4 +- src/ui/App.tsx | 83 +++++++++++++++++++++++++--- 3 files changed, 97 insertions(+), 80 deletions(-) diff --git a/src/components/map/Processing.tsx b/src/components/map/Processing.tsx index 7f82616..844b4e5 100644 --- a/src/components/map/Processing.tsx +++ b/src/components/map/Processing.tsx @@ -1,9 +1,7 @@ -import { useAreaStore } from "@/state/areaStore"; import { css, keyframes } from "@emotion/react"; import { Loader2 } from "lucide-react"; -import React, { useState } from "react"; -interface Building { +export interface Building { id: number; tags: { [key: string]: string | undefined }; geometry?: { lat: number; lng: number }[]; @@ -14,85 +12,37 @@ from { transform: rotate(0deg); } to { transform: rotate(360deg); } `; -export function BuildingHeights({ area }: { area: any }) { - const [buildings, setBuildings] = useState([]); - const [loading, setLoading] = useState(false); - - const appendAreas = useAreaStore((state) => state.appendAreas); - - const requestBuildings = () => { - setLoading(true); - - const south = area[1].lat; - const west = area[1].lng; - const north = area[0].lat; - const east = area[0].lng; - console.log(south, west, north, east); - const query = `[out:json][timeout:25];(way["building"]( ${south},${west},${north},${east} );relation["building"]( ${south},${west},${north},${east} ););out body geom;`; - fetch("https://overpass-api.de/api/interpreter", { - method: "POST", - body: query, - headers: { "Content-Type": "application/x-www-form-urlencoded" }, - }) - .then((response) => response.json()) - .then((data) => { - const blds: any = data.elements.map((element) => ({ - id: element.id, - tags: element.tags, - geometry: element.geometry - ? element.geometry.map((pt) => ({ lat: pt.lat, lng: pt.lon })) - : undefined, - })); - setBuildings(blds); - appendAreas(blds); - - console.log("Building Data:", blds); - }) - .catch((error) => { - console.error("Error fetching building data:", error); - }) - .finally(() => { - setLoading(false); - }); - }; - +export function BuildingHeights({ + buildings, + loading, +}: { + buildings: Building[]; + loading: boolean; +}) { return (
- + Fetching building information... +
+ )}
    void; - setCenter: (center: []) => void; + appendAreas: (areas: any[]) => void; + setCenter: (center: any[]) => void; }; export const useAreaStore = create((set) => ({ diff --git a/src/ui/App.tsx b/src/ui/App.tsx index 90766aa..101802c 100644 --- a/src/ui/App.tsx +++ b/src/ui/App.tsx @@ -1,4 +1,4 @@ -import { css } from "@emotion/react"; +import { css, keyframes } from "@emotion/react"; import { Space } from "../three/Space"; import { FullscreenModal } from "../components/FullscreenModal"; import { Title } from "@/components/text/Title"; @@ -11,8 +11,8 @@ import { NextButton, PrevButton, } from "@/components/button/BottomButton"; -import { BuildingHeights } from "@/components/map/Processing"; -import { ChevronLeft, ChevronRight, Download } from "lucide-react"; +import { BuildingHeights, Building } from "@/components/map/Processing"; +import { ChevronLeft, ChevronRight, Download, Loader2 } from "lucide-react"; import { useAreaStore } from "@/state/areaStore"; import { useActionStore } from "@/state/exportStore"; import { Modal } from "@/components/modal/Modal"; @@ -26,6 +26,11 @@ const IconSize = css({ height: "14px", }); +const spinAnimation = keyframes` +from { transform: rotate(0deg); } +to { transform: rotate(360deg); } +`; + function App() { const [isNextButtonDisabled, setIsNextButtonDisabled] = useState(true); const [areaData, setAreaData] = useState([]); @@ -36,8 +41,12 @@ function App() { const [isFleetLogin, setIsFleetLogin] = useState(false); const [isFleetModal, setIsFleetModal] = useState(false); const [spaceList, setSpaceList] = useState([]); + const [buildings, setBuildings] = useState([]); + const [isFetchingBuildings, setIsFetchingBuildings] = useState(false); + const [hasFetchedBuildings, setHasFetchedBuildings] = useState(false); const setCenter = useAreaStore((state) => state.setCenter); + const appendAreas = useAreaStore((state) => state.appendAreas); const setAction = useActionStore((state) => state.setAction); const setFleet = useActionStore((state) => state.setFleet); @@ -101,18 +110,58 @@ function App() { setCenter(data); console.log(data, "AAEE"); setIsNextButtonDisabled(false); + setBuildings([]); + setHasFetchedBuildings(false); }; const handleRemove = () => { setAreaData([]); setIsNextButtonDisabled(true); + setBuildings([]); + setHasFetchedBuildings(false); }; - const handleClickNextStep = () => { + const requestBuildings = async () => { + setIsFetchingBuildings(true); + + const south = areaData[1].lat; + const west = areaData[1].lng; + const north = areaData[0].lat; + const east = areaData[0].lng; + const query = `[out:json][timeout:25];(way["building"]( ${south},${west},${north},${east} );relation["building"]( ${south},${west},${north},${east} ););out body geom;`; + try { + const response = await fetch("https://overpass-api.de/api/interpreter", { + method: "POST", + body: query, + headers: { "Content-Type": "application/x-www-form-urlencoded" }, + }); + const data = await response.json(); + const blds: Building[] = data.elements.map((element) => ({ + id: element.id, + tags: element.tags, + geometry: element.geometry + ? element.geometry.map((pt) => ({ lat: pt.lat, lng: pt.lon })) + : undefined, + })); + setBuildings(blds); + appendAreas(blds); + setHasFetchedBuildings(true); + } catch (error) { + console.error("Error fetching building data:", error); + } finally { + setIsFetchingBuildings(false); + } + }; + + const handleClickNextStep = async () => { if (step == 0 && checkIsBig()) { setIsWarnModal(true); return false; } + if (step == 1 && !hasFetchedBuildings) { + await requestBuildings(); + return; + } setStep(step + 1); }; @@ -153,10 +202,14 @@ function App() { Processing - Click the button below to get the building information. + Click Next Step to fetch building information. Once loaded, click + Next Step again to view the 3D scene. - + @@ -167,10 +220,24 @@ function App() { - Next Step + {isFetchingBuildings ? ( + <> + + Fetching... + + ) : ( + <> + Next Step + + )}