Dallas Makerspace Show and Tell - December 2016

A gift for the MultiCam (users)…

-- VECTRIC LUA SCRIPT

require "strict"


--[[
================================================================================
  Copyright (c) 2016 Rowdy Dog Software

  Permission is hereby granted, free of charge, to any person obtaining a copy
  of this software and associated documentation files (the "Software"), to
  deal in the Software without restriction, including without limitation the
  rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  sell copies of the Software, and to permit persons to whom the Software is
  furnished to do so, subject to the following conditions:

  The above copyright notice and this permission notice shall be included in
  all copies or substantial portions of the Software.

  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  IN THE SOFTWARE.
================================================================================

  VCarve Gadget that...
  - Ensures a job is loaded
  - Prepares an output directory for the MultiCam g-code files
  - Moves any files already in the output directory to a backup directory
  - Ensures all toolpaths are up-to-date
  - Outputs one g-code file for each toolpath where the filename is
        Sequence - Abbreviation for Tool Type - Abbreviation for Tool Size

  Future enhancements...
  - Squash toolpaths that use the same tool
  - Display a summary / success report
  - Output a summary / success report
  - Perform a two-phase commit on the output directory

================================================================================
]]

function main(script_path)

    -- Ensure a job is loaded or bail out
    local job
    job = VectricJob()
    if (job == nil) or (not job.Exists) then
        local dlg
        dlg = FileDialog()
        if not dlg:FileOpen( "crv", "*.crv", "VCarve Files (*.crv)||" ) then
            return false
        end
        OpenExistingJob(dlg.PathName)
    end

    -- Ensure the job has a name
    if job.Name == '' then
        MessageBox("For this gadget to work correctly the job must have a name.  Save the current job then try again.")
        return false
    end

    -- Determine where output should go
    local username
    local userpath
    local usermkdir
    local outputpath
    local backuppath
    username = os.getenv("USERNAME")
    userpath = '\\\\files\\committees\\woodworking\\CNC Router\\_Programs\\' .. username .. '\\'
    outputpath = userpath .. job.Name .. '\\'
    backuppath = outputpath .. 'Backup' .. '\\'

    -- Create the base output directory, the project output directory, and the backup directory
    usermkdir = 'mkdir \"'..userpath..'\"'
    os.execute( usermkdir )
    usermkdir = 'mkdir \"'..outputpath..'\"'
    os.execute( usermkdir )
    usermkdir = 'mkdir \"'..backuppath..'\"'
    os.execute( usermkdir )

    -- Remove existing files from outputpath
    local usercopy
    local reader = DirectoryReader()
    reader:BuildDirectoryList( outputpath, false )
    if reader:NumberOfDirs() ~= 1 then
        MessageBox("Unexpected failure trying to clear the output directory")
        return false
    end
    reader:GetFiles( "*.*", true, false )
    for i1 = 1, reader:NumberOfFiles() do
        local entry = reader:FileAtIndex( i1 )
        if string.find( entry.Name, username ) ~= nil then
            usercopy = 'copy \"'..entry.Name..'\" \"'..backuppath..'.\"'
            os.execute( usercopy )
            os.remove( entry.Name )
        end
    end

    -- Ensure all toolpaths are up-to-date
    local tpm = ToolpathManager()
    local rv1 = tpm:RecalculateAllToolpaths()
    if rv1 == nil then
        MessageBox("Recalculate all toolpaths failed")
        return false;
    end

    -- Prepare for post-processing
    local tps = ToolpathSaver();
    local pp = tps:GetPostWithName( "MultiCam G Code Arc (inch) (*.cnc)" )
    if pp == nil then
        MessageBox("Failed to load post processor")
        return false
    end

    -- Generate one g-code file for each toolpath
    local toolpath
    local s1
    local sequence = 1
    local position = tpm:GetHeadPosition()
    while position ~= nil do
        toolpath, position = tpm:GetNext( position )
        s1 = outputpath ..
            tostring(sequence) ..
            "-" ..
            FilenameFromTool(toolpath.Tool) ..
            ".cnc"
        tps:ClearToolpathList()
        tps:AddToolpath( toolpath )
        tps:SaveToolpaths( pp, s1, false )
        sequence = sequence + 1
    end

    return true
end


--[[
  Abbreviate a toolpath.Tool.ToolDia for use in a short filename.
]]
function AbbreviateToolDiameter(tool)
    local sixteenths = math.floor((tool.ToolDia*16)+0.5)
    if (sixteenths == 2) then
        return "1_8"
    elseif (sixteenths == 4) then
        return "1_4"
    elseif (sixteenths == 6) then
        return "3_8"
    elseif (sixteenths == 8) then
        return "1_2"
    else
        return tostring(sixteenths)
    end
end


--[[
  Abbreviate details about a Tool for use as a short filename.
]]
function FilenameFromTool(tool)
    local rv
    local ts
    local tnu

    rv = tool.ToolTypeText
    tnu = string.upper(tool.Name)

    if tool.ToolType == Tool.BALL_NOSE then
        rv = "BN"
        rv = rv .. '-' .. AbbreviateToolDiameter(tool)
    elseif tool.ToolType == Tool.END_MILL then
        rv = "EM"
        ts = AbbreviateToolDiameter(tool)
        if string.find( tnu, "DOWNCUT" ) ~= nil then
            rv = "DC"
        elseif string.find( tnu, "UPCUT" ) ~= nil then
            rv = "UC"
        elseif string.find( tnu, "COMPRESSION" ) ~= nil then
            rv = "C"
        elseif string.find( tnu, "SUPER O" ) ~= nil then
            rv = "SO"
        elseif string.find( tnu, "DIAMOND" ) ~= nil then
            rv = "DD"
            if string.find( tnu, "120" ) ~= nil then
                ts = "120"
            elseif string.find( tnu, "90" ) ~= nil then
                ts = "90"
            else
              -- fix?  Do what?
            end
        end
        rv = rv .. '-' .. ts
    elseif tool.ToolType == Tool.VBIT then
        rv = "VB"
        rv = rv .. '-' .. tostring(tool.VBit_Angle)
    elseif tool.ToolType == Tool.DIAMOND_DRAG then
        rv = "DD"
        if string.find( tnu, "120" ) ~= nil then
            ts = "120"
        elseif string.find( tnu, "90" ) ~= nil then
            ts = "90"
        else
            ts = tostring(tool.VBit_Angle)
        end
        rv = rv .. '-' .. ts
    end
    return rv
end
3 Likes