summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjaseg <git@jaseg.net>2019-09-26 19:45:54 +0200
committerjaseg <git@jaseg.net>2019-09-26 19:45:54 +0200
commitb2eb56076d47af08a11e10fa53446a00b849a13c (patch)
tree4537c06e2e9bc5b78a731231e6c049c8cd5f376c
parent82b88f920a85487372cc6e0b46633e4aa328eb69 (diff)
downloadpogojig-b2eb56076d47af08a11e10fa53446a00b849a13c.tar.gz
pogojig-b2eb56076d47af08a11e10fa53446a00b849a13c.tar.bz2
pogojig-b2eb56076d47af08a11e10fa53446a00b849a13c.zip
Pogojig mostly done: KiCAD export works
-rw-r--r--Makefile41
-rw-r--r--readme.md219
-rw-r--r--src/jig.scad2
-rw-r--r--support/asymptote/__main__.py63
-rwxr-xr-xsupport/generate_kicad.py322
-rwxr-xr-x[-rw-r--r--]support/inkscape_exporter.py (renamed from support/inkscape/__main__.py)53
-rw-r--r--support/lib/make.py5
-rw-r--r--support/lib/util.py130
-rw-r--r--support/openscad/__init__.py0
-rw-r--r--support/openscad/__main__.py46
-rw-r--r--support/pogojig/__init__.py (renamed from support/asymptote/__init__.py)0
-rw-r--r--support/pogojig/inkscape/__init__.py (renamed from support/inkscape/__init__.py)0
-rw-r--r--[-rwxr-xr-x]support/pogojig/inkscape/bezmisc.py (renamed from support/inkscape/bezmisc.py)38
-rw-r--r--[-rwxr-xr-x]support/pogojig/inkscape/cspsubdiv.py (renamed from support/inkscape/cspsubdiv.py)7
-rw-r--r--[-rwxr-xr-x]support/pogojig/inkscape/cubicsuperpath.py (renamed from support/inkscape/cubicsuperpath.py)2
-rw-r--r--support/pogojig/inkscape/dxf_footer.txt (renamed from support/inkscape/dxf_footer.txt)0
-rw-r--r--support/pogojig/inkscape/dxf_header.txt (renamed from support/inkscape/dxf_header.txt)0
-rw-r--r--support/pogojig/inkscape/effect.py (renamed from support/inkscape/effect.py)17
-rw-r--r--[-rwxr-xr-x]support/pogojig/inkscape/ffgeom.py (renamed from support/inkscape/ffgeom.py)18
-rw-r--r--[-rwxr-xr-x]support/pogojig/inkscape/inkex.py (renamed from support/inkscape/inkex.py)13
-rw-r--r--support/pogojig/inkscape/inkscape.py (renamed from support/inkscape/inkscape.py)50
-rw-r--r--[-rwxr-xr-x]support/pogojig/inkscape/simplepath.py (renamed from support/inkscape/simplepath.py)15
-rw-r--r--[-rwxr-xr-x]support/pogojig/inkscape/simpletransform.py (renamed from support/inkscape/simpletransform.py)7
-rw-r--r--support/pogojig/kicad/__init__.py (renamed from support/lib/__init__.py)0
-rw-r--r--support/pogojig/kicad/kicad-cache.lib21
-rw-r--r--support/pogojig/kicad/kicad.pro34
26 files changed, 497 insertions, 606 deletions
diff --git a/Makefile b/Makefile
index 26672df..4b66b0d 100644
--- a/Makefile
+++ b/Makefile
@@ -1,40 +1,27 @@
-# Installation-dependent settings. You can overwrite these in a file called config.mk in the same directory as this makefile. See readme.creole.
-INKSCAPE := inkscape
-OPENSCAD := openscad
-PYTHON := python2
-ASYMPTOTE := asy
+# Environment variables:
+# INKSCAPE_DXF_FLATNESS controls inkscape SVG->DXF export curve flatness (default: 0.1)
+# INKSCAPE, OPENSCAD: Commands to use for inkscape and openscad
-# Settings affecting the compiled results. You can overwrite these in a file called settings.mk in the same directory as this makefile. See readme.creole.
-DXF_FLATNESS := 0.1
-
-# Non-file goals.
-.PHONY: all clean generated dxf stl asy pdf
-
-# Include the configuration files.
--include config.mk settings.mk
-
-# Command to run the Python scripts.
-PYTHON_CMD := PYTHONPATH="support" $(PYTHON)
-INKSCAPE_CMD := INKSCAPE=$(INKSCAPE) DXF_FLATNESS=$(DXF_FLATNESS) $(PYTHON_CMD) -m inkscape
-OPENSCAD_CMD := OPENSCAD=$(OPENSCAD) $(PYTHON_CMD) -m openscad
+OPENSCAD ?= openscad
all: src/jig.stl src/pcb_shape.dxf
-clean:
- rm -f src/input.preprocessed.dxf
- rm -f src/input.preprocessed.svg
- rm -f src/jig.stl
- rm -f src/pcb_shape.dxf
-
src/input.preprocessed.dxf: src/input.preprocessed.svg
- $(INKSCAPE_CMD) $< $@
+ support/inkscape_exporter.py $< $@
src/pcb_shape.dxf: src/pcb_shape.scad src/input.preprocessed.dxf
- $(OPENSCAD_CMD) $< $@
+ $(OPENSCAD) -o $@ $<
src/jig.stl: src/jig.scad src/input.preprocessed.dxf
- $(OPENSCAD_CMD) $< $@
+ $(OPENSCAD) -o $@ $<
src/input.preprocessed.svg: input.svg
support/inkscape_svg_filter_layers.py $< $@ --only --name "Test Points" "Mounting Holes" "Grip Slots" "Outline"
+.PHONY: clean
+clean:
+ rm -f src/input.preprocessed.dxf
+ rm -f src/input.preprocessed.svg
+ rm -f src/jig.stl
+ rm -f src/pcb_shape.dxf
+
diff --git a/readme.md b/readme.md
deleted file mode 100644
index fe37316..0000000
--- a/readme.md
+++ /dev/null
@@ -1,219 +0,0 @@
-# OpenSCAD Template
-
-## Repository structure
-
-This repository, as it is maintained on
-[GitHub](http://github.com/Feuermurmel/openscad-template), contains two
-important branches, `master` and `examples`. `master` contains an empty project
-which is ready to be cloned and used for new project.
-
-Branch `examples` additionally contains a few example source files which are
-ready to be compiled. The root directory on that branch also contains a second
-text document `examples.creole`, describing the example project in more detail.
-
-
-## Prerequisites
-
-- OpenSCAD snapshot > 2014.11.05
- - Used to compile OpenSCAD source files to STL.
- - A recent development snapshot is recommended, e.g. version 2014.11.05 or
- later.
- - The current release version (2014.03) generates invalid dependency
- information if the path to the project contains spaces or other
- characters that need to be treated specially in a makefile and also
- has trouble with 2D shapes containing holes. The current development
- version solves these problems.
-
-- Inkscape > 0.91
- - Used to export DXF files to SVG.
- - Recommended to edit SVG files, especially if importing of separate layers
- in OpenSCAD is needed.
- - At least version 0.91 (or maybe some earlier development snapshot) is
- necessary because the command line verbs used to transform and massage an
- SVG prior to export have only recently been added.
-
-- Python 2.7
- - Used for to run the plugin that exports DXF to SVG and to run scripts
- that wrap the OpenSCAD command line tool and work around problems with
- generation of dependency information in OpenSCAD.
- - Should already be installed as a dependency to Inkscape. The most recent
- version of Python 2.7 is recommended.
-
-- Asymptote [0]
- - Used to compile Asymptote files to PDF.
- - Recommended when creating Vector cutting projects for Epilog laser
- cutters.
-
-[0]: This project was tested with Asymptote Version 2.35. Earlier Versions will
- probably also work.
-
-
-### Explicitly specifying paths to binaries
-
-If any of the required binaries is not available on `$PATH` or a different
-version should be used, the paths to these binaries can be configured by
-creating a file called `config.mk` in the same directory as the makefile.
-There, variables can be set to the absolute or relative paths to these
-binaries. For example:
-
- # Path to the OpenSCAD binary
- OPENSCAD := /Applications/OpenSCAD.app/Contents/MacOS/OpenSCAD
-
- # Path to the Inkscape binary
- INKSCAPE := /opt/local/bin/inkscape
-
- # Path to the Python 2.7 binary
- PYTHON := /opt/local/bin/python2.7
-
- # Path to the Asymptote binary
- ASYMPTOTE := /opt/local/bin/asy
-
-
-## Supported file types
-
-### Using SVG files from OpenSCAD
-
-Any file whose name ends in `.svg` may be used from an OpenSCAD file like this:
-
- import("file.dxf");
-
-The makefile will automatically convert the SVG file to a DXF file when
-building the project. If Inkscape is used to edit the SVG file, multiple layers
-can be created which can then be imported individually:
-
- import("file.dxf", "background");
-
-The DXF export supports all shapes supported by Inkscape (e.g. rectangles,
-circles, paths, spiro lines, text, …). Before the objects are exported, all
-objects are converted to paths and combined using the union operation. For
-objects which have a stroke style, the stroke instead of the filled area is
-converted to a path. Then, the resulting path is converted to a set of line
-segments which closely follow the curved parts of the path. The resulting line
-segments are exported to DXF and combined to the original shapes when imported
-in OpenSCAD. For these transformations to work, the objects need to be placed
-in Inkscape layers.
-
-OpenSCAD itself does not define which unit is used to measure lengths [1].
-Inkscape OTOH allows the user to define a document wide unit as well as using
-different units when specifying the size and position of shapes. When exporting
-the SVG document using Inkscape, all numbers are converted to the unit
-specified under _General_ in Inkscape's _Document Properties_ dialog. These
-numbers are the written to the DXF document and used OpenSCAD directly.
-
-DXF and OpenSCAD both use a right-handed coordinate system (the Y axis runs up
-while the X-axis runs to the right). While SVG uses a left-handed coordinate
-system (the Y axis runs down instead). But Inkscape, surprisingly, also uses a
-right-handed coordinate system. The DXF export script honors this and places
-the origin of the document in the lower left corner when exporting the
-document.
-
-[1]: Although millimeters seems to be the predominant unit.
-
-
-### Using SVG files from Asymptote
-
-SVG files may instead be used from Asymptote files. For each SVG file, an
-Asymptote file of the same name is generated. These files can be imported as
-modules from other Asymptote files. These modules will contain a member of
-type `path[]` for each layer in the original SVG file:
-
- import test;
-
- draw(test.Layer_1, red + 0.001mm);
-
-The module also contains a member `all`, which just contains all paths in one
-array.
-
-
-### OpenSCAD files
-
-Files whose names end in `.scad` are compiled to STL files using OpenSCAD.
-OpenSCAD files whose name start with `_` are treated as "library" files which
-will not be compiled to STL files. These files can still be used from other
-OpenSCAD files using one of the following commands:
-
- include <filename>
- use <filename>
-
-Please see the
-[OpenSCAD User Manual](http://en.wikibooks.org/wiki/OpenSCAD_User_Manual/Print_version)
-for details this and other OpenSCAD functionality.
-
-
-## Generating Source files
-
-This template includes support for automatically generated source files. This
-works by editing the `generate_sources.sh` script.
-
-The script defines a function `generate_file()`, which should be called in the
-remainder of the script once for each file to generate. The first argument to
-the function is be the name of the file. The remaining arguments are treated as
-a command, which, when run, should output the file's content to standard
-output. For example:
-
- generate_file "src/cube.scad" echo "cube(25);"
-
-How the function `generate_file()` is called is up to the script and may e.g.
-be done from a `for` loop or while iterating over a set of other source files.
-
-
-## Compiling
-
-To compile the whole project, run `make` from the directory in which this
-readme is. This will generate all sources files, if any, process all SVG files
-and produce an STL file for each OpenSCAD source file whose name does not start
-with `_`. Individual files may be created or updated by passing their names to
-the make command, as usual.
-
-
-### Makefile targets
-
-These are the special makefile targets which can be used in addition to the
-names of individual files to update:
-
-- `all`: Builds all files that can be built from any source files. This is the
-default target when running `make` without arguments.
-- `clean`: Removes all built files [2].
-- `generated`: Generates all files generated by `generate_sources.sh`.
-- `dxf`: Exports all SVG files to DXF files.
-- `stl`: Compiles all OpenSCAD files to STL files.
-- `asy`: Exports all configured SVG files to Asymptote files.
-- `pdf`: Compiles all Asymptote files to PDF files.
-
-[2]: This will not remove files for which the source file was removed. There is
-no simple way to detect whether a file was previously built from a source file
-or if it placed in the `src` directory manually.
-
-
-### Settings used for compilation
-
-The quality of the DXF export can be specified by creating a file called
-`settings.mk` in the same directory as the makefile. Setting `DXF_FLATNESS` to
-a smaller value (which defaults to `0.1`) creates a shape that more closely
-follows curved parts of the exported shapes. For example:
-
- # Specify how far the exported approximation may deviate from the actual
- # shape. The default is 0.1.
- DXF_FLATNESS := 0.02
-
- # Specify which SVG files should be exported to Asymptote files instead of
- # DXF files. By default, this list is empty.
- ASYMPTOTE_EXPORTED_SVG_FILES := src/example.svg
-
-
-### Dependency tracking
-
-OpenSCAD has the ability to write dependency files which record all files used
-while producing an STL file. These dependency files can be read by `make`. This
-ability is used to only recompile necessary files when running make.
-
-This same mechanism is currently not used for converting SVG files referring to
-other files or for the script used to generate source files. Therefore, if
-other file used in the process are changed, the corresponding source files
-tracked by the makefile (the main SVG files or the files `generate_sources.sh`
-in case of generated sources) needs to be manually marked as changes by calling
- `touch` on the file before calling `make`.
-
-For Asymptote files, a safer approach is currently taken. If any of the
-Asymptote source files in the `src` directory are changed, all Asymptote source
-files are recompiled.
diff --git a/src/jig.scad b/src/jig.scad
index 67580bf..d953f29 100644
--- a/src/jig.scad
+++ b/src/jig.scad
@@ -1,4 +1,4 @@
include <_settings.scad>
include <_lib.scad>
-jig(height, depth, wall, tolerance, chamfer);
+jig(height, depth, wall, tolerance, chamfer); \ No newline at end of file
diff --git a/support/asymptote/__main__.py b/support/asymptote/__main__.py
deleted file mode 100644
index 77bbdc7..0000000
--- a/support/asymptote/__main__.py
+++ /dev/null
@@ -1,63 +0,0 @@
-import sys, os, shutil
-from lib import util, make
-
-
-def _asymptote(in_path, out_path, asymptote_dir, working_dir):
- args = [os.environ['ASYMPTOTE'], '-vv', '-f', 'pdf', '-o', out_path, in_path]
-
- with util.command_context(args, set_env={'ASYMPTOTE_DIR': asymptote_dir}, working_dir=working_dir, use_stderr=True) as process:
- def get_loaded_file(line):
- if any(line.startswith(j) for j in ['Loading ', 'Including ']):
- parts = line.rstrip('\n').split(' ')
-
- if len(parts) == 4:
- _, _, from_, path = parts
-
- if from_ == 'from':
- return path
-
- return None
-
- def iter_loaded_files():
- for i in process.stderr:
- loaded_file = get_loaded_file(i)
-
- if loaded_file is not None:
- yield loaded_file
- elif not any(i.startswith(j) for j in ['cd ', 'Using configuration ']):
- print >> sys.stderr, i,
-
- loaded_files = list(iter_loaded_files())
-
- return loaded_files
-
-
-@util.main
-def main(in_path, out_path):
- try:
- _, out_suffix = os.path.splitext(out_path)
-
- with util.TemporaryDirectory() as temp_dir:
- absolute_in_path = os.path.abspath(in_path)
- temp_out_path = os.path.join(temp_dir, 'out.pdf')
-
- # Asymptote creates A LOT of temp files (presumably when invoking
- # LaTeX) and leaves some of them behind. Thus we run asymptote
- # in a temporary directory.
- loaded_files = _asymptote(
- absolute_in_path,
- 'out',
- os.path.dirname(absolute_in_path),
- temp_dir)
-
- if not os.path.exists(temp_out_path):
- raise util.UserError('Asymptote did not generate a PDF file.', in_path)
-
- # All dependencies as paths relative to the project root.
- dependencies = set(map(os.path.relpath, loaded_files))
-
- # Write output files.
- make.write_dependencies(out_path + '.d', out_path, dependencies - {in_path})
- shutil.copyfile(temp_out_path, out_path)
- except util.UserError as e:
- raise util.UserError('While processing {}: {}', in_path, e)
diff --git a/support/generate_kicad.py b/support/generate_kicad.py
new file mode 100755
index 0000000..77f58fa
--- /dev/null
+++ b/support/generate_kicad.py
@@ -0,0 +1,322 @@
+#!/usr/bin/env python3
+
+import os
+import sys
+import time
+from os import path
+from textwrap import dedent
+import pkgutil
+import subprocess
+import xml.etree.ElementTree as xe
+
+import ezdxf
+
+
+__version__ = '0.1'
+
+PIN_TS_BASE = 0x23420000
+TEDIT_BASE = 0x23430000
+PATH_BASE = 0x23440000
+
+
+def sch_template(name, num_pins, yspace=200):
+ templ = f'''
+ EESchema Schematic File Version 5
+ EELAYER 30 0
+ EELAYER END
+ $Descr A3 16535 11693
+ encoding utf-8
+ Sheet 1 1
+ Title "{name}"
+ Date "{time.strftime("%d %b %Y")}"
+ Rev ""
+ Comp ""
+ Comment1 ""
+ Comment2 ""
+ Comment3 ""
+ Comment4 ""
+ Comment5 ""
+ Comment6 ""
+ Comment7 ""
+ Comment8 ""
+ Comment9 ""
+ $EndDescr
+ {{components}}
+ $EndSCHEMATC
+ '''
+
+ components = []
+ for i in range(num_pins):
+ identifier = f'TP{i}'
+ value = 'pogopin'
+ x, y = 1000, 1000 + i*yspace
+ components.append(dedent(f'''
+ $Comp
+ L Connector:Conn_01x01_Female {identifier}
+ U 1 1 {PIN_TS_BASE + i:08X}
+ P {x} {y}
+ F 0 "{identifier}" H {x-50} {y+50} 50 0000 R CNN
+ F 1 "{value}" H {x+50} {y} 50 0000 L CNN
+ F 2 "Pogopin:AutogeneratedPogopinFootprint" H {x} {y} 50 0001 C CNN
+ F 3 "~" H {x} {y} 50 0001 C CNN
+ 1 {x} {y}
+ -1 0 0 1
+ $EndComp
+ ''').strip())
+
+ return dedent(templ).lstrip().format(components='\n'.join(components))
+
+def pcb_template(outline, pins, annular=0.5):
+ pcb_templ = f'''
+ (kicad_pcb (version 20190605) (host pogojig "({__version__})")
+
+ (general
+ (thickness 1.6)
+ (drawings {len(pins)})
+ (tracks 0)
+ (modules {len(pins)})
+ (nets {len(pins)+1})
+ )
+
+ (page "A4")
+ (layers
+ (0 "F.Cu" signal)
+ (31 "B.Cu" signal)
+ (32 "B.Adhes" user)
+ (33 "F.Adhes" user)
+ (34 "B.Paste" user)
+ (35 "F.Paste" user)
+ (36 "B.SilkS" user)
+ (37 "F.SilkS" user)
+ (38 "B.Mask" user)
+ (39 "F.Mask" user)
+ (40 "Dwgs.User" user)
+ (41 "Cmts.User" user)
+ (42 "Eco1.User" user)
+ (43 "Eco2.User" user)
+ (44 "Edge.Cuts" user)
+ (45 "Margin" user)
+ (46 "B.CrtYd" user)
+ (47 "F.CrtYd" user)
+ (48 "B.Fab" user)
+ (49 "F.Fab" user)
+ )
+
+ (setup
+ (last_trace_width 0.25)
+ (trace_clearance 0.2)
+ (zone_clearance 0.508)
+ (zone_45_only no)
+ (trace_min 0.2)
+ (via_size 0.8)
+ (via_drill 0.4)
+ (via_min_size 0.4)
+ (via_min_drill 0.3)
+ (uvia_size 0.3)
+ (uvia_drill 0.1)
+ (uvias_allowed no)
+ (uvia_min_size 0.2)
+ (uvia_min_drill 0.1)
+ (max_error 0.005)
+ (defaults
+ (edge_clearance 0.01)
+ (edge_cuts_line_width 0.05)
+ (courtyard_line_width 0.05)
+ (copper_line_width 0.2)
+ (copper_text_dims (size 1.5 1.5) (thickness 0.3) keep_upright)
+ (silk_line_width 0.12)
+ (silk_text_dims (size 1 1) (thickness 0.15) keep_upright)
+ (other_layers_line_width 0.1)
+ (other_layers_text_dims (size 1 1) (thickness 0.15) keep_upright)
+ )
+ (pad_size 3.14159 3.14159)
+ (pad_drill 1.41421)
+ (pad_to_mask_clearance 0.051)
+ (solder_mask_min_width 0.25)
+ (aux_axis_origin 0 0)
+ (visible_elements FFFFFF7F)
+ (pcbplotparams
+ (layerselection 0x010fc_ffffffff)
+ (usegerberextensions false)
+ (usegerberattributes false)
+ (usegerberadvancedattributes false)
+ (creategerberjobfile false)
+ (excludeedgelayer true)
+ (linewidth 0.100000)
+ (plotframeref false)
+ (viasonmask false)
+ (mode 1)
+ (useauxorigin false)
+ (hpglpennumber 1)
+ (hpglpenspeed 20)
+ (hpglpendiameter 15.000000)
+ (psnegative false)
+ (psa4output false)
+ (plotreference true)
+ (plotvalue true)
+ (plotinvisibletext false)
+ (padsonsilk false)
+ (subtractmaskfromsilk false)
+ (outputformat 1)
+ (mirror false)
+ (drillshape 1)
+ (scaleselection 1)
+ (outputdirectory ""))
+ )
+
+ (net 0 "")
+ {{net_defs}}
+
+ (net_class "Default" "This is the default net class."
+ (clearance 0.2)
+ (trace_width 0.25)
+ (via_dia 0.8)
+ (via_drill 0.4)
+ (uvia_dia 0.3)
+ (uvia_drill 0.1)
+ {{net_class_defs}}
+ )
+
+ {{module_defs}}
+
+ {{edge_cuts}}
+ )'''
+
+ module_defs = []
+ for i, pin in enumerate(pins):
+ (x, y), hole_dia = pin # all dimensions in mm here
+ pad_dia = hole_dia + 2*annular
+ mod = f'''
+ (module "Pogopin:AutogeneratedPogopinFootprint" (layer "F.Cu") (tedit {TEDIT_BASE + i:08X}) (tstamp {PIN_TS_BASE + i:08X})
+ (at {x} {y})
+ (descr "Pogo pin {i}")
+ (tags "test point plated hole")
+ (path "/{PATH_BASE + i:08X}")
+ (attr virtual)
+ (fp_text reference "TP{i}" (at 0 -{pad_dia/2 + 1}) (layer "F.SilkS")
+ (effects (font (size 1 1) (thickness 0.15)))
+ )
+ (fp_text value "pogo pin {i}" (at 0 {pad_dia/2 + 1}) (layer "F.Fab")
+ (effects (font (size 1 1) (thickness 0.15)))
+ )
+ (fp_text user "%R" (at 0 -{pad_dia/2 + 1}) (layer "F.Fab")
+ (effects (font (size 1 1) (thickness 0.15)))
+ )
+ (fp_circle (center 0 0) (end {pad_dia} 0) (layer "F.CrtYd") (width 0.05))
+ (fp_circle (center 0 0) (end 0 -{pad_dia}) (layer "F.SilkS") (width 0.12))
+ (pad "1" thru_hole circle (at 0 0) (size {pad_dia} {pad_dia}) (drill {hole_dia}) (layers *.Cu *.Mask)
+ (net {i+1} "pogo{i}"))
+ )'''
+ module_defs.append(mod)
+
+ edge_cuts = [ f'(gr_line (start {x1} {y1}) (end {x2} {y2}) (layer "Edge.Cuts") (width 0.05))'
+ for (x1, y1), (x2, y2) in outline ]
+
+ net_defs = [ f'(net {i+1} "pogo{i}")' for i, _pin in enumerate(pins) ]
+ net_class_defs = [ f'(add_net "pogo{i}")' for i, _pin in enumerate(pins) ]
+ return pcb_templ.format(
+ net_defs='\n'.join(net_defs),
+ net_class_defs='\n'.join(net_class_defs),
+ module_defs='\n'.join(module_defs),
+ edge_cuts='\n'.join(edge_cuts))
+
+def inkscape_query_all(filename):
+ proc = subprocess.run([ os.environ.get('INKSCAPE', 'inkscape'), filename, '--query-all'], capture_output=True)
+ proc.check_returncode()
+ data = [ line.split(',') for line in proc.stdout.decode().splitlines() ]
+ return { id: (float(x), float(y), float(w), float(h)) for id, x, y, w, h in data }
+
+SVG_NS = {
+ 'svg': 'http://www.w3.org/2000/svg',
+ 'inkscape': 'http://www.inkscape.org/namespaces/inkscape',
+ 'sodipodi': 'http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd'
+}
+
+def svg_find_elements(doc, tag, layer=None):
+ for i, g in enumerate(doc.findall('svg:g', SVG_NS)):
+ if g.attrib.get(f'{{{SVG_NS["inkscape"]}}}groupmode') != 'layer':
+ continue
+
+ label = g.attrib.get(f'{{{SVG_NS["inkscape"]}}}label', '')
+ if not layer or label == layer:
+ yield from g.iter(tag)
+
+# def svg_get_scale(doc):
+# w = doc.attrib['width']
+# h = doc.attrib['height']
+#
+# if not w.endswith('mm') and h.endswith('mm'):
+# raise ValueError('Document dimensions in SVG must be set to millimeters')
+#
+# w, h = float(w[:-2]), float(h[:-2])
+# _x, _y, vb_w, vb_h = map(float, doc.attrib['viewBox'].split())
+# scale_x, scale_y = vb_w / w, vb_h / h
+# assert abs(1 - scale_x/scale_y) < 0.001
+# return scale_x
+
+def svg_get_viewbox_mm(doc):
+ w = doc.attrib['width']
+ h = doc.attrib['height']
+
+ if not w.endswith('mm') and h.endswith('mm'):
+ raise ValueError('Document dimensions in SVG must be set to millimeters')
+
+ w, h = float(w[:-2]), float(h[:-2])
+ x, y, vb_w, vb_h = map(float, doc.attrib['viewBox'].split())
+ scale_x, scale_y = vb_w / w, vb_h / h
+ return x/scale_x, y/scale_y, w, h
+
+if __name__ == '__main__':
+ import argparse
+ parser = argparse.ArgumentParser()
+ parser.add_argument('svg', metavar='pogo_map.svg', help='Input inkscape SVG pogo pin map (use provided template!)')
+ parser.add_argument('outline', metavar='outline.dxf', help='Board outline DXF generated by OpenSCAD')
+ parser.add_argument('output', default='kicad', help='Output directory/project name and path')
+ parser.add_argument('-y', '--yspace', type=int, default=200, help='Schematic pin Y spacing in mil (default: 200)')
+ parser.add_argument('-a', '--annular', type=float, default=0.5, help='Pogo pin annular ring width in mm (default: 0.5)')
+ parser.add_argument('-l', '--svg-layer', type=str, default='Test Points', help='Name of SVG layer containing pogo pins')
+ args = parser.parse_args()
+
+ if not path.exists(args.output):
+ os.mkdir(args.output)
+
+ if not path.isdir(args.output):
+ raise SystemError(f'Output path "{args.output}" is not a directory')
+
+ with open(args.svg, 'r') as f:
+ doc = xe.fromstring(f.read())
+ pogo_circle_ids = [ circle.attrib['id'] for circle in svg_find_elements(doc, f'{{{SVG_NS["svg"]}}}circle', args.svg_layer) ]
+ # scale = svg_get_scale(doc)
+ page_x, page_y, page_w, page_h = svg_get_viewbox_mm(doc)
+ MM_PER_IN = 25.4
+ SVG_DEF_DPI = 96
+ px_to_mm = lambda px: px/SVG_DEF_DPI * MM_PER_IN
+ query = inkscape_query_all(args.svg)
+ dims = [ query[id] for id in pogo_circle_ids ]
+ assert all( abs(1 - w/h) < 0.001 for _x, _y, w, h in dims )
+ print('origin:', page_x, page_y)
+ print('dims:', page_w, page_h)
+ pins = [ (
+ (page_x + px_to_mm(x) + px_to_mm(w)/2,
+ page_y - page_h + px_to_mm(y) + px_to_mm(w)/2),
+ px_to_mm(w)) for x, y, w, h in dims ]
+
+ doc = ezdxf.readfile(args.outline)
+ outline = []
+ for line in doc.modelspace().query('LINE'):
+ (x1, y1, _z1), (x2, y2, _z2) = line.dxf.start, line.dxf.end
+ outline.append(((x1, -y1), (x2, -y2)))
+
+ out_name = path.basename(args.output)
+ with open(path.join(args.output, f'{out_name}.sch'), 'w', encoding='utf8') as sch:
+ sch.write(sch_template(f'{out_name} generated schematic (PogoJig v{__version__})', len(pins), yspace=args.yspace))
+
+ with open(path.join(args.output, f'{out_name}.kicad_pcb'), 'w', encoding='utf8') as pcb:
+ pcb.write(pcb_template(outline, pins, annular=args.annular))
+
+ with open(path.join(args.output, f'{out_name}.pro'), 'w', encoding='utf8') as f:
+ f.write(pkgutil.get_data('pogojig.kicad', 'kicad.pro').decode('utf8'))
+
+ with open(path.join(args.output, f'{out_name}-cache.lib'), 'w', encoding='utf8') as f:
+ f.write(pkgutil.get_data('pogojig.kicad', 'kicad-cache.lib').decode('utf8'))
+
diff --git a/support/inkscape/__main__.py b/support/inkscape_exporter.py
index 29ac745..4e80c63 100644..100755
--- a/support/inkscape/__main__.py
+++ b/support/inkscape_exporter.py
@@ -1,6 +1,10 @@
-import os, shutil
-from lib import util
-from . import effect, inkscape
+#!/usr/bin/env python3
+
+import os
+import shutil
+import tempfile
+
+from pogojig.inkscape import effect, inkscape
def _unfuck_svg_document(temp_svg_path):
@@ -32,33 +36,26 @@ def _unfuck_svg_document(temp_svg_path):
command_line.delete_layer(copy)
command_line.apply_to_document('FileSave', 'FileClose', 'FileQuit')
-
command_line.run()
-@util.main
-def main(in_path, out_path):
- try:
- _, out_suffix = os.path.splitext(out_path)
+if __name__ == '__main__':
+ import argparse
+ parser = argparse.ArgumentParser()
+ parser.add_argument('infile', metavar='input.svg', help='Inkscape SVG input file')
+ parser.add_argument('outfile', metavar='output.dxf', help='DXF output file')
+ args = parser.parse_args()
+
+ effect.ExportEffect.check_document_units(args.infile)
+
+ with tempfile.TemporaryDirectory() as tmpdir:
+ temp_svg_path = os.path.join(tmpdir, os.path.basename(args.infile))
+ shutil.copyfile(args.infile, temp_svg_path)
+
+ _unfuck_svg_document(temp_svg_path)
- effect.ExportEffect.check_document_units(in_path)
+ export_effect = effect.ExportEffect()
+ export_effect.affect(args=[temp_svg_path], output=False)
- with util.TemporaryDirectory() as temp_dir:
- temp_svg_path = os.path.join(temp_dir, os.path.basename(in_path))
-
- shutil.copyfile(in_path, temp_svg_path)
-
- _unfuck_svg_document(temp_svg_path)
-
- export_effect = effect.ExportEffect()
- export_effect.affect(args=[temp_svg_path], output=False)
-
- with open(out_path, 'w') as file:
- if out_suffix == '.dxf':
- export_effect.write_dxf(file)
- elif out_suffix == '.asy':
- export_effect.write_asy(file)
- else:
- raise Exception('Unknown file type: {}'.format(out_suffix))
- except util.UserError as e:
- raise util.UserError('While processing {}: {}', in_path, e)
+ with open(args.outfile, 'w') as f:
+ export_effect.write_dxf(f)
diff --git a/support/lib/make.py b/support/lib/make.py
deleted file mode 100644
index c89b306..0000000
--- a/support/lib/make.py
+++ /dev/null
@@ -1,5 +0,0 @@
-from . import util
-
-
-def write_dependencies(path, target, dependencies):
- util.write_file(path, '{}: {}\n'.format(target, ' '.join(dependencies)).encode())
diff --git a/support/lib/util.py b/support/lib/util.py
deleted file mode 100644
index c00a5fe..0000000
--- a/support/lib/util.py
+++ /dev/null
@@ -1,130 +0,0 @@
-import contextlib
-import inspect
-import os
-import re
-import shutil
-import subprocess
-import sys
-import tempfile
-
-
-class UserError(Exception):
- def __init__(self, message, *args):
- super(UserError, self).__init__(message.format(*args))
-
-
-def main(fn):
- """
- Decorator for "main" functions. Decorates a function that should be
- called when the containing module is run as a script (e.g. via python -m
- <module>).
- """
- frame = inspect.currentframe().f_back
-
- def wrapped_fn(*args, **kwargs):
- try:
- fn(*args, **kwargs)
- except UserError as e:
- print >> sys.stderr, 'Error:', e
- sys.exit(1)
- except KeyboardInterrupt:
- sys.exit(2)
-
- if frame.f_globals['__name__'] == '__main__':
- wrapped_fn(*sys.argv[1:])
-
- # Allow the main function also to be called explicitly
- return wrapped_fn
-
-
-def rename_atomic(source_path, target_path):
- """
- Move the file at source_path to target_path.
-
- If both paths reside on the same device, os.rename() is used, otherwise
- the file is copied to a temporary name next to target_path and moved from
- there using os.rename().
- """
- source_dir_stat = os.stat(os.path.dirname(source_path))
- target_dir_stat = os.stat(os.path.dirname(target_path))
-
- if source_dir_stat.st_dev == target_dir_stat.st_dev:
- os.rename(source_path, target_path)
- else:
- temp_path = target_path + '~'
-
- shutil.copyfile(source_path, temp_path)
- os.rename(temp_path, target_path)
-
-
-@contextlib.contextmanager
-def TemporaryDirectory():
- dir = tempfile.mkdtemp()
-
- try:
- yield dir
- finally:
- shutil.rmtree(dir)
-
-
-@contextlib.contextmanager
-def command_context(args, remove_env=[], set_env={}, working_dir=None, use_stderr=False):
- env = dict(os.environ)
-
- for i in remove_env:
- del env[i]
-
- for k, v in set_env.items():
- env[k] = v
-
- if use_stderr:
- stderr = subprocess.PIPE
- else:
- stderr = None
-
- try:
- process = subprocess.Popen(args, env=env, cwd=working_dir, stderr=stderr)
- except OSError as e:
- raise UserError('Error running {}: {}', args[0], e)
-
- try:
- yield process
- except:
- try:
- process.kill()
- except OSError:
- # Ignore exceptions here so we don't mask the
- # already-being-thrown exception.
- pass
-
- raise
- finally:
- # Use communicate so that we won't deadlock if the process generates
- # some unread output.
- process.communicate()
-
- if process.returncode:
- raise UserError('Command failed: {}', ' '.join(args))
-
-
-def command(args, remove_env=[], set_env={}, working_dir=None):
- with command_context(args, remove_env, set_env, working_dir):
- pass
-
-
-def bash_escape_string(string):
- return "'{}'".format(re.sub("'", "'\"'\"'", string))
-
-
-def write_file(path, data):
- temp_path = path + '~'
-
- with open(temp_path, 'wb') as file:
- file.write(data)
-
- os.rename(temp_path, path)
-
-
-def read_file(path):
- with open(path, 'rb') as file:
- return file.read()
diff --git a/support/openscad/__init__.py b/support/openscad/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/support/openscad/__init__.py
+++ /dev/null
diff --git a/support/openscad/__main__.py b/support/openscad/__main__.py
deleted file mode 100644
index 85f8b99..0000000
--- a/support/openscad/__main__.py
+++ /dev/null
@@ -1,46 +0,0 @@
-import os
-
-from lib import util, make
-
-
-def _openscad(in_path, out_path, deps_path):
- util.command([os.environ['OPENSCAD'], '-o', out_path, '-d', deps_path, in_path])
-
-
-@util.main
-def main(in_path, out_path):
- cwd = os.getcwd()
-
- def relpath(path):
- return os.path.relpath(path, cwd)
-
- with util.TemporaryDirectory() as temp_dir:
- temp_deps_path = os.path.join(temp_dir, 'deps')
- temp_mk_path = os.path.join(temp_dir, 'mk')
- temp_files_path = os.path.join(temp_dir, 'files')
-
- _, out_ext = os.path.splitext(out_path)
-
- # OpenSCAD requires the output file name to end in .stl or .dxf.
- temp_out_path = os.path.join(temp_dir, 'out' + out_ext)
-
- _openscad(in_path, temp_out_path, temp_deps_path)
-
- mk_content = '%:; echo "$@" >> {}'.format(util.bash_escape_string(temp_files_path))
-
- # Use make to parse the dependency makefile written by OpenSCAD.
- util.write_file(temp_mk_path, mk_content.encode())
- util.command(
- ['make', '-s', '-B', '-f', temp_mk_path, '-f', temp_deps_path],
- remove_env=['MAKELEVEL', 'MAKEFLAGS'])
-
- # All dependencies as paths relative to the project root.
- deps = set(map(relpath, util.read_file(temp_files_path).decode().splitlines()))
-
- # Relative paths to all files that should not appear in the
- # dependency makefile.
- ignored_files = set(map(relpath, [in_path, temp_deps_path, temp_mk_path, temp_out_path]))
-
- # Write output files.
- make.write_dependencies(out_path + '.d', out_path, deps - ignored_files)
- util.rename_atomic(temp_out_path, out_path)
diff --git a/support/asymptote/__init__.py b/support/pogojig/__init__.py
index e69de29..e69de29 100644
--- a/support/asymptote/__init__.py
+++ b/support/pogojig/__init__.py
diff --git a/support/inkscape/__init__.py b/support/pogojig/inkscape/__init__.py
index e69de29..e69de29 100644
--- a/support/inkscape/__init__.py
+++ b/support/pogojig/inkscape/__init__.py
diff --git a/support/inkscape/bezmisc.py b/support/pogojig/inkscape/bezmisc.py
index b7f5429..68a338d 100755..100644
--- a/support/inkscape/bezmisc.py
+++ b/support/pogojig/inkscape/bezmisc.py
@@ -55,8 +55,9 @@ def rootWrapper(a,b,c,d):
return 1.0*(-d/c),
return ()
-def bezierparameterize(((bx0,by0),(bx1,by1),(bx2,by2),(bx3,by3))):
+def bezierparameterize(points):
#parametric bezier
+ ((bx0,by0),(bx1,by1),(bx2,by2),(bx3,by3)) = points
x0=bx0
y0=by0
cx=3*(bx1-x0)
@@ -69,8 +70,10 @@ def bezierparameterize(((bx0,by0),(bx1,by1),(bx2,by2),(bx3,by3))):
return ax,ay,bx,by,cx,cy,x0,y0
#ax,ay,bx,by,cx,cy,x0,y0=bezierparameterize(((bx0,by0),(bx1,by1),(bx2,by2),(bx3,by3)))
-def linebezierintersect(((lx1,ly1),(lx2,ly2)),((bx0,by0),(bx1,by1),(bx2,by2),(bx3,by3))):
+def linebezierintersect(line, bezier):
#parametric line
+ ((lx1,ly1),(lx2,ly2)) = line
+ ((bx0,by0),(bx1,by1),(bx2,by2),(bx3,by3)) = bezier
dd=lx1
cc=lx2-lx1
bb=ly1
@@ -99,19 +102,23 @@ def linebezierintersect(((lx1,ly1),(lx2,ly2)),((bx0,by0),(bx1,by1),(bx2,by2),(bx
retval.append(bezierpointatt(((bx0,by0),(bx1,by1),(bx2,by2),(bx3,by3)),i))
return retval
-def bezierpointatt(((bx0,by0),(bx1,by1),(bx2,by2),(bx3,by3)),t):
+def bezierpointatt(xxx_todo_changeme3,t):
+ ((bx0,by0),(bx1,by1),(bx2,by2),(bx3,by3)) = xxx_todo_changeme3
ax,ay,bx,by,cx,cy,x0,y0=bezierparameterize(((bx0,by0),(bx1,by1),(bx2,by2),(bx3,by3)))
x=ax*(t**3)+bx*(t**2)+cx*t+x0
y=ay*(t**3)+by*(t**2)+cy*t+y0
return x,y
-def bezierslopeatt(((bx0,by0),(bx1,by1),(bx2,by2),(bx3,by3)),t):
+def bezierslopeatt(xxx_todo_changeme4,t):
+ ((bx0,by0),(bx1,by1),(bx2,by2),(bx3,by3)) = xxx_todo_changeme4
ax,ay,bx,by,cx,cy,x0,y0=bezierparameterize(((bx0,by0),(bx1,by1),(bx2,by2),(bx3,by3)))
dx=3*ax*(t**2)+2*bx*t+cx
dy=3*ay*(t**2)+2*by*t+cy
return dx,dy
-def beziertatslope(((bx0,by0),(bx1,by1),(bx2,by2),(bx3,by3)),(dy,dx)):
+def beziertatslope(xxx_todo_changeme5, xxx_todo_changeme6):
+ ((bx0,by0),(bx1,by1),(bx2,by2),(bx3,by3)) = xxx_todo_changeme5
+ (dy,dx) = xxx_todo_changeme6
ax,ay,bx,by,cx,cy,x0,y0=bezierparameterize(((bx0,by0),(bx1,by1),(bx2,by2),(bx3,by3)))
#quadratic coefficents of slope formula
if dx:
@@ -136,9 +143,12 @@ def beziertatslope(((bx0,by0),(bx1,by1),(bx2,by2),(bx3,by3)),(dy,dx)):
retval.append(i)
return retval
-def tpoint((x1,y1),(x2,y2),t):
+def tpoint(xxx_todo_changeme7, xxx_todo_changeme8,t):
+ (x1,y1) = xxx_todo_changeme7
+ (x2,y2) = xxx_todo_changeme8
return x1+t*(x2-x1),y1+t*(y2-y1)
-def beziersplitatt(((bx0,by0),(bx1,by1),(bx2,by2),(bx3,by3)),t):
+def beziersplitatt(xxx_todo_changeme9,t):
+ ((bx0,by0),(bx1,by1),(bx2,by2),(bx3,by3)) = xxx_todo_changeme9
m1=tpoint((bx0,by0),(bx1,by1),t)
m2=tpoint((bx1,by1),(bx2,by2),t)
m3=tpoint((bx2,by2),(bx3,by3),t)
@@ -167,7 +177,9 @@ Jens Gravesen <gravesen@mat.dth.dk>
mat-report no. 1992-10, Mathematical Institute, The Technical
University of Denmark.
'''
-def pointdistance((x1,y1),(x2,y2)):
+def pointdistance(xxx_todo_changeme10, xxx_todo_changeme11):
+ (x1,y1) = xxx_todo_changeme10
+ (x2,y2) = xxx_todo_changeme11
return math.sqrt(((x2 - x1) ** 2) + ((y2 - y1) ** 2))
def Gravesen_addifclose(b, len, error = 0.001):
box = 0
@@ -208,19 +220,21 @@ def Simpson(f, a, b, n_limit, tolerance):
asum += bsum
bsum = 0.0
est0 = est1
- for i in xrange(1, n, 2):
+ for i in range(1, n, 2):
bsum += f(a + (i * interval))
est1 = multiplier * (endsum + (2.0 * asum) + (4.0 * bsum))
#print multiplier, endsum, interval, asum, bsum, est1, est0
return est1
-def bezierlengthSimpson(((bx0,by0),(bx1,by1),(bx2,by2),(bx3,by3)), tolerance = 0.001):
+def bezierlengthSimpson(xxx_todo_changeme12, tolerance = 0.001):
+ ((bx0,by0),(bx1,by1),(bx2,by2),(bx3,by3)) = xxx_todo_changeme12
global balfax,balfbx,balfcx,balfay,balfby,balfcy
ax,ay,bx,by,cx,cy,x0,y0=bezierparameterize(((bx0,by0),(bx1,by1),(bx2,by2),(bx3,by3)))
balfax,balfbx,balfcx,balfay,balfby,balfcy = 3*ax,2*bx,cx,3*ay,2*by,cy
return Simpson(balf, 0.0, 1.0, 4096, tolerance)
-def beziertatlength(((bx0,by0),(bx1,by1),(bx2,by2),(bx3,by3)), l = 0.5, tolerance = 0.001):
+def beziertatlength(xxx_todo_changeme13, l = 0.5, tolerance = 0.001):
+ ((bx0,by0),(bx1,by1),(bx2,by2),(bx3,by3)) = xxx_todo_changeme13
global balfax,balfbx,balfcx,balfay,balfby,balfcy
ax,ay,bx,by,cx,cy,x0,y0=bezierparameterize(((bx0,by0),(bx1,by1),(bx2,by2),(bx3,by3)))
balfax,balfbx,balfcx,balfay,balfby,balfcy = 3*ax,2*bx,cx,3*ay,2*by,cy
@@ -267,7 +281,7 @@ if __name__ == '__main__':
print s, st
'''
for curve in curves:
- print beziertatlength(curve,0.5)
+ print(beziertatlength(curve,0.5))
# vim: expandtab shiftwidth=4 tabstop=8 softtabstop=4 fileencoding=utf-8 textwidth=99
diff --git a/support/inkscape/cspsubdiv.py b/support/pogojig/inkscape/cspsubdiv.py
index c34236a..72da473 100755..100644
--- a/support/inkscape/cspsubdiv.py
+++ b/support/pogojig/inkscape/cspsubdiv.py
@@ -1,8 +1,9 @@
#!/usr/bin/env python
-from bezmisc import *
-from ffgeom import *
+from .bezmisc import *
+from .ffgeom import *
-def maxdist(((p0x,p0y),(p1x,p1y),(p2x,p2y),(p3x,p3y))):
+def maxdist(points):
+ ((p0x,p0y),(p1x,p1y),(p2x,p2y),(p3x,p3y)) = points
p0 = Point(p0x,p0y)
p1 = Point(p1x,p1y)
p2 = Point(p2x,p2y)
diff --git a/support/inkscape/cubicsuperpath.py b/support/pogojig/inkscape/cubicsuperpath.py
index 861b9da..a594660 100755..100644
--- a/support/inkscape/cubicsuperpath.py
+++ b/support/pogojig/inkscape/cubicsuperpath.py
@@ -19,7 +19,7 @@ along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
"""
-import simplepath
+from . import simplepath
from math import *
def matprod(mlist):
diff --git a/support/inkscape/dxf_footer.txt b/support/pogojig/inkscape/dxf_footer.txt
index a225dd7..a225dd7 100644
--- a/support/inkscape/dxf_footer.txt
+++ b/support/pogojig/inkscape/dxf_footer.txt
diff --git a/support/inkscape/dxf_header.txt b/support/pogojig/inkscape/dxf_header.txt
index 341cb1b..341cb1b 100644
--- a/support/inkscape/dxf_header.txt
+++ b/support/pogojig/inkscape/dxf_header.txt
diff --git a/support/inkscape/effect.py b/support/pogojig/inkscape/effect.py
index 313032c..89824e9 100644
--- a/support/inkscape/effect.py
+++ b/support/pogojig/inkscape/effect.py
@@ -10,7 +10,6 @@ import pkgutil
import re
from lxml import etree
-from lib import util
from . import inkex, simpletransform, cubicsuperpath, cspsubdiv, inkscape
@@ -39,7 +38,7 @@ class ExportEffect(inkex.Effect):
def __init__(self):
inkex.Effect.__init__(self)
- self._flatness = float(os.environ['DXF_FLATNESS'])
+ self._flatness = float(os.environ.get('INKSCAPE_DXF_FLATNESS', 0.1))
self._layers = None
self._paths = None
@@ -139,11 +138,11 @@ class ExportEffect(inkex.Effect):
layer_indices = {l: i for i, l in enumerate(self._layers)}
- file.write(pkgutil.get_data(__name__, 'dxf_header.txt'))
+ file.write(pkgutil.get_data(__name__, 'dxf_header.txt').decode('ASCII'))
def write_instruction(code, value):
- print >> file, code
- print >> file, value
+ print(code, file=file)
+ print(value, file=file)
handle_iter = itertools.count(256)
@@ -165,7 +164,7 @@ class ExportEffect(inkex.Effect):
write_instruction(21, repr(y2 / unit_factor))
write_instruction(31, 0.0)
- file.write(pkgutil.get_data(__name__, 'dxf_footer.txt'))
+ file.write(pkgutil.get_data(__name__, 'dxf_footer.txt').decode('ASCII'))
def write_asy(self, file):
def write_line(format, *args):
@@ -263,18 +262,18 @@ class ExportEffect(inkex.Effect):
height_attr = document.getroot().get('height')
if height_attr is None:
- raise util.UserError(
+ raise ValueError(
'SVG document has no height attribute. See '
'https://github.com/Feuermurmel/openscad-template/wiki/Absolute-Measurements')
_, height_unit = cls._parse_measure(height_attr)
if height_unit is None or height_unit == 'px':
- raise util.UserError(
+ raise ValueError(
'Height of SVG document is not an absolute measure. See '
'https://github.com/Feuermurmel/openscad-template/wiki/Absolute-Measurements')
if document.getroot().get('viewBox') is None:
- raise util.UserError(
+ raise ValueError(
'SVG document has no viewBox attribute. See '
'https://github.com/Feuermurmel/openscad-template/wiki/Absolute-Measurements')
diff --git a/support/inkscape/ffgeom.py b/support/pogojig/inkscape/ffgeom.py
index ef8799b..368a29a 100755..100644
--- a/support/inkscape/ffgeom.py
+++ b/support/pogojig/inkscape/ffgeom.py
@@ -20,11 +20,6 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
"""
import math
-try:
- NaN = float('NaN')
-except ValueError:
- PosInf = 1e300000
- NaN = PosInf/PosInf
class Point:
precision = 5
@@ -72,11 +67,11 @@ class Segment:
def slope(self):
if self.delta_x() != 0:
return self.delta_x() / self.delta_y()
- return NaN
+ return math.nan
def intercept(self):
if self.delta_x() != 0:
return self[1]['y'] - (self[0]['x'] * self.slope())
- return NaN
+ return math.nan
def distanceToPoint(self, p):
s2 = Segment(self[0],p)
c1 = dot(s2,self)
@@ -88,7 +83,8 @@ class Segment:
return self.perpDistanceToPoint(p)
def perpDistanceToPoint(self, p):
len = self.length()
- if len == 0: return NaN
+ if len == 0:
+ return math.nan
return math.fabs(((self[1]['x'] - self[0]['x']) * (self[0]['y'] - p['y'])) - \
((self[0]['x'] - p['x']) * (self[1]['y'] - self[0]['y']))) / len
def angle(self):
@@ -96,13 +92,13 @@ class Segment:
def length(self):
return math.sqrt((self.delta_x() ** 2) + (self.delta_y() ** 2))
def pointAtLength(self, len):
- if self.length() == 0: return Point(NaN, NaN)
+ if self.length() == 0: return Point(math.nan, math.nan)
ratio = len / self.length()
x = self[0]['x'] + (ratio * self.delta_x())
y = self[0]['y'] + (ratio * self.delta_y())
return Point(x, y)
def pointAtRatio(self, ratio):
- if self.length() == 0: return Point(NaN, NaN)
+ if self.length() == 0: return Point(math.nan, math.nan)
x = self[0]['x'] + (ratio * self.delta_x())
y = self[0]['y'] + (ratio * self.delta_y())
return Point(x, y)
@@ -132,7 +128,7 @@ def intersectSegments(s1, s2):
x = x1 + ((num / denom) * (x2 - x1))
y = y1 + ((num / denom) * (y2 - y1))
return Point(x, y)
- return Point(NaN, NaN)
+ return Point(math.nan, math.nan)
def dot(s1, s2):
return s1.delta_x() * s2.delta_x() + s1.delta_y() * s2.delta_y()
diff --git a/support/inkscape/inkex.py b/support/pogojig/inkscape/inkex.py
index 19e860b..609ffeb 100755..100644
--- a/support/inkscape/inkex.py
+++ b/support/pogojig/inkscape/inkex.py
@@ -35,6 +35,8 @@ import re
import sys
from math import *
+from lxml import etree
+
#a dictionary of all of the xmlns prefixes in a standard inkscape doc
NSS = {
u'sodipodi' :u'http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd',
@@ -107,15 +109,6 @@ def are_near_relative(a, b, eps):
else:
return False
-
-# third party library
-try:
- from lxml import etree
-except Exception, e:
- localize()
- errormsg(_("The fantastic lxml wrapper for libxml2 is required by inkex.py and therefore this extension. Please download and install the latest version from http://cheeseshop.python.org/pypi/lxml/, or install it through your package manager by a command like: sudo apt-get install python-lxml\n\nTechnical details:\n%s" % (e,)))
- sys.exit()
-
def check_inkbool(option, opt, value):
if str(value).capitalize() == 'True':
return True
@@ -126,7 +119,7 @@ def check_inkbool(option, opt, value):
def addNS(tag, ns=None):
val = tag
- if ns!=None and len(ns)>0 and NSS.has_key(ns) and len(tag)>0 and tag[0]!='{':
+ if ns!=None and len(ns)>0 and ns in NSS and len(tag)>0 and tag[0]!='{':
val = "{%s}%s" % (NSS[ns], tag)
return val
diff --git a/support/inkscape/inkscape.py b/support/pogojig/inkscape/inkscape.py
index 9fd9528..efe7677 100644
--- a/support/inkscape/inkscape.py
+++ b/support/pogojig/inkscape/inkscape.py
@@ -1,46 +1,34 @@
import os
+import subprocess
import xml.etree.ElementTree as etree
-from lib import util
-
-
def get_inkscape_layers(svg_path):
document = etree.parse(svg_path)
- def iter_layers():
- nodes = document.findall(
- '{http://www.w3.org/2000/svg}g[@{http://www.inkscape.org/namespaces/inkscape}groupmode="layer"]')
+ layers = []
+ nodes = document.findall(
+ '{http://www.w3.org/2000/svg}g[@{http://www.inkscape.org/namespaces/inkscape}groupmode="layer"]')
+
+ for i in nodes:
+ inkscape_name = i.get('{http://www.inkscape.org/namespaces/inkscape}label').strip()
- for i in nodes:
- inkscape_name = i.get('{http://www.inkscape.org/namespaces/inkscape}label').strip()
+ if inkscape_name.endswith(']'):
+ export_name, args = inkscape_name[:-1].rsplit('[', 1)
- if inkscape_name.endswith(']'):
- export_name, args = inkscape_name[:-1].rsplit('[', 1)
-
- export_name = export_name.strip()
- args = args.strip()
-
- use_paths = 'p' in args
- else:
- use_paths = False
- export_name = inkscape_name
+ export_name = export_name.strip()
+ args = args.strip()
- yield Layer(inkscape_name, export_name, use_paths)
-
- return list(iter_layers())
+ use_paths = 'p' in args
+ else:
+ use_paths = False
+ export_name = inkscape_name
+
+ layers.append(Layer(inkscape_name, export_name, use_paths))
+ return layers
def _inkscape(svg_path, verbs):
- def iter_args():
- yield os.environ['INKSCAPE']
-
- for i in verbs:
- yield '--verb'
- yield i
-
- yield svg_path
-
- util.command(list(iter_args()))
+ subprocess.run([os.environ.get('INKSCAPE', 'inkscape'), *(x for verb in verbs for x in ('--verb', verb)), svg_path])
class Layer(object):
diff --git a/support/inkscape/simplepath.py b/support/pogojig/inkscape/simplepath.py
index 94ab092..8d4f0a7 100755..100644
--- a/support/inkscape/simplepath.py
+++ b/support/pogojig/inkscape/simplepath.py
@@ -49,7 +49,7 @@ def lexPath(d):
offset = m.end()
continue
#TODO: create new exception
- raise Exception, 'Invalid path data!'
+ raise ValueError('Invalid path data!')
'''
pathdefs = {commandfamily:
[
@@ -71,6 +71,7 @@ pathdefs = {
'A':['A', 7, [float, float, float, int, int, float, float], ['r','r','a',0,'s','x','y']],
'Z':['L', 0, [], []]
}
+
def parsePath(d):
"""
Parse SVG path and return an array of segments.
@@ -87,14 +88,14 @@ def parsePath(d):
while 1:
try:
- token, isCommand = lexer.next()
+ token, isCommand = next(lexer)
except StopIteration:
break
params = []
needParam = True
if isCommand:
if not lastCommand and token.upper() != 'M':
- raise Exception, 'Invalid path, must begin with moveto.'
+ raise ValueError('Invalid path, must begin with moveto.')
else:
command = token
else:
@@ -107,16 +108,16 @@ def parsePath(d):
else:
command = pathdefs[lastCommand.upper()][0].lower()
else:
- raise Exception, 'Invalid path, no initial command.'
+ raise ValueError('Invalid path, no initial command.')
numParams = pathdefs[command.upper()][1]
while numParams > 0:
if needParam:
try:
- token, isCommand = lexer.next()
+ token, isCommand = next(lexer)
if isCommand:
- raise Exception, 'Invalid number of parameters'
+ raise ValueError('Invalid number of parameters')
except StopIteration:
- raise Exception, 'Unexpected end of path'
+ raise ValueError('Unexpected end of path')
cast = pathdefs[command.upper()][2][-numParams]
param = cast(token)
if command.islower():
diff --git a/support/inkscape/simpletransform.py b/support/pogojig/inkscape/simpletransform.py
index 55082ed..610cb57 100755..100644
--- a/support/inkscape/simpletransform.py
+++ b/support/pogojig/inkscape/simpletransform.py
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
'''
Copyright (C) 2006 Jean-Francois Barraud, barraud@math.univ-lille1.fr
Copyright (C) 2010 Alvin Penner, penner@vaxxine.com
@@ -21,9 +20,11 @@ barraud@math.univ-lille1.fr
This code defines several functions to make handling of transform
attribute easier.
'''
-import inkex, cubicsuperpath
+
import math, re
+from . import inkex, cubicsuperpath
+
def parseTransform(transf,mat=[[1.0, 0.0, 0.0], [0.0, 1.0, 0.0]]):
if transf=="" or transf==None:
return(mat)
@@ -117,7 +118,7 @@ def applyTransformToPath(mat,path):
def fuseTransform(node):
if node.get('d')==None:
#FIXME: how do you raise errors?
- raise AssertionError, 'can not fuse "transform" of elements that have no "d" attribute'
+ raise AssertionError('can not fuse "transform" of elements that have no "d" attribute')
t = node.get("transform")
if t == None:
return
diff --git a/support/lib/__init__.py b/support/pogojig/kicad/__init__.py
index e69de29..e69de29 100644
--- a/support/lib/__init__.py
+++ b/support/pogojig/kicad/__init__.py
diff --git a/support/pogojig/kicad/kicad-cache.lib b/support/pogojig/kicad/kicad-cache.lib
new file mode 100644
index 0000000..a98cd73
--- /dev/null
+++ b/support/pogojig/kicad/kicad-cache.lib
@@ -0,0 +1,21 @@
+EESchema-LIBRARY Version 2.4
+#encoding utf-8
+#
+# Connector_Conn_01x01_Female
+#
+DEF Connector_Conn_01x01_Female J 0 40 Y N 1 F N
+F0 "J" 0 100 50 H V C CNN
+F1 "Connector_Conn_01x01_Female" 0 -100 50 H V C CNN
+F2 "" 0 0 50 H I C CNN
+F3 "" 0 0 50 H I C CNN
+$FPLIST
+ Connector*:*
+$ENDFPLIST
+DRAW
+A 0 0 20 901 -901 1 1 6 N 0 20 0 -20
+P 2 1 1 6 -50 0 -20 0 N
+X Pin_1 1 -200 0 150 R 50 50 1 1 P
+ENDDRAW
+ENDDEF
+#
+#End Library
diff --git a/support/pogojig/kicad/kicad.pro b/support/pogojig/kicad/kicad.pro
new file mode 100644
index 0000000..5cd0983
--- /dev/null
+++ b/support/pogojig/kicad/kicad.pro
@@ -0,0 +1,34 @@
+update=05/04/2019 20:44:53
+version=1
+last_client=kicad
+[general]
+version=1
+RootSch=
+BoardNm=
+[pcbnew]
+version=1
+LastNetListRead=
+UseCmpFile=1
+PadDrill=0.600000000000
+PadDrillOvalY=0.600000000000
+PadSizeH=1.500000000000
+PadSizeV=1.500000000000
+PcbTextSizeV=1.500000000000
+PcbTextSizeH=1.500000000000
+PcbTextThickness=0.300000000000
+ModuleTextSizeV=1.000000000000
+ModuleTextSizeH=1.000000000000
+ModuleTextSizeThickness=0.150000000000
+SolderMaskClearance=0.000000000000
+SolderMaskMinWidth=0.000000000000
+DrawSegmentWidth=0.200000000000
+BoardOutlineThickness=0.100000000000
+ModuleOutlineThickness=0.150000000000
+CopperEdgeClearance=0.000000000000
+[cvpcb]
+version=1
+NetIExt=net
+[eeschema]
+version=1
+LibDir=
+[eeschema/libraries]