diff --git a/.specify/specs/001-interiorscan-mvp/SPEC.md b/.specify/specs/001-interiorscan-mvp/SPEC.md index b98ff1d..f25f656 100644 --- a/.specify/specs/001-interiorscan-mvp/SPEC.md +++ b/.specify/specs/001-interiorscan-mvp/SPEC.md @@ -8,9 +8,22 @@ ## User Scenarios & Testing +### User Story 0 β Property Setup via Catastro (Priority: P1) π― MVP Entry + +As a real estate agent, I enter a property address and InteriorScan fetches the building's exterior footprint from the Spanish Cadastro (INSPIRE WFS), so the 3D model starts with verified exterior walls before I upload any photos. + +**Why this priority**: The Catastro provides the SSOT for exterior geometry β wall outlines, building height, and number of floors. This eliminates manual exterior wall drawing and ensures dimensional accuracy. Interior walls come from photos or user-uploaded floor plans. + +**Independent Test**: Enter "C/ Altabix 24, Elche" β refcat is resolved β building polygon is displayed on a minimap β exterior walls are generated in the 3D scene. + +**Acceptance Scenarios**: +1. **Given** I am creating a new project, **When** I type a Spanish address and submit, **Then** the system resolves it to a cadastral reference (refcat) and fetches the building footprint polygon from INSPIRE WFS. +2. **Given** a building footprint is fetched, **When** the 3D scene initializes, **Then** exterior walls appear at the correct dimensions matching the Catastro polygon, with the correct number of floors. +3. **Given** the Catastro lookup fails, **When** no polygon is found, **Then** the system falls back to manual wall drawing or DXF/SVG upload. + ### User Story 1 β Upload & Process (Priority: P1) π― MVP Core -As a real estate agent, I upload 30-100 photos of a property and InteriorScan reconstructs the interior as a 3D walkthrough, so I can share a link with potential buyers who navigate it like a first-person game. +As a real estate agent, I upload 30-100 photos of a property and InteriorScan reconstructs the interior as a 3D walkthrough, so I can share a link where potential buyers navigate it like a first-person game. **Why this priority**: Without reconstruction, nothing else matters. This is the core value proposition. diff --git a/.specify/specs/001-interiorscan-mvp/data-model.md b/.specify/specs/001-interiorscan-mvp/data-model.md index 2f0cd51..5df4af5 100644 --- a/.specify/specs/001-interiorscan-mvp/data-model.md +++ b/.specify/specs/001-interiorscan-mvp/data-model.md @@ -148,6 +148,31 @@ export const processingJobs = pgTable('processing_jobs', { createdAt: timestamp('created_at').defaultNow().notNull(), }); +// ββ Catastro Data βββββββββββββββββββββββββββββββββββββ + +export const catastroData = pgTable('catastro_data', { + id: cuid2('id').primaryKey(), + projectId: cuid2('project_id').references(() => projects.id).notNull(), + refcat: text('refcat'), // 14-20 digit cadastral reference + addressNormalized: text('address_normalized'), // Normalized address from Catastro + buildingFootprint: jsonb('building_footprint'), // GeoJSON polygon from INSPIRE WFS + buildingHeight: text('building_height'), // e.g., "12.5" meters + numberOfFloors: integer('number_of_floors'), // From Catastro + floorArea: text('floor_area'), // mΒ² from Catastro + gmlSource: text('gml_source'), // URL of the GML source file + fetchedAt: timestamp('fetched_at').defaultNow().notNull(), +}); + +export const catastroImports = pgTable('catastro_imports', { + id: cuid2('id').primaryKey(), + projectId: cuid2('project_id').references(() => projects.id).notNull(), + format: text('format').notNull(), // 'dxf', 'svg', 'png', 'gml' + originalKey: text('original_key'), // S3 key for uploaded file + parsedWalls: jsonb('parsed_walls'), // Array of {x1, z1, x2, z2, height, thickness} + source: text('source').notNull(), // 'catastro', 'upload', 'manual' + createdAt: timestamp('created_at').defaultNow().notNull(), +}); + // ββ Subscriptions βββββββββββββββββββββββββββββββββββ export const subscriptions = pgTable('subscriptions', { diff --git a/.specify/specs/001-interiorscan-mvp/plan.md b/.specify/specs/001-interiorscan-mvp/plan.md index 8316c43..18251a2 100644 --- a/.specify/specs/001-interiorscan-mvp/plan.md +++ b/.specify/specs/001-interiorscan-mvp/plan.md @@ -46,9 +46,22 @@ See `data-model.md` (separate document β same directory). --- -## Phase 2: Photo Upload & Processing Pipeline (P1) π― MVP Core +## Phase 2: Property Setup & Photo Upload (P1) π― MVP Core -### 2A: Upload API +### 2A: Catastro Integration + +- [ ] T007 Create `packages/catastro/` β Catastro client package +- [ ] T008 Write failing test: address "C/ Altabix 24, Elche" β refcat resolved +- [ ] T009 Implement OVK address search (SOAP/REST β refcat) +- [ ] T010 Write failing test: refcat β building polygon GML from INSPIRE WFS +- [ ] T011 Implement INSPIRE WFS client (GML β GeoJSON polygon) +- [ ] T012 Implement GML polygon β wall segments converter (`{x1,z1,x2,z2,height,thickness}`) +- [ ] T13 Write failing test: POST /api/v1/projects with address β catastro_data populated +- [ ] T014 Implement project creation with Catastro lookup (address β refcat β footprint β walls) + +**Checkpoint**: Enter "C/ Altabix 24, Elche" β building polygon rendered in minimap β exterior walls in 3D scene. + +### 2B: Photo Upload API - [ ] T007 Write failing test: POST /api/v1/projects with photos returns 201 + project ID - [ ] T008 Implement project creation endpoint with Zod validation diff --git a/AGENTS.md b/AGENTS.md index 685e6f7..3454e70 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -41,6 +41,9 @@ See `.specify/memory/constitution.md` β all development must comply. - **Self-hosted**: All infra self-hosted except Stripe. - **API-first**: Every feature has REST API before UI. - **Open exports**: OBJ, E57, LAS/LAZ, DXF minimum. IFC in P4+. +- **Catastro SSOT**: Spanish Cadastro (INSPIRE WFS) is the single source of truth for building exterior geometry. Address β refcat β footprint polygon β exterior walls. Interior comes from photos. +- **3DGS for visuals**: Hybrid pipeline β mesh for collision/measurement, Gaussian Splatting for visual quality (gsplat MIT license, never graphdeco-inria research-only). +- **Plan inputs**: (1) Catastro address lookup, (2) DXF/SVG/PNG upload, (3) manual wall editor, in that order of preference. ## Development Commands diff --git a/demo-v2-textured.html b/demo-v2-textured.html new file mode 100644 index 0000000..7e9158b --- /dev/null +++ b/demo-v2-textured.html @@ -0,0 +1,971 @@ + + +
+ + +