aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHiroshi Murayama <opiopan@gmail.com>2019-09-12 23:44:50 +0900
committerHiroshi Murayama <opiopan@gmail.com>2019-09-12 23:44:50 +0900
commit00351ebe277aeb90e7463d1b0bd55402249c4687 (patch)
treea4c7f3e0e015a88af6770cfe9daa12cd21952b4d
parent4c4ba0762b30fdd4633a6d2868c508184d681b7d (diff)
downloadpcb-tools-extension-00351ebe277aeb90e7463d1b0bd55402249c4687.tar.gz
pcb-tools-extension-00351ebe277aeb90e7463d1b0bd55402249c4687.tar.bz2
pcb-tools-extension-00351ebe277aeb90e7463d1b0bd55402249c4687.zip
add IP command handling function
-rw-r--r--README.md59
-rw-r--r--gerberex/rs274x.py23
-rw-r--r--setup.py4
3 files changed, 83 insertions, 3 deletions
diff --git a/README.md b/README.md
index 271573d..6c879f2 100644
--- a/README.md
+++ b/README.md
@@ -151,3 +151,62 @@ This example board image is generated by following scripts from [these source da
<p align="center">
<img alt="description" src="https://raw.githubusercontent.com/wiki/opiopan/pcb-tools-extension/images/panelized.jpg" width=750>
</p>
+
+## Notes
+
+### Equivalence of output
+pcb-tools-extension generate data block stream to focus equivalence of final image, but not focus equivalence of data block sequence.
+There are some difference between input data and output data as below.
+
+- **File Scope Modifier [RS-274x]**<br>
+ Sometimes, commands that affect entire image and should be specified only once in a file, such as ```MI``` (Mirror Image) command, cause contradiction when multiple gerber file are merged.<br>
+ For example, when mergeing a file containing ```%MIA1B0*%``` command and a file containing ```%MIA0B1*``` command, which command should remain as output?
+ Of cause, it is impossible that generate correct merged image by specifiing any ```MI``` command.<br>
+ pcb-tools-extension translate coordinate data reflecting these file socpe modifier to address this probrem, then ommit these modifier command.<br>
+ ```MI```, ```OF```, ```SF```, ```AS```, ```IP```, and ```IR``` are in a this category.
+
+- **Coodinate Normalizing [RS-274x, Excellon]**<br>
+ RS-274x specification and Excellon specification allow various notation to express a coordinate. However pcb-tools-extension normalize coordinate notation in order to correct deprecated notation and ease internal process as below.
+
+ - Relative coordinates are translated to absolute coordinates.
+ - Ommited coordinate values are compensated.
+ - Leading zeros are ommited.
+
+- **Unimportant Command [RS-274x, Excellon]**<br>
+ Commands not affecting final image such as comment are ommited.
+
+### Negative image polarity
+Sometimes, ```%IPNEG*%``` is specified at header of RS-274x file to create negative image. <br>
+As mentioned [above](#Equivalence%20of%20output), ```IP``` command is ommited when pcb-tools-extension generate output file. In this case, image polarity is nagated by using ```LP``` command. However this generated file doesn't equal to original file since it does'nt contain base dark image.<br>
+Please merge base dark rectangle explicitly when you handle negative image file as below.
+
+```python
+import gerberex
+
+ctx = gerberex.GerberComposition()
+base = gerberex.rectangle(width=30, height=30, left=-5, bottom=-5, units='metric')
+base.draw_mode = base.DM_FILL
+ctx.merge(base)
+metal = gerberex.read('negative_image.gtl')
+ctx.merge(metal)
+```
+
+## Limitations
+
+### RS-274x
+pcb-tools-extension cannot handle all commands that the RS-274x parser implemented in
+[pcb-tool](https://github.com/curtacircuitos/pcb-tools) doesn't handle so far.<br>
+From the imaging point of view, pcb-tools-extension has following limitations.
+
+- Files contains ```IJ``` and ```IO``` commands, that affect entire image, cannot be handled correctly.
+- Files contains ```SR``` command to specify repeated pattern cannot be handled correctly.
+- Aperture block defined by ```AB``` command cannot be handled correctly.
+
+### Excellon
+pcb-tools-extension extends excellon parser in [pcb-tool](https://github.com/curtacircuitos/pcb-tools) to support routing operation. However following limitations still remain.
+
+- User defined stored pattern defined by ```M99``` command cannot be handled.
+- Canned text specified by ```M97``` command cannot be handled.
+- Patten defined by ```M25``` command cannot be handled.
+
+
diff --git a/gerberex/rs274x.py b/gerberex/rs274x.py
index 42ae17d..3a3a712 100644
--- a/gerberex/rs274x.py
+++ b/gerberex/rs274x.py
@@ -53,6 +53,8 @@ class GerberFile(gerber.rs274x.GerberFile):
self.main_statements.extend(stmts)
if self.context.angle != 0:
self.rotate(self.context.angle)
+ if self.context.is_negative:
+ self.nagate_polarity()
self.context.notation = 'absolute'
self.context.zeros = 'trailing'
@@ -128,6 +130,11 @@ class GerberFile(gerber.rs274x.GerberFile):
statement.x = last_rx
statement.y = last_ry
+ def nagate_polarity(self):
+ for statement in self.main_statements:
+ if isinstance(statement, LPParamStmt):
+ statement.lp = 'dark' if statement.lp == 'clear' else 'clear'
+
def _generalize_aperture(self):
RECTANGLE = 0
LANDSCAPE_OBROUND = 1
@@ -208,6 +215,9 @@ class GerberContext(FileSettings):
1, 0,
1, 1)
+ self.is_negative = False
+ self.is_first_coordinate = True
+ self.no_polarity = True
self.in_single_quadrant_mode = False
self.op = None
self.interpolation = self.IP_LINEAR
@@ -216,6 +226,7 @@ class GerberContext(FileSettings):
self.y = 0.
def normalize_statement(self, stmt):
+ additional_stmts = None
if isinstance(stmt, INParamStmt):
self.name = stmt.name
elif isinstance(stmt, MIParamStmt):
@@ -241,14 +252,24 @@ class GerberContext(FileSettings):
elif isinstance(stmt, QuadrantModeStmt):
self.in_single_quadrant_mode = stmt.mode == 'single-quadrant'
stmt.mode = 'multi-quadrant'
+ elif isinstance(stmt, IPParamStmt):
+ self.is_negative = stmt.ip == 'negative'
+ elif isinstance(stmt, LPParamStmt):
+ self.no_polarity = False
elif isinstance(stmt, CoordStmt):
self._normalize_coordinate(stmt)
+ if self.is_first_coordinate:
+ self.is_first_coordinate = False
+ if self.no_polarity:
+ additional_stmts = [LPParamStmt('LP', 'dark'), stmt]
if type(stmt).__name__ in self.ignored_stmt:
return (self.TYPE_NONE, None)
+ elif additional_stmts is not None:
+ return (self.TYPE_MAIN, additional_stmts)
else:
return (self.TYPE_MAIN, [stmt])
-
+
def _update_matrix(self):
if self.axis == 'xy':
mx = -1 if self.mirror[0] else 1
diff --git a/setup.py b/setup.py
index 21341b4..9d2ef54 100644
--- a/setup.py
+++ b/setup.py
@@ -10,7 +10,7 @@ def read(fname):
METADATA = {
'name': 'pcb-tools-extension',
- 'version': "0.1.6",
+ 'version': "0.9.0",
'author': 'Hiroshi Murayama <opiopan@gmail.com>',
'author_email': "opiopan@gmail.com",
'description': ("Extension for pcb-tools package to panelize gerber files"),
@@ -21,7 +21,7 @@ METADATA = {
'long_description': read('README.md'),
'long_description_content_type': 'text/markdown',
'classifiers': [
- "Development Status :: 3 - Alpha",
+ "Development Status :: 4 - Beta",
"Topic :: Utilities",
"License :: OSI Approved :: Apache Software License",
'Programming Language :: Python :: 3',