Implement stair-driven slab hole cutouts

This commit is contained in:
sudhir
2026-04-17 13:13:02 +05:30
parent 0effda29fe
commit b314a8fbf8
12 changed files with 824 additions and 15 deletions
+8 -1
View File
@@ -49,8 +49,15 @@ export { ScanNode } from './nodes/scan'
// Nodes
export { SiteNode } from './nodes/site'
export { SlabNode } from './nodes/slab'
export { StairNode, StairRailingMode, StairTopLandingMode, StairType } from './nodes/stair'
export {
StairNode,
StairRailingMode,
StairSlabOpeningMode,
StairTopLandingMode,
StairType,
} from './nodes/stair'
export { AttachmentSide, StairSegmentNode, StairSegmentType } from './nodes/stair-segment'
export { SurfaceHoleMetadata } from './nodes/surface-hole-metadata'
export { WallNode } from './nodes/wall'
export { WindowNode } from './nodes/window'
export { ZoneNode } from './nodes/zone'
@@ -3,6 +3,7 @@ import { z } from 'zod'
import { BaseNode, nodeType, objectId } from '../base'
import { MaterialSchema } from '../material'
import { ItemNode } from './item'
import { SurfaceHoleMetadata } from './surface-hole-metadata'
export const CeilingNode = BaseNode.extend({
id: objectId('ceiling'),
@@ -12,6 +13,7 @@ export const CeilingNode = BaseNode.extend({
materialPreset: z.string().optional(),
polygon: z.array(z.tuple([z.number(), z.number()])),
holes: z.array(z.array(z.tuple([z.number(), z.number()]))).default([]),
holeMetadata: z.array(SurfaceHoleMetadata).default([]),
height: z.number().default(2.5), // Height in meters
autoFromWalls: z.boolean().default(false),
}).describe(
@@ -19,6 +21,7 @@ export const CeilingNode = BaseNode.extend({
Ceiling node - used to represent a ceiling in the building
- polygon: array of [x, z] points defining the ceiling boundary
- holes: array of polygons representing holes in the ceiling
- holeMetadata: metadata parallel to holes, used to preserve manual and stair-managed cutouts
- autoFromWalls: whether the ceiling is automatically generated from a closed wall loop
`,
)
+4
View File
@@ -2,6 +2,7 @@ import dedent from 'dedent'
import { z } from 'zod'
import { BaseNode, nodeType, objectId } from '../base'
import { MaterialSchema } from '../material'
import { SurfaceHoleMetadata } from './surface-hole-metadata'
export const SlabNode = BaseNode.extend({
id: objectId('slab'),
@@ -10,12 +11,15 @@ export const SlabNode = BaseNode.extend({
materialPreset: z.string().optional(),
polygon: z.array(z.tuple([z.number(), z.number()])),
holes: z.array(z.array(z.tuple([z.number(), z.number()]))).default([]),
holeMetadata: z.array(SurfaceHoleMetadata).default([]),
elevation: z.number().default(0.05), // Elevation in meters
autoFromWalls: z.boolean().default(false),
}).describe(
dedent`
Slab node - used to represent a slab/floor in the building
- polygon: array of [x, z] points defining the slab boundary
- holes: array of [x, z] polygons representing cutouts in the slab
- holeMetadata: metadata parallel to holes, used to preserve manual and stair-managed cutouts
- elevation: elevation in meters
- autoFromWalls: whether the slab is automatically generated from a closed wall loop
`,
+9
View File
@@ -7,10 +7,12 @@ import { StairSegmentNode } from './stair-segment'
export const StairRailingMode = z.enum(['none', 'left', 'right', 'both'])
export const StairType = z.enum(['straight', 'curved', 'spiral'])
export const StairTopLandingMode = z.enum(['none', 'integrated'])
export const StairSlabOpeningMode = z.enum(['none', 'destination'])
export type StairRailingMode = z.infer<typeof StairRailingMode>
export type StairType = z.infer<typeof StairType>
export type StairTopLandingMode = z.infer<typeof StairTopLandingMode>
export type StairSlabOpeningMode = z.infer<typeof StairSlabOpeningMode>
export const StairNode = BaseNode.extend({
id: objectId('stair'),
@@ -21,6 +23,10 @@ export const StairNode = BaseNode.extend({
// Rotation around Y axis in radians
rotation: z.number().default(0),
stairType: StairType.default('straight'),
fromLevelId: z.string().nullable().default(null),
toLevelId: z.string().nullable().default(null),
slabOpeningMode: StairSlabOpeningMode.default('none'),
openingOffset: z.number().default(0),
width: z.number().default(1.0),
totalRise: z.number().default(2.5),
stepCount: z.number().default(10),
@@ -44,6 +50,9 @@ export const StairNode = BaseNode.extend({
- position: center position of the stair group
- rotation: rotation around Y axis
- stairType: straight (segment-based), curved (arc-based), or spiral
- fromLevelId / toLevelId: source and destination levels used for auto slab cutouts
- slabOpeningMode: whether a destination-level slab opening is generated for this stair
- openingOffset: extra opening expansion applied after the cutout polygon is computed
- width: stair width
- totalRise: total stair height
- stepCount: number of visible steps
@@ -0,0 +1,8 @@
import { z } from 'zod'
export const SurfaceHoleMetadata = z.object({
source: z.enum(['manual', 'stair']).default('manual'),
stairId: z.string().optional(),
})
export type SurfaceHoleMetadata = z.infer<typeof SurfaceHoleMetadata>