def _render_component(self, i):
        output_file = self._get_component_file(i)
        for style in ('cut', 'etch'):
            logging.debug('Rendering component %d, %s', i, style)
            try:
                stdout, stderr = openscad.run(
                        self.input_file,
                        output_file,
                        variables = self._get_variables({
                            'render_3d': False,
                            'render_index': i,
                            'render_etch': style == 'etch',
                        }),
                        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
    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
Example #3
0
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,
        ])
Example #4
0
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-width=1010',
            '--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
Example #6
0
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)
        #	(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)
Example #8
0
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'])
Example #9
0
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,
        ])
Example #10
0
        'HEAD',
    ]).strip()

    extra_variables = {
        'render_revision': git_rev,
        'render_date': datetime.date.today().strftime('%Y-%m-%d'),
    }

    renderer = Renderer('splitflap.scad', laser_parts_directory, extra_variables)
    renderer.clean()
    svg_output = renderer.render_svgs()

    # Export to png
    raster_svg = os.path.join(laser_parts_directory, 'raster.svg')
    raster_png = os.path.join(laser_parts_directory, 'raster.png')
    processor = SvgProcessor(svg_output)
    processor.apply_raster_render_style()
    processor.write(raster_svg)

    logging.info('Resize SVG canvas')
    subprocess.check_call([
        'inkscape',
        '--verb=FitCanvasToDrawing',
        '--verb=FileSave',
        '--verb=FileClose',
        raster_svg,
    ])
    logging.info('Export PNG')
    subprocess.check_call([
        'inkscape',
        '--export-width=320',
Example #11
0
    }
    if args.kerf is not None:
        extra_variables['kerf_width'] = args.kerf
    elif args.kerf_preset is not None:
        extra_variables['kerf_width'] = KERF_PRESETS[args.kerf_preset]
    if args.thickness is not None:
        extra_variables['thickness'] = args.thickness

    print('Variables:\n' + json.dumps(extra_variables, indent=4))

    renderer = Renderer(os.path.join(source_parts_dir, 'splitflap.scad'),
                        laser_parts_directory, extra_variables)
    renderer.clean()
    svg_output = renderer.render_svgs(panelize_quantity=args.panelize)

    processor = SvgProcessor(svg_output)

    redundant_lines, merged_lines = None, None
    if not args.skip_optimize:
        logging.info('Removing redundant lines')
        redundant_lines, merged_lines = processor.remove_redundant_lines()

    processor.write(svg_output)
    logging.info(f'\n\n\nDone rendering to SVG: {svg_output}')

    if args.calculate_dimensions:
        svg_for_dimensions = os.path.join(
            laser_parts_directory,
            os.path.splitext(os.path.basename(svg_output))[0] +
            '_dimensions.svg')
        processor.apply_dimension_calculation_style()
Example #12
0
    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()

    # Export to png
    raster_svg = os.path.join(laser_parts_directory, 'raster.svg')
    raster_png = os.path.join(laser_parts_directory, 'raster.png')
    processor = SvgProcessor(svg_output)
    processor.apply_raster_render_style()
    processor.write(raster_svg)

    logging.info('Resize SVG canvas')
    subprocess.check_call([
        'inkscape',
        '--verb=FitCanvasToDrawing',
        '--verb=FileSave',
        '--verb=FileClose',
        raster_svg,
    ])
    logging.info('Export PNG')
    subprocess.check_call([
        'inkscape',
        '--export-width=320',
Example #13
0
        extra_variables['letter_width'] = args.width
    if args.offset_x is not None:
        extra_variables['letter_offset_x'] = args.offset_x
    if args.offset_y is not None:
        extra_variables['letter_offset_y'] = args.offset_y

    if args.ncolumns is not None:
        extra_variables['num_columns'] = args.ncolumns

    if args.kerf is not None:
        extra_variables['kerf_width'] = args.kerf
    if args.fill is True:
        extra_variables['render_fill'] = True
        args.skip_optimize = True

    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)

    redundant_lines, merged_lines = None, None
    if not args.skip_optimize:
        logging.info('Removing redundant lines')
        redundant_lines, merged_lines = processor.remove_redundant_lines()

    processor.write(svg_output)

    logging.info('\n\n\nDone rendering to SVG: ' + svg_output)