Align floorplan drawing with local build coordinates
This commit is contained in:
@@ -11,6 +11,7 @@ type SvgLine = {
|
|||||||
|
|
||||||
type FloorplanDraftLayerProps = {
|
type FloorplanDraftLayerProps = {
|
||||||
draftPolygonPoints: string | null
|
draftPolygonPoints: string | null
|
||||||
|
linearDraftSegment: SvgLine | null
|
||||||
polygonDraftPolygonPoints: string | null
|
polygonDraftPolygonPoints: string | null
|
||||||
polygonDraftPolylinePoints: string | null
|
polygonDraftPolylinePoints: string | null
|
||||||
polygonDraftClosingSegment: SvgLine | null
|
polygonDraftClosingSegment: SvgLine | null
|
||||||
@@ -22,6 +23,7 @@ type FloorplanDraftLayerProps = {
|
|||||||
|
|
||||||
export const FloorplanDraftLayer = memo(function FloorplanDraftLayer({
|
export const FloorplanDraftLayer = memo(function FloorplanDraftLayer({
|
||||||
draftPolygonPoints,
|
draftPolygonPoints,
|
||||||
|
linearDraftSegment,
|
||||||
polygonDraftPolygonPoints,
|
polygonDraftPolygonPoints,
|
||||||
polygonDraftPolylinePoints,
|
polygonDraftPolylinePoints,
|
||||||
polygonDraftClosingSegment,
|
polygonDraftClosingSegment,
|
||||||
@@ -44,6 +46,21 @@ export const FloorplanDraftLayer = memo(function FloorplanDraftLayer({
|
|||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
{linearDraftSegment && (
|
||||||
|
<line
|
||||||
|
stroke={draftStroke}
|
||||||
|
strokeDasharray="0.2 0.12"
|
||||||
|
strokeLinecap="round"
|
||||||
|
strokeOpacity={0.95}
|
||||||
|
strokeWidth="0.08"
|
||||||
|
vectorEffect="non-scaling-stroke"
|
||||||
|
x1={linearDraftSegment.x1}
|
||||||
|
x2={linearDraftSegment.x2}
|
||||||
|
y1={linearDraftSegment.y1}
|
||||||
|
y2={linearDraftSegment.y2}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
{polygonDraftPolygonPoints && (
|
{polygonDraftPolygonPoints && (
|
||||||
<polygon fill={draftFill} fillOpacity={0.2} points={polygonDraftPolygonPoints} stroke="none" />
|
<polygon fill={draftFill} fillOpacity={0.2} points={polygonDraftPolygonPoints} stroke="none" />
|
||||||
)}
|
)}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -111,15 +111,15 @@ export const CeilingTool: React.FC = () => {
|
|||||||
const onGridMove = (event: GridEvent) => {
|
const onGridMove = (event: GridEvent) => {
|
||||||
if (!(cursorRef.current && gridCursorRef.current)) return
|
if (!(cursorRef.current && gridCursorRef.current)) return
|
||||||
|
|
||||||
const gridX = Math.round(event.position[0] * 2) / 2
|
const gridX = Math.round(event.localPosition[0] * 2) / 2
|
||||||
const gridZ = Math.round(event.position[2] * 2) / 2
|
const gridZ = Math.round(event.localPosition[2] * 2) / 2
|
||||||
const gridPosition: [number, number] = [gridX, gridZ]
|
const gridPosition: [number, number] = [gridX, gridZ]
|
||||||
|
|
||||||
setCursorPosition(gridPosition)
|
setCursorPosition(gridPosition)
|
||||||
setLevelY(event.position[1])
|
setLevelY(event.localPosition[1])
|
||||||
|
|
||||||
const ceilingY = event.position[1] + CEILING_HEIGHT
|
const ceilingY = event.localPosition[1] + CEILING_HEIGHT
|
||||||
const gridY = event.position[1] + GRID_OFFSET
|
const gridY = event.localPosition[1] + GRID_OFFSET
|
||||||
|
|
||||||
// Calculate snapped display position (bypass snap when Shift is held)
|
// Calculate snapped display position (bypass snap when Shift is held)
|
||||||
const lastPoint = points[points.length - 1]
|
const lastPoint = points[points.length - 1]
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import type {
|
import type {
|
||||||
|
CeilingNode,
|
||||||
DoorNode,
|
DoorNode,
|
||||||
ItemNode,
|
ItemNode,
|
||||||
RoofNode,
|
RoofNode,
|
||||||
@@ -46,6 +47,12 @@ type SlabEntry = {
|
|||||||
holes: Point2D[][]
|
holes: Point2D[][]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type CeilingEntry = {
|
||||||
|
ceiling: CeilingNode
|
||||||
|
polygon: Point2D[]
|
||||||
|
holes: Point2D[][]
|
||||||
|
}
|
||||||
|
|
||||||
type RoofEntry = {
|
type RoofEntry = {
|
||||||
roof: RoofNode
|
roof: RoofNode
|
||||||
segments: Array<{
|
segments: Array<{
|
||||||
@@ -63,6 +70,7 @@ type FloorplanSelectionToolContext = {
|
|||||||
stairs: StairEntry[]
|
stairs: StairEntry[]
|
||||||
walls: WallEntry[]
|
walls: WallEntry[]
|
||||||
slabs: SlabEntry[]
|
slabs: SlabEntry[]
|
||||||
|
ceilings: CeilingEntry[]
|
||||||
roofs: RoofEntry[]
|
roofs: RoofEntry[]
|
||||||
openingHitTolerance: number
|
openingHitTolerance: number
|
||||||
wallHitTolerance: number
|
wallHitTolerance: number
|
||||||
@@ -131,6 +139,13 @@ export function getFloorplanHitNodeId(context: FloorplanSelectionToolContext) {
|
|||||||
return roofHit.roof.id
|
return roofHit.roof.id
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const ceilingHit = context.ceilings.find(({ polygon, holes }) =>
|
||||||
|
isPointInsidePolygonWithHoles(context.point, polygon, holes),
|
||||||
|
)
|
||||||
|
if (ceilingHit) {
|
||||||
|
return ceilingHit.ceiling.id
|
||||||
|
}
|
||||||
|
|
||||||
const slabHit = context.slabs.find(({ polygon, holes }) =>
|
const slabHit = context.slabs.find(({ polygon, holes }) =>
|
||||||
isPointInsidePolygonWithHoles(context.point, polygon, holes),
|
isPointInsidePolygonWithHoles(context.point, polygon, holes),
|
||||||
)
|
)
|
||||||
@@ -150,6 +165,7 @@ type FloorplanSelectionBoundsContext = {
|
|||||||
walls: WallEntry[]
|
walls: WallEntry[]
|
||||||
openings: OpeningPolygonEntry[]
|
openings: OpeningPolygonEntry[]
|
||||||
slabs: SlabEntry[]
|
slabs: SlabEntry[]
|
||||||
|
ceilings: CeilingEntry[]
|
||||||
stairs: StairEntry[]
|
stairs: StairEntry[]
|
||||||
roofs: RoofEntry[]
|
roofs: RoofEntry[]
|
||||||
}
|
}
|
||||||
@@ -162,6 +178,7 @@ export function getFloorplanSelectionIdsInBounds({
|
|||||||
walls,
|
walls,
|
||||||
openings,
|
openings,
|
||||||
slabs,
|
slabs,
|
||||||
|
ceilings,
|
||||||
stairs,
|
stairs,
|
||||||
roofs,
|
roofs,
|
||||||
}: FloorplanSelectionBoundsContext) {
|
}: FloorplanSelectionBoundsContext) {
|
||||||
@@ -184,6 +201,9 @@ export function getFloorplanSelectionIdsInBounds({
|
|||||||
const slabIds = slabs
|
const slabIds = slabs
|
||||||
.filter(({ polygon }) => doesPolygonIntersectSelectionBounds(polygon, bounds))
|
.filter(({ polygon }) => doesPolygonIntersectSelectionBounds(polygon, bounds))
|
||||||
.map(({ slab }) => slab.id)
|
.map(({ slab }) => slab.id)
|
||||||
|
const ceilingIds = ceilings
|
||||||
|
.filter(({ polygon }) => doesPolygonIntersectSelectionBounds(polygon, bounds))
|
||||||
|
.map(({ ceiling }) => ceiling.id)
|
||||||
const stairIds = stairs
|
const stairIds = stairs
|
||||||
.filter((stair) =>
|
.filter((stair) =>
|
||||||
getStairHitPolygons(stair).some((polygon) =>
|
getStairHitPolygons(stair).some((polygon) =>
|
||||||
@@ -198,6 +218,14 @@ export function getFloorplanSelectionIdsInBounds({
|
|||||||
.map(({ roof }) => roof.id)
|
.map(({ roof }) => roof.id)
|
||||||
|
|
||||||
return Array.from(
|
return Array.from(
|
||||||
new Set([...itemIds, ...wallIds, ...openingIds, ...slabIds, ...stairIds, ...roofIds]),
|
new Set([
|
||||||
|
...itemIds,
|
||||||
|
...wallIds,
|
||||||
|
...openingIds,
|
||||||
|
...slabIds,
|
||||||
|
...ceilingIds,
|
||||||
|
...stairIds,
|
||||||
|
...roofIds,
|
||||||
|
]),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user