def main(argv): """Main program for the dxfgerber utility. :param argv: command line arguments """ parser = argparse.ArgumentParser(description=__doc__) argtxt = """maximum distance between two points considered equal when searching for contours (defaults to 0.5 mm)""" parser.add_argument('-l', '--limit', nargs=1, help=argtxt, dest='limit', metavar='F', type=float, default=0.5) group = parser.add_mutually_exclusive_group() group.add_argument('-L', '--license', action=LicenseAction, nargs=0, help="print the license") group.add_argument('-V', '--version', action='version', version=__version__) parser.add_argument('-v', '--verbose', dest='verbose', action="store_true") parser.add_argument('files', nargs='*', help='one or more file names', metavar='file') pv = parser.parse_args(argv) msg = utils.Msg(pv.verbose) lim = pv.limit**2 if not pv.files: parser.print_help() sys.exit(0) for f in utils.xpand(pv.files): msg.say('Starting file "{}"'.format(f)) try: ofn = utils.outname(f, extension='.dxf', addenum='_mod') entities = dxf.reader(f) except Exception as ex: # pylint: disable=W0703 utils.skip(ex, f) continue num = len(entities) if num == 0: msg.say('No entities found!') continue if num > 1: msg.say('Contains {} entities'.format(num)) bbe = [e.bbox for e in entities] bb = bbox.merge(bbe) msg.say('Gathering connected entities into contours') contours, rement = ent.findcontours(entities, lim) ncon = 'Found {} contours, {} remaining single entities' msg.say(ncon.format(len(contours), len(rement))) entities = contours + rement msg.say('Sorting entities') entities.sort(key=lambda e: (e.bbox.minx, e.bbox.miny)) else: msg.say('Contains: 1 entity') bb = entities[0].bbox es = 'Original extents: {:.1f} ≤ x ≤ {:.1f} mm,' \ ' {:.1f} ≤ y ≤ {:.1f} mm' msg.say(es.format(bb.minx, bb.maxx, bb.miny, bb.maxy)) # move entities so that the bounding box begins at 0,0 if bb.minx != 0 or bb.miny != 0: ms = 'Moving all entities by ({:.1f}, {:.1f}) mm' msg.say(ms.format(-bb.minx, -bb.miny)) for e in entities: e.move(-bb.minx, -bb.miny) length = sum(e.length for e in entities) msg.say('Total length of entities: {:.0f} mm'.format(length)) msg.say('Writing output to "{}"'.format(ofn)) dxf.writer(ofn, 'dxfgerber', entities) msg.say('File "{}" done.'.format(f))
from nctools import dxf ents = dxf.reader('../test/test1.dxf') from collections import defaultdict d = defaultdict(list) for e in ents: s, f = e.points d[s].append(e) d[f].append(e) # All points that are in >1 lines. [ln for k in d for ln in d[k] if len(d[k]) > 1]
def main(argv): """Main program for the dxf2nc utility. :param argv: command line arguments """ parser = argparse.ArgumentParser(description=__doc__) argtxt = """maximum distance between two points considered equal when searching for contours (defaults to 0.5 mm)""" argtxt2 = u"""minimum rotation angle in degrees where the knife needs to be lifted to prevent breaking (defaults to 60°)""" argtxt4 = "assemble connected lines into contours (off by default)" parser.add_argument('-l', '--limit', help=argtxt, dest='limit', metavar='F', type=float, default=0.5) parser.add_argument('-a', '--angle', help=argtxt2, dest='ang', metavar='F', type=float, default=60) parser.add_argument('-c', '--contours', help=argtxt4, dest='contours', action="store_true") group = parser.add_mutually_exclusive_group() group.add_argument('-L', '--license', action=LicenseAction, nargs=0, help="print the license") group.add_argument('-V', '--version', action='version', version=__version__) parser.add_argument('-v', '--verbose', dest='verbose', action="store_true") parser.add_argument('files', nargs='*', help='one or more file names', metavar='file') pv = parser.parse_args(argv) msg = utils.Msg(pv.verbose) lim = pv.limit**2 if not pv.files: parser.print_help() sys.exit(0) for f in utils.xpand(pv.files): parts = [] msg.say('Starting file "{}"'.format(f)) try: ofn = utils.outname(f, extension='') entities = dxf.reader(f) except Exception as ex: # pylint: disable=W0703 utils.skip(ex, f) continue # separate entities into parts according to their layers layers = {e.layer for e in entities} # Delete layer names that are not numbers layers = [la for la in layers if re.search('^[0-9]+', la)] layers.sort(key=lambda x: int(x)) # sort by integer value! # remove entities from unused layers. entities = [e for e in entities if e.layer in layers] num = len(entities) if num == 0: msg.say('No entities found!') continue if num > 1: msg.say('Contains {} entities'.format(num)) bbe = [e.bbox for e in entities] bb = bbox.merge(bbe) es = 'Original extents: {:.1f} ≤ x ≤ {:.1f} mm,' \ ' {:.1f} ≤ y ≤ {:.1f} mm' msg.say(es.format(bb.minx, bb.maxx, bb.miny, bb.maxy)) for layer in layers: msg.say('Found layer: "{}"'.format(layer)) le = [e for e in entities if e.layer == layer] if pv.contours: msg.say('Gathering connected entities into contours') contours, rement = ent.findcontours(le, lim) for c in contours: c.layer = layer ncon = 'Found {} contours, {} remaining single entities' msg.say(ncon.format(len(contours), len(rement))) le = contours + rement msg.say('Sorting entities') le.sort(key=lambda e: (e.bbox.minx, e.bbox.miny)) parts.append(le) msg.say('Sorting pieces') parts.sort(key=lambda p: bbox.merge([e.bbox for e in p]).minx) length = sum(e.length for e in entities) msg.say('Total length of entities: {:.0f} mm'.format(length)) msg.say('Writing output to "{}"'.format(ofn)) write_entities(ofn, parts, pv.ang) msg.say('File "{}" done.'.format(f))
def main(argv): """Main program for the readdxf utility. :param argv: command line arguments """ parser = argparse.ArgumentParser(description=__doc__) group = parser.add_mutually_exclusive_group() group.add_argument('-L', '--license', action=LicenseAction, nargs=0, help="print the license") group.add_argument('-V', '--version', action='version', version=__version__) parser.add_argument('-v', '--verbose', dest='verbose', action="store_true") parser.add_argument('files', nargs='*', help='one or more file names', metavar='file') pv = parser.parse_args(argv) msg = utils.Msg(pv.verbose) if not pv.files: parser.print_help() sys.exit(0) offset = 40 for f in utils.xpand(pv.files): msg.say('Starting file "{}"'.format(f)) try: ofn = utils.outname(f, extension='.pdf', addenum='_dxf') entities = dxf.reader(f) except ValueError as ex: msg.say(str(ex)) fns = "Cannot construct output filename. Skipping file '{}'." msg.say(fns.format(f)) continue except IOError as ex: msg.say(str(ex)) msg.say("Cannot open the file '{}'. Skipping it.".format(f)) continue # Output num = len(entities) if num == 0: msg.say('No entities found!') continue if num > 1: msg.say('Contains {} entities'.format(num)) bbx = [e.bbox for e in entities] bb = bbox.merge(bbx) else: msg.say('Contains: 1 entity') bb = entities[0].bbox w = bb.width + offset h = bb.height + offset xf = cairo.Matrix(xx=1.0, yy=-1.0, y0=h) out = cairo.PDFSurface(ofn, w, h) ctx = cairo.Context(out) ctx.set_matrix(xf) ctx.set_line_cap(cairo.LINE_CAP_ROUND) ctx.set_line_join(cairo.LINE_JOIN_ROUND) ctx.set_line_width(0.5) plot.plotgrid(ctx, w, h) colors = plot.crange(380, 650, len(entities)) msg.say('Plotting the entities') plot.plotentities(ctx, (offset / 2 - bb.minx, offset / 2 - bb.miny), entities, colors) # plot the color bar plot.plotcolorbar(ctx, w, len(entities), colors) # Plot the filename ctx.save() ctx.set_matrix(cairo.Matrix(xx=1.0, yy=1.0)) ctx.select_font_face('Sans') fh = min(10, h / 40) ctx.set_source_rgb(0.0, 0.0, 0.0) ctx.set_font_size(fh) ctx.move_to(5, fh + 5) txt = ' '.join([ 'Produced by: dxf2pdf', __version__, 'on', str(datetime.datetime.now())[:-10] ]) ctx.show_text(txt) ctx.stroke() fh = min(30, h / 20) ctx.move_to(5, h - 15) txt = 'File: "{}", last modified: {}' ctx.show_text(txt.format(f, time.ctime(os.path.getmtime(f)))) ctx.stroke() ctx.restore() # Finish the page. out.show_page() out.finish() msg.say('File "{}" done.'.format(f))
def main(argv): """Main program for the readdxf utility. :param argv: command line arguments """ parser = argparse.ArgumentParser(description=__doc__) argtxt = """maximum distance between two points considered equal when searching for contours (defaults to 0.5 mm)""" parser.add_argument('-l', '--limit', nargs='?', help=argtxt, dest='limit', type=float, default=0.5) group = parser.add_mutually_exclusive_group() group.add_argument('-L', '--license', action=LicenseAction, nargs=0, help="print the license") group.add_argument('-V', '--version', action='version', version=__version__) parser.add_argument('files', metavar='file', nargs='*', help='one or more file names') pv = parser.parse_args(argv) msg = utils.Msg() lim = pv.limit**2 parts = [] if not pv.files: parser.print_help() sys.exit(0) for f in utils.xpand(pv.files): try: entities = dxf.reader(f) except Exception as ex: utils.skip(ex, f) continue num = len(entities) msg.say('Filename: {}'.format(f)) if num == 0: msg.say('No entities found!') sys.exit(1) if num > 1: msg.say('Contains: {} entities'.format(num)) bbe = [e.bbox for e in entities] bb = bbox.merge(bbe) layers = {e.layer for e in entities} for layer in layers: msg.say('Layer: "{}"'.format(layer)) le = [e for e in entities if e.layer == layer] contours, rement = ent.findcontours(le, lim) for c in contours: c.layer = layer ncon = 'Found {} contours, {} remaining single entities' msg.say(ncon.format(len(contours), len(rement))) le = contours + rement le.sort(key=lambda x: x.bbox.minx) parts.append(le) else: msg.say('Contains: 1 entity') msg.say('Layer: "{}"'.format(entities[0].layer)) bb = entities[0].bbox parts.append(entities) es = 'Extents: {:.1f} ≤ x ≤ {:.1f}, {:.1f} ≤ y ≤ {:.1f}' msg.say(es.format(bb.minx, bb.maxx, bb.miny, bb.maxy)) length = sum(e.length for e in entities) msg.say('Total length of entities: {:.0f} mm'.format(length)) for p in parts: msg.say('Layer: "{}"'.format(p[0].layer)) for e in p: msg.say(e) if isinstance(e, ent.Contour): for c in e.entities: msg.say('..', c)