diff options
author | Hiroshi Murayama <opiopan@gmail.com> | 2019-09-12 23:44:50 +0900 |
---|---|---|
committer | Hiroshi Murayama <opiopan@gmail.com> | 2019-09-12 23:44:50 +0900 |
commit | 00351ebe277aeb90e7463d1b0bd55402249c4687 (patch) | |
tree | a4c7f3e0e015a88af6770cfe9daa12cd21952b4d | |
parent | 4c4ba0762b30fdd4633a6d2868c508184d681b7d (diff) | |
download | pcb-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.md | 59 | ||||
-rw-r--r-- | gerberex/rs274x.py | 23 | ||||
-rw-r--r-- | setup.py | 4 |
3 files changed, 83 insertions, 3 deletions
@@ -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 @@ -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', |