Post

Replies

Boosts

Views

Activity

Reply to How to get a 2D floor plan with dimensions from RoomPlan
To clarify, the code below will generate SKShapeNodes for all walls captured in the CapturedRoom attribute. It uses the extensions mentioned in my previous answer. Hope this'll help. class Walls: SKNode { init() { for wall in CapturedRoom.walls { let wallNode = SKNode() addChild(wallNode) // Position wallNode wallNode.position.x = -CGFloat(wall.transform.position.x) * 200 wallNode.position.y = CGFloat(wall.transform.position.z) * 200 wallNode.zRotation = -CGFloat(wall.transform.eulerAngles.z - wall.transform.eulerAngles.y) // Create the path for the wall let surfacePath = CGMutablePath() let span = CGFloat(wall.dimensions.x) * 200 / 2 surfacePath.move(to: CGPoint(x: -span, y: 0)) surfacePath.addLine(to: CGPoint(x: span, y: 0)) // Draw the wall using an SKShapeNode and the path let wallShape = SKShapeNode(path: surfacePath) wallShape.strokeColor = .white wallShape.lineWidth = 5 wallShape.lineCap = .square wallNode.addChild(wallShape) } } }
Nov ’22
Reply to How to get a 2D floor plan with dimensions from RoomPlan
I've found a solution for this. As suggested, the simd_float4x4 matrix is the key to the solution here. Using SpriteKit I've created my 2D map using RoomPlan data. To start with, I've created a couple of extensions for simd_float4x4. These extract the data we need from the metrix so it's easier to work with: extension simd_float4x4 {     var eulerAngles: simd_float3 {         simd_float3(             x: asin(-self[2][1]),             y: atan2(self[2][0], self[2][2]),             z: atan2(self[0][1], self[1][1])         )     }     var position: simd_float3 {         simd_float3(x: self.columns.3.x,                     y: self.columns.3.y,                     z: self.columns.3.z         )     }     var positionVector: SCNVector3 {         SCNVector3(x: self.columns.3.x,                    y: self.columns.3.y,                    z: self.columns.3.z         )     } } To build my 2D map in SpriteKit, I created a separate SKNode for every RoomPlan surface. In each node I set the correct position and rotation using the sims_float4x4 matrix, create a path using the dimensions and draw the surface using an SKShapeNode. Using the eulerAngles and position extensions, I set the correct rotation and position of every surface: // Position surface position.x = -CGFloat(transform.position.x) * mapScale position.y = CGFloat(transform.position.z) * mapScale zRotation = -CGFloat(transform.eulerAngles.z - transform.eulerAngles.y) The mapScale is just a scaling factor I applied. The measurements that come out of RoomPlan are in meters. In SpriteKit they're in points. If you don't apply a scale, the whole map will display within a few pixels. Setting the mapScale to 100-300 will do fine, depending on the device's screen size and SpriteKit camera. The x position is the same in both RoomPlan's and SpriteKit's coordinate system. In RoomPlan however, the x- and y-axis are horizontal and vertical and the z-axis is the "depth" axis. We're interested in the "top" view, ignoring RoomPlan's y-axis so we'll need to use the z value for SpriteKit's y component (I hope my explanation makes any sense :p). The surfaceRotation is a weird one. I still don't fully get why this works like this, but it does xd. As pointed out by @ArthurPhilipenko the matrix only tells us about the position and rotation of the surface which will result in a point in space, but not a line, like we want to draw. For this, we also need the "dimension" component from the RoomPlan surface. This is a simd_float3. Using this dimension component, we can draw a line using the width of the surface (or the dimension.x) and positioning it equally on both sides of out position and rotation point of the node. // Create surface path let surfacePath = CGMutablePath() let span = CGFloat(dimensions.x) * mapScale / 2 surfacePath.move(to: CGPoint(x: -span, y: 0)) surfacePath.addLine(to: CGPoint(x: span, y: 0)) Finally, I create a SKShapeNode to draw the line on the screen: // Draw surface path func draw() { let surfaceShape = SKShapeNode(path: surfacePath) surfaceShape.strokeColor = surfaceColor surfaceShape.lineWidth = wallThickness surfaceShape.lineCap = .square addChild(surfaceShape) } If you do this for every surface you'll get a nice 2D map using the 3D RoomPlan data.
Oct ’22