Easy-to-manage touch screens
무료 오픈소스 터치스크린으로 USB 설정 가이드, 드래그‑드롭 편집기, 로컬 제어를 제공하며 Home Assistant용으로 제작되었습니다
싱가포 HDB BTO 각 가구에 시간별 직사광량을 3D로 확인하고 인근 매매가와 AI 재판매 추정치를 볼 수 있다
See how much direct sun reaches every unit in Singapore HDB BTO projects, hour by hour, in 3D, with nearby resale prices and an ML resale estimate.
라이프스타일JavaScript · PythonGitHub @Perryong온라인운영자 미확인
써 보셨어요? 한 번만 눌러 주세요. 로그인은 필요 없어요.
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기메이커가 쓴 소개는 위의 한 줄이 전부입니다. 더 자세한 내용은 저장소 README에서 읽을 수 있습니다. 저장소 README ↗
README 전체를 불러오는 중입니다.
README 전문 보기 ↗Pick a unit in an HDB BTO project and see how much direct sun reaches its windows, hour by hour and for any date. The 3D model is built from HDB's own site plan, with the real neighbouring blocks, schools, malls and MRT stations around it, plus nearby resale prices and a machine-learning estimate of what the unit would resell for.
Live: https://singapore-housing-lab.vercel.app · 29 projects (every BTO launched from Oct 2025 to Jun 2026 except Redhill Peaks II, plus the 7 upcoming Oct 2026 sites)
test/sky_test.mjs).flowchart LR
subgraph Offline["Offline pipeline (Python, Blender)"]
A[HDB site plan PDF] -->|OpenCV: scale bar, colour regions, OCR| B[trace.json: blocks, stacks, flat types]
B --> C[project.json]
D[data.gov.sg: HDB footprints, property info] -->|register to the plan| C
E[OpenStreetMap / OneMap: malls, MRT, schools] --> C
T[LTA DataMall: bus stops, routes, frequencies] -->|transit graph, door-to-hub search| C
B -->|headless Blender| F[model.glb]
G[HDB brochure floor plans] -->|OpenCV + Blender| H[plans3d/*.glb]
I[data.gov.sg: 240k resale sales] -->|scikit-learn gradient boosting| J[value estimates]
J --> C
end
subgraph Browser["Browser (no build step)"]
C --> K[app.js: state and events]
F --> L[three.js scene]
K --> L
K --> M[panel HTML: pure, unit-tested modules]
N[sun.js / moon.js: NOAA and Meeus maths] --> K
end
| Decision | Why |
|---|---|
| Split train and test by time, not at random | The model prices the future from the past. A random split leaks each block's own recent sales and flatters the error. |
| Compare with town-median and linear baselines | A model error means little without a simple baseline beside it. |
| Never place a block at a guessed location | Unlinked blocks are dropped rather than drawn wrong; a wrong shadow is worse than none. |
| Bake the models in Blender offline | The browser downloads a small, ready-made GLB instead of building geometry at load time. |
| Merge the surroundings into one mesh per kind | About 300 extra buildings cost 3 draw calls, so the frame rate stays at 120 fps. |
| Don't publish HDB brochures and site plans | Copyright: the app links to HDB's own pages, and only the floor-plan crops are published. |
18 test scripts run in CI on every push (npm test, the same command locally). The parts that need HDB's brochures,
site plans or large data.gov.sg files print "skipped" in CI and only run on a machine that has them:
projects/index.json catalogue (node tools/make_index.js)
projects/<id>/project.json site, plan scale/north, blocks, stacks, unit types, neighbouring blocks
projects/<id>/trace.json what was read off HDB's site plan (BTOs)
projects/<id>/siteplan.jpg site plan laid on the ground
projects/<id>/model.glb generated — do not edit (node tools/build.js projects/<id>)
web/ the app (no build step): open /web/ or /web/?p=<id>
blender/build_model.py layout.json -> study model GLB (unit bodies carry a _UNIT attribute for colouring)
tools/ derive, build, trace_siteplan, find_scalebar, grid_tiles, fetch_context,
make_bto_project, make_upcoming, make_index
test/sun.test.js ported logic must reproduce the original Thomson Reserve table (kept out of the catalogue)
python3 -m http.server 8781 # then open http://localhost:8781/web/
npm test
reference/hdb/siteplans/<slug>.jpg and an entry in reference/hdb/launched.json.python3 tools/find_scalebar.py <plan> x0 y0 x1 y1 → scale bar ends; write projects/<slug>/trace.json
(planBox, scale, legend swatch points per flat type).python3 tools/trace_siteplan.py projects/<slug> --regions → regions.png; name each stack by region id
("r12", or "r12.a"/"r12.b" for the left/right half of a shared region) or a full-image point; add
types overrides where colour matching is ambiguous. Run without --regions and check trace-debug.png and
the flat-type counts against HDB's block table.python3 tools/make_bto_project.py <slug> (approximate georeference + neighbouring HDB blocks from data.gov.sg/OneMap).python3 tools/register_context.py projects/<slug> --apply fits the footprints onto
the existing blocks drawn on the sheet (accepted only when ≥65% of on-sheet edges land on drawn outlines). If it
can't, pin with printed block numbers — python3 tools/anchor_fit.py projects/<slug> 269:298,964 266:329,1436
(block : plan pixel of its label) — then register_context.py --range 25 --apply. Check with
python3 tools/overlay_context.py projects/<slug> out.png; python3 tools/drop_overlaps.py projects/<slug> removes
demolished blocks under the new towers.python3 tools/trace_facilities.py projects/<slug> reads the numbered estate facilities off the site plan
(legend + markers, OCR); python3 tools/fetch_amenities.py projects/<slug> adds nearby MRT/LRT, bus stops,
schools, preschools, hawker centres, supermarkets, clinics, parks, libraries and CCs from
reference/amenities/all.json (built by python3 tools/build_amenities.py from data.gov.sg + OneMap).python3 tools/fetch_transit.py caches LTA DataMall bus data in reference/transit/ from the weekly
sg-bus-data files (no LTA key needed; --lta fetches straight from DataMall
instead, with a free DataMall key as LTA_KEY=...
in a git-ignored .env) and ~45 MB of OSM bus/rail route relations from Overpass (--osm refreshes only those; works offline: it builds from a local copy of sg-bus-data's and skips OSM), then
writes and from both.
Live arrivals for the selected stop come from the separate API (github.com/Perryong/sg-bus-api) (LTA BusArrival), polled every
30 s, from ( in ); locally, run that API on to see live minutes.Projects live outside ~/Documents: macOS revokes access when Blender is launched on files there.
HDB's site plans, sales brochures and launch annexes are not committed. After cloning, re-create them locally:
download site plans (reference/hdb/launched.json lists the projects), then run tools/trace_siteplan.py (writes
siteplan.jpg). Until then the app runs without the site-plan overlay. Open data (HDB buildings / property
information, amenity layers, resale prices) is re-downloaded from data.gov.sg by the tools.
Each stack's floor-plan crop (projects/<id>/layouts/, cut from HDB's sales brochure by tools/extract_layouts.py)
is committed so the deployed site can show it; the unit card also links to the page in HDB's own published brochure
(project.json["brochure"], assets.hdb.gov.sg). Floor plans © Housing & Development Board.
--from-local DIRdata/python3 tools/build_commute.py projects/*/projects/<slug>/transit.jsonweb/rail.jsonsg-bus-apiPROD_APIweb/live.js:8010node tools/build.js projects/<slug>, node tools/make_index.js.