We are working on 2D Panel Cutting program and Im stuck on calculating the remaining areas after adding for ex 4 elements on board
For ex: I have 2.44×1.22 m2 board
I want to add
element 1: 2.1×0.3
element 2: 2.0×0.8
element 2: 0.3×0.9
element 2: 0.2×0.9
as you can see in the image
so I have written the code many times but the best one is as below:
let allElemants = [bedBack, bedFront, bedSide1, bedSide2, comdinaSide1, comdinaSide2, comdinaUp, comdinaDrawer1, comdinaDrawer2, wardrobeSide1, wardrobeSide2, wardrobeUp, wardrobeDown, wardrobeDoor1, wardrobeDoor2, wardrobeDoor3]
var currentElemants = [bedBack, bedFront, bedSide1, bedSide2, comdinaSide1, comdinaSide2, comdinaUp, comdinaDrawer1, comdinaDrawer2, wardrobeSide1, wardrobeSide2, wardrobeUp, wardrobeDown, wardrobeDoor1, wardrobeDoor2, wardrobeDoor3]
enum Orientation {
case BottomVirticaly
case BottomHorizontally
case SideVirticaly
case SideHorizontally
}
calculate()
func calculate() {
var largestElemant = findLargestElemant()
if !unUsedBoardsParts.isEmpty {
lookForExistsBoardParts(largestElemant: largestElemant)
} else {
useNewBoard(largestElemant: largestElemant)
}
checkIfNoElemantLeft()
}
func findLargestElemant() -> (String, Decimal, Decimal, UIColor) {
var largestElemantIndex = 0
var largestElemant = currentElemants[0]
for i in 0...currentElemants.count - 1 {
if currentElemants[i].1 * currentElemants[i].2 > largestElemant.1 * largestElemant.2 {
largestElemantIndex = i
largestElemant = currentElemants[i]
}
}
currentElemants.remove(at: largestElemantIndex)
return largestElemant
}
func lookForExistsBoardParts(largestElemant: (String, Decimal, Decimal, UIColor)) {
var partFits = false
for i in 0...unUsedBoardsParts.count - 1 {
if unUsedBoardsParts[i].4 == largestElemant.3 {
let checkIfBottomVirticalyFits = largestElemant.1 < unUsedBoardsParts[i].2.0 && largestElemant.2 < unUsedBoardsParts[i].2.1
let checkIfBottomHorizontallyFits = largestElemant.2 < unUsedBoardsParts[i].2.0 && largestElemant.1 < unUsedBoardsParts[i].2.1
let checkIfSideVirticalyFits = largestElemant.1 < unUsedBoardsParts[i].3.0 && largestElemant.2 < unUsedBoardsParts[i].3.1
let checkIfSideHorizontallyFits = largestElemant.2 < unUsedBoardsParts[i].3.0 && largestElemant.1 < unUsedBoardsParts[i].3.1
if checkIfBottomVirticalyFits {
partFits = true
useUsedBoardPart(largestElemant: largestElemant, boardPart: unUsedBoardsParts[i], orientation: .BottomVirticaly)
break
} else if checkIfBottomHorizontallyFits {
partFits = true
useUsedBoardPart(largestElemant: largestElemant, boardPart: unUsedBoardsParts[i], orientation: .BottomHorizontally)
break
} else if checkIfSideVirticalyFits {
partFits = true
useUsedBoardPart(largestElemant: largestElemant, boardPart: unUsedBoardsParts[i], orientation: .SideVirticaly)
break
} else if checkIfSideHorizontallyFits {
partFits = true
useUsedBoardPart(largestElemant: largestElemant, boardPart: unUsedBoardsParts[i], orientation: .SideHorizontally)
break
}
}
}
if !partFits {
useNewBoard(largestElemant: largestElemant)
}
}
func useUsedBoardPart(largestElemant: (String, Decimal, Decimal, UIColor), boardPart: (Int, Int, (Decimal, Decimal), (Decimal, Decimal), UIColor), orientation: Orientation) {
let boardPartIndex = unUsedBoardsParts.firstIndex { (index, boardNumber, bottom, side, color) in
index == boardPart.0
}
guard boardPartIndex != nil else { return }
if orientation == .BottomVirticaly {
let heightLeft = boardPart.2.0 - largestElemant.1
usedElemantPartsOnBoard.append((boardPart.1, largestElemant.0))
unUsedBoardsParts[boardPartIndex ?? 0] = (boardPart.0, boardPart.1, (heightLeft, boardPart.2.1), boardPart.3, largestElemant.3)
} else if orientation == .BottomHorizontally {
let heightLeft = boardPart.2.1 - largestElemant.1
usedElemantPartsOnBoard.append((boardPart.1, largestElemant.0))
unUsedBoardsParts[boardPartIndex ?? 0] = (boardPart.0, boardPart.1, (heightLeft, boardPart.2.1), boardPart.3, largestElemant.3)
} else if orientation == .SideVirticaly {
let heightLeft = boardPart.3.0 - largestElemant.1
usedElemantPartsOnBoard.append((boardPart.1, largestElemant.0))
unUsedBoardsParts[boardPartIndex ?? 0] = (boardPart.0, boardPart.1, boardPart.2, (heightLeft, boardPart.3.1), largestElemant.3)
} else if orientation == .SideHorizontally {
let heightLeft = boardPart.3.1 - largestElemant.1
usedElemantPartsOnBoard.append((boardPart.1, largestElemant.0))
unUsedBoardsParts[boardPartIndex ?? 0] = (boardPart.0, boardPart.1, boardPart.2, (heightLeft, boardPart.3.1), largestElemant.3)
}
}
func useNewBoard(largestElemant: (String, Decimal, Decimal, UIColor)) {
usedBoard.append(largestElemant.3)
let heightLeft = baseBoard.0 - largestElemant.1
let widthLeft = baseBoard.1 - largestElemant.2
usedElemantPartsOnBoard.append((usedBoard.endIndex, largestElemant.0))
unUsedBoardsPartsIndex += 1
unUsedBoardsParts.append((unUsedBoardsPartsIndex, usedBoard.endIndex, (heightLeft, baseBoard.1), (baseBoard.0, widthLeft), largestElemant.3))
}
func checkIfNoElemantLeft() {
if currentElemants.isEmpty {
print("Done: used boards: (usedBoard.count)")
print("Done: used elemant parts on Board: (usedElemantPartsOnBoard)")
print("Done: un used boards parts: (unUsedBoardsParts)")
} else {
calculate()
}
}
I know using the enum Orientation
will create a gaps after adding multiple element
but that is my best.
The main Idea of the code is to calculate the minimum panels to used for an amount of elements .
thanks for helping.