Added STEP file output

This commit is contained in:
Salvador E. Tropea 2020-06-15 13:21:24 -03:00
parent 8fbcffba0f
commit 2766b5afcb
4 changed files with 90 additions and 2 deletions

View File

@ -339,7 +339,7 @@ class CfgYamlReader(CfgReader):
},
{
'key': 'metric_units',
'types': ['excellon'],
'types': ['excellon', 'step'],
'to': 'metric_units',
'required': lambda opts: True,
},
@ -409,6 +409,24 @@ class CfgYamlReader(CfgReader):
'to': 'output_name',
'required': lambda opts: True,
},
{
'key': 'origin',
'types': ['step'],
'to': 'origin',
'required': lambda opts: True,
},
{
'key': 'no_virtual',
'types': ['step'],
'to': 'no_virtual',
'required': lambda opts: False,
},
{
'key': 'min_distance',
'types': ['step'],
'to': 'min_distance',
'required': lambda opts: False,
},
]
po = PC.OutputOptions(otype)
@ -501,7 +519,7 @@ class CfgYamlReader(CfgReader):
config_error("Output '"+name+"' needs a type")
if otype not in ['gerber', 'ps', 'hpgl', 'dxf', 'pdf', 'svg',
'gerb_drill', 'excellon', 'position',
'gerb_drill', 'excellon', 'position', 'step',
'kibom', 'ibom', 'pdf_sch_print', 'pdf_pcb_print']:
config_error("Unknown output type '"+otype+"' in '"+name+"'")

View File

@ -123,6 +123,8 @@ class Plotter(object):
self._do_sch_print(output_dir, op, brd_file)
elif self._output_is_pcb_print(op):
self._do_pcb_print(board, output_dir, op, brd_file)
elif self._output_is_step(op):
self._do_step(output_dir, op, brd_file)
else: # pragma no cover
# We shouldn't get here, means the above if is incomplete
plot_error("Don't know how to plot type "+op.options.type)
@ -269,6 +271,9 @@ class Plotter(object):
def _output_is_pcb_print(self, output):
return output.options.type == PCfg.OutputOptions.PDF_PCB_PRINT
def _output_is_step(self, output):
return output.options.type == PCfg.OutputOptions.STEP
def _output_is_bom(self, output):
return output.options.type in [
PCfg.OutputOptions.KIBOM,
@ -602,6 +607,45 @@ class Plotter(object):
logger.debug('Moving '+cur+' -> '+new)
os.rename(cur, new)
def _do_step(self, output_dir, op, brd_file):
to = op.options.type_options
# Output file name
output = to.output
if output is None:
output = os.path.splitext(os.path.basename(brd_file))[0]+'.step'
output = os.path.abspath(os.path.join(output_dir, output))
# Make units explicit
if to.metric_units:
units = 'mm'
else:
units = 'in'
# Base command with overwrite
cmd = [misc.KICAD2STEP, '-o', output, '-f']
# Add user options
if to.no_virtual:
cmd.append('--no-virtual')
if to.min_distance is not None:
cmd.append('--min-distance="{}{}"'.format(to.min_distance, units))
if to.origin == 'drill':
cmd.append('--drill-origin')
elif to.origin == 'grid':
cmd.append('--grid-origin')
else:
to.origin.replace(',', 'x')
cmd.append('--user-origin="{}{}"'.format(to.origin, units))
# The board
cmd.append(brd_file)
# Execute and inform is successful
logger.debug('Executing: '+str(cmd))
try:
cmd_output = check_output(cmd, stderr=STDOUT)
except CalledProcessError as e:
logger.error('Failed to create Step file, error %d', e.returncode)
if e.output:
logger.debug('Output from command: '+e.output.decode())
exit(misc.KICAD2STEP_ERR)
logger.debug('Output from command:\n'+cmd_output.decode())
def _do_pcb_print(self, board, output_dir, output, brd_file):
check_script(misc.CMD_PCBNEW_PRINT_LAYERS,
misc.URL_PCBNEW_PRINT_LAYERS, '1.4.1')

View File

@ -19,6 +19,7 @@ PLOT_ERROR = 14
NO_YAML_MODULE = 15
NO_PCBNEW_MODULE = 16
CORRUPTED_PCB = 17
KICAD2STEP_ERR = 18
CMD_EESCHEMA_DO = 'eeschema_do'
URL_EESCHEMA_DO = 'https://github.com/INTI-CMNB/kicad-automation-scripts'
@ -30,3 +31,4 @@ CMD_KIBOM = 'KiBOM_CLI.py'
URL_KIBOM = 'https://github.com/INTI-CMNB/KiBoM'
CMD_IBOM = 'generate_interactive_bom.py'
URL_IBOM = 'https://github.com/INTI-CMNB/InteractiveHtmlBom'
KICAD2STEP = 'kicad2step'

View File

@ -1,4 +1,5 @@
import pcbnew
import re
from . import error
from . import log
@ -377,6 +378,26 @@ class PositionOptions(TypeOptions):
return errs
class StepOptions(TypeOptions):
def __init__(self):
self.metric_units = True
self.origin = None
self.min_distance = None
self.no_virtual = False
self.output = None
def validate(self):
errs = []
# origin (required)
if (self.origin not in ['grid', 'drill']) and (re.match(r'[-\d\.]+\s*,\s*[-\d\.]+\s*$', self.origin) is None):
errs.append('Origin must be "grid" or "drill" or "X,Y"')
# min_distance (not required)
if (self.min_distance is not None) and (not isinstance(self.min_distance, (int, float))):
errs.append('min_distance must be a number')
return errs
class KiBoMOptions(TypeOptions):
def __init__(self):
@ -424,6 +445,7 @@ class OutputOptions(object):
IBOM = 'ibom'
PDF_SCH_PRINT = 'pdf_sch_print'
PDF_PCB_PRINT = 'pdf_pcb_print'
STEP = 'step'
def __init__(self, otype):
self.type = otype
@ -454,6 +476,8 @@ class OutputOptions(object):
self.type_options = SchPrintOptions()
elif otype == self.PDF_PCB_PRINT:
self.type_options = PcbPrintOptions()
elif otype == self.STEP:
self.type_options = StepOptions()
else: # pragma: no cover
# If we get here it means the above if is incomplete
raise KiPlotConfigurationError("Output options not implemented for "+otype)