add IP command handling function
This commit is contained in:
parent
4c4ba0762b
commit
00351ebe27
3 changed files with 83 additions and 3 deletions
59
README.md
59
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.
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
4
setup.py
4
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',
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue