From 29deffcf77e963ae81aec9f8cbc61b029f3052d5 Mon Sep 17 00:00:00 2001 From: Hamilton Kibbe Date: Fri, 5 Dec 2014 23:59:28 -0500 Subject: add ipc2581 primitives --- doc/source/about.rst | 38 ++++++++++++++++++ doc/source/index.rst | 2 +- doc/source/intro.rst | 19 --------- gerber/gerber_statements.py | 16 +++++++- gerber/primitives.py | 94 +++++++++++++++++++++++++++++++++++++-------- gerber/rs274x.py | 4 +- 6 files changed, 133 insertions(+), 40 deletions(-) create mode 100644 doc/source/about.rst delete mode 100644 doc/source/intro.rst diff --git a/doc/source/about.rst b/doc/source/about.rst new file mode 100644 index 0000000..1bb354c --- /dev/null +++ b/doc/source/about.rst @@ -0,0 +1,38 @@ +About PCB Tools +=============== + +PCB CAM Files +~~~~~~~~~~~~~ + +PCB design (artwork) files are most often stored in `Gerber` files. This is +a generic term that may refer to `RS-274X (Gerber) `_, +`ODB++ `_ , or `Excellon `_ +files. These file formats are used by the CNC equipment used to manufacutre PCBs. + +PCB Tools provides a set of utilities for visualizing and working with PCB design files +in a variety of formats. PCB Tools currently supports the following file formats: + +- Gerber (RS-274X) +- Excellon + +with planned support for IPC-2581, IPC-D-356 Netlists, ODB++ and more. + +Visualization +~~~~~~~~~~~~~~ +.. image:: ../../examples/composite_top.png + :alt: Rendering Example + +The PCB Tools module provides tools to visualize PCBs and export images in a variety of formats, +including SVG and PNG. + + +Future Plans +~~~~~~~~~~~~ +We are working on adding the following features to PCB Tools: + +- Design Rules Checking +- Editing +- Panelization + + + diff --git a/doc/source/index.rst b/doc/source/index.rst index 309cf88..ab29738 100644 --- a/doc/source/index.rst +++ b/doc/source/index.rst @@ -11,7 +11,7 @@ Contents: .. toctree:: :maxdepth: 1 - intro + about documentation/index Indices and tables diff --git a/doc/source/intro.rst b/doc/source/intro.rst deleted file mode 100644 index 4db80ad..0000000 --- a/doc/source/intro.rst +++ /dev/null @@ -1,19 +0,0 @@ -PCB Tools Intro -================== - -PCB CAM (Gerber) Files ------------- - -PCB design files (artwork) are most often stored in `Gerber` files. This is -a generic term that may refer to `RS-274X (Gerber) `_, -`ODB++ `_, or `Excellon `_ -files. - - -PCB-Tools ------------- - -The gerber-tools module provides tools for working with and rendering Gerber -and Excellon files. - - diff --git a/gerber/gerber_statements.py b/gerber/gerber_statements.py index 4aaa1d0..05c84b8 100644 --- a/gerber/gerber_statements.py +++ b/gerber/gerber_statements.py @@ -1,5 +1,19 @@ -#! /usr/bin/env python +#!/usr/bin/env python # -*- coding: utf-8 -*- + +# copyright 2014 Hamilton Kibbe +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. """ Gerber (RS-274X) Statements =========================== diff --git a/gerber/primitives.py b/gerber/primitives.py index f934f74..e13e37f 100644 --- a/gerber/primitives.py +++ b/gerber/primitives.py @@ -19,10 +19,11 @@ from operator import sub class Primitive(object): - - def __init__(self, level_polarity='dark'): + + def __init__(self, level_polarity='dark', rotation=0): self.level_polarity = level_polarity - + self.rotation = rotation + def bounding_box(self): """ Calculate bounding box @@ -36,8 +37,8 @@ class Primitive(object): class Line(Primitive): """ """ - def __init__(self, start, end, width, level_polarity='dark'): - super(Line, self).__init__(level_polarity) + def __init__(self, start, end, width, **kwargs): + super(Line, self).__init__(**kwargs) self.start = start self.end = end self.width = width @@ -61,8 +62,8 @@ class Line(Primitive): class Arc(Primitive): """ """ - def __init__(self, start, end, center, direction, width, level_polarity='dark'): - super(Arc, self).__init__(level_polarity) + def __init__(self, start, end, center, direction, width, **kwargs): + super(Arc, self).__init__(**kwargs) self.start = start self.end = end self.center = center @@ -139,8 +140,8 @@ class Arc(Primitive): class Circle(Primitive): """ """ - def __init__(self, position, diameter, level_polarity='dark'): - super(Circle, self).__init__(level_polarity) + def __init__(self, position, diameter, **kwargs): + super(Circle, self).__init__(**kwargs) self.position = position self.diameter = diameter @@ -161,11 +162,29 @@ class Circle(Primitive): return self.diameter +class Ellipse(Primitive): + """ + """ + def __init__(self, position, width, height, **kwargs): + super(Ellipse, self).__init__(**kwargs) + self.position = position + self.width = width + self.height = height + + @property + def bounding_box(self): + min_x = self.position[0] - (self.width / 2.0) + max_x = self.position[0] + (self.width / 2.0) + min_y = self.position[1] - (self.height / 2.0) + max_y = self.position[1] + (self.height / 2.0) + return ((min_x, max_x), (min_y, max_y)) + + class Rectangle(Primitive): """ """ - def __init__(self, position, width, height, level_polarity='dark'): - super(Rectangle, self).__init__(level_polarity) + def __init__(self, position, width, height, **kwargs): + super(Rectangle, self).__init__(**kwargs) self.position = position self.width = width self.height = height @@ -193,11 +212,23 @@ class Rectangle(Primitive): return max((self.width, self.height)) +class Diamond(Primitive): + pass + + +class ChamferRectangle(Primitive): + pass + + +class RoundRectangle(Primitive): + pass + + class Obround(Primitive): """ """ - def __init__(self, position, width, height, level_polarity='dark'): - super(Obround, self).__init__(level_polarity) + def __init__(self, position, width, height, **kwargs): + super(Obround, self).__init__(**kwargs) self.position = position self.width = width self.height = height @@ -242,11 +273,12 @@ class Obround(Primitive): self.height) return {'circle1': circle1, 'circle2': circle2, 'rectangle': rect} + class Polygon(Primitive): """ """ - def __init__(self, position, sides, radius, level_polarity='dark'): - super(Polygon, self).__init__(level_polarity) + def __init__(self, position, sides, radius, **kwargs): + super(Polygon, self).__init__(**kwargs) self.position = position self.sides = sides self.radius = radius @@ -263,8 +295,8 @@ class Polygon(Primitive): class Region(Primitive): """ """ - def __init__(self, points, level_polarity='dark'): - super(Region, self).__init__(level_polarity) + def __init__(self, points, **kwargs): + super(Region, self).__init__(**kwargs) self.points = points @property @@ -277,6 +309,34 @@ class Region(Primitive): return ((min_x, max_x), (min_y, max_y)) +class RoundButterfly(Primitive): + """ + """ + def __init__(self, position, diameter, **kwargs): + super(RoundButterfly, self).__init__(**kwargs) + self.position = position + self.diameter = diameter + + @property + def radius(self): + return self.diameter / 2. + + @property + def bounding_box(self): + min_x = self.position[0] - self.radius + max_x = self.position[0] + self.radius + min_y = self.position[1] - self.radius + max_y = self.position[1] + self.radius + return ((min_x, max_x), (min_y, max_y)) + +class SquareButterfly(Primitive): + pass + + +class Donut(Primitive): + pass + + class Drill(Primitive): """ """ diff --git a/gerber/rs274x.py b/gerber/rs274x.py index a41760e..6dbcc63 100644 --- a/gerber/rs274x.py +++ b/gerber/rs274x.py @@ -403,10 +403,10 @@ class GerberParser(object): end = (x, y) width = self.apertures[self.aperture].stroke_width if self.interpolation == 'linear': - self.primitives.append(Line(start, end, width, self.level_polarity)) + self.primitives.append(Line(start, end, width, level_polarity=self.level_polarity)) else: center = (start[0] + stmt.i, start[1] + stmt.j) - self.primitives.append(Arc(start, end, center, self.direction, width, self.level_polarity)) + self.primitives.append(Arc(start, end, center, self.direction, width, level_polarity=self.level_polarity)) elif stmt.op == "D02": pass -- cgit