def plot_to_directory(pcb_file, output_directory, temp_dir): layers = [ { 'layer': pcbnew.B_SilkS, 'color': '#CC00CC', 'alpha': 0.8, }, { 'layer': pcbnew.B_Cu, 'color': '#33EE33', 'alpha': 0.5, }, { 'layer': pcbnew.F_Cu, 'color': '#CC0000', 'alpha': 0.5, }, { 'layer': pcbnew.F_SilkS, 'color': '#00CCCC', 'alpha': 0.8, }, ] with pcb_util.get_plotter(pcb_file, temp_dir) as plotter: processed_svg_files = [] for i, layer in enumerate(layers): output_filename = plotter.plot(layer['layer'], pcbnew.PLOT_FORMAT_SVG) logger.info('Post-processing %s...', output_filename) processor = SvgProcessor(output_filename) def colorize(original): if original.lower() == '#000000': return layer['color'] return original processor.apply_color_transform(colorize) processor.wrap_with_group({ 'opacity': str(layer['alpha']), }) output_filename2 = os.path.join( temp_dir, 'processed-' + os.path.basename(output_filename)) processor.write(output_filename2) processed_svg_files.append((output_filename2, processor)) logger.info('Merging layers...') final_svg = os.path.join(output_directory, 'merged.svg') shutil.copyfile(processed_svg_files[0][0], final_svg) output_processor = SvgProcessor(final_svg) for _, processor in processed_svg_files: output_processor.import_groups(processor) output_processor.write(final_svg)
def plot_job(job, output_directory, temp_dir): logger.info("processing job " + job["filename"]) with pcb_util.get_plotter(PCB_FILENAME, temp_dir) as plotter: plotter.plot_options.SetMirror(job["mirror"]) plotter.plot_options.SetExcludeEdgeLayer(False) processed_svg_files = [] for i, layer in enumerate(job["layers"]): output_filename = plotter.plot(layer['layer'], pcbnew.PLOT_FORMAT_SVG) logger.info('Post-processing %s...', output_filename) processor = SvgProcessor(output_filename) def colorize(original): if original.lower() == '#000000': return layer['color'] return original processor.apply_color_transform(colorize) processor.wrap_with_group({ 'opacity': str(layer['alpha']), }) output_filename2 = os.path.join( temp_dir, 'processed-' + os.path.basename(output_filename)) processor.write(output_filename2) processed_svg_files.append((output_filename2, processor)) logger.info('merging layers...') final_svg = os.path.join(output_directory, job["filename"] + '.svg') shutil.copyfile(processed_svg_files[0][0], final_svg) output_processor = SvgProcessor(final_svg) for _, processor in processed_svg_files: output_processor.import_groups(processor) output_processor.write(final_svg) logger.info('rasterizing...') final_png = os.path.join(output_directory, job["filename"] + '.png') subprocess.check_call([ 'inkscape', '--export-area-drawing', '--export-dpi=600', '--export-png', final_png, '--export-background', '#FFFFFF', final_svg, ])
def render(extra_variables, skip_optimize, output_directory): renderer = Renderer(os.path.join(source_parts_dir, 'font_generator.scad'), output_directory, extra_variables) renderer.clean() svg_output = renderer.render_svgs(panelize_quantity=1) processor = SvgProcessor(svg_output) if not skip_optimize: logging.info('Removing redundant lines') processor.remove_redundant_lines() processor.write(svg_output) logging.info('\n\n\nDone rendering to SVG: ' + svg_output)
def _render_component(self, i, panel_horizontal, panel_vertical): output_file = self._get_component_file(i) style_options = ['cut'] if self.etch_enabled: style_options.append('etch') for style in (style_options): logging.debug('Rendering component %d, %s', i, style) try: _ = openscad.run( self.input_file, output_file, variables=self._get_variables({ '_is_projection_rendering': True, 'render_3d': False, 'render_index': i, 'render_etch': style == 'etch', 'panel_horizontal': panel_horizontal, 'panel_vertical': panel_vertical, }), capture_output=True, ) except openscad.OpenSCADException as e: if b'Current top level object is not a 2D object.' in e.stderr: # This is expected if we try rendering an etch layer as a # cut, since there will be nothing to export continue else: raise processor = SvgProcessor(output_file) if style == 'cut': processor.apply_laser_cut_style() elif style == 'etch': processor.apply_laser_etch_style() return processor logging.debug('Component %d has no geometry', i) return None
def _render_component(self, i, panel_horizontal, panel_vertical): output_file = self._get_component_file(i) for style in ('cut', 'etch'): logging.debug('Rendering component %d, %s', i, style) try: _ = openscad.run( self.input_file, output_file, variables=self._get_variables({ 'render_3d': False, 'render_index': i, 'render_etch': style == 'etch', 'panel_horizontal': panel_horizontal, 'panel_vertical': panel_vertical, }), capture_output=True, ) except openscad.OpenSCADException as e: if 'Current top level object is not a 2D object.' in e.stderr: # This is expected if we try rendering an etch layer as a # cut, since there will be nothing to export continue else: raise processor = SvgProcessor(output_file) processor.fix_dimens() if style == 'cut': processor.apply_laser_cut_style() elif style == 'etch': processor.apply_laser_etch_style() break else: raise ValueError("Invalid component!", i) return processor
args = parser.parse_args() laser_parts_directory = os.path.join('build', 'laser_parts') extra_variables = { 'render_revision': rev_info.git_short_rev(), 'render_date': rev_info.current_date(), } renderer = Renderer('splitflap.scad', laser_parts_directory, extra_variables) renderer.clean() svg_output = renderer.render_svgs(panelize_quantity=args.panelize) logging.info('Removing redundant lines') processor = SvgProcessor(svg_output) redundant_lines = processor.remove_redundant_lines() processor.write(svg_output) # Export to png logging.info('Generating raster preview') raster_svg = os.path.join(laser_parts_directory, 'raster.svg') raster_png = os.path.join(laser_parts_directory, 'raster.png') processor.apply_raster_render_style() # Show which redundant lines were removed processor.add_highlight_lines(redundant_lines) processor.write(raster_svg) logging.info('Resize SVG canvas')
def screenshot(self): print("Taking a screenshot") self.board = pcbnew.GetBoard() board_path = self.board.GetFileName() board_filename = os.path.basename(board_path) board_filename_noex = os.path.splitext(board_filename)[0] project_folder = os.path.dirname(board_path) timelapse_folder = board_filename_noex + '-timelapse' timelapse_folder_path = os.path.join(project_folder, timelapse_folder) if not os.path.exists(timelapse_folder_path): print('Timelapse folder does not exist. creating one now') os.mkdir(timelapse_folder_path) print('Timelapse folder created') timelapse_files = os.listdir(timelapse_folder_path) timelapse_number = extract_biggest_number(timelapse_files) pc = pcbnew.PLOT_CONTROLLER(self.board) po = pc.GetPlotOptions() po.SetOutputDirectory(timelapse_folder_path) po.SetPlotFrameRef(False) po.SetLineWidth(pcbnew.FromMM(0.35)) po.SetScale(1) po.SetUseAuxOrigin(True) po.SetMirror(False) po.SetExcludeEdgeLayer(True) # Set current layer # Plot single layer to file timelapse_number += 1 processed_svg_files = [] for layer in layers: pc.SetLayer(layer['layer']) layer['layer'] pc.OpenPlotfile( '-' + layer['name'] + '-' + str(timelapse_number).zfill(4), pcbnew.PLOT_FORMAT_SVG, layer['name']) pc.PlotLayer() pc.ClosePlot() output_filename = pc.GetPlotFileName() processor = SvgProcessor(output_filename) def colorize(original): if original.lower() == '#000000': return layer['color'] return original processor.apply_color_transform(colorize) processor.wrap_with_group({ 'opacity': str(layer['alpha']), }) output_filename2 = os.path.join( timelapse_folder_path, 'processed-' + os.path.basename(output_filename)) processor.write(output_filename2) processed_svg_files.append((output_filename2, processor)) os.remove(output_filename) final_svg = os.path.join( timelapse_folder_path, board_filename_noex + '-' + str(timelapse_number).zfill(4) + '.svg') shutil.copyfile(processed_svg_files[0][0], final_svg) output_processor = SvgProcessor(final_svg) for processed_svg_file, processor in processed_svg_files: output_processor.import_groups(processor) os.remove(processed_svg_file) output_processor.write(final_svg)
def plot_to_directory(pcb_file, output_directory, temp_dir): board_name = os.path.splitext(os.path.basename(pcb_file))[0] layers = [ { 'layer': pcbnew.B_SilkS, 'color': '#CC00CC', 'alpha': 0.8, }, { 'layer': pcbnew.B_Cu, 'color': '#33EE33', 'alpha': 0.5, }, { 'layer': pcbnew.F_Cu, 'color': '#CC0000', 'alpha': 0.5, }, { 'layer': pcbnew.F_SilkS, 'color': '#00CCCC', 'alpha': 0.8, }, { 'layer': pcbnew.Cmts_User, 'color': '#333333', 'alpha': 0.8, }, { 'layer': pcbnew.Edge_Cuts, 'color': '#3333CC', 'alpha': 0.8, }, ] with pcb_util.get_plotter(pcb_file, temp_dir) as plotter: plotter.plot_options.SetExcludeEdgeLayer(True) processed_svg_files = [] for i, layer in enumerate(layers): output_filename = plotter.plot(layer['layer'], pcbnew.PLOT_FORMAT_SVG) logger.info('Post-processing %s...', output_filename) processor = SvgProcessor(output_filename) def colorize(original): if original.lower() == '#000000': return layer['color'] return original processor.apply_color_transform(colorize) processor.wrap_with_group({ 'opacity': str(layer['alpha']), }) output_filename2 = os.path.join( temp_dir, 'processed-' + os.path.basename(output_filename)) processor.write(output_filename2) processed_svg_files.append((output_filename2, processor)) # Plot the paste layer to its own SVG logger.info('Plotting paste SVG') output_filename = plotter.plot(pcbnew.F_Paste, pcbnew.PLOT_FORMAT_SVG) processor = SvgProcessor(output_filename) def colorize(original): if original.lower() == '#000000': return '#FF0000' return original processor.apply_group_style_transforms({ 'fill-opacity': lambda _: '0', 'stroke': lambda _: '#FF0000', 'stroke-opacity': lambda _: '1', 'stroke-width': lambda _: '20', }) paste_filename = os.path.join(output_directory, '%s_paste.svg' % board_name) processor.write(paste_filename) logger.info('Merging layers...') final_svg = os.path.join(output_directory, '%s_merged.svg' % board_name) shutil.copyfile(processed_svg_files[0][0], final_svg) output_processor = SvgProcessor(final_svg) for _, processor in processed_svg_files: output_processor.import_groups(processor) output_processor.write(final_svg) logger.info('Rasterizing...') raster_width = 1280 final_png = os.path.join(output_directory, '%s_merged.png' % board_name) subprocess.check_call([ 'inkscape', '--export-area-drawing', '--export-width', str(raster_width), '--export-png', final_png, '--export-background', '#FFFFFF', final_svg, ])
def screenshot(self): print("Taking a screenshot") self.board = pcbnew.GetBoard() board_path=self.board.GetFileName() # There doesn't seem to be a clean way to detect when KiCad is shutting down. # Check for an empty board path and return False to signal that the timer should not restart. if board_path == "": print("Shutting down") return False board_filename=os.path.basename(board_path) board_filename_noex=os.path.splitext(board_filename)[0] project_folder=os.path.dirname(board_path) timelapse_folder=board_filename_noex+'-timelapse' timelapse_folder_path=os.path.join(project_folder, timelapse_folder) if not os.path.exists(timelapse_folder_path): print('Timelapse folder does not exist. creating one now') os.mkdir(timelapse_folder_path) print('Timelapse folder created') timelapse_files=os.listdir(timelapse_folder_path) timelapse_number=extract_biggest_number(timelapse_files) pc = pcbnew.PLOT_CONTROLLER(self.board) po = pc.GetPlotOptions() po.SetOutputDirectory(timelapse_folder_path) po.SetPlotFrameRef(False) po.SetLineWidth(pcbnew.FromMM(0.35)) po.SetScale(1) po.SetUseAuxOrigin(True) po.SetMirror(False) po.SetExcludeEdgeLayer(True) # Set current layer # Plot single layer to file timelapse_number += 1 processed_svg_files = [] for layer in layers: pc.SetLayer(layer['layer']) layer['layer'] pc.OpenPlotfile('-'+layer['name']+'-'+str(timelapse_number).zfill(4), pcbnew.PLOT_FORMAT_SVG, layer['name']) pc.PlotLayer() pc.ClosePlot() output_filename = pc.GetPlotFileName() processor = SvgProcessor(output_filename) def colorize(original): if original.lower() == '#000000': return layer['color'] return original processor.apply_color_transform(colorize) processor.wrap_with_group({ 'opacity': str(layer['alpha']), }) output_filename2 = os.path.join(timelapse_folder_path, 'processed-' + os.path.basename(output_filename)) processor.write(output_filename2) processed_svg_files.append((output_filename2, processor)) os.remove(output_filename) final_svg = os.path.join(timelapse_folder_path, board_filename_noex+'-'+str(timelapse_number).zfill(4)+'.svg') shutil.copyfile(processed_svg_files[0][0], final_svg) output_processor = SvgProcessor(final_svg) for processed_svg_file, processor in processed_svg_files: output_processor.import_groups(processor) os.remove(processed_svg_file) output_processor.set_title(board_filename_noex) output_processor.write(final_svg) # Remove the exported file if there were no new changes if timelapse_number != 1: with open(os.path.join(timelapse_folder_path, board_filename_noex+'-'+str(timelapse_number - 1).zfill(4)+'.svg')) as old_file: with open(final_svg) as new_file: if old_file.read() == new_file.read(): timelapse_number -= 1 os.remove(final_svg) return True
# (pcbnew.F_Mask , "F.Mask", "#800000", "0.8"), # (pcbnew.B_Mask , "B.Mask", "#800000", "0.8") ] processed_svg_files = [] # Plot each layer, in turn, to a temporary file, and then change the colour of the # generated svg. for a in layers: pc.SetLayer(a[0]) pc.OpenPlotfile("layer_ " + a[1], pcbnew.PLOT_FORMAT_SVG, "idk") layerFilename = pc.GetPlotFileName() pc.PlotLayer() pc.ClosePlot() processor = SvgProcessor(layerFilename) def colorize(original): if original.lower() == '#000000': return a[2] return original processor.apply_color_transform(colorize) processor.wrap_with_group({ 'opacity': a[3], }) processed_svg_files.append((processor, layerFilename)) # Finally, combine all the layers together. shutil.copyfile(layerFilename, svgfilename)
def plot_to_directory(pcb_filename, svg_filename_top, svg_filename_bot, temp_dir): sides = [ { 'svg_filename': svg_filename_bot, 'layers':[ { 'layer': pcbnew.B_SilkS, 'color': '#CC00CC', 'alpha': 0.8, }, { 'layer': pcbnew.B_Cu, 'color': '#33EE33', 'alpha': 0.5, }, ] }, { 'svg_filename': svg_filename_top, 'layers':[ { 'layer': pcbnew.F_Cu, 'color': '#CC0000', 'alpha': 0.5, }, { 'layer': pcbnew.F_SilkS, 'color': '#00CCCC', 'alpha': 0.8, }, ] } ] with pcb_util.get_plotter(pcb_filename, temp_dir) as plotter: plotter.plot_options.SetExcludeEdgeLayer(False) #plotter.plot_options.SetAutoScale(False) for i, side in enumerate(sides): processed_svg_files = [] for i, layer in enumerate(side['layers']): output_filename = plotter.plot(layer['layer'], pcbnew.PLOT_FORMAT_SVG) #logger.info('Post-processing %s...', output_filename) processor = SvgProcessor(output_filename) def colorize(original): if original.lower() == '#000000': return layer['color'] return original processor.apply_color_transform(colorize) processor.wrap_with_group({ 'opacity': str(layer['alpha']), }) output_filename2 = os.path.join(temp_dir, 'processed-' + os.path.basename(output_filename)) processor.write(output_filename2) processed_svg_files.append((output_filename2, processor)) shutil.copyfile(processed_svg_files[0][0], side['svg_filename']) output_processor = SvgProcessor(side['svg_filename']) for _, processor in processed_svg_files: output_processor.import_groups(processor) output_processor.write(side['svg_filename'])
def plot_to_directory(output_directory, temp_dir): layers = [ { 'layer': pcbnew.B_SilkS, 'color': '#CC00CC', 'alpha': 0.8, }, { 'layer': pcbnew.B_Cu, 'color': '#33EE33', 'alpha': 0.5, }, { 'layer': pcbnew.F_Cu, 'color': '#CC0000', 'alpha': 0.5, }, { 'layer': pcbnew.F_SilkS, 'color': '#00CCCC', 'alpha': 0.8, }, ] with pcb_util.get_plotter(PCB_FILENAME, temp_dir) as plotter: plotter.plot_options.SetExcludeEdgeLayer(False) processed_svg_files = [] for i, layer in enumerate(layers): output_filename = plotter.plot(layer['layer'], pcbnew.PLOT_FORMAT_SVG) logger.info('Post-processing %s...', output_filename) processor = SvgProcessor(output_filename) def colorize(original): if original.lower() == '#000000': return layer['color'] return original processor.apply_color_transform(colorize) processor.wrap_with_group({ 'opacity': str(layer['alpha']), }) output_filename2 = os.path.join( temp_dir, 'processed-' + os.path.basename(output_filename)) processor.write(output_filename2) processed_svg_files.append((output_filename2, processor)) logger.info('Merging layers...') final_svg = os.path.join(output_directory, 'merged.svg') shutil.copyfile(processed_svg_files[0][0], final_svg) output_processor = SvgProcessor(final_svg) for _, processor in processed_svg_files: output_processor.import_groups(processor) output_processor.write(final_svg) logger.info('Rasterizing...') final_png = os.path.join(output_directory, 'merged.png') subprocess.check_call([ 'inkscape', '--export-area-drawing', '--export-width=320', '--export-png', final_png, '--export-background', '#FFFFFF', final_svg, ])