summaryrefslogtreecommitdiff
path: root/ShedCalc
diff options
context:
space:
mode:
authorArturs Artamonovs <arturs.artamonovs@protonmail.com>2026-08-26 21:37:56 +0100
committerArturs Artamonovs <arturs.artamonovs@protonmail.com>2026-08-26 21:37:56 +0100
commite8b5398d8f9a2d4fa9ed339fec774badc270979f (patch)
tree2e4607262e7887cdb37003568d846503b35f9cc8 /ShedCalc
parent91d0042017e6c46f2c9f5d42d438836efa6d53e4 (diff)
downloadShedCalc-e8b5398d8f9a2d4fa9ed339fec774badc270979f.tar.gz
ShedCalc-e8b5398d8f9a2d4fa9ed339fec774badc270979f.zip
All views seem to work ok
Diffstat (limited to 'ShedCalc')
-rw-r--r--ShedCalc/BOMController.swift153
-rw-r--r--ShedCalc/BOMView.swift48
-rw-r--r--ShedCalc/ParamModel.swift40
-rw-r--r--ShedCalc/ParamView.swift101
-rw-r--r--ShedCalc/RenderController.swift106
-rw-r--r--ShedCalc/RenderModel.swift4
-rw-r--r--ShedCalc/RenderView.swift39
7 files changed, 423 insertions, 68 deletions
diff --git a/ShedCalc/BOMController.swift b/ShedCalc/BOMController.swift
index fa05eeb..be70a65 100644
--- a/ShedCalc/BOMController.swift
+++ b/ShedCalc/BOMController.swift
@@ -4,4 +4,157 @@
//
// Created by Jacky Jack on 01/08/2026.
//
+import SwiftUI
+import Combine
+private func roundUpPieces(_ value: Float) -> Int {
+ Int(value.rounded(.up))
+}
+
+private func roundUpPieces(_ value: Double) -> Int {
+ Int(value.rounded(.up))
+}
+
+struct MaterialItem: Identifiable {
+ let materialName: String
+ let pricePerMeter: Double
+ let totalMeters: Double
+ let totalPrice: Double
+ let metersPerPiece: Double
+ let totalPieces: Double
+
+ let id = UUID()
+}
+class BOMController {
+
+ func calcBOM(from paramModel: ParamModel) -> [MaterialItem] {
+ var items: [MaterialItem] = []
+ items.append(calcOSB(from: paramModel))
+ items.append(calcWallTimber2x4(from: paramModel))
+ items.append(calcFloorTimber2x4(from: paramModel))
+ items.append(calcRoofTimber2x4(from: paramModel))
+ items.append(calcRoofFelt(from: paramModel))
+ items.append(calcWeatherWrap(from: paramModel))
+ items.append(calcCladding(from: paramModel))
+ return items
+ }
+
+ private func calcOSB(from paramModel: ParamModel) -> MaterialItem {
+ let totalOSBarea = paramModel.floorArea()
+ let OSBPrice = totalOSBarea*paramModel.OSBSheetPrice
+ let OSBPricePerMeter = paramModel.OSBSheetPrice / (1.2*2.4)
+ let totalPieces = roundUpPieces(totalOSBarea / (1.2*2.4))
+ return MaterialItem(
+ materialName: "OSB",
+ pricePerMeter: Double(OSBPricePerMeter),
+ totalMeters: Double(totalOSBarea),
+ totalPrice: Double(totalPieces)*Double(paramModel.OSBSheetPrice),
+ metersPerPiece:Double(paramModel.OSBSheetPrice),
+ totalPieces: Double(totalPieces))
+ }
+
+ private func calcWallTimber2x4(from paramModel: ParamModel) -> MaterialItem {
+ let totalLength = paramModel.totalWallBeamLength()
+ let timberBeamPrice = paramModel.timberBeamPrice
+ let totalPrice = totalLength*timberBeamPrice
+ let pieceSize = paramModel.timberLengthSize
+ let totalPieces = roundUpPieces(totalLength/pieceSize)
+ return MaterialItem(
+ materialName: "2x4",
+ pricePerMeter: Double(timberBeamPrice),
+ totalMeters: Double(totalLength),
+ totalPrice: Double(totalPrice),
+ metersPerPiece:Double(pieceSize),
+ totalPieces: Double(totalPieces)
+ )
+ }
+ private func calcFloorTimber2x4(from paramModel: ParamModel) -> MaterialItem {
+ let joistLength = paramModel.totalJoistBeamLength() * 2
+ let spacersLength = Double(paramModel.lengthBeamNum())*paramModel.beamSpace
+ let timberBeamPrice = paramModel.timberBeamPrice
+ let totalLength = Double(paramModel.lengthBeamNum())*paramModel.beamSpace
+ let totalPrice = totalLength*timberBeamPrice
+ let pieceSize = Double(paramModel.timberLengthSize)
+ let totalPieces = roundUpPieces(totalLength/pieceSize)
+ return MaterialItem(
+ materialName: "Floor 2x4",
+ pricePerMeter: Double(timberBeamPrice),
+ totalMeters: Double(totalLength),
+ totalPrice: Double(totalPrice),
+ metersPerPiece:Double(pieceSize),
+ totalPieces: Double(totalPieces)
+ )
+ }
+
+ private func calcRoofTimber2x4(from paramModel: ParamModel) -> MaterialItem {
+ let joistLength = paramModel.totalJoistBeamLength() * 2
+ let spacersLength = Double(paramModel.lengthBeamNum())*paramModel.beamSpace
+ let timberBeamPrice = paramModel.timberBeamPrice
+ let totalLength = Double(paramModel.lengthBeamNum())*paramModel.beamSpace
+ let totalPrice = totalLength*timberBeamPrice
+ let pieceSize = Double(paramModel.timberLengthSize)
+ let totalPieces = roundUpPieces(totalLength/pieceSize)
+ return MaterialItem(
+ materialName: "Roof 2x4",
+ pricePerMeter: Double(timberBeamPrice),
+ totalMeters: Double(totalLength),
+ totalPrice: Double(totalPrice),
+ metersPerPiece:Double(pieceSize),
+ totalPieces: Double(totalPieces)
+ )
+ }
+
+ private func calcRoofFelt(from paramModel: ParamModel) -> MaterialItem {
+ let roofArea = paramModel.roofArea()
+ let feltRollArea = Double(paramModel.feltWidth)*Double(paramModel.feltLength)
+ var feltPricePerMeter:Double = 0.0
+ if paramModel.feltPrice > 0.0 {
+ feltPricePerMeter = Double(paramModel.feltPrice) / feltRollArea
+ }
+ let totalPieces = roundUpPieces(Double(roofArea)/Double(feltRollArea))
+
+ let totalPrice = Double(totalPieces) * paramModel.feltPrice
+
+ return MaterialItem(
+ materialName: "Roof Felt",
+ pricePerMeter: Double(feltPricePerMeter),
+ totalMeters: Double(roofArea),
+ totalPrice: Double(totalPrice),
+ metersPerPiece:Double(feltRollArea),
+ totalPieces: Double(totalPieces)
+ )
+ }
+
+ private func calcWeatherWrap(from paramModel: ParamModel) -> MaterialItem {
+
+ return MaterialItem(
+ materialName: "Weather Wrap",
+ pricePerMeter: Double(0.1),
+ totalMeters: Double(0.1),
+ totalPrice: Double(0.1),
+ metersPerPiece:Double(0.1),
+ totalPieces: Double(0.1)
+ )
+ }
+
+ private func calcCladding(from paramModel: ParamModel) -> MaterialItem {
+ let wallArea = Double(paramModel.length*paramModel.height)*2 + Double(paramModel.width*paramModel.height)*2
+ let singleCladArea = paramModel.claddingLength * (Double(paramModel.claddingWidth) - paramModel.claddingOverlap)
+ let claddingPieces = wallArea/singleCladArea
+ let totalPieces = roundUpPieces(claddingPieces)
+ let totalPrice = Double(totalPieces) * paramModel.claddingPrice
+ return MaterialItem(
+ materialName: "Cladding",
+ pricePerMeter: Double(paramModel.claddingPrice),
+ totalMeters: Double(claddingPieces*paramModel.claddingLength),
+ totalPrice: Double(totalPrice),
+ metersPerPiece:Double(paramModel.claddingLength),
+ totalPieces: Double(totalPieces)
+ )
+ }
+
+ private func calcBeam(from paramModel: ParamModel) -> MaterialItem {
+ return MaterialItem(materialName: "2x4", pricePerMeter: 1.0, totalMeters: 10, totalPrice: 100, metersPerPiece: 1.2, totalPieces: 11.2)
+ }
+
+}
diff --git a/ShedCalc/BOMView.swift b/ShedCalc/BOMView.swift
index 1bb6523..2cde6f3 100644
--- a/ShedCalc/BOMView.swift
+++ b/ShedCalc/BOMView.swift
@@ -8,29 +8,25 @@
import SwiftUI
import Combine
-struct Materials: Identifiable {
- let materialName: String
- let pricePerMeter: Double
- let totalMeters: Double
- let totalPrice: Double
- let metersPerPiece: Double
- let totalPieces: Double
-
- let id = UUID()
-}
-
-
-
struct BOMView: View {
@Environment(ParamModel.self) private var paramModel
+ private let bomController = BOMController()
- @State private var materials = [
- Materials(materialName: "2x4", pricePerMeter: 1.2, totalMeters: 10, totalPrice: 12, metersPerPiece: 4.8, totalPieces: 23),
- Materials(materialName: "OSB", pricePerMeter: 1.2, totalMeters: 10, totalPrice: 12, metersPerPiece: 4.8, totalPieces: 23),
- Materials(materialName: "Roof Felt", pricePerMeter: 1.2, totalMeters: 10, totalPrice: 12, metersPerPiece: 4.8, totalPieces: 23),
- Materials(materialName: "Nails", pricePerMeter: 1.2, totalMeters: 10, totalPrice: 12, metersPerPiece: 4.8, totalPieces: 23),
- Materials(materialName: "Cladding", pricePerMeter: 1.2, totalMeters: 10, totalPrice: 12, metersPerPiece: 4.8, totalPieces: 23)
- ]
+ private var materials: [MaterialItem] {
+ bomController.calcBOM(from: paramModel)
+ }
+
+ private var totalPrice: Double {
+ materials.reduce(0) { $0 + $1.totalPrice }
+ }
+
+ /*@State private var materials = [
+ MaterialItem(materialName: "2x4", pricePerMeter: 1.2, totalMeters: 10, totalPrice: 12, metersPerPiece: 4.8, totalPieces: 23),
+ MaterialItem(materialName: "OSB", pricePerMeter: 1.2, totalMeters: 10, totalPrice: 12, metersPerPiece: 4.8, totalPieces: 23),
+ MaterialItem(materialName: "Roof Felt", pricePerMeter: 1.2, totalMeters: 10, totalPrice: 12, metersPerPiece: 4.8, totalPieces: 23),
+ MaterialItem(materialName: "Nails", pricePerMeter: 1.2, totalMeters: 10, totalPrice: 12, metersPerPiece: 4.8, totalPieces: 23),
+ MaterialItem(materialName: "Cladding", pricePerMeter: 1.2, totalMeters: 10, totalPrice: 12, metersPerPiece: 4.8, totalPieces: 23)
+ ]*/
var body: some View {
VStack {
@@ -39,14 +35,11 @@ struct BOMView: View {
VStack {
Table(materials) {
TableColumn("Material", value: \.materialName)
- TableColumn("Price per m") { material in
- Text(material.pricePerMeter, format: .number.precision(.fractionLength(2)))
- }
TableColumn("Total m") { material in
Text(material.totalMeters, format: .number.precision(.fractionLength(2)))
}
- TableColumn("Total price") { material in
- Text(material.totalPrice, format: .number.precision(.fractionLength(2)))
+ TableColumn("Price per m") { material in
+ Text(material.pricePerMeter, format: .number.precision(.fractionLength(2)))
}
TableColumn("m per Piece") { material in
Text(material.metersPerPiece, format: .number.precision(.fractionLength(2)))
@@ -54,10 +47,13 @@ struct BOMView: View {
TableColumn("Pieces") { material in
Text(material.totalPieces, format: .number)
}
+ TableColumn("Total price") { material in
+ Text(material.totalPrice, format: .number.precision(.fractionLength(2)))
+ }
}
}
HStack {
- Text("Total price: 0.00")
+ Text("Total price: \(totalPrice, format: .number.precision(.fractionLength(2)))")
}
}
}
diff --git a/ShedCalc/ParamModel.swift b/ShedCalc/ParamModel.swift
index 4935bcd..f3cbbd7 100644
--- a/ShedCalc/ParamModel.swift
+++ b/ShedCalc/ParamModel.swift
@@ -10,20 +10,30 @@ import Observation
@Observable
class ParamModel {
- var width: Float = 1.0
- var height: Float = 1.0
- var length: Float = 1.0
- var beamSpace: Float = 0.6
+ var width: Double = 3.0
+ var height: Double = 1.0
+ var length: Double = 1.0
+ var beamSpace: Double = 0.6
+ var OSBSheetPrice: Double = 0.0
+ var timberBeamPrice: Double = 0.0
+ var timberLengthSize: Double = 2.4
+ var feltPrice: Double = 0.0
+ var feltWidth: Double = 1.0
+ var feltLength: Double = 10
+ var claddingPrice: Double = 0.1
+ var claddingLength: Double = 0.1
+ var claddingWidth: Double = 0.1
+ var claddingOverlap: Double = 0.1
- func floorArea() -> Float {
+ func floorArea() -> Double {
return width*length
}
- func roofArea() -> Float {
+ func roofArea() -> Double {
return width*length
}
- func dimensions() -> SIMD3<Float> {
+ func dimensions() -> SIMD3<Double> {
return [width,length,height]
}
@@ -34,4 +44,20 @@ class ParamModel {
func lengthBeamNum() -> Int {
return Int(length/beamSpace) + 1
}
+
+ func setBeamSpace(_ bs: Double) {
+ self.beamSpace = bs
+ }
+
+ func totalWallBeams() -> Int {
+ return 2 * (widthBeamNum() + lengthBeamNum())
+ }
+
+ func totalWallBeamLength() -> Double {
+ return Double(totalWallBeams()) * self.height
+ }
+
+ func totalJoistBeamLength() -> Double {
+ return Double(widthBeamNum())*beamSpace
+ }
}
diff --git a/ShedCalc/ParamView.swift b/ShedCalc/ParamView.swift
index 3e27978..1f02856 100644
--- a/ShedCalc/ParamView.swift
+++ b/ShedCalc/ParamView.swift
@@ -16,19 +16,51 @@ struct ParamView: View {
@Bindable var paramModel = paramModel
VStack {
HStack {
- Text("All in meters")
+ Text("Set shed dimensions")
}
HStack {
Text("Width")
- TextField("Width", value: $paramModel.width, format: .number)
+ TextField("Width", value: Binding(
+ get: { paramModel.width },
+ set: { newValue in
+ if !newValue.isNaN && !newValue.isInfinite && newValue > 0.5 {
+ paramModel.width = newValue
+ }
+ }
+ ), format: .number.precision(.fractionLength(2)))
+ }
+ HStack {
+ Text("Length")
+ TextField("Length", value: Binding(
+ get: { paramModel.length },
+ set: { newValue in
+ if !newValue.isNaN && !newValue.isInfinite && newValue > 0.5 {
+ paramModel.length = newValue
+ }
+ }
+ ), format: .number.precision(.fractionLength(2)))
}
HStack {
Text("Height")
- TextField("Height", value: $paramModel.height, format: .number)
+ TextField("Height", value: Binding(
+ get: { paramModel.height },
+ set: { newValue in
+ if !newValue.isNaN && !newValue.isInfinite && newValue > 0.5 {
+ paramModel.height = newValue
+ }
+ }
+ ), format: .number.precision(.fractionLength(2)))
}
HStack {
- Text("Length")
- TextField("Length", value: $paramModel.length, format: .number)
+ Text("Spacing")
+ TextField("Spacing", value: Binding(
+ get: { paramModel.beamSpace },
+ set: { newValue in
+ if !newValue.isNaN && !newValue.isInfinite && newValue > 0.15 {
+ paramModel.beamSpace = newValue
+ }
+ }
+ ), format: .number.precision(.fractionLength(2)))
}
HStack {
Text("Total floor area: \(paramModel.floorArea(), specifier: "%.2f") m^2")
@@ -36,6 +68,65 @@ struct ParamView: View {
HStack {
Text("Total roof area: \(paramModel.roofArea(), specifier: "%.2f") m^2")
}
+ HStack {
+ Text("Total wall beams: \(paramModel.totalWallBeams()) ")
+ }
+ HStack {
+ Text("Set Timber Prices")
+ }
+ HStack {
+ Text("OSB per sheet price")
+ TextField("per sheet", value: Binding(
+ get: { paramModel.OSBSheetPrice },
+ set: { newValue in
+ if !newValue.isNaN && !newValue.isInfinite && newValue > 0.15 {
+ paramModel.beamSpace = newValue
+ }
+ }
+ ), format: .number)
+ }
+ HStack {
+ Text("Beam price per meter")
+ TextField("per meter", value: Binding(
+ get: { paramModel.timberBeamPrice },
+ set: { newValue in
+ if !newValue.isNaN && !newValue.isInfinite && newValue > 0.0 {
+ paramModel.timberBeamPrice = newValue
+ }
+ }
+ ), format: .number)
+
+ Text("Piece size")
+ TextField("per meter", value: Binding(
+ get: { paramModel.timberLengthSize },
+ set: { newValue in
+ if !newValue.isNaN && !newValue.isInfinite && newValue > 0.0 {
+ paramModel.timberLengthSize = newValue
+ }
+ }
+ ), format: .number)
+ }
+ HStack {
+ Text("Felt price")
+ TextField("per meter", value: $paramModel.feltPrice, format: .number)
+ Text("Felt width")
+ TextField("per meter", value: $paramModel.feltWidth, format: .number)
+ Text("Felt length")
+ TextField("per meter", value: $paramModel.feltLength, format: .number)
+ }
+ HStack {
+ Text("Cladding dimensions and price")
+ }
+ HStack {
+ Text("Cladding price per meter")
+ TextField("", value: $paramModel.claddingPrice, format: .number)
+ Text("Length")
+ TextField("", value: $paramModel.claddingLength, format: .number)
+ Text("Width")
+ TextField("", value: $paramModel.claddingWidth, format: .number)
+ Text("Overlap")
+ TextField("", value: $paramModel.claddingOverlap, format: .number)
+ }
}
}
}
diff --git a/ShedCalc/RenderController.swift b/ShedCalc/RenderController.swift
index 1a57cb0..8ceef21 100644
--- a/ShedCalc/RenderController.swift
+++ b/ShedCalc/RenderController.swift
@@ -8,23 +8,25 @@
import SwiftUI
import RealityKit
-let BEAM_2x4_WIDTH: Float = 0.02
-let BEAM_2x4_LENGTH: Float = 0.04
+let BEAM_2x4_WIDTH: Double = 0.02
+let BEAM_2x4_LENGTH: Double = 0.04
struct BeamData {
let id: String
- let position: SIMD3<Float>
- let height: Float
- let rotation: SIMD3<Float>
+ let position: SIMD3<Double>
+ let height: Double
+ let rotation: SIMD3<Double>
}
class RenderController {
- func createScene(dimensions: SIMD3<Float>, rotation: SIMD2<Float>) -> Entity {
+ var beamMaxId = 0
+
+ func createScene(dimensions: SIMD3<Double>, rotation: SIMD2<Double>) -> Entity {
let scene = Entity()
scene.name = "scene"
- let box = createBox(dimensions: [1,1,1])
- scene.addChild(box)
+ //let box = createBox(dimensions: [1,1,1])
+ //scene.addChild(box)
let beam0 = createBeam2x4(position: [1,1,0], height: 2.4, rotate: [90,0,0], id: "beam0")
scene.addChild(beam0)
@@ -69,12 +71,12 @@ class RenderController {
func handleDragGesture(
_ value: DragGesture.Value,
lastDrag: CGSize,
- currentRotation: SIMD2<Float>
- ) -> (rotation: SIMD2<Float>, drag: CGSize) {
- let dx = Float(value.translation.width - lastDrag.width) * 0.01
- let dy = Float(value.translation.height - lastDrag.height) * 0.01
+ currentRotation: SIMD2<Double>
+ ) -> (rotation: SIMD2<Double>, drag: CGSize) {
+ let dx = Double(value.translation.width - lastDrag.width) * 0.01
+ let dy = Double(value.translation.height - lastDrag.height) * 0.01
- let newRotation = SIMD2<Float>(
+ let newRotation = SIMD2<Double>(
currentRotation.x + dy,
currentRotation.y + dx
)
@@ -94,9 +96,9 @@ class RenderController {
return box
}
- private func createBeam2x4(position: SIMD3<Float>, height: Float, rotate: SIMD3<Float>, id: String) -> ModelEntity {
+ private func createBeam2x4(position: SIMD3<Float>, height: Double, rotate: SIMD3<Float>, id: String) -> ModelEntity {
let box = ModelEntity(
- mesh: .generateBox(size: SIMD3(BEAM_2x4_WIDTH,BEAM_2x4_LENGTH,height), cornerRadius: 0.02),
+ mesh: .generateBox(size: SIMD3(Float(BEAM_2x4_WIDTH),Float(BEAM_2x4_LENGTH),Float(height)), cornerRadius: 0.02),
materials: [SimpleMaterial(color: .yellow, isMetallic: false)]
)
//box.look(at: position, from: lookFrom, relativeTo: nil)
@@ -113,24 +115,90 @@ class RenderController {
return box
}
- func generateShedWall(position: SIMD3<Float>, height: Float, widthNum: Int, lengthNum: Int, spaceBeem: Float) -> [BeamData] {
+ func generateShedWall(position: SIMD3<Double>, height: Double, widthNum: Int, lengthNum: Int, spaceBeam: Double) -> [BeamData] {
var beams: [BeamData] = []
var id: Int = 0
//Wall 0
for i in 0...widthNum {
- let x0 = Float(i)*spaceBeem
- beams.append(BeamData(id: "beam\(id)", position: [x0,position.y, position.z], height: height, rotation: [90,0,0]))
+ let x0 = Double(i)*spaceBeam
+ beams.append(BeamData(id: "beam-\(id)", position: [position.x+x0,position.y, position.z], height: height, rotation: [90,0,0]))
id += 1
}
//Wall 1
+ for i in 0...widthNum {
+ let x0 = Double(i)*spaceBeam
+ beams.append(BeamData(id: "beam-\(id)", position: [position.x+x0,position.y, position.z + Double(lengthNum)*spaceBeam], height: height, rotation: [90,0,0]))
+ //print("\(id)")
+ id += 1
+ }
//Wall 2
+ for i in 0...lengthNum {
+ let z0 = Double(i)*spaceBeam
+ beams.append(BeamData(id: "beam-\(id)", position: [position.x,position.y, position.z + z0], height: height, rotation: [90,90,0]))
+ //print("\(id)")
+ id += 1
+ }
//Wall 3
+ for i in 0...lengthNum {
+ let z0 = Double(i)*spaceBeam
+ beams.append(BeamData(id: "beam-\(id)", position: [position.x+Double(widthNum)*spaceBeam,position.y, position.z + z0], height: height, rotation: [90,90,0]))
+ //print("\(id)")
+ id += 1
+ }
+
+ self.beamMaxId = id
+ return beams
+ }
+
+ func generateShedFloor(position: SIMD3<Double>, height: Double, width: Double, widthNum: Int, spaceBeam: Double) -> [BeamData] {
+ var beams: [BeamData] = []
+ var id = self.beamMaxId+1
+
+ //all space
+ for i in 0...widthNum {
+ let x0 = Double(i)*spaceBeam
+ let length = width
+ beams.append(BeamData(id: "beam-\(id)", position:[position.x+x0,position.y-height/2, position.z+length/2], height: length, rotation: [0,0,0]))
+ id += 1
+ }
+
+ //2 beams for length
+ let length = Double(widthNum)*spaceBeam
+ beams.append(BeamData(id: "beam-\(id)", position:[position.x+length/2, position.y-height/2, position.z], height: length, rotation: [0,90,0]))
+ id += 1
+ beams.append(BeamData(id: "beam-\(id)", position:[position.x+length/2,position.y-height/2, position.z+width], height: length, rotation: [0,90,0]))
+ id += 1
+
+ self.beamMaxId = id
+ return beams
+ }
+
+ func generateShedRoof(position: SIMD3<Double>, height: Double, width: Double, widthNum: Int, spaceBeam: Double) -> [BeamData] {
+ var beams: [BeamData] = []
+ var id = self.beamMaxId+1
+
+ //all space
+ for i in 0...widthNum {
+ let x0 = Double(i)*spaceBeam
+ let length = width
+ beams.append(BeamData(id: "beam-\(id)", position:[position.x+x0,position.y+height/2, position.z+length/2], height: length, rotation: [0,0,0]))
+ id += 1
+ }
+
+ //2 beams for length
+ let length = Double(widthNum)*spaceBeam
+ beams.append(BeamData(id: "beam-\(id)", position:[position.x+length/2, position.y+height/2, position.z], height: length, rotation: [0,90,0]))
+ id += 1
+ beams.append(BeamData(id: "beam-\(id)", position:[position.x+length/2,position.y+height/2, position.z+width], height: length, rotation: [0,90,0]))
+ id += 1
+
+ self.beamMaxId = id
return beams
}
func createBeams(_ beams: [BeamData]) -> [ModelEntity] {
return beams.map { beam in
- createBeam2x4(position: beam.position, height: beam.height, rotate: beam.rotation, id: beam.id)
+ createBeam2x4(position: SIMD3<Float>(beam.position), height: beam.height, rotate: SIMD3<Float>(beam.rotation), id: beam.id)
}
}
diff --git a/ShedCalc/RenderModel.swift b/ShedCalc/RenderModel.swift
index 86c5a1d..7a74d6e 100644
--- a/ShedCalc/RenderModel.swift
+++ b/ShedCalc/RenderModel.swift
@@ -9,8 +9,8 @@ import Combine
class RenderModel: ObservableObject {
// Scene rotation
- @Published var rotationX: Float = 0.4
- @Published var rotationY: Float = 0.6
+ @Published var rotationX: Double = 0.4
+ @Published var rotationY: Double = 0.6
func reset() {
rotationX = 0.4
diff --git a/ShedCalc/RenderView.swift b/ShedCalc/RenderView.swift
index a143e99..b71b741 100644
--- a/ShedCalc/RenderView.swift
+++ b/ShedCalc/RenderView.swift
@@ -31,23 +31,44 @@ struct RenderView: View {
//content.addChild(beam)
//draw all beams
- let beamData = renderController.generateShedWall(position: [0,0,0], height: paramModel.height, widthNum: paramModel.widthBeamNum(), lengthNum: paramModel.lengthBeamNum(), spaceBeem: paramModel.beamSpace)
- //content.add(beams)
- let beams = renderController.createBeams(beamData)
- beams.forEach { scene.addChild($0) }
+ let beamData = renderController.generateShedWall(position: [0,0,0], height: paramModel.height, widthNum: paramModel.widthBeamNum(), lengthNum: paramModel.lengthBeamNum(), spaceBeam: paramModel.beamSpace)
+ let wallBeams = renderController.createBeams(beamData)
+ wallBeams.forEach { scene.addChild($0) }
+
+ //let floorBeamData = renderController.generateShedFloor(position: [0,0,0], width: Float(1.0), widthNum: paramModel.widthBeamNum(), spaceBeam: paramModel.beamSpace)
+ //let floorBeams = renderController.createBeams(floorBeamData)
+ //floorBeams.forEach { scene.addChild($0) }
} update: { content in
// Update box geometry directly in the scene
- if let scene = content.entities.first(where: { $0.name == "scene" }),
- let box = scene.findEntity(named: "box") as? ModelEntity {
- box.model?.mesh = .generateBox(size: paramModel.dimensions(), cornerRadius: 0.02)
+ //if let scene = content.entities.first(where: { $0.name == "scene" }),
+ //let box = scene.findEntity(named: "box") as? ModelEntity {
+ //box.model?.mesh = .generateBox(size: paramModel.dimensions(), cornerRadius: 0.02)
+ //}
+ if let scene = content.entities.first(where: { $0.name == "scene"}) {
+ let oldBeams = scene.children.filter { $0.name.hasPrefix("beam-") }
+ oldBeams.forEach { $0.removeFromParent() }
+
+ let beamData = renderController.generateShedWall(position: [0,0,0], height: paramModel.height, widthNum: paramModel.widthBeamNum(), lengthNum: paramModel.lengthBeamNum(), spaceBeam: paramModel.beamSpace)
+ let beams = renderController.createBeams(beamData)
+ beams.forEach { scene.addChild($0) }
+
+ let floorBeamData = renderController.generateShedFloor(position: [0,0,0], height: paramModel.height, width: Double(paramModel.lengthBeamNum())*paramModel.beamSpace, widthNum: paramModel.widthBeamNum(), spaceBeam: paramModel.beamSpace)
+ let floorBeams = renderController.createBeams(floorBeamData)
+ floorBeams.forEach { scene.addChild($0) }
+
+ let roofBeamData = renderController.generateShedRoof(position: [0,0,0], height: paramModel.height, width: Double(paramModel.lengthBeamNum())*paramModel.beamSpace, widthNum: paramModel.widthBeamNum(), spaceBeam: paramModel.beamSpace)
+ let roofBeams = renderController.createBeams(roofBeamData)
+ roofBeams.forEach { scene.addChild($0) }
}
+
// Update scene rotation directly
if let scene = content.entities.first(where: { $0.name == "scene" }) {
- let xRot = simd_quatf(angle: viewModel.rotationX, axis: [1, 0, 0])
- let yRot = simd_quatf(angle: viewModel.rotationY, axis: [0, 1, 0])
+ let xRot = simd_quatf(angle: Float(viewModel.rotationX), axis: [1, 0, 0])
+ let yRot = simd_quatf(angle: Float(viewModel.rotationY), axis: [0, 1, 0])
scene.transform.rotation = yRot * xRot
}
+ //update amount of beams
}.gesture(
DragGesture()
.onChanged { value in