diff --git a/TODO.md b/TODO.md deleted file mode 100644 index f5aa93b..0000000 --- a/TODO.md +++ /dev/null @@ -1,3 +0,0 @@ -* add command line utilities: gerber svg, gerber transform --rotate --scale --translate, gerber merge --blueprint - -* AM defined apertures \ No newline at end of file diff --git a/doc/source/conf.py b/doc/source/conf.py index ac0fdf7..a118546 100644 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -86,7 +86,7 @@ exclude_patterns = [] # If true, sectionauthor and moduleauthor directives will be shown in the # output. They are ignored by default. -#show_authors = False +show_authors = False # The name of the Pygments (syntax highlighting) style to use. pygments_style = 'sphinx' diff --git a/doc/source/documentation/index.rst b/doc/source/documentation/index.rst index 110df87..3d8241a 100644 --- a/doc/source/documentation/index.rst +++ b/doc/source/documentation/index.rst @@ -4,7 +4,7 @@ Gerber Tools Reference .. toctree:: :maxdepth: 2 - Gerber (RS-274X) Files + Gerber (RS-274X) Files Excellon Files Rendering diff --git a/doc/source/documentation/gerber.rst b/doc/source/documentation/rs274x.rst similarity index 65% rename from doc/source/documentation/gerber.rst rename to doc/source/documentation/rs274x.rst index 78870a9..bc99519 100644 --- a/doc/source/documentation/gerber.rst +++ b/doc/source/documentation/rs274x.rst @@ -1,7 +1,7 @@ -:mod:`gerber` --- RS-274X file handling +:mod:`rs274x` --- RS-274X file handling ============================================== -.. module:: gerber +.. module:: rs274x :synopsis: Functions and classes for handling RS-274X files .. sectionauthor:: Hamilton Kibbe @@ -9,28 +9,29 @@ The RS-274X (Gerber) format is the most common format for exporting PCB artwork. The Specification is published by Ucamco and is available `here `_. -The :mod:`gerber` submodule implements calsses to read and write +The :mod:`rs274x` submodule implements calsses to read and write RS-274X files without having to know the precise details of the format. -The :mod:`gerber` submodule's :func:`read` function serves as a +The :mod:`rs274x` submodule's :func:`read` function serves as a simple interface for parsing gerber files. The :class:`GerberFile` class stores all the information contained in a gerber file allowing the file to be analyzed, modified, and updated. The :class:`GerberParser` class is used in the background for parsing RS-274X files. .. _gerber-contents: + Functions --------- -The :mod:`gerber` module defines the following functions: +The :mod:`rs274x` module defines the following functions: -.. autofunction:: gerber.gerber.read +.. autofunction:: gerber.rs274x.read Classes ------- -The :mod:`gerber` module defines the following classes: +The :mod:`rs274x` module defines the following classes: -.. autoclass:: gerber.gerber.GerberFile +.. autoclass:: gerber.rs274x.GerberFile :members: -.. autoclass:: gerber.gerber.GerberParser +.. autoclass:: gerber.rs274x.GerberParser :members: \ No newline at end of file diff --git a/examples/composite_bottom.png b/examples/composite_bottom.png index 76451a5..4d13bfd 100644 Binary files a/examples/composite_bottom.png and b/examples/composite_bottom.png differ diff --git a/examples/composite_bottom.svg b/examples/composite_bottom.svg new file mode 100644 index 0000000..c2e176d --- /dev/null +++ b/examples/composite_bottom.svg @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/examples/composite_top.png b/examples/composite_top.png index a68bac8..d1dfe15 100644 Binary files a/examples/composite_top.png and b/examples/composite_top.png differ diff --git a/examples/composite_top.svg b/examples/composite_top.svg new file mode 100644 index 0000000..21b01fa --- /dev/null +++ b/examples/composite_top.svg @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/gerber.md b/gerber.md deleted file mode 100644 index 865d177..0000000 --- a/gerber.md +++ /dev/null @@ -1,73 +0,0 @@ - -# Gerber (RS-274X or Extended Gerber) is a bilevel, resolution independent image format. - -# // graphic objects -# // draw: line segment, thickness, round or square line endings. (solid circle and rectangule apertures only) -# // arc: circular arc, thickness, round endings. (solid circle standard aperture only) -# // flash: replication of a given apertura (shape) -# // region: are defined by a countour (linear/arc segments.) -# -# // draw/arc: can have zero length (just flash the aperture) -# // flash: any aperture can be flashed -# -# // operation codes operates on coordinate data blocks. each operation code is for one coordinate data block pair and vice-versa. -# // D01: stroke an aperture from current point to coordinate pair. region mode off. lights-on move. -# // D02: move current point to this coordinate pair -# // D03: flash current aperture at this coordinate pair. -# -# // graphics state -# // all state controlled by codes and parameters, except current point -# // -# // state fixed? initial value -# // coordinate format fixed undefined -# // unit fixed undefined -# // image polarity fixed positive -# // steps/repeat variable 1,1,-,- -# // level polarity variable dark -# // region mode variable off -# // current aperture variable undefined -# // quadrant mode variable undefined -# // interpolation mode variable undefined -# // current point variable (0,0) -# -# // attributes: metadata, both standard and custom. No change on image. -# -# // G01: linear -# // G04: comment -# // M02: end of file -# // D: select aperture -# // G75: multi quadrant mode (circles) -# // G36: region begin -# // G37: region end -# -# // [G01] [Xnnfffff] [Ynnffff] D01* -# -# // ASCII 32-126, CR LF. -# // * end-of-block -# // % parameer delimiter -# // , field separator -# // only in comments -# // case sensitive -# -# // int: +/- 32 bit signed -# // decimal: +/- digits -# // names: [a-zA-Z_$]{[a-zA-Z_$0-9]+} (255) -# // strings: [a-zA-Z0-9_+-/!?<>”’(){}.\|&@# ]+ (65535) -# -# // data block: end in * -# // statement: one or more data block, if contain parameters starts and end in % (parameter statement) -# // statement: [%]{}[%] -# // statements: function code, coordinate data, parameters -# -# // function code: operation codes (D01..) or code that set state. -# // function codes applies before operation codes act on coordinates -# -# // coordinate data: : [X][Y][I][J](D01|D02|D03) -# // offsets are not modal -# -# // parameter: %Parameter code[optional modifiers]*% -# // code: 2 characters -# -# // parameters can have line separators: %{{}}% -# -# // function code: (GDM){1}[number], parameters: [AZ]{2} \ No newline at end of file diff --git a/gerber/__main__.py b/gerber/__main__.py index 1af4c0f..ab0f377 100644 --- a/gerber/__main__.py +++ b/gerber/__main__.py @@ -30,7 +30,6 @@ if __name__ == '__main__': print "parsing %s" % filename gerberfile = read(filename) gerberfile.render(ctx) - ctx.set_color(tuple([color * 0.4 for color in ctx.color])) print('Saving image to test.svg') ctx.dump('test.svg') diff --git a/gerber/common.py b/gerber/common.py index 0092ec8..6e8c862 100644 --- a/gerber/common.py +++ b/gerber/common.py @@ -30,12 +30,12 @@ def read(filename): CncFile object representing the file, either GerberFile or ExcellonFile. Returns None if file is not an Excellon or Gerber file. """ - import gerber + import rs274x import excellon from utils import detect_file_format fmt = detect_file_format(filename) if fmt == 'rs274x': - return gerber.read(filename) + return rs274x.read(filename) elif fmt == 'excellon': return excellon.read(filename) else: diff --git a/gerber/excellon.py b/gerber/excellon.py index f5d6c29..13aacc6 100755 --- a/gerber/excellon.py +++ b/gerber/excellon.py @@ -39,6 +39,7 @@ def read(filename): ------- file : :class:`gerber.excellon.ExcellonFile` An ExcellonFile created from the specified file. + """ detected_settings = detect_excellon_format(filename) settings = FileSettings(**detected_settings) @@ -317,7 +318,7 @@ def detect_excellon_format(filename): hole_area = 0.0 for hit in p.hits: tool = hit[0] - hole_area += math.pow(math.pi * tool.diameter, 2) + hole_area += math.pow(math.pi * tool.diameter / 2., 2) results[key] = (size, p.hole_count, hole_area) except: pass diff --git a/gerber/render/render.py b/gerber/render/render.py index 48a53f8..f7e4485 100644 --- a/gerber/render/render.py +++ b/gerber/render/render.py @@ -83,6 +83,9 @@ class GerberContext(object): background_color : tuple (, , ) Color of the background. Used when exposing areas in 'clear' level polarity mode. Format is the same as for `color`. + + alpha : float + Rendering opacity. Between 0.0 (transparent) and 1.0 (opaque.) """ def __init__(self): self.settings = {} @@ -100,7 +103,8 @@ class GerberContext(object): self.color = (0.7215, 0.451, 0.200) self.drill_color = (0.25, 0.25, 0.25) self.background_color = (0.0, 0.0, 0.0) - + self.alpha = 1.0 + def set_format(self, settings): """ Set source file format. @@ -260,6 +264,19 @@ class GerberContext(object): """ self.background_color = color + def set_alpha(self, alpha): + """ Set layer rendering opacity + + .. note:: + Not all backends/rendering devices support this parameter. + + Parameters + ---------- + alpha : float + Rendering opacity. must be between 0.0 (transparent) and 1.0 (opaque) + """ + self.alpha = alpha + def resolve(self, x, y): """ Resolve missing x or y coordinates in a coordinate command. diff --git a/gerber/render/svgwrite_backend.py b/gerber/render/svgwrite_backend.py index 886b4f8..78961da 100644 --- a/gerber/render/svgwrite_backend.py +++ b/gerber/render/svgwrite_backend.py @@ -117,6 +117,7 @@ class GerberSvgContext(GerberContext): self.apertures = {} self.dwg = svgwrite.Drawing() + self.dwg.transform = 'scale 1 -1' self.background = False self.region_path = None @@ -124,11 +125,17 @@ class GerberSvgContext(GerberContext): xbounds, ybounds = bounds size = (SCALE * (xbounds[1] - xbounds[0]), SCALE * (ybounds[1] - ybounds[0])) if not self.background: + self.dwg = svgwrite.Drawing(viewBox='%f, %f, %f, %f' % (SCALE*xbounds[0], -SCALE*ybounds[1],size[0], size[1])) self.dwg.add(self.dwg.rect(insert=(SCALE * xbounds[0], -SCALE * ybounds[1]), size=size, fill=convert_color(self.background_color))) self.background = True + def set_alpha(self, alpha): + super(GerberSvgContext, self).set_alpha(alpha) + import warnings + warnings.warn('SVG output does not support transparency') + def define_aperture(self, d, shape, modifiers): aperture = None if shape == 'C': diff --git a/gerber/gerber.py b/gerber/rs274x.py similarity index 92% rename from gerber/gerber.py rename to gerber/rs274x.py index 335b443..4076f77 100644 --- a/gerber/gerber.py +++ b/gerber/rs274x.py @@ -37,7 +37,7 @@ def read(filename): Returns ------- - file : :class:`gerber.gerber.GerberFile` + file : :class:`gerber.rs274x.GerberFile` A GerberFile created from the specified file. """ return GerberParser().parse(filename) @@ -91,24 +91,19 @@ class GerberFile(CamFile): ybounds = [0.0, 0.0] for stmt in [stmt for stmt in self.statements if isinstance(stmt, CoordStmt)]: - if stmt.x is not None and stmt.x < xbounds[0]: - xbounds[0] = stmt.x - if stmt.x is not None and stmt.x > xbounds[1]: - xbounds[1] = stmt.x - if stmt.i is not None and stmt.i < xbounds[0]: - xbounds[0] = stmt.i - if stmt.i is not None and stmt.i > xbounds[1]: - xbounds[1] = stmt.i - if stmt.y is not None and stmt.y < ybounds[0]: - ybounds[0] = stmt.y - if stmt.y is not None and stmt.y > ybounds[1]: - ybounds[1] = stmt.y - if stmt.j is not None and stmt.j < ybounds[0]: - ybounds[0] = stmt.j - if stmt.j is not None and stmt.j > ybounds[1]: - ybounds[1] = stmt.j + if stmt.x is not None: + if stmt.x < xbounds[0]: + xbounds[0] = stmt.x + elif stmt.x > xbounds[1]: + xbounds[1] = stmt.x + if stmt.y is not None: + if stmt.y < ybounds[0]: + ybounds[0] = stmt.y + elif stmt.y > ybounds[1]: + ybounds[1] = stmt.y return (xbounds, ybounds) + def write(self, filename): """ Write data out to a gerber file """