Idea for LUA script to create a knolling layout


RE: Idea for LUA script to create a knolling layout
#2
Hi! I think this is a really interesting idea. I would love to help make this at some point but I do not have a lot of time on my hands right now. I did however try our latest helper (AI) to see if we could get a working prototype to work from. It actually worked fairly well.

This script can layout all selected parts but it does not do it in nested mode and it does not reset rotation. With some work that should be possible to change. I must admit that for small stuff like this AI is pretty cool.

Code:
-- Function to get the X, Y (min), and Z dimensions of a subfile using its bounding box
function getSubfileDimensions(subfile)
    local minVec = subfile:getBoundingBoxMin()
    local maxVec = subfile:getBoundingBoxMax()
    return maxVec:getX() - minVec:getX(), minVec:getY(), maxVec:getZ() - minVec:getZ()  -- Return width, minY, and depth
end

-- Function to sort subfiles by their combined XY size
function sortSubfilesBySizeXY(a, b)
    local widthA, depthA = getSubfileDimensions(a)
    local widthB, depthB = getSubfileDimensions(b)
    local sizeA = widthA * depthA
    local sizeB = widthB * depthB
    return sizeA < sizeB
end

-- Function to layout parts in a knolling grid arrangement on the XY plane
function knollingLayout()
    local ses = ldc.session()
    if not ses:isLinked() then
        ldc.dialog.runMessage('No active model.')
        return
    end

    local sel = ses:getSelection()
    local cnt = sel:getRefCount()

    if cnt < 2 then
        ldc.dialog.runMessage('At least two items should be selected.')
        return
    end

    local subfiles = {}
    -- Collect all subfiles (Parts in the selection)
    for i = 1, cnt do
        table.insert(subfiles, sel:getRef(i))
    end

    -- Sort subfiles by size (combined X and Z dimensions)
    table.sort(subfiles, function(a, b)
        return sortSubfilesBySizeXY(a:getSubfile(), b:getSubfile())
    end)

    -- Determine grid dimensions and spacing
    local gridSize = 20  -- Minimum grid size, consider part size + desired spacing
    local xOffset = 0
    local zOffset = 0
    local rowWidth = 0

    for i, part in ipairs(subfiles) do
        local subfile = part:getSubfile()
        local width, minY, depth = getSubfileDimensions(subfile) -- X and Z dimensions, and minY for the Y position

        -- Set the part's position
        local pos = ldc.vector(xOffset, minY, zOffset)
        part:setPos(pos)

        -- Update offset for next part
        zOffset = zOffset + depth + gridSize  -- Move right to the next column

        -- Keep track of the maximum width in the current row
        rowWidth= math.max(rowWidth, width + gridSize)

        -- Check if we need to start a new row
        if zOffset + depth > gridSize * 100 then  -- Assuming grid is 10 columns wide
            xOffset = xOffset + rowWidth
            zOffset =  0 -- Move down to the next row
            rowWidth = 0  -- Reset row width for the new row
        end
    end
end

-- Register the macro for the knolling layout
function register()
    local macro_lo = ldc.macro('Perform knolling layout')
    macro_lo:setHint('Arrange elements in a knolling layout based on size in XY plane with Z = 0.')
    macro_lo:setEvent('run', 'knollingLayout')
end

register()
Reply
« Next Oldest | Next Newest »



Messages In This Thread
RE: Idea for LUA script to create a knolling layout - by Fredrik Hareide - 2024-10-11, 7:03

Forum Jump:


Users browsing this thread: 13 Guest(s)