All Downloads are FREE. Search and download functionalities are using the official Maven repository.

commonMain.ru.casperix.multiplatform.rectangle_packer.RectanglePacker.kt Maven / Gradle / Ivy

There is a newer version: 1.1.1
Show newest version
package ru.casperix.multiplatform.rectangle_packer

import ru.casperix.math.axis_aligned.int32.Dimension2i
import ru.casperix.math.collection.getLooped
import ru.casperix.math.vector.int32.Vector2i

class RectangleSource(
    val source: Source,
    val size: Vector2i,
)

class RectangleTarget(
    val source: Source,
    val position: Vector2i,
)

data class PackedRectangles(val dimension: Dimension2i, val containers: List>)

object RectanglePacker {
    private val sizeList = listOf(4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096)

    fun  pack(images: List>): PackedRectangles? {
        sizeList.forEachIndexed { index, sizeX ->
            listOf(sizeX, sizeList.getLooped(index + 1)).forEach { sizeY ->
                val dimension = Dimension2i(sizeX, sizeY)

                val result = pack(images, dimension.toVector2i())
                if (result != null) {
                    return PackedRectangles(dimension, result)
                }
            }
        }
        return null
    }

    fun  pack(images: List>, size: Vector2i): List>? {
        val sorted = images.sortedBy { it.size.y }.toMutableList()
        val result = mutableListOf>()

        var minCorner = Vector2i.ZERO
        var maxCorner = Vector2i.ZERO

        while (true) {
            val current = sorted.lastOrNull() ?: return result
            val maxCornerCandidate = minCorner + current.size

            if (size.greaterOrEq(maxCornerCandidate)) {
                sorted.removeLast()

                result += RectangleTarget(current.source, minCorner)

                minCorner += current.size.xAxis
                maxCorner = maxCorner.upper(maxCornerCandidate)
            } else {
                if (minCorner.x == 0) {
                    return null
                }
                minCorner = maxCorner.yAxis
                maxCorner = minCorner

                if (minCorner.y >= size.y) {
                    return null
                }
            }
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy