add IP command handling function

This commit is contained in:
Hiroshi Murayama 2019-09-12 23:44:50 +09:00
parent 4c4ba0762b
commit 00351ebe27
3 changed files with 83 additions and 3 deletions

View file

@ -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.

View file

@ -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

View file

@ -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',