Compare commits

...

53 commits

Author SHA1 Message Date
73775d6999 pre update 2024-02-23 17:55:10 +01:00
5060864b08 fix 4.0 2024-02-23 17:55:10 +01:00
efc7329646 add choc version 2024-02-23 17:55:10 +01:00
85bd46a4d8 version 003 2024-02-23 17:55:10 +01:00
c57440a231 fix matrix :< 2024-02-23 17:55:10 +01:00
a48fb3c064 allow keeping of gerber files 2024-02-23 17:55:10 +01:00
56a81c20b8 add v002 2024-02-23 17:55:10 +01:00
9370da75b7 add v2 with support for powerswitch and reset 2024-02-23 17:55:10 +01:00
fd3fd6b5c0 rename board 2024-02-23 17:55:10 +01:00
Stefan Schwarz
73483e290b add groundplane 2024-02-23 17:55:10 +01:00
Stefan Schwarz
35f2684348 add a switchplate 2024-02-23 17:55:10 +01:00
Stefan Schwarz
ce65a9ef5d cleanup 2024-02-23 17:55:10 +01:00
Stefan Schwarz
3032e6b3d1 rearrange via and connect grounds 2024-02-23 17:55:10 +01:00
Stefan Schwarz
57e8173848 remove bak files from github 2024-02-23 17:55:10 +01:00
Stefan Schwarz
85a13fa4e7 add first routed version 2024-02-23 17:55:10 +01:00
6afbf0385a rotate the diode for cleaner wireing 2024-02-23 17:55:10 +01:00
bec14b1705 remove reverse option 2024-02-23 17:55:10 +01:00
99acabbd12 fix pin assignments 2024-02-23 17:55:10 +01:00
1190f35c66 add makefile and kicad project 2024-02-23 17:55:10 +01:00
52af7f0a20 fix case 2024-02-23 17:55:10 +01:00
Stefan Schwarz
96d043126a wip 2024-02-23 17:55:10 +01:00
Bán Dénes
21e50cb11d 4.0.5 2024-01-22 17:34:20 +01:00
Bán Dénes
353e07654d Package audit 2024-01-22 17:33:56 +01:00
Bán Dénes
e1697e367f Autobind vs. mirroring bugfix (#119) 2024-01-22 15:56:45 +01:00
Bán Dénes
1f57ec4e19 Footprint param streamlining 2023-08-14 19:00:37 +02:00
Kim
6e520e745a
Add intersect aggregator (#102)
* Added intersect aggregator

* Addressed stylistic PR feedback

* Set the rotation of the intersected point to the second point’s rotation

* Revert "Set the rotation of the intersected point to the second point’s rotation"

This reverts commit d210a98f79a8866519fc9695487a9ea235167b8b.

* Adjusted aggregate function to not need axis1 and axis2 parameters

* Add assert to check for exactly 2 parts

* Add unit tests for the aggregate intersect method

* Change the assert string to use ${name.length}

* Change test group name to align with style guide

* Update intersect logic to consider negative Y axis

---------

Co-authored-by: Marco Massarelli <60667061+ceoloide@users.noreply.github.com>
2023-07-19 23:00:44 +02:00
Bán Dénes
e924352763 Allow outline adjusts to use shape-specific units 2023-05-31 11:01:43 +02:00
Bán Dénes
14cd499182 4.0.4 2023-05-20 22:07:22 +02:00
Bán Dénes
7baa6a3b3a 4.0.3 2023-05-20 22:03:21 +02:00
Bán Dénes
9f644c2e2b Independent per-point adjustment 2023-05-20 22:03:21 +02:00
Bán Dénes
9832489d41
Sponsor fixes 2023-05-08 18:46:26 +02:00
Bán Dénes
89981199d9
Initial list of distinguished sponsors 2023-05-08 17:42:43 +02:00
Bán Dénes
63684e33d7
Add donate button to readme 2023-05-01 13:37:48 +02:00
Bán Dénes
d74f657f24
Add sponsorship button 2023-05-01 13:25:16 +02:00
Bán Dénes
daaef0af79 4.0.2 2023-03-18 16:24:47 +01:00
Bán Dénes
4d65eb19a6 Filter negation bugfix 2023-03-18 16:23:05 +01:00
Bán Dénes
3eac7f8e6d Rollup CJS changes 2023-03-18 00:04:38 +01:00
Bán Dénes
5761266260 4.0.1 2023-03-17 23:44:22 +01:00
Luke Kershaw
244fc53eae Handle backslashes in windows tests (#82) 2023-03-17 10:45:04 +01:00
Bán Dénes
9ad080d24c Templating bugfix (#86) 2023-03-17 10:29:55 +01:00
Bán Dénes
f0d22328cd Filter/mirror bugfix 2023-02-09 23:50:18 +01:00
Bán Dénes
480c362c1e Preprocessing bugfix 2023-01-30 15:01:52 +01:00
Bán Dénes
c45523f38a Getting coverage to 100% 2023-01-23 23:34:06 +01:00
Anarion
b27e10374e
Add array to footprint param types (#76) 2023-01-23 21:21:49 +01:00
Luke Kershaw
75f907917b
Extra test coverage for expand_shorthand (#80) 2023-01-23 14:46:57 +01:00
Luke Kershaw
86a74945ca
Fix typo in error message if using incorrect type for stagger (#75) 2023-01-23 12:22:59 +01:00
Bán Dénes
c480a33fa3 Readme postprocessing 2023-01-23 12:19:45 +01:00
Bán Dénes
841addb9ad Roadmap update 2023-01-23 11:17:27 +01:00
Bán Dénes
d2c3999d41 Fix multiple extrusions of the same outline in cases 2023-01-23 11:17:27 +01:00
Bán Dénes
77778249d2 Dependency update 2023-01-23 11:17:27 +01:00
トトも
357e01d639
Improve readme formatting (#62)
* Fixed LICENSE File Name
* Adjusted README Name
* Formatted Contribution Section
* Added License Badge
* Formatted Getting Started
* Moved Getting Started Into Dedicated File
* Added Quicklinks
* Fixed File Name
* Formatted Description + Added Showcase
* Adjusted Image Padding
* Adjusted Spacing
2023-01-23 11:17:01 +01:00
Luke Kershaw
e0eb43566f
Expand test coverage (#77)
* ignore line endings in cli tests
* ignore line endings in integration tests
* expand code coverage for `choc` footprint
* expand code coverage for `chocmini` footprint
* expand code coverage for `mx` footprint
* expand code coverage for `pad` footprint
* expand code coverage for rest of footprints
* expand code coverage for `anchor.js`
* expand code coverage for `units.js`
* expand code coverage for `points.js`
* expand code coverage for `filter.js`
* expand code coverage for `outlines.js`
* expand code coverage for `pcbs.js`
* expand code coverage for `ergogen.js`
* expand code coverage for `kle.js`
* more code coverage for `outlines.js`
* expand code coverage for `cases.js`
2023-01-23 10:02:08 +01:00
Luke Kershaw
3746900490
Bugfix for expand_shorthand (#79) 2023-01-23 09:32:22 +01:00
124 changed files with 44597 additions and 2891 deletions

1
.envrc Normal file
View file

@ -0,0 +1 @@
eval "$(lorri direnv)"

13
.github/FUNDING.yml vendored Normal file
View file

@ -0,0 +1,13 @@
# These are supported funding model platforms
github: [mrzealot] # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
patreon: # Replace with a single Patreon username
open_collective: # Replace with a single Open Collective username
ko_fi: # Replace with a single Ko-fi username
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
liberapay: # Replace with a single Liberapay username
issuehunt: # Replace with a single IssueHunt username
otechie: # Replace with a single Otechie username
lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']

249
.gitignore vendored
View file

@ -1,120 +1,129 @@
# Logs # Logs
logs logs
*.log *.log
npm-debug.log* npm-debug.log*
yarn-debug.log* yarn-debug.log*
yarn-error.log* yarn-error.log*
lerna-debug.log* lerna-debug.log*
# Diagnostic reports (https://nodejs.org/api/report.html) # Diagnostic reports (https://nodejs.org/api/report.html)
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
# Runtime data # Runtime data
pids pids
*.pid *.pid
*.seed *.seed
*.pid.lock *.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover # Directory for instrumented libs generated by jscoverage/JSCover
lib-cov lib-cov
# Coverage directory used by tools like istanbul # Coverage directory used by tools like istanbul
coverage coverage
*.lcov *.lcov
# nyc test coverage # nyc test coverage
.nyc_output .nyc_output
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
.grunt .grunt
# Bower dependency directory (https://bower.io/) # Bower dependency directory (https://bower.io/)
bower_components bower_components
# node-waf configuration # node-waf configuration
.lock-wscript .lock-wscript
# Compiled binary addons (https://nodejs.org/api/addons.html) # Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release build/Release
# Dependency directories # Dependency directories
node_modules/ node_modules/
jspm_packages/ jspm_packages/
# Snowpack dependency directory (https://snowpack.dev/) # Snowpack dependency directory (https://snowpack.dev/)
web_modules/ web_modules/
# TypeScript cache # TypeScript cache
*.tsbuildinfo *.tsbuildinfo
# Optional npm cache directory # Optional npm cache directory
.npm .npm
# Optional eslint cache # Optional eslint cache
.eslintcache .eslintcache
# Microbundle cache # Microbundle cache
.rpt2_cache/ .rpt2_cache/
.rts2_cache_cjs/ .rts2_cache_cjs/
.rts2_cache_es/ .rts2_cache_es/
.rts2_cache_umd/ .rts2_cache_umd/
# Optional REPL history # Optional REPL history
.node_repl_history .node_repl_history
# Output of 'npm pack' # Output of 'npm pack'
*.tgz *.tgz
# Yarn Integrity file # Yarn Integrity file
.yarn-integrity .yarn-integrity
# dotenv environment variables file # dotenv environment variables file
.env .env
.env.test .env.test
# parcel-bundler cache (https://parceljs.org/) # parcel-bundler cache (https://parceljs.org/)
.cache .cache
.parcel-cache .parcel-cache
# Next.js build output # Next.js build output
.next .next
out out
# Nuxt.js build / generate output # Nuxt.js build / generate output
.nuxt .nuxt
dist dist
# Gatsby files # Gatsby files
.cache/ .cache/
# Comment in the public line in if your project uses Gatsby and not Next.js # Comment in the public line in if your project uses Gatsby and not Next.js
# https://nextjs.org/blog/next-9-1#public-directory-support # https://nextjs.org/blog/next-9-1#public-directory-support
# public # public
# vuepress build output # vuepress build output
.vuepress/dist .vuepress/dist
# Serverless directories # Serverless directories
.serverless/ .serverless/
# FuseBox cache # FuseBox cache
.fusebox/ .fusebox/
# DynamoDB Local files # DynamoDB Local files
.dynamodb/ .dynamodb/
# TernJS port file # TernJS port file
.tern-port .tern-port
# Stores VSCode versions used for testing VSCode extensions # Stores VSCode versions used for testing VSCode extensions
.vscode-test .vscode-test
# yarn v2 # yarn v2
.yarn/cache .yarn/cache
.yarn/unplugged .yarn/unplugged
.yarn/build-state.yml .yarn/build-state.yml
.yarn/install-state.gz .yarn/install-state.gz
.pnp.* .pnp.*
# Project specific # Project specific
output output
temp* temp*
kicad/45treus/main.pro
kicad/45treus/main.kicad_pcb
*.kicad_pcb-bak
kicad/45treus/gerber_v*/*.gbr
kicad/45treus/gerber_v*/*.gbrjob
kicad/45treus/gerber_v*/*.drl
kicad/23creus/23creus-backups
kicad/23creus/fp-info-cache

271
23creus.yaml Normal file
View file

@ -0,0 +1,271 @@
# yaml-language-server: $schema=./meta/schema.json
units:
kx: cx
ky: cy
px: 2
py: 2
step: .5
points:
zones:
matrix:
columns:
pinky:
key:
column_net: P21
mirror: { column_net: P2 }
ring:
key:
stagger: 4
spread: kx + step
column_net: P20
mirror: { column_net: P3 }
middle:
key:
stagger: 5
spread: kx + step
column_net: P19
mirror: { column_net: P4 }
index:
key:
stagger: -5
spread: kx + step
column_net: P18
mirror: { column_net: P5 }
inner:
key:
stagger: -6
spread: kx + step
column_net: P15
mirror: { column_net: P6 }
thumb:
rows:
bottom:
skip: false
key:
skip: true
spread: kx + step
stagger: 10
column_net: P14
mirror: { column_net: P7 }
rows:
bottom:
row_net: P16
home:
spread: ky + step
row_net: P10
top:
spread: ky + step
row_net: P9
num:
spread: ky + step
row_net: P8
rotate: -23
mirror:
ref: matrix_thumb_bottom
distance: 42
outlines:
# outer border
farouter:
- what: polygon
points:
- ref: matrix_inner_num
shift: [13, 13]
- ref: matrix_middle_num
shift: [13, 13]
- ref: matrix_middle_num
shift: [-13, 13]
- ref: matrix_pinky_num
shift: [-13, 13]
- ref: matrix_pinky_bottom
shift: [-13, -13]
- ref: matrix_pinky_bottom
shift: [13, -13]
- ref: matrix_inner_bottom
shift: [-13, -13]
- ref: matrix_inner_bottom
shift: [13, -13]
- ref: mirror_matrix_inner_bottom
shift: [13, -13]
- ref: mirror_matrix_inner_bottom
shift: [-13, -13]
- ref: mirror_matrix_pinky_bottom
shift: [13, -13]
- ref: mirror_matrix_pinky_bottom
shift: [-13, -13]
- ref: mirror_matrix_pinky_num
shift: [-13, 13]
- ref: mirror_matrix_middle_num
shift: [-13, 13]
- ref: mirror_matrix_middle_num
shift: [13, 13]
- ref: mirror_matrix_inner_num
shift: [13, 13]
compatouter:
- what: polygon
points:
- ref: matrix_inner_num
shift: [11, 11]
- ref: matrix_middle_num
shift: [11, 11]
- ref: matrix_middle_num
shift: [-11, 11]
- ref: matrix_pinky_num
shift: [-11, 11]
- ref: matrix_pinky_bottom
shift: [-11, -11]
- ref: matrix_pinky_bottom
shift: [11, -11]
- ref: matrix_inner_bottom
shift: [-11, -11]
- ref: matrix_inner_bottom
shift: [11, -11]
- ref: mirror_matrix_inner_bottom
shift: [11, -11]
- ref: mirror_matrix_inner_bottom
shift: [-11, -11]
- ref: mirror_matrix_pinky_bottom
shift: [11, -11]
- ref: mirror_matrix_pinky_bottom
shift: [-11, -11]
- ref: mirror_matrix_pinky_num
shift: [-11, 11]
- ref: mirror_matrix_middle_num
shift: [-11, 11]
- ref: mirror_matrix_middle_num
shift: [11, 11]
- ref: mirror_matrix_inner_num
shift: [11, 11]
outer:
- what: polygon
points:
- ref: matrix_inner_num
shift: [10, 10]
- ref: matrix_middle_num
shift: [10, 10]
- ref: matrix_middle_num
shift: [-10, 10]
- ref: matrix_pinky_num
shift: [-10, 10]
- ref: matrix_pinky_bottom
shift: [-10, -10]
- ref: matrix_pinky_bottom
shift: [10, -10]
- ref: matrix_inner_bottom
shift: [-10, -10]
- ref: matrix_inner_bottom
shift: [10, -10]
- ref: mirror_matrix_inner_bottom
shift: [10, -10]
- ref: mirror_matrix_inner_bottom
shift: [-10, -10]
- ref: mirror_matrix_pinky_bottom
shift: [10, -10]
- ref: mirror_matrix_pinky_bottom
shift: [-10, -10]
- ref: mirror_matrix_pinky_num
shift: [-10, 10]
- ref: mirror_matrix_middle_num
shift: [-10, 10]
- ref: mirror_matrix_middle_num
shift: [10, 10]
- ref: mirror_matrix_inner_num
shift: [10, 10]
# chip
chip:
- what: rectangle
size: [18, 50]
where:
ref:
aggregate.parts:
- matrix_inner_bottom
- mirror_matrix_inner_bottom
shift: [0, 40]
# 14mm holes for cherry switches
keyholes:
- what: rectangle
where: true
asym: source
size: 13.8
# keycaps
keycaps:
- what: rectangle
where: true
asym: source
size: [17.95, 17.5]
# switchplate
switchplate:
- outer
- -keyholes
- -chip
# far outer switchplate
farouterswitchplate:
- farouter
- -keyholes
- -chip
cases:
laser:
- name: farouterswitchplate
extrude: 6.5
- name: compatouter
extrude: 5.2
shift: [0, 0, 1.3]
operation: subtract
pcbs:
main:
outlines:
outer:
outline: outer
footprints:
keys:
what: choc
where: true
params:
from: "{{colrow}}"
to: "{{column_net}}"
keycaps: true
hotswap: true
diode:
what: diode
where: true
params:
from: "{{colrow}}"
to: "{{row_net}}"
adjust:
shift: [0, -5]
rotate: 180
reset:
what: button
params:
from: RST
to: GND
where:
ref:
aggregate.parts:
- matrix_inner_bottom
- mirror_matrix_inner_bottom
rotate: 90
mcu:
what: promicro
where:
rotate: 270
ref:
aggregate.parts:
- matrix_inner_bottom
- mirror_matrix_inner_bottom
shift: [0, -4]

169
23treus.yaml Normal file
View file

@ -0,0 +1,169 @@
points:
key:
footprints:
mx_hotswap:
type: mx
params:
hotswap: true
reverse: false
keycaps: true
nets:
from: =colrow
to: =column_net
diode:
type: diode
nets:
from: =colrow
to: =row_net
anchor:
shift: [0, -5]
rotate: 180
zones:
matrix:
columns:
pinky:
key:
column_net: P21
mirror: { column_net: P2 }
ring:
key:
stagger: 4
column_net: P20
mirror: { column_net: P3 }
middle:
key:
stagger: 5
column_net: P19
mirror: { column_net: P4 }
index:
key:
stagger: -5
column_net: P18
mirror: { column_net: P5 }
inner:
key:
stagger: -6
column_net: P15
mirror: { column_net: P6 }
thumb:
row_overrides:
bottom:
key:
stagger: 10
column_net: P14
mirror: { column_net: P7}
rows:
bottom:
row_net: P16
home:
row_net: P10
top:
row_net: P9
num:
row_net: P8
rotate: -23
mirror:
ref: matrix_thumb_bottom
distance: 42
outlines:
exports:
# outer border
outer:
- type: polygon
points:
- ref: matrix_inner_num
shift: [10, 10]
- ref: matrix_middle_num
shift: [10, 10]
- ref: matrix_middle_num
shift: [-10, 10]
- ref: matrix_pinky_num
shift: [-10, 10]
- ref: matrix_pinky_bottom
shift: [-10, -10]
- ref: matrix_pinky_bottom
shift: [10, -10]
- ref: matrix_inner_bottom
shift: [-10, -10]
- ref: matrix_inner_bottom
shift: [10, -10]
- ref: mirror_matrix_inner_bottom
shift: [10, -10]
- ref: mirror_matrix_inner_bottom
shift: [-10, -10]
- ref: mirror_matrix_pinky_bottom
shift: [10, -10]
- ref: mirror_matrix_pinky_bottom
shift: [-10, -10]
- ref: mirror_matrix_pinky_num
shift: [-10, 10]
- ref: mirror_matrix_middle_num
shift: [-10, 10]
- ref: mirror_matrix_middle_num
shift: [10, 10]
- ref: mirror_matrix_inner_num
shift: [10, 10]
#- type: keys
# side: both
# size: 20
# corner: 1
#- type: polygon
# points:
# - ref: matrix_inner_num
# shift: [0, -5]
# - ref: matrix_thumb_bottom
# shift: [-10, -10]
# - ref: mirror_matrix_thumb_bottom
# shift: [-10, -10]
# - ref: mirror_matrix_inner_num
# shift: [0, -5]
chip:
# cutout for the chip itself
- type: rectangle
size: [18, 33]
anchor:
ref: [matrix_inner_top, mirror_matrix_inner_top]
shift: [-9, -24.5]
# cutout for the cable (looks)
- type: rectangle
size: [8, 50]
anchor:
ref: [matrix_inner_top, mirror_matrix_inner_top]
shift: [-4, -24.5]
# 14mm holes for cherry switches
keyholes:
- type: keys
side: both
size: 14
bound: false
# switchplate
switchplate:
- outer
- -keyholes
- -chip
cases:
pcbs:
main:
outlines:
outer:
outline: outer
footprints:
reset:
type: button
nets:
from: RST
to: GND
anchor:
ref: [matrix_inner_bottom, mirror_matrix_inner_bottom]
rotate: 90
mcu:
type: promicro
anchor:
rotate: 270
ref: [matrix_inner_top, mirror_matrix_inner_top]
shift: [0, -4]

View file

6
Makefile Normal file
View file

@ -0,0 +1,6 @@
all: node_modules
node src/cli.js 23creus.yaml -d -o output
cp output/pcbs/main.kicad_pcb kicad/23creus/
node_modules:
npm ci

111
README.md Normal file
View file

@ -0,0 +1,111 @@
# Ergogen
***Ergonomic Keyboard Generator***
<br>
<img
src = 'showcase.png'
width = 400
align = right
/>
The project aims to provide a common configuration format to describe ***ergonomic*** 2D layouts and generate automatic plates, cases, as well as un-routed PCBs for them. The project grew out of (and is an integral part of) the [Absolem keyboard], and shares its [Discord] server as well.
<div align = center>
<br>
<br>
<br>
---
[![Button WebUI]][WebUI]
[![Button Documentation]][Documentation]
[![Button Discord]][Discord]
[![Button Donate]][Donate]
---
</div>
<br>
<br>
## Getting Started
Until there's a proper "Getting started" guide, try getting acquainted with **Ergogen** by following these steps in order:
<br>
1. Read the **[Documentation]**.
D'uuh.
They're not complete by any measure, but should give you a fairly good idea what you're dealing with here.
<br>
2. Try one of the web-based deployments.
[![Button Official]][WebUI]
[![Button Unofficial]][Unofficial]
The unofficial deployment is probably better, tbh, and will soon be replacing the official one.
Choose either one, then click things, look at outputs and see if things start to make sense.
There is no need for you to download the **CLI** unless you want to do one of the following:
- Preview in-development features
- Use custom modifications
- Contribute code
<br>
3. Search the [`ergogen`][Topic] topic on GitHub.
There, you can look at (and reverse engineer) a variety of real life configs using **Ergogen**.
Pop them into the web UI to see what they do, tinker with them and things should start to make more sense.
<br>
4. If a question persists after all of the above, feel free to ask it over on **[Discord]** and we'll do our best to help you out.
<br>
## Contributions
Feature ideas, documentation improvements, examples, tests, or pull requests welcome!
Get in touch on our **[Discord]**, and we can definitely find something you can help with, if you'd like to.
<br>
## Sponsors
Huge thanks go to everyone who chooses to support my work!
But even huger thanks are due to the following, *distinguished* sponsors:
- [perce](https://madebyperce.com/)
- [Cache](https://github.com/MvEerd)
- [Neil Gilmour](https://github.com/neilgilmour)
- [ochief](https://github.com/ochief)
- [Alyx Brett](https://github.com/alyx-brett)
<!----------------------------------------------------------------------------->
[Absolem keyboard]: https://zealot.hu/absolem
[Documentation]: https://docs.ergogen.xyz
[Discord]: http://discord.ergogen.xyz
[WebUI]: https://ergogen.xyz
[Unofficial]: https://ergogen.cache.works/
[Topic]: https://github.com/topics/ergogen
[Donate]: https://github.com/sponsors/mrzealot
<!--------------------------------{ Buttons }---------------------------------->
[Button WebUI]: https://img.shields.io/badge/Deployment-37a779?style=for-the-badge&logoColor=white&logo=AppleArcade
[Button Unofficial]: https://img.shields.io/badge/Unofficial-yellow?style=for-the-badge
[Button Official]: https://img.shields.io/badge/Official-37a779?style=for-the-badge
[Button Documentation]: https://img.shields.io/badge/Documentation-1793D1?style=for-the-badge&logoColor=white&logo=GitBook
[Button Discord]: https://img.shields.io/badge/Discord-5865F2?style=for-the-badge&logoColor=white&logo=Discord
[Button Donate]: https://img.shields.io/badge/Donate-EA4AAA?style=for-the-badge&logoColor=white&logo=githubsponsors

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,77 @@
{
"board": {
"active_layer": 37,
"active_layer_preset": "All Layers",
"auto_track_width": true,
"hidden_netclasses": [],
"hidden_nets": [],
"high_contrast_mode": 0,
"net_color_mode": 1,
"opacity": {
"images": 0.6,
"pads": 1.0,
"tracks": 1.0,
"vias": 1.0,
"zones": 0.6
},
"ratsnest_display_mode": 0,
"selection_filter": {
"dimensions": true,
"footprints": true,
"graphics": true,
"keepouts": true,
"lockedItems": true,
"otherItems": true,
"pads": true,
"text": true,
"tracks": true,
"vias": true,
"zones": true
},
"visible_items": [
0,
1,
2,
3,
4,
5,
8,
9,
10,
11,
12,
13,
14,
15,
16,
17,
18,
19,
20,
21,
22,
23,
24,
25,
26,
27,
28,
29,
30,
32,
33,
34,
35,
36
],
"visible_layers": "fffffff_ffffffff",
"zone_display_mode": 0
},
"meta": {
"filename": "23creus.kicad_prl",
"version": 3
},
"project": {
"files": []
}
}

View file

@ -0,0 +1,731 @@
{
"board": {
"3dviewports": [],
"design_settings": {
"defaults": {
"board_outline_line_width": 0.049999999999999996,
"copper_line_width": 0.19999999999999998,
"copper_text_italic": false,
"copper_text_size_h": 1.5,
"copper_text_size_v": 1.5,
"copper_text_thickness": 0.3,
"copper_text_upright": false,
"courtyard_line_width": 0.049999999999999996,
"dimension_precision": 4,
"dimension_units": 3,
"dimensions": {
"arrow_length": 1270000,
"extension_offset": 500000,
"keep_text_aligned": true,
"suppress_zeroes": false,
"text_position": 0,
"units_format": 1
},
"fab_line_width": 0.09999999999999999,
"fab_text_italic": false,
"fab_text_size_h": 1.0,
"fab_text_size_v": 1.0,
"fab_text_thickness": 0.15,
"fab_text_upright": false,
"other_line_width": 0.09999999999999999,
"other_text_italic": false,
"other_text_size_h": 1.0,
"other_text_size_v": 1.0,
"other_text_thickness": 0.15,
"other_text_upright": false,
"pads": {
"drill": 0.762,
"height": 1.524,
"width": 1.524
},
"silk_line_width": 0.12,
"silk_text_italic": false,
"silk_text_size_h": 1.0,
"silk_text_size_v": 1.0,
"silk_text_thickness": 0.15,
"silk_text_upright": false,
"zones": {
"min_clearance": 0.508
}
},
"diff_pair_dimensions": [],
"drc_exclusions": [],
"meta": {
"filename": "board_design_settings.json",
"version": 2
},
"rule_severities": {
"annular_width": "error",
"clearance": "error",
"connection_width": "warning",
"copper_edge_clearance": "error",
"copper_sliver": "warning",
"courtyards_overlap": "error",
"diff_pair_gap_out_of_range": "error",
"diff_pair_uncoupled_length_too_long": "error",
"drill_out_of_range": "error",
"duplicate_footprints": "warning",
"extra_footprint": "warning",
"footprint": "error",
"footprint_type_mismatch": "ignore",
"hole_clearance": "error",
"hole_near_hole": "error",
"invalid_outline": "error",
"isolated_copper": "warning",
"item_on_disabled_layer": "error",
"items_not_allowed": "error",
"length_out_of_range": "error",
"lib_footprint_issues": "warning",
"lib_footprint_mismatch": "warning",
"malformed_courtyard": "error",
"microvia_drill_out_of_range": "error",
"missing_courtyard": "ignore",
"missing_footprint": "warning",
"net_conflict": "warning",
"npth_inside_courtyard": "ignore",
"padstack": "warning",
"pth_inside_courtyard": "ignore",
"shorting_items": "error",
"silk_edge_clearance": "warning",
"silk_over_copper": "warning",
"silk_overlap": "warning",
"skew_out_of_range": "error",
"solder_mask_bridge": "error",
"starved_thermal": "error",
"text_height": "warning",
"text_thickness": "warning",
"through_hole_pad_without_hole": "error",
"too_many_vias": "error",
"track_dangling": "warning",
"track_width": "error",
"tracks_crossing": "error",
"unconnected_items": "error",
"unresolved_variable": "error",
"via_dangling": "warning",
"zones_intersect": "error"
},
"rules": {
"max_error": 0.005,
"min_clearance": 0.0,
"min_connection": 0.0,
"min_copper_edge_clearance": 0.075,
"min_hole_clearance": 0.25,
"min_hole_to_hole": 0.25,
"min_microvia_diameter": 0.19999999999999998,
"min_microvia_drill": 0.09999999999999999,
"min_resolved_spokes": 2,
"min_silk_clearance": 0.0,
"min_text_height": 0.7999999999999999,
"min_text_thickness": 0.08,
"min_through_hole_diameter": 0.3,
"min_track_width": 0.19999999999999998,
"min_via_annular_width": 0.09999999999999999,
"min_via_diameter": 0.39999999999999997,
"solder_mask_to_copper_clearance": 0.0,
"use_height_for_length_calcs": true
},
"teardrop_options": [
{
"td_allow_use_two_tracks": true,
"td_curve_segcount": 5,
"td_on_pad_in_zone": false,
"td_onpadsmd": true,
"td_onroundshapesonly": false,
"td_ontrackend": false,
"td_onviapad": true
}
],
"teardrop_parameters": [
{
"td_curve_segcount": 0,
"td_height_ratio": 1.0,
"td_length_ratio": 0.5,
"td_maxheight": 2.0,
"td_maxlen": 1.0,
"td_target_name": "td_round_shape",
"td_width_to_size_filter_ratio": 0.9
},
{
"td_curve_segcount": 0,
"td_height_ratio": 1.0,
"td_length_ratio": 0.5,
"td_maxheight": 2.0,
"td_maxlen": 1.0,
"td_target_name": "td_rect_shape",
"td_width_to_size_filter_ratio": 0.9
},
{
"td_curve_segcount": 0,
"td_height_ratio": 1.0,
"td_length_ratio": 0.5,
"td_maxheight": 2.0,
"td_maxlen": 1.0,
"td_target_name": "td_track_end",
"td_width_to_size_filter_ratio": 0.9
}
],
"track_widths": [],
"via_dimensions": [],
"zones_allow_external_fillets": false,
"zones_use_no_outline": true
},
"layer_presets": [],
"viewports": []
},
"boards": [],
"cvpcb": {
"equivalence_files": []
},
"erc": {
"erc_exclusions": [],
"meta": {
"version": 0
},
"pin_map": [
[
0,
0,
0,
0,
0,
0,
1,
0,
0,
0,
0,
2
],
[
0,
2,
0,
1,
0,
0,
1,
0,
2,
2,
2,
2
],
[
0,
0,
0,
0,
0,
0,
1,
0,
1,
0,
1,
2
],
[
0,
1,
0,
0,
0,
0,
1,
1,
2,
1,
1,
2
],
[
0,
0,
0,
0,
0,
0,
1,
0,
0,
0,
0,
2
],
[
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
2
],
[
1,
1,
1,
1,
1,
0,
1,
1,
1,
1,
1,
2
],
[
0,
0,
0,
1,
0,
0,
1,
0,
0,
0,
0,
2
],
[
0,
2,
1,
2,
0,
0,
1,
0,
2,
2,
2,
2
],
[
0,
2,
0,
1,
0,
0,
1,
0,
2,
0,
0,
2
],
[
0,
2,
1,
1,
0,
0,
1,
0,
2,
0,
0,
2
],
[
2,
2,
2,
2,
2,
2,
2,
2,
2,
2,
2,
2
]
],
"rule_severities": {
"bus_definition_conflict": "error",
"bus_entry_needed": "error",
"bus_label_syntax": "error",
"bus_to_bus_conflict": "error",
"bus_to_net_conflict": "error",
"different_unit_footprint": "error",
"different_unit_net": "error",
"duplicate_reference": "error",
"duplicate_sheet_names": "error",
"extra_units": "error",
"global_label_dangling": "warning",
"hier_label_mismatch": "error",
"label_dangling": "error",
"lib_symbol_issues": "warning",
"multiple_net_names": "warning",
"net_not_bus_member": "warning",
"no_connect_connected": "warning",
"no_connect_dangling": "warning",
"pin_not_connected": "error",
"pin_not_driven": "error",
"pin_to_pin": "warning",
"power_pin_not_driven": "error",
"similar_labels": "warning",
"unannotated": "error",
"unit_value_mismatch": "error",
"unresolved_variable": "error",
"wire_dangling": "error"
}
},
"libraries": {
"pinned_footprint_libs": [],
"pinned_symbol_libs": []
},
"meta": {
"filename": "23creus.kicad_pro",
"version": 1
},
"net_settings": {
"classes": [
{
"bus_width": 12,
"clearance": 0.2,
"diff_pair_gap": 0.25,
"diff_pair_via_gap": 0.25,
"diff_pair_width": 0.2,
"line_style": 0,
"microvia_diameter": 0.3,
"microvia_drill": 0.1,
"name": "Default",
"pcb_color": "rgba(0, 0, 0, 0.000)",
"schematic_color": "rgba(0, 0, 0, 0.000)",
"track_width": 0.25,
"via_diameter": 0.8,
"via_drill": 0.4,
"wire_width": 6
}
],
"meta": {
"version": 3
},
"net_colors": null,
"netclass_assignments": null,
"netclass_patterns": [
{
"netclass": "Default",
"pattern": ""
},
{
"netclass": "Default",
"pattern": "pinky_bottom"
},
{
"netclass": "Default",
"pattern": "P21"
},
{
"netclass": "Default",
"pattern": "pinky_home"
},
{
"netclass": "Default",
"pattern": "pinky_top"
},
{
"netclass": "Default",
"pattern": "pinky_num"
},
{
"netclass": "Default",
"pattern": "ring_bottom"
},
{
"netclass": "Default",
"pattern": "P20"
},
{
"netclass": "Default",
"pattern": "ring_home"
},
{
"netclass": "Default",
"pattern": "ring_top"
},
{
"netclass": "Default",
"pattern": "ring_num"
},
{
"netclass": "Default",
"pattern": "middle_bottom"
},
{
"netclass": "Default",
"pattern": "P19"
},
{
"netclass": "Default",
"pattern": "middle_home"
},
{
"netclass": "Default",
"pattern": "middle_top"
},
{
"netclass": "Default",
"pattern": "middle_num"
},
{
"netclass": "Default",
"pattern": "index_bottom"
},
{
"netclass": "Default",
"pattern": "P18"
},
{
"netclass": "Default",
"pattern": "index_home"
},
{
"netclass": "Default",
"pattern": "index_top"
},
{
"netclass": "Default",
"pattern": "index_num"
},
{
"netclass": "Default",
"pattern": "inner_bottom"
},
{
"netclass": "Default",
"pattern": "P15"
},
{
"netclass": "Default",
"pattern": "inner_home"
},
{
"netclass": "Default",
"pattern": "inner_top"
},
{
"netclass": "Default",
"pattern": "inner_num"
},
{
"netclass": "Default",
"pattern": "thumb_bottom"
},
{
"netclass": "Default",
"pattern": "P14"
},
{
"netclass": "Default",
"pattern": "mirror_pinky_bottom"
},
{
"netclass": "Default",
"pattern": "P2"
},
{
"netclass": "Default",
"pattern": "mirror_pinky_home"
},
{
"netclass": "Default",
"pattern": "mirror_pinky_top"
},
{
"netclass": "Default",
"pattern": "mirror_pinky_num"
},
{
"netclass": "Default",
"pattern": "mirror_ring_bottom"
},
{
"netclass": "Default",
"pattern": "P3"
},
{
"netclass": "Default",
"pattern": "mirror_ring_home"
},
{
"netclass": "Default",
"pattern": "mirror_ring_top"
},
{
"netclass": "Default",
"pattern": "mirror_ring_num"
},
{
"netclass": "Default",
"pattern": "mirror_middle_bottom"
},
{
"netclass": "Default",
"pattern": "P4"
},
{
"netclass": "Default",
"pattern": "mirror_middle_home"
},
{
"netclass": "Default",
"pattern": "mirror_middle_top"
},
{
"netclass": "Default",
"pattern": "mirror_middle_num"
},
{
"netclass": "Default",
"pattern": "mirror_index_bottom"
},
{
"netclass": "Default",
"pattern": "P5"
},
{
"netclass": "Default",
"pattern": "mirror_index_home"
},
{
"netclass": "Default",
"pattern": "mirror_index_top"
},
{
"netclass": "Default",
"pattern": "mirror_index_num"
},
{
"netclass": "Default",
"pattern": "mirror_inner_bottom"
},
{
"netclass": "Default",
"pattern": "P6"
},
{
"netclass": "Default",
"pattern": "mirror_inner_home"
},
{
"netclass": "Default",
"pattern": "mirror_inner_top"
},
{
"netclass": "Default",
"pattern": "mirror_inner_num"
},
{
"netclass": "Default",
"pattern": "mirror_thumb_bottom"
},
{
"netclass": "Default",
"pattern": "P7"
},
{
"netclass": "Default",
"pattern": "P16"
},
{
"netclass": "Default",
"pattern": "P10"
},
{
"netclass": "Default",
"pattern": "P9"
},
{
"netclass": "Default",
"pattern": "P8"
},
{
"netclass": "Default",
"pattern": "RST"
},
{
"netclass": "Default",
"pattern": "GND"
},
{
"netclass": "Default",
"pattern": "RAW"
},
{
"netclass": "Default",
"pattern": "VCC"
},
{
"netclass": "Default",
"pattern": "P1"
},
{
"netclass": "Default",
"pattern": "P0"
}
]
},
"pcbnew": {
"last_paths": {
"gencad": "",
"idf": "",
"netlist": "",
"specctra_dsn": "",
"step": "",
"vrml": ""
},
"page_layout_descr_file": ""
},
"schematic": {
"annotate_start_num": 0,
"drawing": {
"default_line_thickness": 6.0,
"default_text_size": 50.0,
"field_names": [],
"intersheets_ref_own_page": false,
"intersheets_ref_prefix": "",
"intersheets_ref_short": false,
"intersheets_ref_show": false,
"intersheets_ref_suffix": "",
"junction_size_choice": 3,
"label_size_ratio": 0.375,
"pin_symbol_size": 25.0,
"text_offset_ratio": 0.15
},
"legacy_lib_dir": "",
"legacy_lib_list": [],
"meta": {
"version": 1
},
"net_format_name": "",
"ngspice": {
"fix_include_paths": true,
"fix_passive_vals": false,
"meta": {
"version": 0
},
"model_mode": 0,
"workbook_filename": ""
},
"page_layout_descr_file": "",
"plot_directory": "",
"spice_adjust_passive_values": false,
"spice_external_command": "spice \"%I\"",
"subpart_first_id": 65,
"subpart_id_separator": 0
},
"sheets": [],
"text_variables": {}
}

View file

@ -0,0 +1,5 @@
(kicad_sch (version 20211123) (generator eeschema)
(paper "A4")
(lib_symbols)
(symbol_instances)
)

7254
kicad/23creus/main.kicad_pcb Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1 @@
(kicad_pcb (version 4) (host kicad "dummy file") )

33
kicad/45treus/45treus.pro Normal file
View file

@ -0,0 +1,33 @@
update=22/05/2015 07: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
[cvpcb]
version=1
NetIExt=net
[eeschema]
version=1
LibDir=
[eeschema/libraries]

View file

@ -0,0 +1,4 @@
EESchema Schematic File Version 2
EELAYER 25 0
EELAYER END
$EndSCHEMATC

View file

@ -0,0 +1 @@
0

Binary file not shown.

Binary file not shown.

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,33 @@
update=22/05/2015 07: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
[cvpcb]
version=1
NetIExt=net
[eeschema]
version=1
LibDir=
[eeschema/libraries]

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,33 @@
update=22/05/2015 07: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
[cvpcb]
version=1
NetIExt=net
[eeschema]
version=1
LibDir=
[eeschema/libraries]

File diff suppressed because it is too large Load diff

3418
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,6 @@
{ {
"name": "ergogen", "name": "ergogen",
"version": "4.0.0", "version": "4.0.5",
"description": "Ergonomic keyboard layout generator", "description": "Ergonomic keyboard layout generator",
"author": "Bán Dénes <mr@zealot.hu>", "author": "Bán Dénes <mr@zealot.hu>",
"license": "MIT", "license": "MIT",
@ -15,24 +15,25 @@
"coverage": "nyc --reporter=html --reporter=text npm test" "coverage": "nyc --reporter=html --reporter=text npm test"
}, },
"dependencies": { "dependencies": {
"fs-extra": "^10.0.1", "fs-extra": "^11.1.0",
"js-yaml": "^3.14.1", "js-yaml": "^3.14.1",
"jszip": "^3.10.1", "jszip": "^3.10.1",
"kle-serial": "github:ergogen/kle-serial#ergogen", "kle-serial": "github:ergogen/kle-serial#ergogen",
"makerjs": "github:ergogen/maker.js#ergogen", "makerjs": "github:ergogen/maker.js#ergogen",
"mathjs": "^10.1.1", "mathjs": "^11.5.0",
"yargs": "^17.3.1" "yargs": "^17.6.2"
}, },
"devDependencies": { "devDependencies": {
"@rollup/plugin-commonjs": "^21.0.2", "@rollup/plugin-commonjs": "^24.0.1",
"@rollup/plugin-json": "^4.1.0", "@rollup/plugin-json": "^6.0.0",
"chai": "^4.3.6", "chai": "^4.3.7",
"chai-as-promised": "^7.1.1", "chai-as-promised": "^7.1.1",
"dir-compare": "^4.0.0", "dir-compare": "^4.0.0",
"glob": "^7.2.0", "glob": "^8.1.0",
"mocha": "^9.2.1", "mocha": "^10.2.0",
"nyc": "^15.1.0", "nyc": "^15.1.0",
"rollup": "^2.68.0" "rollup": "^3.10.1",
"sinon": "^15.0.1"
}, },
"nyc": { "nyc": {
"all": true, "all": true,

View file

@ -1,22 +0,0 @@
# Ergogen
Ergogen is a keyboard generator that aims to provide a common configuration format to describe **ergonomic** 2D layouts, and generate automatic plates, cases, and (un-routed) PCBs for them.
The project grew out of (and is an integral part of) the [Absolem keyboard](https://zealot.hu/absolem), and shares its [Discord server](https://discord.gg/nbKcAZB) as well.
## Getting started
Until there's a proper "Getting started" guide, try getting acquainted with ergogen by following these steps in order:
1. Read the [docs](https://docs.ergogen.xyz). D'uuh. They're not complete by any measure, but should give you a fairly good idea what you're dealing with here.
1. Try one of the web-based deployments ([official](https://ergogen.xyz); [unofficial](https://ergogen.cache.works/) but probably better and soon to be official) - no need to download the CLI unless you want to A) preview in-development features, B) use custom modifications, or C) contribute code. Click things, look at outputs; see if things start to make sense.
1. Search the [`#ergogen`](https://github.com/topics/ergogen) topic on GitHub to look at (and reverse engineer) a variety of real life configs using ergogen. Pop them into the web UI, see what they do, tinker with them; things should start to make more and more sense.
1. If a question persists after all of the above, feel free to ask it over on [Discord](https://discord.gg/nbKcAZB) and we'll do our best to help you out.
## Contributions
Feature ideas, documentation improvements, examples, tests, or pull requests welcome!
Get in touch [on Discord](https://discord.gg/nbKcAZB), and we can definitely find something you can help with, if you'd like to.

View file

@ -14,6 +14,10 @@
### Minor ### Minor
- Support "direct" anchors, as in, recognize num arrays and parse them as x/y/r
- Add `origin` to zone-wide and global rotation in points
- Handle unnecessary (but seemingly consistent, so easy to confuse) `key` subfield of row-level overrides
- Allow footprints to access raw array/object fields from points with templating
- Include raw kicad footprint integrations - Include raw kicad footprint integrations
- pull torik's script to be able to convert raw kicad footprints into positionable ergogen ones - pull torik's script to be able to convert raw kicad footprints into positionable ergogen ones
- have a `dummy` footprint which can just be updated from schematic - have a `dummy` footprint which can just be updated from schematic

View file

@ -1,4 +1,4 @@
import pkg from './package.json' import pkg from './package.json' assert { type: 'json' }
import json from '@rollup/plugin-json' import json from '@rollup/plugin-json'
import commonjs from '@rollup/plugin-commonjs' import commonjs from '@rollup/plugin-commonjs'

8
shell.nix Normal file
View file

@ -0,0 +1,8 @@
{ pkgs ? import <nixpkgs> {} }:
pkgs.mkShell {
buildInputs = with pkgs; [
bashInteractive
nodejs-16_x
];
}

BIN
showcase.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

View file

@ -1,6 +1,7 @@
const u = require('./utils') const u = require('./utils')
const a = require('./assert') const a = require('./assert')
const Point = require('./point') const Point = require('./point')
const m = require('makerjs')
const mirror_ref = exports.mirror = (ref, mirror=true) => { const mirror_ref = exports.mirror = (ref, mirror=true) => {
if (mirror) { if (mirror) {
@ -17,15 +18,52 @@ const aggregator_common = ['parts', 'method']
const aggregators = { const aggregators = {
average: (config, name, parts) => { average: (config, name, parts) => {
a.unexpected(config, name, aggregator_common) a.unexpected(config, name, aggregator_common)
let x = 0, y = 0, r = 0
const len = parts.length const len = parts.length
if (len == 0) {
return new Point()
}
let x = 0, y = 0, r = 0
for (const part of parts) { for (const part of parts) {
x += part.x x += part.x
y += part.y y += part.y
r += part.r r += part.r
} }
return new Point(x / len, y / len, r / len) return new Point(x / len, y / len, r / len)
} },
intersect: (config, name, parts) => {
// a line is generated from a point by taking their
// (rotated) Y axis. The line is not extended to
// +/- Infinity as that doesn't work with makerjs.
// An arbitrary offset of 1 meter is considered
// sufficient for practical purposes, and the point
// coordinates are used as pivot point for the rotation.
const get_line_from_point = (point, offset=1000) => {
const origin = [point.x, point.y]
const p1 = [point.x, point.y - offset]
const p2 = [point.x, point.y + offset]
let line = new m.paths.Line(p1, p2)
line = m.path.rotate(line, point.r, origin)
return line
}
a.unexpected(config, name, aggregator_common)
a.assert(parts.length==2, `Intersect expects exactly two parts, but it got ${parts.length}!`)
const line1 = get_line_from_point(parts[0])
const line2 = get_line_from_point(parts[1])
const intersection = m.path.intersection(line1, line2)
a.assert(intersection, `The points under "${name}.parts" do not intersect!`)
const intersection_point_arr = intersection.intersectionPoints[0]
const intersection_point = new Point(
intersection_point_arr[0], intersection_point_arr[1], 0
)
return intersection_point
},
} }
const anchor = exports.parse = (raw, name, points={}, start=new Point(), mirror=false) => units => { const anchor = exports.parse = (raw, name, points={}, start=new Point(), mirror=false) => units => {
@ -53,7 +91,7 @@ const anchor = exports.parse = (raw, name, points={}, start=new Point(), mirror=
// //
// Reference or aggregate handling // Reference or aggregate handling
// //
let point = start.clone() let point = start.clone()
if (raw.ref !== undefined && raw.aggregate !== undefined) { if (raw.ref !== undefined && raw.aggregate !== undefined) {
throw new Error(`Fields "ref" and "aggregate" cannot appear together in anchor "${name}"!`) throw new Error(`Fields "ref" and "aggregate" cannot appear together in anchor "${name}"!`)

View file

@ -69,15 +69,19 @@ exports.parse = (config, outlines, units) => {
const extrude = a.sane(part.extrude || 1, `${part_qname}.extrude`, 'number')(units) const extrude = a.sane(part.extrude || 1, `${part_qname}.extrude`, 'number')(units)
const outline = outlines[name] const outline = outlines[name]
a.assert(outline, `Field "${part_qname}.name" does not name a valid outline!`) a.assert(outline, `Field "${part_qname}.name" does not name a valid outline!`)
if (!scripts[name]) { // This is a hack to separate multiple calls to the same outline with different extrude values
scripts[name] = m.exporter.toJscadScript(outline, { // I know it needlessly duplicates a lot of code, but it's the quickest fix in the short term
functionName: `${name}_outline_fn`, // And on the long run, we'll probably be moving to CADQuery anyway...
const extruded_name = `${name}_extrude_` + ('' + extrude).replace(/\D/g, '_')
if (!scripts[extruded_name]) {
scripts[extruded_name] = m.exporter.toJscadScript(outline, {
functionName: `${extruded_name}_outline_fn`,
extrude: extrude, extrude: extrude,
indent: 4 indent: 4
}) })
} }
outline_dependencies.push(name) outline_dependencies.push(extruded_name)
base = `${name}_outline_fn()` base = `${extruded_name}_outline_fn()`
} else { } else {
a.assert(part.extrude === undefined, `Field "${part_qname}.extrude" should not be used when what=case!`) a.assert(part.extrude === undefined, `Field "${part_qname}.extrude" should not be used when what=case!`)
a.in(name, `${part_qname}.name`, Object.keys(cases)) a.in(name, `${part_qname}.name`, Object.keys(cases))

View file

@ -132,12 +132,14 @@ try {
// output helpers // output helpers
const yamldump = data => yaml.dump(data, {indent: 4, noRefs: true})
const single = (data, rel) => { const single = (data, rel) => {
if (!data) return if (!data) return
const abs = path.join(args.o, rel) const abs = path.join(args.o, rel)
fs.mkdirpSync(path.dirname(abs)) fs.mkdirpSync(path.dirname(abs))
if (abs.endsWith('.yaml')) { if (abs.endsWith('.yaml')) {
fs.writeFileSync(abs, yaml.dump(data, {indent: 4})) fs.writeFileSync(abs, yamldump(data))
} else { } else {
fs.writeFileSync(abs, data) fs.writeFileSync(abs, data)
} }
@ -148,7 +150,7 @@ const composite = (data, rel) => {
const abs = path.join(args.o, rel) const abs = path.join(args.o, rel)
if (data.yaml) { if (data.yaml) {
fs.mkdirpSync(path.dirname(abs)) fs.mkdirpSync(path.dirname(abs))
fs.writeFileSync(abs + '.yaml', yaml.dump(data.yaml, {indent: 4})) fs.writeFileSync(abs + '.yaml', yamldump(data.yaml))
} }
for (const format of ['svg', 'dxf', 'jscad']) { for (const format of ['svg', 'dxf', 'jscad']) {
if (data[format]) { if (data[format]) {

View file

@ -9,9 +9,8 @@ const _false = () => false
const _and = arr => p => arr.map(e => e(p)).reduce((a, b) => a && b) const _and = arr => p => arr.map(e => e(p)).reduce((a, b) => a && b)
const _or = arr => p => arr.map(e => e(p)).reduce((a, b) => a || b) const _or = arr => p => arr.map(e => e(p)).reduce((a, b) => a || b)
const similar = (key, reference, name, units) => { const similar = (keys, reference, name, units) => {
let neg = false let neg = false
if (reference.startsWith('-')) { if (reference.startsWith('-')) {
neg = true neg = true
reference = reference.slice(1) reference = reference.slice(1)
@ -20,15 +19,19 @@ const similar = (key, reference, name, units) => {
// support both string or regex as reference // support both string or regex as reference
let internal_tester = val => (''+val) == reference let internal_tester = val => (''+val) == reference
if (reference.startsWith('/')) { if (reference.startsWith('/')) {
const regex_parts = reference.split('/') try {
regex_parts.shift() // remove starting slash const regex_parts = reference.split('/')
const flags = regex_parts.pop() regex_parts.shift() // remove starting slash
const regex = new RegExp(regex_parts.join('/'), flags) const flags = regex_parts.pop()
internal_tester = val => regex.test(''+val) const regex = new RegExp(regex_parts.join('/'), flags)
internal_tester = val => regex.test(''+val)
} catch (ex) {
throw new Error(`Invalid regex "${reference}" found at filter "${name}"!`)
}
} }
// support strings, arrays, or objects as key // support strings, arrays, or objects as key
const external_tester = point => { const external_tester = (point, key) => {
const value = u.deep(point, key) const value = u.deep(point, key)
if (a.type(value)() == 'array') { if (a.type(value)() == 'array') {
return value.some(subkey => internal_tester(subkey)) return value.some(subkey => internal_tester(subkey))
@ -39,11 +42,12 @@ const similar = (key, reference, name, units) => {
} }
} }
// negation happens at the end // consider negation
if (neg) { if (neg) {
return point => !external_tester(point) return point => keys.every(key => !external_tester(point, key))
} else {
return point => keys.some(key => external_tester(point, key))
} }
return external_tester
} }
const comparators = { const comparators = {
@ -75,7 +79,7 @@ const simple = (exp, name, units) => {
value = exp value = exp
} }
return point => keys.some(key => comparators[op](key, value, name, units)(point)) return point => comparators[op](keys, value, name, units)(point)
} }
const complex = (config, name, units, aggregator=_or) => { const complex = (config, name, units, aggregator=_or) => {
@ -109,7 +113,7 @@ const contains_object = (val) => {
} }
exports.parse = (config, name, points={}, units={}, asym='source') => { exports.parse = (config, name, points={}, units={}, asym='source') => {
let result = [] let result = []
// if a filter decl is undefined, it's just the default point at [0, 0] // if a filter decl is undefined, it's just the default point at [0, 0]
@ -123,7 +127,11 @@ exports.parse = (config, name, points={}, units={}, asym='source') => {
} }
if (['clone', 'both'].includes(asym)) { if (['clone', 'both'].includes(asym)) {
// this is strict: if the ref of the anchor doesn't have a mirror pair, it will error out // this is strict: if the ref of the anchor doesn't have a mirror pair, it will error out
result.push(anchor(config, name, points, undefined, true)(units)) // also, we check for duplicates as ref-less anchors mirror to themselves
const clone = anchor(config, name, points, undefined, true)(units)
if (result.every(p => !p.equals(clone))) {
result.push(clone)
}
} }
// otherwise, it is treated as a condition to filter all available points // otherwise, it is treated as a condition to filter all available points
@ -132,9 +140,15 @@ exports.parse = (config, name, points={}, units={}, asym='source') => {
if (['source', 'both'].includes(asym)) { if (['source', 'both'].includes(asym)) {
result = result.concat(source) result = result.concat(source)
} }
if (['source', 'both'].includes(asym)) { if (['clone', 'both'].includes(asym)) {
// this is permissive: we only include mirrored versions if they exist, and don't fuss if they don't // this is permissive: we only include mirrored versions if they exist, and don't fuss if they don't
result = result.concat(source.map(p => points[anchor_lib.mirror(p.meta.name)]).filter(p => !!p)) // also, we check for duplicates as clones can potentially refer back to their sources, too
const pool = result.map(p => p.meta.name)
result = result.concat(
source.map(p => points[anchor_lib.mirror(p.meta.name)])
.filter(p => !!p)
.filter(p => !pool.includes(p.meta.name))
)
} }
} }

View file

@ -25,8 +25,8 @@ module.exports = {
(fp_line (start 7 -7) (end 7 -6) (layer Dwgs.User) (width 0.15)) (fp_line (start 7 -7) (end 7 -6) (layer Dwgs.User) (width 0.15))
${''/* pins */} ${''/* pins */}
(pad 1 thru_hole circle (at 2.5 -4.5) (size 2.25 2.25) (drill 1.47) (layers *.Cu *.Mask) ${p.from.str}) (pad 1 thru_hole circle (at 2.5 -4.5) (size 2.25 2.25) (drill 1.47) (layers *.Cu *.Mask) ${p.from})
(pad 2 thru_hole circle (at -2.5 -4) (size 2.25 2.25) (drill 1.47) (layers *.Cu *.Mask) ${p.to.str}) (pad 2 thru_hole circle (at -2.5 -4) (size 2.25 2.25) (drill 1.47) (layers *.Cu *.Mask) ${p.to})
) )
` `

View file

@ -28,10 +28,10 @@ module.exports = {
(fp_line (start -2.75 -1.25) (end -2.75 1.25) (layer ${p.side}.SilkS) (width 0.15)) (fp_line (start -2.75 -1.25) (end -2.75 1.25) (layer ${p.side}.SilkS) (width 0.15))
${'' /* pins */} ${'' /* pins */}
(pad 1 smd rect (at -3.1 -1.85 ${p.rot}) (size 1.8 1.1) (layers ${p.side}.Cu ${p.side}.Paste ${p.side}.Mask) ${p.from.str}) (pad 1 smd rect (at -3.1 -1.85 ${p.r}) (size 1.8 1.1) (layers ${p.side}.Cu ${p.side}.Paste ${p.side}.Mask) ${p.from})
(pad 1 smd rect (at 3.1 -1.85 ${p.rot}) (size 1.8 1.1) (layers ${p.side}.Cu ${p.side}.Paste ${p.side}.Mask) ${p.from.str}) (pad 1 smd rect (at 3.1 -1.85 ${p.r}) (size 1.8 1.1) (layers ${p.side}.Cu ${p.side}.Paste ${p.side}.Mask) ${p.from})
(pad 2 smd rect (at -3.1 1.85 ${p.rot}) (size 1.8 1.1) (layers ${p.side}.Cu ${p.side}.Paste ${p.side}.Mask) ${p.to.str}) (pad 2 smd rect (at -3.1 1.85 ${p.r}) (size 1.8 1.1) (layers ${p.side}.Cu ${p.side}.Paste ${p.side}.Mask) ${p.to})
(pad 2 smd rect (at 3.1 1.85 ${p.rot}) (size 1.8 1.1) (layers ${p.side}.Cu ${p.side}.Paste ${p.side}.Mask) ${p.to.str}) (pad 2 smd rect (at 3.1 1.85 ${p.r}) (size 1.8 1.1) (layers ${p.side}.Cu ${p.side}.Paste ${p.side}.Mask) ${p.to})
) )
` `

View file

@ -62,14 +62,14 @@ module.exports = {
(pad "" np_thru_hole circle (at 0 -5.95) (size 3 3) (drill 3) (layers *.Cu *.Mask)) (pad "" np_thru_hole circle (at 0 -5.95) (size 3 3) (drill 3) (layers *.Cu *.Mask))
${'' /* net pads */} ${'' /* net pads */}
(pad 1 smd rect (at ${def_neg}3.275 -5.95 ${p.rot}) (size 2.6 2.6) (layers ${def_side}.Cu ${def_side}.Paste ${def_side}.Mask) ${p.from.str}) (pad 1 smd rect (at ${def_neg}3.275 -5.95 ${p.r}) (size 2.6 2.6) (layers ${def_side}.Cu ${def_side}.Paste ${def_side}.Mask) ${p.from})
(pad 2 smd rect (at ${def_pos}8.275 -3.75 ${p.rot}) (size 2.6 2.6) (layers ${def_side}.Cu ${def_side}.Paste ${def_side}.Mask) ${p.to.str}) (pad 2 smd rect (at ${def_pos}8.275 -3.75 ${p.r}) (size 2.6 2.6) (layers ${def_side}.Cu ${def_side}.Paste ${def_side}.Mask) ${p.to})
` `
} else { } else {
return ` return `
${''/* pins */} ${''/* pins */}
(pad 1 thru_hole circle (at ${def_pos}5 -3.8) (size 2.032 2.032) (drill 1.27) (layers *.Cu *.Mask) ${p.from.str}) (pad 1 thru_hole circle (at ${def_pos}5 -3.8) (size 2.032 2.032) (drill 1.27) (layers *.Cu *.Mask) ${p.from})
(pad 2 thru_hole circle (at ${def_pos}0 -5.9) (size 2.032 2.032) (drill 1.27) (layers *.Cu *.Mask) ${p.to.str}) (pad 2 thru_hole circle (at ${def_pos}0 -5.9) (size 2.032 2.032) (drill 1.27) (layers *.Cu *.Mask) ${p.to})
` `
} }
} }

View file

@ -69,8 +69,8 @@ module.exports = {
function pins(def_neg, def_pos) { function pins(def_neg, def_pos) {
return ` return `
${''/* pins */} ${''/* pins */}
(pad 1 thru_hole circle (at ${def_neg}4.58 5.1) (size 1.6 1.6) (drill 1.1) (layers *.Cu *.Mask) ${p.from.str} (clearance 0.2)) (pad 1 thru_hole circle (at ${def_neg}4.58 5.1) (size 1.6 1.6) (drill 1.1) (layers *.Cu *.Mask) ${p.from} (clearance 0.2))
(pad 2 thru_hole circle (at ${def_pos}2 5.4) (size 1.6 1.6) (drill 1.1) (layers *.Cu *.Mask) ${p.to.str} (clearance 0.2)) (pad 2 thru_hole circle (at ${def_pos}2 5.4) (size 1.6 1.6) (drill 1.1) (layers *.Cu *.Mask) ${p.to} (clearance 0.2))
` `
} }
if(p.reverse){ if(p.reverse){

View file

@ -32,14 +32,14 @@ module.exports = {
(fp_line (start -0.75 0) (end -0.35 0) (layer B.SilkS) (width 0.1)) (fp_line (start -0.75 0) (end -0.35 0) (layer B.SilkS) (width 0.1))
${''/* SMD pads on both sides */} ${''/* SMD pads on both sides */}
(pad 1 smd rect (at -1.65 0 ${p.rot}) (size 0.9 1.2) (layers F.Cu F.Paste F.Mask) ${p.to.str}) (pad 1 smd rect (at -1.65 0 ${p.r}) (size 0.9 1.2) (layers F.Cu F.Paste F.Mask) ${p.to})
(pad 2 smd rect (at 1.65 0 ${p.rot}) (size 0.9 1.2) (layers B.Cu B.Paste B.Mask) ${p.from.str}) (pad 2 smd rect (at 1.65 0 ${p.r}) (size 0.9 1.2) (layers B.Cu B.Paste B.Mask) ${p.from})
(pad 1 smd rect (at -1.65 0 ${p.rot}) (size 0.9 1.2) (layers B.Cu B.Paste B.Mask) ${p.to.str}) (pad 1 smd rect (at -1.65 0 ${p.r}) (size 0.9 1.2) (layers B.Cu B.Paste B.Mask) ${p.to})
(pad 2 smd rect (at 1.65 0 ${p.rot}) (size 0.9 1.2) (layers F.Cu F.Paste F.Mask) ${p.from.str}) (pad 2 smd rect (at 1.65 0 ${p.r}) (size 0.9 1.2) (layers F.Cu F.Paste F.Mask) ${p.from})
${''/* THT terminals */} ${''/* THT terminals */}
(pad 1 thru_hole rect (at -3.81 0 ${p.rot}) (size 1.778 1.778) (drill 0.9906) (layers *.Cu *.Mask) ${p.to.str}) (pad 1 thru_hole rect (at -3.81 0 ${p.r}) (size 1.778 1.778) (drill 0.9906) (layers *.Cu *.Mask) ${p.to})
(pad 2 thru_hole circle (at 3.81 0 ${p.rot}) (size 1.905 1.905) (drill 0.9906) (layers *.Cu *.Mask) ${p.from.str}) (pad 2 thru_hole circle (at 3.81 0 ${p.r}) (size 1.905 1.905) (drill 0.9906) (layers *.Cu *.Mask) ${p.from})
) )
` `

View file

@ -30,8 +30,8 @@ module.exports = {
(fp_line (start -1 1.5) (end -1 2.0) (layer ${p.side}.SilkS) (width 0.15)) (fp_line (start -1 1.5) (end -1 2.0) (layer ${p.side}.SilkS) (width 0.15))
(fp_line (start -1.25 1.75) (end -0.75 1.75) (layer ${p.side}.SilkS) (width 0.15)) (fp_line (start -1.25 1.75) (end -0.75 1.75) (layer ${p.side}.SilkS) (width 0.15))
(pad 1 thru_hole rect (at -1 0 ${p.rot}) (size 1.2 1.7) (drill 0.75) (layers *.Cu *.Mask) ${p.pos.str}) (pad 1 thru_hole rect (at -1 0 ${p.r}) (size 1.2 1.7) (drill 0.75) (layers *.Cu *.Mask) ${p.pos})
(pad 2 thru_hole oval (at 1 0 ${p.rot}) (size 1.2 1.7) (drill 0.75) (layers *.Cu *.Mask) ${p.neg.str}) (pad 2 thru_hole oval (at 1 0 ${p.r}) (size 1.2 1.7) (drill 0.75) (layers *.Cu *.Mask) ${p.neg})
) )

View file

@ -14,9 +14,9 @@ module.exports = {
(fp_text value Jumper (at 0 -7.3) (layer F.Fab) (effects (font (size 1 1) (thickness 0.15)))) (fp_text value Jumper (at 0 -7.3) (layer F.Fab) (effects (font (size 1 1) (thickness 0.15))))
${'' /* pins */} ${'' /* pins */}
(pad 1 smd rect (at -0.50038 0 ${p.rot}) (size 0.635 1.143) (layers ${p.side}.Cu ${p.side}.Paste ${p.side}.Mask) (pad 1 smd rect (at -0.50038 0 ${p.r}) (size 0.635 1.143) (layers ${p.side}.Cu ${p.side}.Paste ${p.side}.Mask)
(clearance 0.1905) ${p.from.str}) (clearance 0.1905) ${p.from})
(pad 2 smd rect (at 0.50038 0 ${p.rot}) (size 0.635 1.143) (layers ${p.side}.Cu ${p.side}.Paste ${p.side}.Mask) (pad 2 smd rect (at 0.50038 0 ${p.r}) (size 0.635 1.143) (layers ${p.side}.Cu ${p.side}.Paste ${p.side}.Mask)
(clearance 0.1905) ${p.to.str})) (clearance 0.1905) ${p.to}))
` `
} }

View file

@ -62,14 +62,14 @@ module.exports = {
(pad "" np_thru_hole circle (at ${def_neg}3.81 -2.54) (size 3 3) (drill 3) (layers *.Cu *.Mask)) (pad "" np_thru_hole circle (at ${def_neg}3.81 -2.54) (size 3 3) (drill 3) (layers *.Cu *.Mask))
${'' /* net pads */} ${'' /* net pads */}
(pad 1 smd rect (at ${def_neg}7.085 -2.54 ${p.rot}) (size 2.55 2.5) (layers ${def_side}.Cu ${def_side}.Paste ${def_side}.Mask) ${p.from.str}) (pad 1 smd rect (at ${def_neg}7.085 -2.54 ${p.r}) (size 2.55 2.5) (layers ${def_side}.Cu ${def_side}.Paste ${def_side}.Mask) ${p.from})
(pad 2 smd rect (at ${def_pos}5.842 -5.08 ${p.rot}) (size 2.55 2.5) (layers ${def_side}.Cu ${def_side}.Paste ${def_side}.Mask) ${p.to.str}) (pad 2 smd rect (at ${def_pos}5.842 -5.08 ${p.r}) (size 2.55 2.5) (layers ${def_side}.Cu ${def_side}.Paste ${def_side}.Mask) ${p.to})
` `
} else { } else {
return ` return `
${''/* pins */} ${''/* pins */}
(pad 1 thru_hole circle (at ${def_pos}2.54 -5.08) (size 2.286 2.286) (drill 1.4986) (layers *.Cu *.Mask) ${p.from.str}) (pad 1 thru_hole circle (at ${def_pos}2.54 -5.08) (size 2.286 2.286) (drill 1.4986) (layers *.Cu *.Mask) ${p.from})
(pad 2 thru_hole circle (at ${def_neg}3.81 -2.54) (size 2.286 2.286) (drill 1.4986) (layers *.Cu *.Mask) ${p.to.str}) (pad 2 thru_hole circle (at ${def_neg}3.81 -2.54) (size 2.286 2.286) (drill 1.4986) (layers *.Cu *.Mask) ${p.to})
` `
} }
} }

View file

@ -16,14 +16,14 @@ module.exports = {
(fp_text value OLED (at 0 -7.3) (layer F.Fab) (effects (font (size 1 1) (thickness 0.15)))) (fp_text value OLED (at 0 -7.3) (layer F.Fab) (effects (font (size 1 1) (thickness 0.15))))
${'' /* pins */} ${'' /* pins */}
(pad 4 thru_hole oval (at 1.6 2.18 ${p.rot+270}) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask) (pad 4 thru_hole oval (at 1.6 2.18 ${p.r+270}) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask)
${p.SDA.str}) ${p.SDA})
(pad 3 thru_hole oval (at 1.6 4.72 ${p.rot+270}) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask) (pad 3 thru_hole oval (at 1.6 4.72 ${p.r+270}) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask)
${p.SCL.str}) ${p.SCL})
(pad 2 thru_hole oval (at 1.6 7.26 ${p.rot+270}) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask) (pad 2 thru_hole oval (at 1.6 7.26 ${p.r+270}) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask)
${p.VCC.str}) ${p.VCC})
(pad 1 thru_hole rect (at 1.6 9.8 ${p.rot+270}) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask) (pad 1 thru_hole rect (at 1.6 9.8 ${p.r+270}) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask)
${p.GND.str}) ${p.GND})
) )
` `
} }

View file

@ -24,10 +24,10 @@ module.exports = {
(fp_line (start -6 6) (end -6 -6) (layer Dwgs.User) (width 0.15)) (fp_line (start -6 6) (end -6 -6) (layer Dwgs.User) (width 0.15))
${'' /* pins */} ${'' /* pins */}
(pad 1 np_thru_hole circle (at 6.25 -2.5) (size 1.2 1.2) (drill 1.2) (layers *.Cu *.Mask) ${p.from.str}) (pad 1 np_thru_hole circle (at 6.25 -2.5) (size 1.2 1.2) (drill 1.2) (layers *.Cu *.Mask) ${p.from})
(pad 2 np_thru_hole circle (at -6.25 -2.5) (size 1.2 1.2) (drill 1.2) (layers *.Cu *.Mask) ${p.from.str}) (pad 2 np_thru_hole circle (at -6.25 -2.5) (size 1.2 1.2) (drill 1.2) (layers *.Cu *.Mask) ${p.from})
(pad 3 np_thru_hole circle (at 6.25 2.5) (size 1.2 1.2) (drill 1.2) (layers *.Cu *.Mask) ${p.to.str}) (pad 3 np_thru_hole circle (at 6.25 2.5) (size 1.2 1.2) (drill 1.2) (layers *.Cu *.Mask) ${p.to})
(pad 4 np_thru_hole circle (at -6.25 2.5 ) (size 1.2 1.2) (drill 1.2) (layers *.Cu *.Mask) ${p.to.str}) (pad 4 np_thru_hole circle (at -6.25 2.5 ) (size 1.2 1.2) (drill 1.2) (layers *.Cu *.Mask) ${p.to})
) )
` `

View file

@ -28,9 +28,9 @@ module.exports = {
if (align == 'down') y -= p.height / 2 + plus if (align == 'down') y -= p.height / 2 + plus
let text = '' let text = ''
if (p.text.length) { if (p.text.length) {
text = `(fp_text user ${p.text} (at ${x} ${y} ${p.rot}) (layer ${side}.SilkS) (effects (font (size 0.8 0.8) (thickness 0.15)) ${mirror}))` text = `(fp_text user ${p.text} (at ${x} ${y} ${p.r}) (layer ${side}.SilkS) (effects (font (size 0.8 0.8) (thickness 0.15)) ${mirror}))`
} }
return `(pad 1 smd rect (at 0 0 ${p.rot}) (size ${p.width} ${p.height}) (layers ${side}.Cu ${side}.Paste ${side}.Mask) ${p.net.str})\n${text}` return `(pad 1 smd rect (at 0 0 ${p.r}) (size ${p.width} ${p.height}) (layers ${side}.Cu ${side}.Paste ${side}.Mask) ${p.net})\n${text}`
} }
return ` return `

View file

@ -60,58 +60,58 @@ module.exports = {
(fp_line (start -12.7 ${def_pos}6.35) (end -12.7 ${def_pos}8.89) (layer F.SilkS) (width 0.15)) (fp_line (start -12.7 ${def_pos}6.35) (end -12.7 ${def_pos}8.89) (layer F.SilkS) (width 0.15))
${''/* pin names */} ${''/* pin names */}
(fp_text user RAW (at -13.97 ${def_pos}4.8 ${p.rot + 90}) (layer F.SilkS) (effects (font (size 0.8 0.8) (thickness 0.15)))) (fp_text user RAW (at -13.97 ${def_pos}4.8 ${p.r + 90}) (layer F.SilkS) (effects (font (size 0.8 0.8) (thickness 0.15))))
(fp_text user GND (at -11.43 ${def_pos}4.8 ${p.rot + 90}) (layer F.SilkS) (effects (font (size 0.8 0.8) (thickness 0.15)))) (fp_text user GND (at -11.43 ${def_pos}4.8 ${p.r + 90}) (layer F.SilkS) (effects (font (size 0.8 0.8) (thickness 0.15))))
(fp_text user RST (at -8.89 ${def_pos}4.8 ${p.rot + 90}) (layer F.SilkS) (effects (font (size 0.8 0.8) (thickness 0.15)))) (fp_text user RST (at -8.89 ${def_pos}4.8 ${p.r + 90}) (layer F.SilkS) (effects (font (size 0.8 0.8) (thickness 0.15))))
(fp_text user VCC (at -6.35 ${def_pos}4.8 ${p.rot + 90}) (layer F.SilkS) (effects (font (size 0.8 0.8) (thickness 0.15)))) (fp_text user VCC (at -6.35 ${def_pos}4.8 ${p.r + 90}) (layer F.SilkS) (effects (font (size 0.8 0.8) (thickness 0.15))))
(fp_text user P21 (at -3.81 ${def_pos}4.8 ${p.rot + 90}) (layer F.SilkS) (effects (font (size 0.8 0.8) (thickness 0.15)))) (fp_text user P21 (at -3.81 ${def_pos}4.8 ${p.r + 90}) (layer F.SilkS) (effects (font (size 0.8 0.8) (thickness 0.15))))
(fp_text user P20 (at -1.27 ${def_pos}4.8 ${p.rot + 90}) (layer F.SilkS) (effects (font (size 0.8 0.8) (thickness 0.15)))) (fp_text user P20 (at -1.27 ${def_pos}4.8 ${p.r + 90}) (layer F.SilkS) (effects (font (size 0.8 0.8) (thickness 0.15))))
(fp_text user P19 (at 1.27 ${def_pos}4.8 ${p.rot + 90}) (layer F.SilkS) (effects (font (size 0.8 0.8) (thickness 0.15)))) (fp_text user P19 (at 1.27 ${def_pos}4.8 ${p.r + 90}) (layer F.SilkS) (effects (font (size 0.8 0.8) (thickness 0.15))))
(fp_text user P18 (at 3.81 ${def_pos}4.8 ${p.rot + 90}) (layer F.SilkS) (effects (font (size 0.8 0.8) (thickness 0.15)))) (fp_text user P18 (at 3.81 ${def_pos}4.8 ${p.r + 90}) (layer F.SilkS) (effects (font (size 0.8 0.8) (thickness 0.15))))
(fp_text user P15 (at 6.35 ${def_pos}4.8 ${p.rot + 90}) (layer F.SilkS) (effects (font (size 0.8 0.8) (thickness 0.15)))) (fp_text user P15 (at 6.35 ${def_pos}4.8 ${p.r + 90}) (layer F.SilkS) (effects (font (size 0.8 0.8) (thickness 0.15))))
(fp_text user P14 (at 8.89 ${def_pos}4.8 ${p.rot + 90}) (layer F.SilkS) (effects (font (size 0.8 0.8) (thickness 0.15)))) (fp_text user P14 (at 8.89 ${def_pos}4.8 ${p.r + 90}) (layer F.SilkS) (effects (font (size 0.8 0.8) (thickness 0.15))))
(fp_text user P16 (at 11.43 ${def_pos}4.8 ${p.rot + 90}) (layer F.SilkS) (effects (font (size 0.8 0.8) (thickness 0.15)))) (fp_text user P16 (at 11.43 ${def_pos}4.8 ${p.r + 90}) (layer F.SilkS) (effects (font (size 0.8 0.8) (thickness 0.15))))
(fp_text user P10 (at 13.97 ${def_pos}4.8 ${p.rot + 90}) (layer F.SilkS) (effects (font (size 0.8 0.8) (thickness 0.15)))) (fp_text user P10 (at 13.97 ${def_pos}4.8 ${p.r + 90}) (layer F.SilkS) (effects (font (size 0.8 0.8) (thickness 0.15))))
(fp_text user P01 (at -13.97 ${def_neg}4.8 ${p.rot + 90}) (layer F.SilkS) (effects (font (size 0.8 0.8) (thickness 0.15)))) (fp_text user P01 (at -13.97 ${def_neg}4.8 ${p.r + 90}) (layer F.SilkS) (effects (font (size 0.8 0.8) (thickness 0.15))))
(fp_text user P00 (at -11.43 ${def_neg}4.8 ${p.rot + 90}) (layer F.SilkS) (effects (font (size 0.8 0.8) (thickness 0.15)))) (fp_text user P00 (at -11.43 ${def_neg}4.8 ${p.r + 90}) (layer F.SilkS) (effects (font (size 0.8 0.8) (thickness 0.15))))
(fp_text user GND (at -8.89 ${def_neg}4.8 ${p.rot + 90}) (layer F.SilkS) (effects (font (size 0.8 0.8) (thickness 0.15)))) (fp_text user GND (at -8.89 ${def_neg}4.8 ${p.r + 90}) (layer F.SilkS) (effects (font (size 0.8 0.8) (thickness 0.15))))
(fp_text user GND (at -6.35 ${def_neg}4.8 ${p.rot + 90}) (layer F.SilkS) (effects (font (size 0.8 0.8) (thickness 0.15)))) (fp_text user GND (at -6.35 ${def_neg}4.8 ${p.r + 90}) (layer F.SilkS) (effects (font (size 0.8 0.8) (thickness 0.15))))
(fp_text user P02 (at -3.81 ${def_neg}4.8 ${p.rot + 90}) (layer F.SilkS) (effects (font (size 0.8 0.8) (thickness 0.15)))) (fp_text user P02 (at -3.81 ${def_neg}4.8 ${p.r + 90}) (layer F.SilkS) (effects (font (size 0.8 0.8) (thickness 0.15))))
(fp_text user P03 (at -1.27 ${def_neg}4.8 ${p.rot + 90}) (layer F.SilkS) (effects (font (size 0.8 0.8) (thickness 0.15)))) (fp_text user P03 (at -1.27 ${def_neg}4.8 ${p.r + 90}) (layer F.SilkS) (effects (font (size 0.8 0.8) (thickness 0.15))))
(fp_text user P04 (at 1.27 ${def_neg}4.8 ${p.rot + 90}) (layer F.SilkS) (effects (font (size 0.8 0.8) (thickness 0.15)))) (fp_text user P04 (at 1.27 ${def_neg}4.8 ${p.r + 90}) (layer F.SilkS) (effects (font (size 0.8 0.8) (thickness 0.15))))
(fp_text user P05 (at 3.81 ${def_neg}4.8 ${p.rot + 90}) (layer F.SilkS) (effects (font (size 0.8 0.8) (thickness 0.15)))) (fp_text user P05 (at 3.81 ${def_neg}4.8 ${p.r + 90}) (layer F.SilkS) (effects (font (size 0.8 0.8) (thickness 0.15))))
(fp_text user P06 (at 6.35 ${def_neg}4.8 ${p.rot + 90}) (layer F.SilkS) (effects (font (size 0.8 0.8) (thickness 0.15)))) (fp_text user P06 (at 6.35 ${def_neg}4.8 ${p.r + 90}) (layer F.SilkS) (effects (font (size 0.8 0.8) (thickness 0.15))))
(fp_text user P07 (at 8.89 ${def_neg}4.8 ${p.rot + 90}) (layer F.SilkS) (effects (font (size 0.8 0.8) (thickness 0.15)))) (fp_text user P07 (at 8.89 ${def_neg}4.8 ${p.r + 90}) (layer F.SilkS) (effects (font (size 0.8 0.8) (thickness 0.15))))
(fp_text user P08 (at 11.43 ${def_neg}4.8 ${p.rot + 90}) (layer F.SilkS) (effects (font (size 0.8 0.8) (thickness 0.15)))) (fp_text user P08 (at 11.43 ${def_neg}4.8 ${p.r + 90}) (layer F.SilkS) (effects (font (size 0.8 0.8) (thickness 0.15))))
(fp_text user P09 (at 13.97 ${def_neg}4.8 ${p.rot + 90}) (layer F.SilkS) (effects (font (size 0.8 0.8) (thickness 0.15)))) (fp_text user P09 (at 13.97 ${def_neg}4.8 ${p.r + 90}) (layer F.SilkS) (effects (font (size 0.8 0.8) (thickness 0.15))))
${''/* and now the actual pins */} ${''/* and now the actual pins */}
(pad 1 thru_hole rect (at -13.97 ${def_pos}7.62 ${p.rot}) (size 1.7526 1.7526) (drill 1.0922) (layers *.Cu *.SilkS *.Mask) ${p.RAW.str}) (pad 1 thru_hole rect (at -13.97 ${def_pos}7.62 ${p.r}) (size 1.7526 1.7526) (drill 1.0922) (layers *.Cu *.SilkS *.Mask) ${p.RAW})
(pad 2 thru_hole circle (at -11.43 ${def_pos}7.62 0) (size 1.7526 1.7526) (drill 1.0922) (layers *.Cu *.SilkS *.Mask) ${p.GND.str}) (pad 2 thru_hole circle (at -11.43 ${def_pos}7.62 0) (size 1.7526 1.7526) (drill 1.0922) (layers *.Cu *.SilkS *.Mask) ${p.GND})
(pad 3 thru_hole circle (at -8.89 ${def_pos}7.62 0) (size 1.7526 1.7526) (drill 1.0922) (layers *.Cu *.SilkS *.Mask) ${p.RST.str}) (pad 3 thru_hole circle (at -8.89 ${def_pos}7.62 0) (size 1.7526 1.7526) (drill 1.0922) (layers *.Cu *.SilkS *.Mask) ${p.RST})
(pad 4 thru_hole circle (at -6.35 ${def_pos}7.62 0) (size 1.7526 1.7526) (drill 1.0922) (layers *.Cu *.SilkS *.Mask) ${p.VCC.str}) (pad 4 thru_hole circle (at -6.35 ${def_pos}7.62 0) (size 1.7526 1.7526) (drill 1.0922) (layers *.Cu *.SilkS *.Mask) ${p.VCC})
(pad 5 thru_hole circle (at -3.81 ${def_pos}7.62 0) (size 1.7526 1.7526) (drill 1.0922) (layers *.Cu *.SilkS *.Mask) ${p.P21.str}) (pad 5 thru_hole circle (at -3.81 ${def_pos}7.62 0) (size 1.7526 1.7526) (drill 1.0922) (layers *.Cu *.SilkS *.Mask) ${p.P21})
(pad 6 thru_hole circle (at -1.27 ${def_pos}7.62 0) (size 1.7526 1.7526) (drill 1.0922) (layers *.Cu *.SilkS *.Mask) ${p.P20.str}) (pad 6 thru_hole circle (at -1.27 ${def_pos}7.62 0) (size 1.7526 1.7526) (drill 1.0922) (layers *.Cu *.SilkS *.Mask) ${p.P20})
(pad 7 thru_hole circle (at 1.27 ${def_pos}7.62 0) (size 1.7526 1.7526) (drill 1.0922) (layers *.Cu *.SilkS *.Mask) ${p.P19.str}) (pad 7 thru_hole circle (at 1.27 ${def_pos}7.62 0) (size 1.7526 1.7526) (drill 1.0922) (layers *.Cu *.SilkS *.Mask) ${p.P19})
(pad 8 thru_hole circle (at 3.81 ${def_pos}7.62 0) (size 1.7526 1.7526) (drill 1.0922) (layers *.Cu *.SilkS *.Mask) ${p.P18.str}) (pad 8 thru_hole circle (at 3.81 ${def_pos}7.62 0) (size 1.7526 1.7526) (drill 1.0922) (layers *.Cu *.SilkS *.Mask) ${p.P18})
(pad 9 thru_hole circle (at 6.35 ${def_pos}7.62 0) (size 1.7526 1.7526) (drill 1.0922) (layers *.Cu *.SilkS *.Mask) ${p.P15.str}) (pad 9 thru_hole circle (at 6.35 ${def_pos}7.62 0) (size 1.7526 1.7526) (drill 1.0922) (layers *.Cu *.SilkS *.Mask) ${p.P15})
(pad 10 thru_hole circle (at 8.89 ${def_pos}7.62 0) (size 1.7526 1.7526) (drill 1.0922) (layers *.Cu *.SilkS *.Mask) ${p.P14.str}) (pad 10 thru_hole circle (at 8.89 ${def_pos}7.62 0) (size 1.7526 1.7526) (drill 1.0922) (layers *.Cu *.SilkS *.Mask) ${p.P14})
(pad 11 thru_hole circle (at 11.43 ${def_pos}7.62 0) (size 1.7526 1.7526) (drill 1.0922) (layers *.Cu *.SilkS *.Mask) ${p.P16.str}) (pad 11 thru_hole circle (at 11.43 ${def_pos}7.62 0) (size 1.7526 1.7526) (drill 1.0922) (layers *.Cu *.SilkS *.Mask) ${p.P16})
(pad 12 thru_hole circle (at 13.97 ${def_pos}7.62 0) (size 1.7526 1.7526) (drill 1.0922) (layers *.Cu *.SilkS *.Mask) ${p.P10.str}) (pad 12 thru_hole circle (at 13.97 ${def_pos}7.62 0) (size 1.7526 1.7526) (drill 1.0922) (layers *.Cu *.SilkS *.Mask) ${p.P10})
(pad 13 thru_hole circle (at -13.97 ${def_neg}7.62 0) (size 1.7526 1.7526) (drill 1.0922) (layers *.Cu *.SilkS *.Mask) ${p.P1.str}) (pad 13 thru_hole circle (at -13.97 ${def_neg}7.62 0) (size 1.7526 1.7526) (drill 1.0922) (layers *.Cu *.SilkS *.Mask) ${p.P1})
(pad 14 thru_hole circle (at -11.43 ${def_neg}7.62 0) (size 1.7526 1.7526) (drill 1.0922) (layers *.Cu *.SilkS *.Mask) ${p.P0.str}) (pad 14 thru_hole circle (at -11.43 ${def_neg}7.62 0) (size 1.7526 1.7526) (drill 1.0922) (layers *.Cu *.SilkS *.Mask) ${p.P0})
(pad 15 thru_hole circle (at -8.89 ${def_neg}7.62 0) (size 1.7526 1.7526) (drill 1.0922) (layers *.Cu *.SilkS *.Mask) ${p.GND.str}) (pad 15 thru_hole circle (at -8.89 ${def_neg}7.62 0) (size 1.7526 1.7526) (drill 1.0922) (layers *.Cu *.SilkS *.Mask) ${p.GND})
(pad 16 thru_hole circle (at -6.35 ${def_neg}7.62 0) (size 1.7526 1.7526) (drill 1.0922) (layers *.Cu *.SilkS *.Mask) ${p.GND.str}) (pad 16 thru_hole circle (at -6.35 ${def_neg}7.62 0) (size 1.7526 1.7526) (drill 1.0922) (layers *.Cu *.SilkS *.Mask) ${p.GND})
(pad 17 thru_hole circle (at -3.81 ${def_neg}7.62 0) (size 1.7526 1.7526) (drill 1.0922) (layers *.Cu *.SilkS *.Mask) ${p.P2.str}) (pad 17 thru_hole circle (at -3.81 ${def_neg}7.62 0) (size 1.7526 1.7526) (drill 1.0922) (layers *.Cu *.SilkS *.Mask) ${p.P2})
(pad 18 thru_hole circle (at -1.27 ${def_neg}7.62 0) (size 1.7526 1.7526) (drill 1.0922) (layers *.Cu *.SilkS *.Mask) ${p.P3.str}) (pad 18 thru_hole circle (at -1.27 ${def_neg}7.62 0) (size 1.7526 1.7526) (drill 1.0922) (layers *.Cu *.SilkS *.Mask) ${p.P3})
(pad 19 thru_hole circle (at 1.27 ${def_neg}7.62 0) (size 1.7526 1.7526) (drill 1.0922) (layers *.Cu *.SilkS *.Mask) ${p.P4.str}) (pad 19 thru_hole circle (at 1.27 ${def_neg}7.62 0) (size 1.7526 1.7526) (drill 1.0922) (layers *.Cu *.SilkS *.Mask) ${p.P4})
(pad 20 thru_hole circle (at 3.81 ${def_neg}7.62 0) (size 1.7526 1.7526) (drill 1.0922) (layers *.Cu *.SilkS *.Mask) ${p.P5.str}) (pad 20 thru_hole circle (at 3.81 ${def_neg}7.62 0) (size 1.7526 1.7526) (drill 1.0922) (layers *.Cu *.SilkS *.Mask) ${p.P5})
(pad 21 thru_hole circle (at 6.35 ${def_neg}7.62 0) (size 1.7526 1.7526) (drill 1.0922) (layers *.Cu *.SilkS *.Mask) ${p.P6.str}) (pad 21 thru_hole circle (at 6.35 ${def_neg}7.62 0) (size 1.7526 1.7526) (drill 1.0922) (layers *.Cu *.SilkS *.Mask) ${p.P6})
(pad 22 thru_hole circle (at 8.89 ${def_neg}7.62 0) (size 1.7526 1.7526) (drill 1.0922) (layers *.Cu *.SilkS *.Mask) ${p.P7.str}) (pad 22 thru_hole circle (at 8.89 ${def_neg}7.62 0) (size 1.7526 1.7526) (drill 1.0922) (layers *.Cu *.SilkS *.Mask) ${p.P7})
(pad 23 thru_hole circle (at 11.43 ${def_neg}7.62 0) (size 1.7526 1.7526) (drill 1.0922) (layers *.Cu *.SilkS *.Mask) ${p.P8.str}) (pad 23 thru_hole circle (at 11.43 ${def_neg}7.62 0) (size 1.7526 1.7526) (drill 1.0922) (layers *.Cu *.SilkS *.Mask) ${p.P8})
(pad 24 thru_hole circle (at 13.97 ${def_neg}7.62 0) (size 1.7526 1.7526) (drill 1.0922) (layers *.Cu *.SilkS *.Mask) ${p.P9.str}) (pad 24 thru_hole circle (at 13.97 ${def_neg}7.62 0) (size 1.7526 1.7526) (drill 1.0922) (layers *.Cu *.SilkS *.Mask) ${p.P9})
` `
} }
if(p.orientation == 'down') { if(p.orientation == 'down') {

View file

@ -29,15 +29,15 @@ module.exports = {
(fp_poly (pts (xy 4 2.2) (xy 4 0.375) (xy 5 1.2875)) (layer ${p.side}.SilkS) (width 0.1)) (fp_poly (pts (xy 4 2.2) (xy 4 0.375) (xy 5 1.2875)) (layer ${p.side}.SilkS) (width 0.1))
(pad 1 smd rect (at -2.2 -0.875 ${p.rot}) (size 2.6 1) (layers ${p.side}.Cu ${p.side}.Paste ${p.side}.Mask) ${p.VCC.str}) (pad 1 smd rect (at -2.2 -0.875 ${p.r}) (size 2.6 1) (layers ${p.side}.Cu ${p.side}.Paste ${p.side}.Mask) ${p.VCC})
(pad 2 smd rect (at -2.2 0.875 ${p.rot}) (size 2.6 1) (layers ${p.side}.Cu ${p.side}.Paste ${p.side}.Mask) ${p.dout.str}) (pad 2 smd rect (at -2.2 0.875 ${p.r}) (size 2.6 1) (layers ${p.side}.Cu ${p.side}.Paste ${p.side}.Mask) ${p.dout})
(pad 3 smd rect (at 2.2 0.875 ${p.rot}) (size 2.6 1) (layers ${p.side}.Cu ${p.side}.Paste ${p.side}.Mask) ${p.GND.str}) (pad 3 smd rect (at 2.2 0.875 ${p.r}) (size 2.6 1) (layers ${p.side}.Cu ${p.side}.Paste ${p.side}.Mask) ${p.GND})
(pad 4 smd rect (at 2.2 -0.875 ${p.rot}) (size 2.6 1) (layers ${p.side}.Cu ${p.side}.Paste ${p.side}.Mask) ${p.din.str}) (pad 4 smd rect (at 2.2 -0.875 ${p.r}) (size 2.6 1) (layers ${p.side}.Cu ${p.side}.Paste ${p.side}.Mask) ${p.din})
(pad 11 smd rect (at -2.5 -1.6 ${p.rot}) (size 2 1.2) (layers ${p.side}.Cu ${p.side}.Paste ${p.side}.Mask) ${p.VCC.str}) (pad 11 smd rect (at -2.5 -1.6 ${p.r}) (size 2 1.2) (layers ${p.side}.Cu ${p.side}.Paste ${p.side}.Mask) ${p.VCC})
(pad 22 smd rect (at -2.5 1.6 ${p.rot}) (size 2 1.2) (layers ${p.side}.Cu ${p.side}.Paste ${p.side}.Mask) ${p.dout.str}) (pad 22 smd rect (at -2.5 1.6 ${p.r}) (size 2 1.2) (layers ${p.side}.Cu ${p.side}.Paste ${p.side}.Mask) ${p.dout})
(pad 33 smd rect (at 2.5 1.6 ${p.rot}) (size 2 1.2) (layers ${p.side}.Cu ${p.side}.Paste ${p.side}.Mask) ${p.GND.str}) (pad 33 smd rect (at 2.5 1.6 ${p.r}) (size 2 1.2) (layers ${p.side}.Cu ${p.side}.Paste ${p.side}.Mask) ${p.GND})
(pad 44 smd rect (at 2.5 -1.6 ${p.rot}) (size 2 1.2) (layers ${p.side}.Cu ${p.side}.Paste ${p.side}.Mask) ${p.din.str}) (pad 44 smd rect (at 2.5 -1.6 ${p.r}) (size 2 1.2) (layers ${p.side}.Cu ${p.side}.Paste ${p.side}.Mask) ${p.din})
) )

View file

@ -56,15 +56,15 @@ module.exports = {
(fp_circle (center -0.12 -0.04) (end 2.88 -0.04) (layer F.Fab) (width 0.12)) (fp_circle (center -0.12 -0.04) (end 2.88 -0.04) (layer F.Fab) (width 0.12))
${''/* pin names */} ${''/* pin names */}
(pad A thru_hole rect (at -7.62 -2.54 ${p.rot}) (size 2 2) (drill 1) (layers *.Cu *.Mask) ${p.A.str}) (pad A thru_hole rect (at -7.62 -2.54 ${p.r}) (size 2 2) (drill 1) (layers *.Cu *.Mask) ${p.A})
(pad C thru_hole circle (at -7.62 -0.04) (size 2 2) (drill 1) (layers *.Cu *.Mask) ${p.C.str}) (pad C thru_hole circle (at -7.62 -0.04) (size 2 2) (drill 1) (layers *.Cu *.Mask) ${p.C})
(pad B thru_hole circle (at -7.62 2.46) (size 2 2) (drill 1) (layers *.Cu *.Mask) ${p.B.str}) (pad B thru_hole circle (at -7.62 2.46) (size 2 2) (drill 1) (layers *.Cu *.Mask) ${p.B})
(pad 1 thru_hole circle (at 6.88 -2.54) (size 1.5 1.5) (drill 1) (layers *.Cu *.Mask) ${p.from.str}) (pad 1 thru_hole circle (at 6.88 -2.54) (size 1.5 1.5) (drill 1) (layers *.Cu *.Mask) ${p.from})
(pad 2 thru_hole circle (at 6.88 2.46) (size 1.5 1.5) (drill 1) (layers *.Cu *.Mask) ${p.to.str}) (pad 2 thru_hole circle (at 6.88 2.46) (size 1.5 1.5) (drill 1) (layers *.Cu *.Mask) ${p.to})
${''/* Legs */} ${''/* Legs */}
(pad "" thru_hole rect (at -0.12 -5.64 ${p.rot}) (size 3.2 2) (drill oval 2.8 1.5) (layers *.Cu *.Mask)) (pad "" thru_hole rect (at -0.12 -5.64 ${p.r}) (size 3.2 2) (drill oval 2.8 1.5) (layers *.Cu *.Mask))
(pad "" thru_hole rect (at -0.12 5.56 ${p.rot}) (size 3.2 2) (drill oval 2.8 1.5) (layers *.Cu *.Mask)) (pad "" thru_hole rect (at -0.12 5.56 ${p.r}) (size 3.2 2) (drill oval 2.8 1.5) (layers *.Cu *.Mask))
) )
` `
} }

View file

@ -35,8 +35,8 @@ module.exports = {
const standard = ` const standard = `
(module RollerEncoder_Panasonic_EVQWGD001 (layer F.Cu) (tedit 6040A10C) (module RollerEncoder_Panasonic_EVQWGD001 (layer F.Cu) (tedit 6040A10C)
${p.at /* parametric position */} ${p.at /* parametric position */}
(fp_text reference REF** (at 0 0 ${p.rot}) (layer F.Fab) (effects (font (size 1 1) (thickness 0.15)))) (fp_text reference REF** (at 0 0 ${p.r}) (layer F.Fab) (effects (font (size 1 1) (thickness 0.15))))
(fp_text value RollerEncoder_Panasonic_EVQWGD001 (at -0.1 9 ${p.rot}) (layer F.Fab) (effects (font (size 1 1) (thickness 0.15)))) (fp_text value RollerEncoder_Panasonic_EVQWGD001 (at -0.1 9 ${p.r}) (layer F.Fab) (effects (font (size 1 1) (thickness 0.15))))
${'' /* corner marks */} ${'' /* corner marks */}
(fp_line (start -8.4 -6.4) (end 8.4 -6.4) (layer Dwgs.User) (width 0.12)) (fp_line (start -8.4 -6.4) (end 8.4 -6.4) (layer Dwgs.User) (width 0.12))
@ -57,15 +57,15 @@ module.exports = {
(fp_arc (start ${def_pos}9.5 -6.3) (end ${def_pos}9.8 -6.3) (angle ${def_neg}90) (layer Edge.Cuts) (width 0.15)) (fp_arc (start ${def_pos}9.5 -6.3) (end ${def_pos}9.8 -6.3) (angle ${def_neg}90) (layer Edge.Cuts) (width 0.15))
${'' /* pins */} ${'' /* pins */}
(pad S1 thru_hole circle (at ${def_neg}6.85 -6.2 ${p.rot}) (size 1.6 1.6) (drill 0.9) (layers *.Cu *.Mask) ${p.from.str}) (pad S1 thru_hole circle (at ${def_neg}6.85 -6.2 ${p.r}) (size 1.6 1.6) (drill 0.9) (layers *.Cu *.Mask) ${p.from})
(pad S2 thru_hole circle (at ${def_neg}5 -6.2 ${p.rot}) (size 1.6 1.6) (drill 0.9) (layers *.Cu *.Mask) ${p.to.str}) (pad S2 thru_hole circle (at ${def_neg}5 -6.2 ${p.r}) (size 1.6 1.6) (drill 0.9) (layers *.Cu *.Mask) ${p.to})
(pad A thru_hole circle (at ${def_neg}5.625 -3.81 ${p.rot}) (size 1.6 1.6) (drill 0.9) (layers *.Cu *.Mask) ${p.A.str}) (pad A thru_hole circle (at ${def_neg}5.625 -3.81 ${p.r}) (size 1.6 1.6) (drill 0.9) (layers *.Cu *.Mask) ${p.A})
(pad B thru_hole circle (at ${def_neg}5.625 -1.27 ${p.rot}) (size 1.6 1.6) (drill 0.9) (layers *.Cu *.Mask) ${p.B.str}) (pad B thru_hole circle (at ${def_neg}5.625 -1.27 ${p.r}) (size 1.6 1.6) (drill 0.9) (layers *.Cu *.Mask) ${p.B})
(pad C thru_hole circle (at ${def_neg}5.625 1.27 ${p.rot}) (size 1.6 1.6) (drill 0.9) (layers *.Cu *.Mask) ${p.C.str}) (pad C thru_hole circle (at ${def_neg}5.625 1.27 ${p.r}) (size 1.6 1.6) (drill 0.9) (layers *.Cu *.Mask) ${p.C})
(pad D thru_hole circle (at ${def_neg}5.625 3.81 ${p.rot}) (size 1.6 1.6) (drill 0.9) (layers *.Cu *.Mask) ${p.D.str}) (pad D thru_hole circle (at ${def_neg}5.625 3.81 ${p.r}) (size 1.6 1.6) (drill 0.9) (layers *.Cu *.Mask) ${p.D})
${'' /* stabilizer */} ${'' /* stabilizer */}
(pad "" np_thru_hole circle (at ${def_neg}5.625 6.3 ${p.rot}) (size 1.5 1.5) (drill 1.5) (layers *.Cu *.Mask)) (pad "" np_thru_hole circle (at ${def_neg}5.625 6.3 ${p.r}) (size 1.5 1.5) (drill 1.5) (layers *.Cu *.Mask))
` `
} }
if(p.reverse) { if(p.reverse) {

View file

@ -38,15 +38,15 @@ module.exports = {
(pad "" np_thru_hole circle (at -1.5 0) (size 1 1) (drill 0.9) (layers *.Cu *.Mask)) (pad "" np_thru_hole circle (at -1.5 0) (size 1 1) (drill 0.9) (layers *.Cu *.Mask))
${'' /* pins */} ${'' /* pins */}
(pad 1 smd rect (at ${right}2.25 2.075 ${p.rot}) (size 0.9 1.25) (layers ${p.side}.Cu ${p.side}.Paste ${p.side}.Mask) ${p.from.str}) (pad 1 smd rect (at ${right}2.25 2.075 ${p.r}) (size 0.9 1.25) (layers ${p.side}.Cu ${p.side}.Paste ${p.side}.Mask) ${p.from})
(pad 2 smd rect (at ${left}0.75 2.075 ${p.rot}) (size 0.9 1.25) (layers ${p.side}.Cu ${p.side}.Paste ${p.side}.Mask) ${p.to.str}) (pad 2 smd rect (at ${left}0.75 2.075 ${p.r}) (size 0.9 1.25) (layers ${p.side}.Cu ${p.side}.Paste ${p.side}.Mask) ${p.to})
(pad 3 smd rect (at ${left}2.25 2.075 ${p.rot}) (size 0.9 1.25) (layers ${p.side}.Cu ${p.side}.Paste ${p.side}.Mask)) (pad 3 smd rect (at ${left}2.25 2.075 ${p.r}) (size 0.9 1.25) (layers ${p.side}.Cu ${p.side}.Paste ${p.side}.Mask))
${'' /* side mounts */} ${'' /* side mounts */}
(pad "" smd rect (at 3.7 -1.1 ${p.rot}) (size 0.9 0.9) (layers ${p.side}.Cu ${p.side}.Paste ${p.side}.Mask)) (pad "" smd rect (at 3.7 -1.1 ${p.r}) (size 0.9 0.9) (layers ${p.side}.Cu ${p.side}.Paste ${p.side}.Mask))
(pad "" smd rect (at 3.7 1.1 ${p.rot}) (size 0.9 0.9) (layers ${p.side}.Cu ${p.side}.Paste ${p.side}.Mask)) (pad "" smd rect (at 3.7 1.1 ${p.r}) (size 0.9 0.9) (layers ${p.side}.Cu ${p.side}.Paste ${p.side}.Mask))
(pad "" smd rect (at -3.7 1.1 ${p.rot}) (size 0.9 0.9) (layers ${p.side}.Cu ${p.side}.Paste ${p.side}.Mask)) (pad "" smd rect (at -3.7 1.1 ${p.r}) (size 0.9 0.9) (layers ${p.side}.Cu ${p.side}.Paste ${p.side}.Mask))
(pad "" smd rect (at -3.7 -1.1 ${p.rot}) (size 0.9 0.9) (layers ${p.side}.Cu ${p.side}.Paste ${p.side}.Mask)) (pad "" smd rect (at -3.7 -1.1 ${p.r}) (size 0.9 0.9) (layers ${p.side}.Cu ${p.side}.Paste ${p.side}.Mask))
) )
` `

View file

@ -71,10 +71,10 @@ module.exports = {
} }
function pins(def_neg, def_pos) { function pins(def_neg, def_pos) {
return ` return `
(pad 1 thru_hole oval (at ${def_neg} 11.3 ${p.rot}) (size 1.6 2.2) (drill oval 0.9 1.5) (layers *.Cu *.Mask) ${p.A.str}) (pad 1 thru_hole oval (at ${def_neg} 11.3 ${p.r}) (size 1.6 2.2) (drill oval 0.9 1.5) (layers *.Cu *.Mask) ${p.A})
(pad 2 thru_hole oval (at ${def_pos} 10.2 ${p.rot}) (size 1.6 2.2) (drill oval 0.9 1.5) (layers *.Cu *.Mask) ${p.B.str}) (pad 2 thru_hole oval (at ${def_pos} 10.2 ${p.r}) (size 1.6 2.2) (drill oval 0.9 1.5) (layers *.Cu *.Mask) ${p.B})
(pad 3 thru_hole oval (at ${def_pos} 6.2 ${p.rot}) (size 1.6 2.2) (drill oval 0.9 1.5) (layers *.Cu *.Mask) ${p.C.str}) (pad 3 thru_hole oval (at ${def_pos} 6.2 ${p.r}) (size 1.6 2.2) (drill oval 0.9 1.5) (layers *.Cu *.Mask) ${p.C})
(pad 4 thru_hole oval (at ${def_pos} 3.2 ${p.rot}) (size 1.6 2.2) (drill oval 0.9 1.5) (layers *.Cu *.Mask) ${p.D.str}) (pad 4 thru_hole oval (at ${def_pos} 3.2 ${p.r}) (size 1.6 2.2) (drill oval 0.9 1.5) (layers *.Cu *.Mask) ${p.D})
` `
} }
if(p.reverse & p.symmetric) { if(p.reverse & p.symmetric) {

View file

@ -14,7 +14,7 @@ module.exports = {
(fp_text value VIA-0.6mm (at 0 -1.4) (layer F.Fab) hide (effects (font (size 1 1) (thickness 0.15)))) (fp_text value VIA-0.6mm (at 0 -1.4) (layer F.Fab) hide (effects (font (size 1 1) (thickness 0.15))))
${'' /* via */} ${'' /* via */}
(pad 1 thru_hole circle (at 0 0) (size 0.6 0.6) (drill 0.3) (layers *.Cu) (zone_connect 2) ${p.net.str}) (pad 1 thru_hole circle (at 0 0) (size 0.6 0.6) (drill 0.3) (layers *.Cu) (zone_connect 2) ${p.net})
) )
` `
} }

View file

@ -70,4 +70,4 @@ exports.convert = (config, logger) => {
} }
return result return result
} }

View file

@ -136,20 +136,15 @@ const whats = {
outline outline
} }
const expand_shorthand = (config, units) => { const expand_shorthand = (config, name, units) => {
if (a.type(config.expand)(units) == 'string') { if (a.type(config.expand)(units) == 'string') {
const prefix = config.expand.slice(0, -1) const prefix = config.expand.slice(0, -1)
const suffix = config.expand.slice(-1) const suffix = config.expand.slice(-1)
let expand = suffix const valid_suffixes = [')', '>', ']']
let joints = 0 a.assert(valid_suffixes.includes(suffix), `If field "${name}" is a string, ` +
`it should end with one of [${valid_suffixes.map(s => `'${s}'`).join(', ')}]!`)
if (suffix == ')') ; // noop config.expand = prefix
else if (suffix == '>') joints = 1 config.joints = config.joints || valid_suffixes.indexOf(suffix)
else if (suffix == ']') joints = 2
else expand = config.expand
config.expand = parseFloat(expand)
config.joints = config.joints || joints
} }
if (a.type(config.joints)(units) == 'string') { if (a.type(config.joints)(units) == 'string') {
@ -159,7 +154,7 @@ const expand_shorthand = (config, units) => {
} }
} }
exports.parse = (config = {}, points = {}, units = {}) => { exports.parse = (config, points, units) => {
// output outlines will be collected here // output outlines will be collected here
const outlines = {} const outlines = {}
@ -199,9 +194,8 @@ exports.parse = (config = {}, points = {}, units = {}) => {
const where = units => filter(original_where, `${name}.where`, points, units, asym) const where = units => filter(original_where, `${name}.where`, points, units, asym)
const original_adjust = part.adjust // same as above const original_adjust = part.adjust // same as above
const adjust = start => anchor(original_adjust || {}, `${name}.adjust`, points, start)(units)
const fillet = a.sane(part.fillet || 0, `${name}.fillet`, 'number')(units) const fillet = a.sane(part.fillet || 0, `${name}.fillet`, 'number')(units)
expand_shorthand(part, units) expand_shorthand(part, `${name}.expand`, units)
const expand = a.sane(part.expand || 0, `${name}.expand`, 'number')(units) const expand = a.sane(part.expand || 0, `${name}.expand`, 'number')(units)
const joints = a.in(a.sane(part.joints || 0, `${name}.joints`, 'number')(units), `${name}.joints`, [0, 1, 2]) const joints = a.in(a.sane(part.joints || 0, `${name}.joints`, 'number')(units), `${name}.joints`, [0, 1, 2])
const scale = a.sane(part.scale || 1, `${name}.scale`, 'number')(units) const scale = a.sane(part.scale || 1, `${name}.scale`, 'number')(units)
@ -220,6 +214,7 @@ exports.parse = (config = {}, points = {}, units = {}) => {
// a prototype "shape" maker (and its units) are computed // a prototype "shape" maker (and its units) are computed
const [shape_maker, shape_units] = whats[what](part, name, points, outlines, units) const [shape_maker, shape_units] = whats[what](part, name, points, outlines, units)
const adjust = start => anchor(original_adjust || {}, `${name}.adjust`, points, start)(shape_units)
// and then the shape is repeated for all where positions // and then the shape is repeated for all where positions
for (const w of where(shape_units)) { for (const w of where(shape_units)) {

View file

@ -1,4 +1,6 @@
const m = require('makerjs') const m = require('makerjs')
const yaml = require('js-yaml')
const u = require('./utils') const u = require('./utils')
const a = require('./assert') const a = require('./assert')
const prep = require('./prepare') const prep = require('./prepare')
@ -115,7 +117,7 @@ const kicad_netclass = `
) )
` `
const makerjs2kicad = exports._makerjs2kicad = (model, layer='Edge.Cuts') => { const makerjs2kicad = exports._makerjs2kicad = (model, layer) => {
const grs = [] const grs = []
const xy = val => `${val[0]} ${-val[1]}` const xy = val => `${val[0]} ${-val[1]}`
m.model.walk(model, { m.model.walk(model, {
@ -151,6 +153,24 @@ exports.inject_footprint = (name, fp) => {
footprint_types[name] = fp footprint_types[name] = fp
} }
const xy_obj = (x, y) => {
return {
x,
y,
str: `${x} ${y}`,
toString: function() { return this.str }
}
}
const net_obj = (name, index) => {
return {
name,
index,
str: `(net ${index} "${name}")`,
toString: function() { return this.str }
}
}
const footprint = exports._footprint = (points, net_indexer, component_indexer, units, extra) => (config, name, point) => { const footprint = exports._footprint = (points, net_indexer, component_indexer, units, extra) => (config, name, point) => {
// config sanitization // config sanitization
@ -169,7 +189,7 @@ const footprint = exports._footprint = (points, net_indexer, component_indexer,
params = prep.extend(params, mirror_overrides) params = prep.extend(params, mirror_overrides)
} }
a.unexpected(params, `${name}.params`, Object.keys(fp.params)) a.unexpected(params, `${name}.params`, Object.keys(fp.params))
// parsing parameters // parsing parameters
const parsed_params = {} const parsed_params = {}
for (const [param_name, param_def] of Object.entries(fp.params)) { for (const [param_name, param_def] of Object.entries(fp.params)) {
@ -183,40 +203,51 @@ const footprint = exports._footprint = (points, net_indexer, component_indexer,
parsed_def = {type: 'number', value: a.mathnum(param_def)(units)} parsed_def = {type: 'number', value: a.mathnum(param_def)(units)}
} else if (def_type == 'boolean') { } else if (def_type == 'boolean') {
parsed_def = {type: 'boolean', value: param_def} parsed_def = {type: 'boolean', value: param_def}
} else if (def_type == 'undefined') { } else if (def_type == 'array') {
parsed_def = {type: 'array', value: param_def}
} else if (def_type == 'object') {
// parsed param definitions also expand to an object
// so to detect whether this is an arbitrary object,
// we first have to make sure it's not an expanded param def
// (this has to be a heuristic, but should be pretty reliable)
const defarr = Object.keys(param_def)
const already_expanded = defarr.length == 2 && defarr.includes('type') && defarr.includes('value')
if (!already_expanded) {
parsed_def = {type: 'object', value: param_def}
}
} else {
parsed_def = {type: 'net', value: undefined} parsed_def = {type: 'net', value: undefined}
} }
// combine default value with potential user override // combine default value with potential user override
let value = prep.extend(parsed_def.value, params[param_name]) let value = params[param_name] !== undefined ? params[param_name] : parsed_def.value
let type = parsed_def.type const type = parsed_def.type
// templating support, with conversion back to raw datatypes // templating support, with conversion back to raw datatypes
const converters = { const converters = {
string: v => v, string: v => v,
number: v => a.sane(v, `${name}.params.${param_name}`, 'number')(units), number: v => a.sane(v, `${name}.params.${param_name}`, 'number')(units),
boolean: v => v === 'true', boolean: v => v === 'true',
array: v => yaml.load(v),
object: v => yaml.load(v),
net: v => v, net: v => v,
anchor: v => v anchor: v => yaml.load(v)
} }
a.in(type, `${name}.params.${param_name}.type`, Object.keys(converters))
if (a.type(value)() == 'string') { if (a.type(value)() == 'string') {
value = u.template(value, point.meta) value = u.template(value, point.meta)
value = converters[type](value) value = converters[type](value)
} }
// type-specific processing // type-specific postprocessing
if (['string', 'number', 'boolean'].includes(type)) { if (['string', 'number', 'boolean', 'array', 'object'].includes(type)) {
parsed_params[param_name] = value parsed_params[param_name] = value
} else if (type == 'net') { } else if (type == 'net') {
const net = a.sane(value, `${name}.params.${param_name}`, 'string')(units) const net = a.sane(value, `${name}.params.${param_name}`, 'string')(units)
const index = net_indexer(net) const index = net_indexer(net)
parsed_params[param_name] = { parsed_params[param_name] = net_obj(net, index)
name: net, } else { // anchor
index: index, let parsed_anchor = anchor(value, `${name}.params.${param_name}`, points, point)(units)
str: `(net ${index} "${net}")`
}
} else if (type == 'anchor') {
let parsed_anchor = anchor(value || {}, `${name}.params.${param_name}`, points, point)(units)
parsed_anchor.y = -parsed_anchor.y // kicad mirror, as per usual parsed_anchor.y = -parsed_anchor.y // kicad mirror, as per usual
parsed_params[param_name] = parsed_anchor parsed_params[param_name] = parsed_anchor
} }
@ -227,31 +258,35 @@ const footprint = exports._footprint = (points, net_indexer, component_indexer,
parsed_params.ref_hide = extra.references ? '' : 'hide' parsed_params.ref_hide = extra.references ? '' : 'hide'
// footprint positioning // footprint positioning
parsed_params.x = point.x
parsed_params.y = -point.y
parsed_params.r = point.r
parsed_params.rot = point.r // to be deprecated
parsed_params.xy = `${point.x} ${-point.y}`
parsed_params.at = `(at ${point.x} ${-point.y} ${point.r})` parsed_params.at = `(at ${point.x} ${-point.y} ${point.r})`
parsed_params.rot = point.r
parsed_params.ixy = (x, y) => { const internal_xyfunc = (x, y, resist) => {
const sign = point.meta.mirrored ? -1 : 1 const sign = resist ? 1 : (point.meta.mirrored ? -1 : 1)
return `${sign * x} ${y}` return xy_obj(sign * x, y)
} }
const xyfunc = (x, y, resist=true) => { parsed_params.isxy = (x, y) => internal_xyfunc(x, y, false)
parsed_params.iaxy = (x, y) => internal_xyfunc(x, y, true)
const external_xyfunc = (x, y, resist) => {
const new_anchor = anchor({ const new_anchor = anchor({
shift: [x, -y], shift: [x, -y],
resist: resist resist: resist
}, '_internal_footprint_xy', points, point)(units) }, '_internal_footprint_xy', points, point)(units)
return `${new_anchor.x} ${-new_anchor.y}` return xy_obj(new_anchor.x, -new_anchor.y)
} }
parsed_params.xy = (x, y) => xyfunc(x, y, true) parsed_params.esxy = (x, y) => external_xyfunc(x, y, false)
parsed_params.sxy = (x, y) => xyfunc(x, y, false) parsed_params.eaxy = (x, y) => external_xyfunc(x, y, true)
// allowing footprints to add dynamic nets // allowing footprints to add dynamic nets
parsed_params.local_net = suffix => { parsed_params.local_net = suffix => {
const net = `${component_ref}_${suffix}` const net = `${component_ref}_${suffix}`
const index = net_indexer(net) const index = net_indexer(net)
return { return net_obj(net, index)
name: net,
index: index,
str: `(net ${index} "${net}")`
}
} }
return fp.body(parsed_params) return fp.body(parsed_params)

View file

@ -76,4 +76,11 @@ module.exports = class Point {
const dy = other.y - this.y const dy = other.y - this.y
return -Math.atan2(dx, dy) * (180 / Math.PI) return -Math.atan2(dx, dy) * (180 / Math.PI)
} }
equals(other) {
return this.x === other.x
&& this.y === other.y
&& this.r === other.r
&& JSON.stringify(this.meta) === JSON.stringify(other.meta)
}
} }

View file

@ -21,7 +21,7 @@ const render_zone = exports._render_zone = (zone_name, zone, anchor, global_key,
a.unexpected(zone, `points.zones.${zone_name}`, ['columns', 'rows', 'key']) a.unexpected(zone, `points.zones.${zone_name}`, ['columns', 'rows', 'key'])
// the anchor comes from "above", because it needs other zones too (for references) // the anchor comes from "above", because it needs other zones too (for references)
const cols = a.sane(zone.columns || {}, `points.zones.${zone_name}.columns`, 'object')() const cols = zone.columns = a.sane(zone.columns || {}, `points.zones.${zone_name}.columns`, 'object')()
const zone_wide_rows = a.sane(zone.rows || {}, `points.zones.${zone_name}.rows`, 'object')() const zone_wide_rows = a.sane(zone.rows || {}, `points.zones.${zone_name}.rows`, 'object')()
for (const [key, val] of Object.entries(zone_wide_rows)) { for (const [key, val] of Object.entries(zone_wide_rows)) {
zone_wide_rows[key] = val || {} // no check yet, as it will be extended later zone_wide_rows[key] = val || {} // no check yet, as it will be extended later
@ -43,7 +43,6 @@ const render_zone = exports._render_zone = (zone_name, zone, anchor, global_key,
// column layout // column layout
const col_minmax = {}
if (!Object.keys(cols).length) { if (!Object.keys(cols).length) {
cols.default = {} cols.default = {}
} }
@ -53,7 +52,6 @@ const render_zone = exports._render_zone = (zone_name, zone, anchor, global_key,
// column-level sanitization // column-level sanitization
col = col || {} col = col || {}
col_minmax[col_name] = {min: Infinity, max: -Infinity}
a.unexpected( a.unexpected(
col, col,
@ -92,6 +90,7 @@ const render_zone = exports._render_zone = (zone_name, zone, anchor, global_key,
orient: 0, orient: 0,
shift: [0, 0], shift: [0, 0],
rotate: 0, rotate: 0,
adjust: {},
width: units.$default_width, width: units.$default_width,
height: units.$default_height, height: units.$default_height,
padding: units.$default_padding, padding: units.$default_padding,
@ -117,7 +116,7 @@ const render_zone = exports._render_zone = (zone_name, zone, anchor, global_key,
key.col.name = col_name key.col.name = col_name
key.row = row key.row = row
key.stagger = a.sane(key.stagger, `${key.name}.shift`, 'number')(units) key.stagger = a.sane(key.stagger, `${key.name}.stagger`, 'number')(units)
key.spread = a.sane(key.spread, `${key.name}.spread`, 'number')(units) key.spread = a.sane(key.spread, `${key.name}.spread`, 'number')(units)
key.splay = a.sane(key.splay, `${key.name}.splay`, 'number')(units) key.splay = a.sane(key.splay, `${key.name}.splay`, 'number')(units)
key.origin = a.xy(key.origin, `${key.name}.origin`)(units) key.origin = a.xy(key.origin, `${key.name}.origin`)(units)
@ -168,83 +167,34 @@ const render_zone = exports._render_zone = (zone_name, zone, anchor, global_key,
// copy the current column anchor // copy the current column anchor
let point = running_anchor.clone() let point = running_anchor.clone()
// apply per-key adjustments // apply cumulative per-key adjustments
point.r += key.orient point.r += key.orient
point.shift(key.shift) point.shift(key.shift)
point.r += key.rotate point.r += key.rotate
// commit running anchor
running_anchor = point.clone()
// apply independent adjustments
point = anchor_lib.parse(key.adjust, `${key.name}.adjust`, {}, point)(units)
// save new key // save new key
point.meta = key point.meta = key
points[key.name] = point points[key.name] = point
// collect minmax stats for autobind
col_minmax[col_name].min = Math.min(col_minmax[col_name].min, point.y)
col_minmax[col_name].max = Math.max(col_minmax[col_name].max, point.y)
// advance the running anchor to the next position // advance the running anchor to the next position
running_anchor = point.clone()
running_anchor.shift([0, key.padding]) running_anchor.shift([0, key.padding])
} }
first_col = false first_col = false
} }
// autobind
let col_names = Object.keys(col_minmax)
let col_index = 0
for (const [col_name, bounds] of Object.entries(col_minmax)) {
for (const point of Object.values(points)) {
if (point.meta.col.name != col_name) continue
if (!point.meta.autobind) continue
const autobind = a.sane(point.meta.autobind, `${point.meta.name}.autobind`, 'number')(units)
// specify default as -1, so we can recognize where it was left undefined even after number-ification
const bind = point.meta.bind = a.trbl(point.meta.bind, `${point.meta.name}.bind`, -1)(units)
// up
if (bind[0] == -1) {
if (point.y < bounds.max) bind[0] = autobind
else bind[0] = 0
}
// right
if (bind[1] == -1) {
bind[1] = 0
if (col_index < col_names.length - 1) {
const right = col_minmax[col_names[col_index + 1]]
if (point.y >= right.min && point.y <= right.max) {
bind[1] = autobind
}
}
}
// down
if (bind[2] == -1) {
if (point.y > bounds.min) bind[2] = autobind
else bind[2] = 0
}
// left
if (bind[3] == -1) {
bind[3] = 0
if (col_index > 0) {
const left = col_minmax[col_names[col_index - 1]]
if (point.y >= left.min && point.y <= left.max) {
bind[3] = autobind
}
}
}
}
col_index++
}
return points return points
} }
const parse_axis = exports._parse_axis = (config, name, points, units) => { const parse_axis = exports._parse_axis = (config, name, points, units) => {
if (!['number', 'undefined'].includes(a.type(config)(units))) { if (!['number', 'undefined'].includes(a.type(config)(units))) {
const mirror_obj = a.sane(config || {}, name, 'object')() const mirror_obj = a.sane(config, name, 'object')()
const distance = a.sane(mirror_obj.distance || 0, `${name}.distance`, 'number')(units) const distance = a.sane(mirror_obj.distance || 0, `${name}.distance`, 'number')(units)
delete mirror_obj.distance delete mirror_obj.distance
let axis = anchor_lib.parse(mirror_obj, name, points)(units).x let axis = anchor_lib.parse(mirror_obj, name, points)(units).x
@ -254,21 +204,91 @@ const parse_axis = exports._parse_axis = (config, name, points, units) => {
} }
const perform_mirror = exports._perform_mirror = (point, axis) => { const perform_mirror = exports._perform_mirror = (point, axis) => {
if (axis !== undefined) { point.meta.mirrored = false
point.meta.mirrored = false if (point.meta.asym == 'source') return ['', null]
if (point.meta.asym == 'source') return ['', null] const mp = point.clone().mirror(axis)
const mp = point.clone().mirror(axis) const mirrored_name = `mirror_${point.meta.name}`
const mirrored_name = `mirror_${point.meta.name}` mp.meta = prep.extend(mp.meta, mp.meta.mirror || {})
mp.meta = prep.extend(mp.meta, mp.meta.mirror || {}) mp.meta.name = mirrored_name
mp.meta.name = mirrored_name mp.meta.colrow = `mirror_${mp.meta.colrow}`
mp.meta.colrow = `mirror_${mp.meta.colrow}` mp.meta.mirrored = true
mp.meta.mirrored = true if (point.meta.asym == 'clone') {
if (point.meta.asym == 'clone') { point.meta.skip = true
point.meta.skip = true }
} return [mirrored_name, mp]
return [mirrored_name, mp] }
const perform_autobind = exports._perform_autobind = (points, units) => {
const bounds = {}
const col_lists = {}
const mirrorzone = p => (p.meta.mirrored ? 'mirror_' : '') + p.meta.zone.name
// round one: get column upper/lower bounds and per-zone column lists
for (const p of Object.values(points)) {
const zone = mirrorzone(p)
const col = p.meta.col.name
if (!bounds[zone]) bounds[zone] = {}
if (!bounds[zone][col]) bounds[zone][col] = {min: Infinity, max: -Infinity}
if (!col_lists[zone]) col_lists[zone] = Object.keys(p.meta.zone.columns)
bounds[zone][col].min = Math.min(bounds[zone][col].min, p.y)
bounds[zone][col].max = Math.max(bounds[zone][col].max, p.y)
}
// round two: apply autobind as appropriate
for (const p of Object.values(points)) {
const autobind = a.sane(p.meta.autobind, `${p.meta.name}.autobind`, 'number')(units)
if (!autobind) continue
const zone = mirrorzone(p)
const col = p.meta.col.name
const col_list = col_lists[zone]
const col_bounds = bounds[zone][col]
// specify default as -1, so we can recognize where it was left undefined even after number-ification
const bind = p.meta.bind = a.trbl(p.meta.bind, `${p.meta.name}.bind`, -1)(units)
// up
if (bind[0] == -1) {
if (p.y < col_bounds.max) bind[0] = autobind
else bind[0] = 0
}
// down
if (bind[2] == -1) {
if (p.y > col_bounds.min) bind[2] = autobind
else bind[2] = 0
}
// left
if (bind[3] == -1) {
bind[3] = 0
const col_index = col_list.indexOf(col)
if (col_index > 0) {
const left = bounds[zone][col_list[col_index - 1]]
if (left && p.y >= left.min && p.y <= left.max) {
bind[3] = autobind
}
}
}
// right
if (bind[1] == -1) {
bind[1] = 0
const col_index = col_list.indexOf(col)
if (col_index < col_list.length - 1) {
const right = bounds[zone][col_list[col_index + 1]]
if (right && p.y >= right.min && p.y <= right.max) {
bind[1] = autobind
}
}
}
} }
return ['', null]
} }
exports.parse = (config, units) => { exports.parse = (config, units) => {
@ -300,13 +320,11 @@ exports.parse = (config, units) => {
// simplifying the names in individual point "zones" and single-key columns // simplifying the names in individual point "zones" and single-key columns
while (Object.keys(new_points).some(k => k.endsWith('_default'))) { while (Object.keys(new_points).some(k => k.endsWith('_default'))) {
for (const key of Object.keys(new_points)) { for (const key of Object.keys(new_points).filter(k => k.endsWith('_default'))) {
if (key.endsWith('_default')) { const new_key = key.slice(0, -8)
const new_key = key.slice(0, -8) new_points[new_key] = new_points[key]
new_points[new_key] = new_points[key] new_points[new_key].meta.name = new_key
new_points[new_key].meta.name = new_key delete new_points[key]
delete new_points[key]
}
} }
} }
@ -352,7 +370,7 @@ exports.parse = (config, units) => {
const global_axis = parse_axis(global_mirror, `points.mirror`, points, units) const global_axis = parse_axis(global_mirror, `points.mirror`, points, units)
const global_mirrored_points = {} const global_mirrored_points = {}
for (const point of Object.values(points)) { for (const point of Object.values(points)) {
if (global_axis !== undefined && point.mirrored === undefined) { if (global_axis !== undefined && point.meta.mirrored === undefined) {
const [mname, mp] = perform_mirror(point, global_axis) const [mname, mp] = perform_mirror(point, global_axis)
if (mp) { if (mp) {
global_mirrored_points[mname] = mp global_mirrored_points[mname] = mp
@ -368,6 +386,9 @@ exports.parse = (config, units) => {
filtered[k] = p filtered[k] = p
} }
// apply autobind
perform_autobind(filtered, units)
// done // done
return filtered return filtered
} }

View file

@ -42,11 +42,14 @@ const traverse = exports.traverse = (config, root, breadcrumbs, op) => {
} }
return result return result
} else if (a.type(config)() == 'array') { } else if (a.type(config)() == 'array') {
// needed so that arrays can set output the same way as objects within ops
const dummy = {}
const result = [] const result = []
let index = 0 let index = 0
for (const val of config) { for (const val of config) {
breadcrumbs.push(`[${index}]`) breadcrumbs.push(`[${index}]`)
result[index] = traverse(val, root, breadcrumbs, op) op(dummy, 'dummykey', traverse(val, root, breadcrumbs, op), root, breadcrumbs)
result[index] = dummy.dummykey
breadcrumbs.pop() breadcrumbs.pop()
index++ index++
} }

View file

@ -23,7 +23,7 @@ exports.template = (str, vals={}) => {
let res = str let res = str
let shift = 0 let shift = 0
for (const match of str.matchAll(regex)) { for (const match of str.matchAll(regex)) {
const replacement = deep(vals, match[1]) || '' const replacement = (deep(vals, match[1]) || '') + ''
res = res.substring(0, match.index + shift) res = res.substring(0, match.index + shift)
+ replacement + replacement
+ res.substring(match.index + shift + match[0].length) + res.substring(match.index + shift + match[0].length)

View file

@ -1,4 +1,4 @@
function square_outline_fn(){ function square_extrude_5_outline_fn(){
return new CSG.Path2D([[-2.5,-2.5],[2.5,-2.5]]).appendPoint([2.5,2.5]).appendPoint([-2.5,2.5]).appendPoint([-2.5,-2.5]).close().innerToCAG() return new CSG.Path2D([[-2.5,-2.5],[2.5,-2.5]]).appendPoint([2.5,2.5]).appendPoint([-2.5,2.5]).appendPoint([-2.5,-2.5]).close().innerToCAG()
.extrude({ offset: [0, 0, 5] }); .extrude({ offset: [0, 0, 5] });
} }
@ -10,7 +10,7 @@ function square_outline_fn(){
// creating part 0 of case cube // creating part 0 of case cube
let cube__part_0 = square_outline_fn(); let cube__part_0 = square_extrude_5_outline_fn();
// make sure that rotations are relative // make sure that rotations are relative
let cube__part_0_bounds = cube__part_0.getBounds(); let cube__part_0_bounds = cube__part_0.getBounds();

View file

@ -0,0 +1,36 @@
points.zones.matrix: {}
outlines:
_square:
- what: rectangle
where: true
size: [8, 8]
_circle:
- what: circle
where: true
radius: 3
cases:
_cube:
- name: _square
extrude: 8
_cylinder_one:
- name: _circle
extrude: 8
_subtract:
target:
name: _cube
what: case
tool:
name: _cylinder_one
what: case
operation: subtract
_cylinder_two:
- name: _circle
extrude: 8
shift: [0,4,4]
rotate: [90,0,0]
_flat_square:
- "_square"
combination:
- "_subtract"
- "~_cylinder_two"
- "+_flat_square"

View file

@ -0,0 +1,211 @@
function _square_extrude_8_outline_fn(){
return new CSG.Path2D([[-4,-4],[4,-4]]).appendPoint([4,4]).appendPoint([-4,4]).appendPoint([-4,-4]).close().innerToCAG()
.extrude({ offset: [0, 0, 8] });
}
function _circle_extrude_8_outline_fn(){
return CAG.circle({"center":[0,0],"radius":3})
.extrude({ offset: [0, 0, 8] });
}
function _square_extrude_1_outline_fn(){
return new CSG.Path2D([[-4,-4],[4,-4]]).appendPoint([4,4]).appendPoint([-4,4]).appendPoint([-4,-4]).close().innerToCAG()
.extrude({ offset: [0, 0, 1] });
}
function _subtract_case_fn() {
// creating part target of case _subtract
let _subtract__part_target = _cube_case_fn();
// make sure that rotations are relative
let _subtract__part_target_bounds = _subtract__part_target.getBounds();
let _subtract__part_target_x = _subtract__part_target_bounds[0].x + (_subtract__part_target_bounds[1].x - _subtract__part_target_bounds[0].x) / 2
let _subtract__part_target_y = _subtract__part_target_bounds[0].y + (_subtract__part_target_bounds[1].y - _subtract__part_target_bounds[0].y) / 2
_subtract__part_target = translate([-_subtract__part_target_x, -_subtract__part_target_y, 0], _subtract__part_target);
_subtract__part_target = rotate([0,0,0], _subtract__part_target);
_subtract__part_target = translate([_subtract__part_target_x, _subtract__part_target_y, 0], _subtract__part_target);
_subtract__part_target = translate([0,0,0], _subtract__part_target);
let result = _subtract__part_target;
// creating part tool of case _subtract
let _subtract__part_tool = _cylinder_one_case_fn();
// make sure that rotations are relative
let _subtract__part_tool_bounds = _subtract__part_tool.getBounds();
let _subtract__part_tool_x = _subtract__part_tool_bounds[0].x + (_subtract__part_tool_bounds[1].x - _subtract__part_tool_bounds[0].x) / 2
let _subtract__part_tool_y = _subtract__part_tool_bounds[0].y + (_subtract__part_tool_bounds[1].y - _subtract__part_tool_bounds[0].y) / 2
_subtract__part_tool = translate([-_subtract__part_tool_x, -_subtract__part_tool_y, 0], _subtract__part_tool);
_subtract__part_tool = rotate([0,0,0], _subtract__part_tool);
_subtract__part_tool = translate([_subtract__part_tool_x, _subtract__part_tool_y, 0], _subtract__part_tool);
_subtract__part_tool = translate([0,0,0], _subtract__part_tool);
result = result.subtract(_subtract__part_tool);
return result;
}
function _cube_case_fn() {
// creating part 0 of case _cube
let _cube__part_0 = _square_extrude_8_outline_fn();
// make sure that rotations are relative
let _cube__part_0_bounds = _cube__part_0.getBounds();
let _cube__part_0_x = _cube__part_0_bounds[0].x + (_cube__part_0_bounds[1].x - _cube__part_0_bounds[0].x) / 2
let _cube__part_0_y = _cube__part_0_bounds[0].y + (_cube__part_0_bounds[1].y - _cube__part_0_bounds[0].y) / 2
_cube__part_0 = translate([-_cube__part_0_x, -_cube__part_0_y, 0], _cube__part_0);
_cube__part_0 = rotate([0,0,0], _cube__part_0);
_cube__part_0 = translate([_cube__part_0_x, _cube__part_0_y, 0], _cube__part_0);
_cube__part_0 = translate([0,0,0], _cube__part_0);
let result = _cube__part_0;
return result;
}
function _cylinder_one_case_fn() {
// creating part 0 of case _cylinder_one
let _cylinder_one__part_0 = _circle_extrude_8_outline_fn();
// make sure that rotations are relative
let _cylinder_one__part_0_bounds = _cylinder_one__part_0.getBounds();
let _cylinder_one__part_0_x = _cylinder_one__part_0_bounds[0].x + (_cylinder_one__part_0_bounds[1].x - _cylinder_one__part_0_bounds[0].x) / 2
let _cylinder_one__part_0_y = _cylinder_one__part_0_bounds[0].y + (_cylinder_one__part_0_bounds[1].y - _cylinder_one__part_0_bounds[0].y) / 2
_cylinder_one__part_0 = translate([-_cylinder_one__part_0_x, -_cylinder_one__part_0_y, 0], _cylinder_one__part_0);
_cylinder_one__part_0 = rotate([0,0,0], _cylinder_one__part_0);
_cylinder_one__part_0 = translate([_cylinder_one__part_0_x, _cylinder_one__part_0_y, 0], _cylinder_one__part_0);
_cylinder_one__part_0 = translate([0,0,0], _cylinder_one__part_0);
let result = _cylinder_one__part_0;
return result;
}
function _cylinder_two_case_fn() {
// creating part 0 of case _cylinder_two
let _cylinder_two__part_0 = _circle_extrude_8_outline_fn();
// make sure that rotations are relative
let _cylinder_two__part_0_bounds = _cylinder_two__part_0.getBounds();
let _cylinder_two__part_0_x = _cylinder_two__part_0_bounds[0].x + (_cylinder_two__part_0_bounds[1].x - _cylinder_two__part_0_bounds[0].x) / 2
let _cylinder_two__part_0_y = _cylinder_two__part_0_bounds[0].y + (_cylinder_two__part_0_bounds[1].y - _cylinder_two__part_0_bounds[0].y) / 2
_cylinder_two__part_0 = translate([-_cylinder_two__part_0_x, -_cylinder_two__part_0_y, 0], _cylinder_two__part_0);
_cylinder_two__part_0 = rotate([90,0,0], _cylinder_two__part_0);
_cylinder_two__part_0 = translate([_cylinder_two__part_0_x, _cylinder_two__part_0_y, 0], _cylinder_two__part_0);
_cylinder_two__part_0 = translate([0,4,4], _cylinder_two__part_0);
let result = _cylinder_two__part_0;
return result;
}
function _flat_square_case_fn() {
// creating part 0 of case _flat_square
let _flat_square__part_0 = _square_extrude_1_outline_fn();
// make sure that rotations are relative
let _flat_square__part_0_bounds = _flat_square__part_0.getBounds();
let _flat_square__part_0_x = _flat_square__part_0_bounds[0].x + (_flat_square__part_0_bounds[1].x - _flat_square__part_0_bounds[0].x) / 2
let _flat_square__part_0_y = _flat_square__part_0_bounds[0].y + (_flat_square__part_0_bounds[1].y - _flat_square__part_0_bounds[0].y) / 2
_flat_square__part_0 = translate([-_flat_square__part_0_x, -_flat_square__part_0_y, 0], _flat_square__part_0);
_flat_square__part_0 = rotate([0,0,0], _flat_square__part_0);
_flat_square__part_0 = translate([_flat_square__part_0_x, _flat_square__part_0_y, 0], _flat_square__part_0);
_flat_square__part_0 = translate([0,0,0], _flat_square__part_0);
let result = _flat_square__part_0;
return result;
}
function combination_case_fn() {
// creating part 0 of case combination
let combination__part_0 = _subtract_case_fn();
// make sure that rotations are relative
let combination__part_0_bounds = combination__part_0.getBounds();
let combination__part_0_x = combination__part_0_bounds[0].x + (combination__part_0_bounds[1].x - combination__part_0_bounds[0].x) / 2
let combination__part_0_y = combination__part_0_bounds[0].y + (combination__part_0_bounds[1].y - combination__part_0_bounds[0].y) / 2
combination__part_0 = translate([-combination__part_0_x, -combination__part_0_y, 0], combination__part_0);
combination__part_0 = rotate([0,0,0], combination__part_0);
combination__part_0 = translate([combination__part_0_x, combination__part_0_y, 0], combination__part_0);
combination__part_0 = translate([0,0,0], combination__part_0);
let result = combination__part_0;
// creating part 1 of case combination
let combination__part_1 = _cylinder_two_case_fn();
// make sure that rotations are relative
let combination__part_1_bounds = combination__part_1.getBounds();
let combination__part_1_x = combination__part_1_bounds[0].x + (combination__part_1_bounds[1].x - combination__part_1_bounds[0].x) / 2
let combination__part_1_y = combination__part_1_bounds[0].y + (combination__part_1_bounds[1].y - combination__part_1_bounds[0].y) / 2
combination__part_1 = translate([-combination__part_1_x, -combination__part_1_y, 0], combination__part_1);
combination__part_1 = rotate([0,0,0], combination__part_1);
combination__part_1 = translate([combination__part_1_x, combination__part_1_y, 0], combination__part_1);
combination__part_1 = translate([0,0,0], combination__part_1);
result = result.intersect(combination__part_1);
// creating part 2 of case combination
let combination__part_2 = _flat_square_case_fn();
// make sure that rotations are relative
let combination__part_2_bounds = combination__part_2.getBounds();
let combination__part_2_x = combination__part_2_bounds[0].x + (combination__part_2_bounds[1].x - combination__part_2_bounds[0].x) / 2
let combination__part_2_y = combination__part_2_bounds[0].y + (combination__part_2_bounds[1].y - combination__part_2_bounds[0].y) / 2
combination__part_2 = translate([-combination__part_2_x, -combination__part_2_y, 0], combination__part_2);
combination__part_2 = rotate([0,0,0], combination__part_2);
combination__part_2 = translate([combination__part_2_x, combination__part_2_y, 0], combination__part_2);
combination__part_2 = translate([0,0,0], combination__part_2);
result = result.union(combination__part_2);
return result;
}
function main() {
return combination_case_fn();
}

View file

@ -1,4 +1,4 @@
function export_outline_fn(){ function export_extrude_1_outline_fn(){
return new CSG.Path2D([[-9,-9],[9,-9]]).appendPoint([9,9]).appendPoint([-9,9]).appendPoint([-9,-9]).close().innerToCAG() return new CSG.Path2D([[-9,-9],[9,-9]]).appendPoint([9,9]).appendPoint([-9,9]).appendPoint([-9,-9]).close().innerToCAG()
.extrude({ offset: [0, 0, 1] }); .extrude({ offset: [0, 0, 1] });
} }
@ -10,7 +10,7 @@ function export_outline_fn(){
// creating part 0 of case _export // creating part 0 of case _export
let _export__part_0 = export_outline_fn(); let _export__part_0 = export_extrude_1_outline_fn();
// make sure that rotations are relative // make sure that rotations are relative
let _export__part_0_bounds = _export__part_0.getBounds(); let _export__part_0_bounds = _export__part_0.getBounds();

View file

@ -1,4 +1,4 @@
function export_outline_fn(){ function export_extrude_1_outline_fn(){
return new CSG.Path2D([[-9,-9],[9,-9]]).appendPoint([9,9]).appendPoint([-9,9]).appendPoint([-9,-9]).close().innerToCAG() return new CSG.Path2D([[-9,-9],[9,-9]]).appendPoint([9,9]).appendPoint([-9,9]).appendPoint([-9,-9]).close().innerToCAG()
.extrude({ offset: [0, 0, 1] }); .extrude({ offset: [0, 0, 1] });
} }
@ -10,7 +10,7 @@ function export_outline_fn(){
// creating part 0 of case export // creating part 0 of case export
let export__part_0 = export_outline_fn(); let export__part_0 = export_extrude_1_outline_fn();
// make sure that rotations are relative // make sure that rotations are relative
let export__part_0_bounds = export__part_0.getBounds(); let export__part_0_bounds = export__part_0.getBounds();

View file

@ -5,8 +5,8 @@
(page A3) (page A3)
(title_block (title_block
(title _export) (title _export)
(rev v1.0.0) (rev v3.14)
(company Unknown) (company MrZealot)
) )
(general (general

View file

@ -5,8 +5,8 @@
(page A3) (page A3)
(title_block (title_block
(title export) (title export)
(rev v1.0.0) (rev v3.14)
(company Unknown) (company MrZealot)
) )
(general (general

View file

@ -14,6 +14,7 @@ matrix:
- 0 - 0
- 0 - 0
rotate: 0 rotate: 0
adjust: {}
width: 18 width: 18
height: 18 height: 18
padding: 19 padding: 19
@ -23,6 +24,11 @@ matrix:
colrow: default_default colrow: default_default
name: matrix name: matrix
zone: zone:
columns:
default:
rows: {}
key: {}
name: default
name: matrix name: matrix
col: col:
rows: {} rows: {}

View file

@ -1,3 +1,6 @@
meta:
author: MrZealot
version: v3.14
units: units:
a: 28 + u a: 28 + u
points: points:

View file

@ -1,3 +1,6 @@
meta:
author: MrZealot
version: v3.14
units: units:
a: 28 + u a: 28 + u
points.zones.matrix: points.zones.matrix:

View file

@ -14,6 +14,7 @@ matrix_col_row:
- 0 - 0
- 0 - 0
rotate: 0 rotate: 0
adjust: {}
width: 18 width: 18
height: 18 height: 18
padding: 19 padding: 19
@ -24,14 +25,17 @@ matrix_col_row:
name: matrix_col_row name: matrix_col_row
zone: zone:
columns: columns:
col: &ref_0 col:
rows: {} rows: {}
key: {} key: {}
name: col name: col
rows: rows:
row: {} row: {}
name: matrix name: matrix
col: *ref_0 col:
rows: {}
key: {}
name: col
row: row row: row
bind: bind:
- 0 - 0

View file

@ -1,3 +1,6 @@
meta:
author: MrZealot
version: v3.14
units: units:
a: 28 + u a: 28 + u
points.zones.matrix: points.zones.matrix:

15
test/fixtures/minimal_kle.json vendored Normal file
View file

@ -0,0 +1,15 @@
[
[
"0_0",
"0_1"
],
[
"1_0",
"1_1"
],
[
"",
""
]
]

View file

@ -38,4 +38,14 @@ pcbs.pcb.footprints:
to: to to: to
reverse: true reverse: true
hotswap: true hotswap: true
adjust.shift: [200, 0] adjust.shift: [200, 0]
# all of keycaps, reverse and hotswap
- what: choc
params:
from: from
to: to
keycaps: true
reverse: true
hotswap: true
adjust.shift: [250, 0]

View file

@ -284,6 +284,58 @@
(pad "" np_thru_hole circle (at 5 -3.75) (size 3 3) (drill 3) (layers *.Cu *.Mask))
(pad "" np_thru_hole circle (at 0 -5.95) (size 3 3) (drill 3) (layers *.Cu *.Mask))
(pad 1 smd rect (at -3.275 -5.95 0) (size 2.6 2.6) (layers B.Cu B.Paste B.Mask) (net 1 "from"))
(pad 2 smd rect (at 8.275 -3.75 0) (size 2.6 2.6) (layers B.Cu B.Paste B.Mask) (net 2 "to"))
(pad "" np_thru_hole circle (at -5 -3.75) (size 3 3) (drill 3) (layers *.Cu *.Mask))
(pad "" np_thru_hole circle (at 0 -5.95) (size 3 3) (drill 3) (layers *.Cu *.Mask))
(pad 1 smd rect (at 3.275 -5.95 0) (size 2.6 2.6) (layers F.Cu F.Paste F.Mask) (net 1 "from"))
(pad 2 smd rect (at -8.275 -3.75 0) (size 2.6 2.6) (layers F.Cu F.Paste F.Mask) (net 2 "to"))
)
(module PG1350 (layer F.Cu) (tedit 5DD50112)
(at 250 0 0)
(fp_text reference "S6" (at 0 0) (layer F.SilkS) hide (effects (font (size 1.27 1.27) (thickness 0.15))))
(fp_text value "" (at 0 0) (layer F.SilkS) hide (effects (font (size 1.27 1.27) (thickness 0.15))))
(fp_line (start -7 -6) (end -7 -7) (layer Dwgs.User) (width 0.15))
(fp_line (start -7 7) (end -6 7) (layer Dwgs.User) (width 0.15))
(fp_line (start -6 -7) (end -7 -7) (layer Dwgs.User) (width 0.15))
(fp_line (start -7 7) (end -7 6) (layer Dwgs.User) (width 0.15))
(fp_line (start 7 6) (end 7 7) (layer Dwgs.User) (width 0.15))
(fp_line (start 7 -7) (end 6 -7) (layer Dwgs.User) (width 0.15))
(fp_line (start 6 7) (end 7 7) (layer Dwgs.User) (width 0.15))
(fp_line (start 7 -7) (end 7 -6) (layer Dwgs.User) (width 0.15))
(pad "" np_thru_hole circle (at 0 0) (size 3.429 3.429) (drill 3.429) (layers *.Cu *.Mask))
(pad "" np_thru_hole circle (at 5.5 0) (size 1.7018 1.7018) (drill 1.7018) (layers *.Cu *.Mask))
(pad "" np_thru_hole circle (at -5.5 0) (size 1.7018 1.7018) (drill 1.7018) (layers *.Cu *.Mask))
(fp_line (start -9 -8.5) (end 9 -8.5) (layer Dwgs.User) (width 0.15))
(fp_line (start 9 -8.5) (end 9 8.5) (layer Dwgs.User) (width 0.15))
(fp_line (start 9 8.5) (end -9 8.5) (layer Dwgs.User) (width 0.15))
(fp_line (start -9 8.5) (end -9 -8.5) (layer Dwgs.User) (width 0.15))
(pad "" np_thru_hole circle (at 5 -3.75) (size 3 3) (drill 3) (layers *.Cu *.Mask)) (pad "" np_thru_hole circle (at 5 -3.75) (size 3 3) (drill 3) (layers *.Cu *.Mask))
(pad "" np_thru_hole circle (at 0 -5.95) (size 3 3) (drill 3) (layers *.Cu *.Mask)) (pad "" np_thru_hole circle (at 0 -5.95) (size 3 3) (drill 3) (layers *.Cu *.Mask))

View file

@ -22,3 +22,12 @@ pcbs.pcb.footprints:
to: to to: to
reverse: true reverse: true
adjust.shift: [100, 0] adjust.shift: [100, 0]
# reverse with keycap visualization
- what: chocmini
params:
from: from
to: to
keycaps: true
reverse: true
adjust.shift: [150, 0]

View file

@ -267,6 +267,67 @@
) )
(module lib:Kailh_PG1232 (layer F.Cu) (tedit 5E1ADAC2)
(at 150 0 0)
(fp_text reference "S4" (at 0 0) (layer F.SilkS) hide (effects (font (size 1.27 1.27) (thickness 0.15))))
(fp_text value Kailh_PG1232 (at 0 -7.3) (layer F.Fab) (effects (font (size 1 1) (thickness 0.15))))
(fp_line (start -7.25 -6.75) (end -6.25 -6.75) (layer Dwgs.User) (width 0.15))
(fp_line (start -7.25 -6.75) (end -7.25 -5.75) (layer Dwgs.User) (width 0.15))
(fp_line (start -7.25 6.75) (end -6.25 6.75) (layer Dwgs.User) (width 0.15))
(fp_line (start -7.25 6.75) (end -7.25 5.75) (layer Dwgs.User) (width 0.15))
(fp_line (start 7.25 -6.75) (end 6.25 -6.75) (layer Dwgs.User) (width 0.15))
(fp_line (start 7.25 -6.75) (end 7.25 -5.75) (layer Dwgs.User) (width 0.15))
(fp_line (start 7.25 6.75) (end 6.25 6.75) (layer Dwgs.User) (width 0.15))
(fp_line (start 7.25 6.75) (end 7.25 5.75) (layer Dwgs.User) (width 0.15))
(fp_line (start 2.8 -5.35) (end -2.8 -5.35) (layer Dwgs.User) (width 0.15))
(fp_line (start -2.8 -3.2) (end 2.8 -3.2) (layer Dwgs.User) (width 0.15))
(fp_line (start 2.8 -3.2) (end 2.8 -5.35) (layer Dwgs.User) (width 0.15))
(fp_line (start -2.8 -3.2) (end -2.8 -5.35) (layer Dwgs.User) (width 0.15))
(fp_line (start 2.25 2.6) (end 5.8 2.6) (layer Edge.Cuts) (width 0.12))
(fp_line (start -2.25 2.6) (end -5.8 2.6) (layer Edge.Cuts) (width 0.12))
(fp_line (start 2.25 3.6) (end 2.25 2.6) (layer Edge.Cuts) (width 0.12))
(fp_line (start -2.25 3.6) (end 2.25 3.6) (layer Edge.Cuts) (width 0.12))
(fp_line (start -2.25 2.6) (end -2.25 3.6) (layer Edge.Cuts) (width 0.12))
(fp_line (start -5.8 2.6) (end -5.8 -2.95) (layer Edge.Cuts) (width 0.12))
(fp_line (start 5.8 -2.95) (end 5.8 2.6) (layer Edge.Cuts) (width 0.12))
(fp_line (start -5.8 -2.95) (end 5.8 -2.95) (layer Edge.Cuts) (width 0.12))
(pad 3 thru_hole circle (at 5.3 -4.75) (size 1.6 1.6) (drill 1.1) (layers *.Cu *.Mask) (clearance 0.2))
(pad 4 thru_hole circle (at -5.3 -4.75) (size 1.6 1.6) (drill 1.1) (layers *.Cu *.Mask) (clearance 0.2))
(fp_line (start -9 -8.5) (end 9 -8.5) (layer Dwgs.User) (width 0.15))
(fp_line (start 9 -8.5) (end 9 8.5) (layer Dwgs.User) (width 0.15))
(fp_line (start 9 8.5) (end -9 8.5) (layer Dwgs.User) (width 0.15))
(fp_line (start -9 8.5) (end -9 -8.5) (layer Dwgs.User) (width 0.15))
(pad 1 thru_hole circle (at -4.58 5.1) (size 1.6 1.6) (drill 1.1) (layers *.Cu *.Mask) (net 1 "from") (clearance 0.2))
(pad 2 thru_hole circle (at 2 5.4) (size 1.6 1.6) (drill 1.1) (layers *.Cu *.Mask) (net 2 "to") (clearance 0.2))
(pad 1 thru_hole circle (at 4.58 5.1) (size 1.6 1.6) (drill 1.1) (layers *.Cu *.Mask) (net 1 "from") (clearance 0.2))
(pad 2 thru_hole circle (at -2 5.4) (size 1.6 1.6) (drill 1.1) (layers *.Cu *.Mask) (net 2 "to") (clearance 0.2))
)
) )

View file

@ -38,4 +38,14 @@ pcbs.pcb.footprints:
to: to to: to
reverse: true reverse: true
hotswap: true hotswap: true
adjust.shift: [200, 0] adjust.shift: [200, 0]
# all of keycaps, reverse and hotswap
- what: mx
params:
from: from
to: to
keycaps: true
reverse: true
hotswap: true
adjust.shift: [250, 0]

View file

@ -284,6 +284,58 @@
(pad "" np_thru_hole circle (at 2.54 -5.08) (size 3 3) (drill 3) (layers *.Cu *.Mask))
(pad "" np_thru_hole circle (at -3.81 -2.54) (size 3 3) (drill 3) (layers *.Cu *.Mask))
(pad 1 smd rect (at -7.085 -2.54 0) (size 2.55 2.5) (layers B.Cu B.Paste B.Mask) (net 1 "from"))
(pad 2 smd rect (at 5.842 -5.08 0) (size 2.55 2.5) (layers B.Cu B.Paste B.Mask) (net 2 "to"))
(pad "" np_thru_hole circle (at -2.54 -5.08) (size 3 3) (drill 3) (layers *.Cu *.Mask))
(pad "" np_thru_hole circle (at 3.81 -2.54) (size 3 3) (drill 3) (layers *.Cu *.Mask))
(pad 1 smd rect (at 7.085 -2.54 0) (size 2.55 2.5) (layers F.Cu F.Paste F.Mask) (net 1 "from"))
(pad 2 smd rect (at -5.842 -5.08 0) (size 2.55 2.5) (layers F.Cu F.Paste F.Mask) (net 2 "to"))
)
(module MX (layer F.Cu) (tedit 5DD4F656)
(at 250 0 0)
(fp_text reference "S6" (at 0 0) (layer F.SilkS) hide (effects (font (size 1.27 1.27) (thickness 0.15))))
(fp_text value "" (at 0 0) (layer F.SilkS) hide (effects (font (size 1.27 1.27) (thickness 0.15))))
(fp_line (start -7 -6) (end -7 -7) (layer Dwgs.User) (width 0.15))
(fp_line (start -7 7) (end -6 7) (layer Dwgs.User) (width 0.15))
(fp_line (start -6 -7) (end -7 -7) (layer Dwgs.User) (width 0.15))
(fp_line (start -7 7) (end -7 6) (layer Dwgs.User) (width 0.15))
(fp_line (start 7 6) (end 7 7) (layer Dwgs.User) (width 0.15))
(fp_line (start 7 -7) (end 6 -7) (layer Dwgs.User) (width 0.15))
(fp_line (start 6 7) (end 7 7) (layer Dwgs.User) (width 0.15))
(fp_line (start 7 -7) (end 7 -6) (layer Dwgs.User) (width 0.15))
(pad "" np_thru_hole circle (at 0 0) (size 3.9878 3.9878) (drill 3.9878) (layers *.Cu *.Mask))
(pad "" np_thru_hole circle (at 5.08 0) (size 1.7018 1.7018) (drill 1.7018) (layers *.Cu *.Mask))
(pad "" np_thru_hole circle (at -5.08 0) (size 1.7018 1.7018) (drill 1.7018) (layers *.Cu *.Mask))
(fp_line (start -9.5 -9.5) (end 9.5 -9.5) (layer Dwgs.User) (width 0.15))
(fp_line (start 9.5 -9.5) (end 9.5 9.5) (layer Dwgs.User) (width 0.15))
(fp_line (start 9.5 9.5) (end -9.5 9.5) (layer Dwgs.User) (width 0.15))
(fp_line (start -9.5 9.5) (end -9.5 -9.5) (layer Dwgs.User) (width 0.15))
(pad "" np_thru_hole circle (at 2.54 -5.08) (size 3 3) (drill 3) (layers *.Cu *.Mask)) (pad "" np_thru_hole circle (at 2.54 -5.08) (size 3 3) (drill 3) (layers *.Cu *.Mask))
(pad "" np_thru_hole circle (at -3.81 -2.54) (size 3 3) (drill 3) (layers *.Cu *.Mask)) (pad "" np_thru_hole circle (at -3.81 -2.54) (size 3 3) (drill 3) (layers *.Cu *.Mask))

View file

@ -25,3 +25,17 @@ pcbs.pcb.footprints:
align: down align: down
mirrored: true mirrored: true
adjust.shift: [50, 50] adjust.shift: [50, 50]
- what: pad
params:
net: net
align: right
mirrored: true
adjust.shift: [100, 0]
- what: pad
params:
net: net
align: left
mirrored: true
adjust.shift: [100, 50]

View file

@ -181,6 +181,44 @@
) )
(module SMDPad (layer F.Cu) (tedit 5B24D78E)
(at 100 0 0)
(fp_text reference "PAD5" (at 0 0) (layer F.SilkS) hide (effects (font (size 1.27 1.27) (thickness 0.15))))
(fp_text value "" (at 0 0) (layer F.SilkS) hide (effects (font (size 1.27 1.27) (thickness 0.15))))
(pad 1 smd rect (at 0 0 0) (size 1 1) (layers F.Cu F.Paste F.Mask) (net 1 "net"))
(pad 1 smd rect (at 0 0 0) (size 1 1) (layers B.Cu B.Paste B.Mask) (net 1 "net"))
)
(module SMDPad (layer F.Cu) (tedit 5B24D78E)
(at 100 -50 0)
(fp_text reference "PAD6" (at 0 0) (layer F.SilkS) hide (effects (font (size 1.27 1.27) (thickness 0.15))))
(fp_text value "" (at 0 0) (layer F.SilkS) hide (effects (font (size 1.27 1.27) (thickness 0.15))))
(pad 1 smd rect (at 0 0 0) (size 1 1) (layers F.Cu F.Paste F.Mask) (net 1 "net"))
(pad 1 smd rect (at 0 0 0) (size 1 1) (layers B.Cu B.Paste B.Mask) (net 1 "net"))
)
) )

View file

@ -64,4 +64,22 @@ pcbs.pcb.footprints:
- what: via - what: via
params: params:
net: net net: net
adjust.shift: [0, 150] adjust.shift: [0, 150]
- what: scrollwheel
params:
from: from
to: to
A: A
B: B
C: C
D: D
reverse: true
adjust.shift: [50, 150]
- what: slider
params:
from: from
to: to
side: B
adjust.shift: [100, 150]

View file

@ -424,6 +424,104 @@
(pad 1 thru_hole circle (at 0 0) (size 0.6 0.6) (drill 0.3) (layers *.Cu) (zone_connect 2) (net 15 "net")) (pad 1 thru_hole circle (at 0 0) (size 0.6 0.6) (drill 0.3) (layers *.Cu) (zone_connect 2) (net 15 "net"))
) )
(module RollerEncoder_Panasonic_EVQWGD001 (layer F.Cu) (tedit 6040A10C)
(at 50 -150 0)
(fp_text reference REF** (at 0 0 0) (layer F.Fab) (effects (font (size 1 1) (thickness 0.15))))
(fp_text value RollerEncoder_Panasonic_EVQWGD001 (at -0.1 9 0) (layer F.Fab) (effects (font (size 1 1) (thickness 0.15))))
(fp_line (start -8.4 -6.4) (end 8.4 -6.4) (layer Dwgs.User) (width 0.12))
(fp_line (start 8.4 -6.4) (end 8.4 7.4) (layer Dwgs.User) (width 0.12))
(fp_line (start 8.4 7.4) (end -8.4 7.4) (layer Dwgs.User) (width 0.12))
(fp_line (start -8.4 7.4) (end -8.4 -6.4) (layer Dwgs.User) (width 0.12))
(fp_line (start 9.8 7.3) (end 9.8 -6.3) (layer Edge.Cuts) (width 0.15))
(fp_line (start 7.4 -6.3) (end 7.4 7.3) (layer Edge.Cuts) (width 0.15))
(fp_line (start 9.5 -6.6) (end 7.7 -6.6) (layer Edge.Cuts) (width 0.15))
(fp_line (start 7.7 7.6) (end 9.5 7.6) (layer Edge.Cuts) (width 0.15))
(fp_arc (start 7.7 7.3) (end 7.4 7.3) (angle -90) (layer Edge.Cuts) (width 0.15))
(fp_arc (start 9.5 7.3) (end 9.5 7.6) (angle -90) (layer Edge.Cuts) (width 0.15))
(fp_arc (start 7.7 -6.3) (end 7.7 -6.6) (angle -90) (layer Edge.Cuts) (width 0.15))
(fp_arc (start 9.5 -6.3) (end 9.8 -6.3) (angle -90) (layer Edge.Cuts) (width 0.15))
(pad S1 thru_hole circle (at -6.85 -6.2 0) (size 1.6 1.6) (drill 0.9) (layers *.Cu *.Mask) (net 1 "from"))
(pad S2 thru_hole circle (at -5 -6.2 0) (size 1.6 1.6) (drill 0.9) (layers *.Cu *.Mask) (net 2 "to"))
(pad A thru_hole circle (at -5.625 -3.81 0) (size 1.6 1.6) (drill 0.9) (layers *.Cu *.Mask) (net 11 "A"))
(pad B thru_hole circle (at -5.625 -1.27 0) (size 1.6 1.6) (drill 0.9) (layers *.Cu *.Mask) (net 12 "B"))
(pad C thru_hole circle (at -5.625 1.27 0) (size 1.6 1.6) (drill 0.9) (layers *.Cu *.Mask) (net 13 "C"))
(pad D thru_hole circle (at -5.625 3.81 0) (size 1.6 1.6) (drill 0.9) (layers *.Cu *.Mask) (net 14 "D"))
(pad "" np_thru_hole circle (at -5.625 6.3 0) (size 1.5 1.5) (drill 1.5) (layers *.Cu *.Mask))
(fp_line (start -9.8 7.3) (end -9.8 -6.3) (layer Edge.Cuts) (width 0.15))
(fp_line (start -7.4 -6.3) (end -7.4 7.3) (layer Edge.Cuts) (width 0.15))
(fp_line (start -9.5 -6.6) (end -7.7 -6.6) (layer Edge.Cuts) (width 0.15))
(fp_line (start -7.7 7.6) (end -9.5 7.6) (layer Edge.Cuts) (width 0.15))
(fp_arc (start -7.7 7.3) (end -7.4 7.3) (angle 90) (layer Edge.Cuts) (width 0.15))
(fp_arc (start -9.5 7.3) (end -9.5 7.6) (angle 90) (layer Edge.Cuts) (width 0.15))
(fp_arc (start -7.7 -6.3) (end -7.7 -6.6) (angle 90) (layer Edge.Cuts) (width 0.15))
(fp_arc (start -9.5 -6.3) (end -9.8 -6.3) (angle 90) (layer Edge.Cuts) (width 0.15))
(pad S1 thru_hole circle (at 6.85 -6.2 0) (size 1.6 1.6) (drill 0.9) (layers *.Cu *.Mask) (net 1 "from"))
(pad S2 thru_hole circle (at 5 -6.2 0) (size 1.6 1.6) (drill 0.9) (layers *.Cu *.Mask) (net 2 "to"))
(pad A thru_hole circle (at 5.625 -3.81 0) (size 1.6 1.6) (drill 0.9) (layers *.Cu *.Mask) (net 11 "A"))
(pad B thru_hole circle (at 5.625 -1.27 0) (size 1.6 1.6) (drill 0.9) (layers *.Cu *.Mask) (net 12 "B"))
(pad C thru_hole circle (at 5.625 1.27 0) (size 1.6 1.6) (drill 0.9) (layers *.Cu *.Mask) (net 13 "C"))
(pad D thru_hole circle (at 5.625 3.81 0) (size 1.6 1.6) (drill 0.9) (layers *.Cu *.Mask) (net 14 "D"))
(pad "" np_thru_hole circle (at 5.625 6.3 0) (size 1.5 1.5) (drill 1.5) (layers *.Cu *.Mask))
)
(module E73:SPDT_C128955 (layer F.Cu) (tstamp 5BF2CC3C)
(at 100 -150 0)
(fp_text reference "T2" (at 0 0) (layer F.SilkS) hide (effects (font (size 1.27 1.27) (thickness 0.15))))
(fp_text value "" (at 0 0) (layer F.SilkS) hide (effects (font (size 1.27 1.27) (thickness 0.15))))
(fp_line (start 1.95 -1.35) (end -1.95 -1.35) (layer B.SilkS) (width 0.15))
(fp_line (start 0 -1.35) (end -3.3 -1.35) (layer B.SilkS) (width 0.15))
(fp_line (start -3.3 -1.35) (end -3.3 1.5) (layer B.SilkS) (width 0.15))
(fp_line (start -3.3 1.5) (end 3.3 1.5) (layer B.SilkS) (width 0.15))
(fp_line (start 3.3 1.5) (end 3.3 -1.35) (layer B.SilkS) (width 0.15))
(fp_line (start 0 -1.35) (end 3.3 -1.35) (layer B.SilkS) (width 0.15))
(fp_line (start -1.95 -3.85) (end 1.95 -3.85) (layer Dwgs.User) (width 0.15))
(fp_line (start 1.95 -3.85) (end 1.95 -1.35) (layer Dwgs.User) (width 0.15))
(fp_line (start -1.95 -1.35) (end -1.95 -3.85) (layer Dwgs.User) (width 0.15))
(pad "" np_thru_hole circle (at 1.5 0) (size 1 1) (drill 0.9) (layers *.Cu *.Mask))
(pad "" np_thru_hole circle (at -1.5 0) (size 1 1) (drill 0.9) (layers *.Cu *.Mask))
(pad 1 smd rect (at -2.25 2.075 0) (size 0.9 1.25) (layers B.Cu B.Paste B.Mask) (net 1 "from"))
(pad 2 smd rect (at 0.75 2.075 0) (size 0.9 1.25) (layers B.Cu B.Paste B.Mask) (net 2 "to"))
(pad 3 smd rect (at 2.25 2.075 0) (size 0.9 1.25) (layers B.Cu B.Paste B.Mask))
(pad "" smd rect (at 3.7 -1.1 0) (size 0.9 0.9) (layers B.Cu B.Paste B.Mask))
(pad "" smd rect (at 3.7 1.1 0) (size 0.9 0.9) (layers B.Cu B.Paste B.Mask))
(pad "" smd rect (at -3.7 1.1 0) (size 0.9 0.9) (layers B.Cu B.Paste B.Mask))
(pad "" smd rect (at -3.7 -1.1 0) (size 0.9 0.9) (layers B.Cu B.Paste B.Mask))
)
) )

View file

@ -3,6 +3,7 @@ exports.inject = (ergogen) => {
params: { params: {
designator: 'T', designator: 'T',
side: 'F', side: 'F',
width: 0.25,
P1: {type: 'net', value: 'P1'} P1: {type: 'net', value: 'P1'}
}, },
body: p => { body: p => {
@ -12,15 +13,15 @@ exports.inject = (ergogen) => {
${p.at /* parametric position */} ${p.at /* parametric position */}
(pad 1 smd rect (at ${p.ixy(0, 0)} ${p.rot}) (size 1 1) (layers ${p.side}.Cu ${p.side}.Paste ${p.side}.Mask) (pad 1 smd rect (at ${p.isxy(0, 0)} ${p.r}) (size 1 1) (layers ${p.side}.Cu ${p.side}.Paste ${p.side}.Mask)
${p.P1.str} (solder_mask_margin 0.2)) ${p.P1} (solder_mask_margin 0.2))
(pad 2 smd rect (at ${p.ixy(5, 5)} ${p.rot}) (size 1 1) (layers ${p.side}.Cu ${p.side}.Paste ${p.side}.Mask) (pad 2 smd rect (at ${p.isxy(5, 5)} ${p.r}) (size 1 1) (layers ${p.side}.Cu ${p.side}.Paste ${p.side}.Mask)
${p.P1.str} (solder_mask_margin 0.2)) ${p.P1} (solder_mask_margin 0.2))
) )
(segment (start ${p.sxy(0, 0)}) (end ${p.sxy(5, 5)}) (width 0.25) (layer ${p.side}.Cu) (net ${p.P1.index})) (segment (start ${p.esxy(0, 0)}) (end ${p.esxy(5, 5)}) (width ${p.width}) (layer ${p.side}.Cu) (net ${p.P1.index}))
` `
} }
@ -39,11 +40,11 @@ exports.inject = (ergogen) => {
${p.at /* parametric position */} ${p.at /* parametric position */}
(pad 1 smd rect (at 0 0 ${p.rot}) (size 1 1) (layers ${p.side}.Cu ${p.side}.Paste ${p.side}.Mask) (pad 1 smd rect (at 0 0 ${p.r}) (size 1 1) (layers ${p.side}.Cu ${p.side}.Paste ${p.side}.Mask)
${p.P1.str} (solder_mask_margin 0.2)) ${p.P1} (solder_mask_margin 0.2))
(pad 2 smd rect (at 5 5 ${p.rot}) (size 1 1) (layers ${p.side}.Cu ${p.side}.Paste ${p.side}.Mask) (pad 2 smd rect (at ${p.iaxy(5, 5)} ${p.r}) (size 1 1) (layers ${p.side}.Cu ${p.side}.Paste ${p.side}.Mask)
${p.P1.str} (solder_mask_margin 0.2)) ${p.P1} (solder_mask_margin 0.2))
) )
@ -51,7 +52,7 @@ exports.inject = (ergogen) => {
(connect_pads (clearance 0.508)) (connect_pads (clearance 0.508))
(min_thickness 0.254) (min_thickness 0.254)
(fill yes (arc_segments 32) (thermal_gap 0.508) (thermal_bridge_width 0.508)) (fill yes (arc_segments 32) (thermal_gap 0.508) (thermal_bridge_width 0.508))
(polygon (pts (xy ${p.xy(5, 5)}) (xy ${p.xy(5, -5)}) (xy ${p.xy(-5, -5)}) (xy ${p.xy(-5, 5)}))) (polygon (pts (xy ${p.eaxy(5, 5)}) (xy ${p.eaxy(5, -5)}) (xy ${p.eaxy(-5, -5)}) (xy ${p.eaxy(-5, 5)})))
) )
` `
@ -70,14 +71,14 @@ exports.inject = (ergogen) => {
${p.at /* parametric position */} ${p.at /* parametric position */}
(pad 1 smd rect (at 0 0 ${p.rot}) (size 1 1) (layers ${p.side}.Cu ${p.side}.Paste ${p.side}.Mask) (pad 1 smd rect (at 0 0 ${p.r}) (size 1 1) (layers ${p.side}.Cu ${p.side}.Paste ${p.side}.Mask)
${p.local_net('1').str} (solder_mask_margin 0.2)) ${p.local_net('1')} (solder_mask_margin 0.2))
(pad 1 smd rect (at 0 0 ${p.rot}) (size 1 1) (layers ${p.side}.Cu ${p.side}.Paste ${p.side}.Mask) (pad 1 smd rect (at 0 0 ${p.r}) (size 1 1) (layers ${p.side}.Cu ${p.side}.Paste ${p.side}.Mask)
${p.local_net('2').str} (solder_mask_margin 0.2)) ${p.local_net('2')} (solder_mask_margin 0.2))
(pad 1 smd rect (at 0 0 ${p.rot}) (size 1 1) (layers ${p.side}.Cu ${p.side}.Paste ${p.side}.Mask) (pad 1 smd rect (at 0 0 ${p.r}) (size 1 1) (layers ${p.side}.Cu ${p.side}.Paste ${p.side}.Mask)
${p.local_net('3').str} (solder_mask_margin 0.2)) ${p.local_net('3')} (solder_mask_margin 0.2))
) )
@ -106,7 +107,33 @@ exports.inject = (ergogen) => {
} }
}) })
ergogen.inject('footprint', 'references_test', { ergogen.inject('footprint', 'arrobj_test', {
params: {
designator: 'T',
side: 'F',
start: {x: 0, y: 0},
end: [[1, 0], [0, 1]]
},
body: p => {
lines = ''
for (const item of p.end) {
lines += `(fp_line (start ${p.start.x} ${p.start.y}) (end ${item[0]} ${item[1]}) (layer Dwgs.User) (width 0.05))\n`
}
return `
(module arrobj_test (layer ${p.side}.Cu) (tedit 5CF31DEF)
${p.at /* parametric position */}
${lines}
)
`
}
})
ergogen.inject('references_test', {
params: {}, params: {},
body: p => { body: p => {
return `references ${p.ref_hide ? 'hidden' : 'shown'}` return `references ${p.ref_hide ? 'hidden' : 'shown'}`

View file

@ -1,4 +1,12 @@
global.chai = require('chai') global.chai = require('chai')
global.chai.use(require('chai-as-promised')) global.chai.use(require('chai-as-promised'))
global.expect = global.chai.expect global.expect = global.chai.expect
global.should = global.chai.should() global.should = global.chai.should()
global.sinon = require('sinon')
// Restore the default sandbox after every test
exports.mochaHooks = {
afterEach() {
sinon.restore()
}
}

View file

@ -9,7 +9,15 @@ require('./helpers/mock_footprints').inject(ergogen)
let what = process.env.npm_config_what let what = process.env.npm_config_what
const dump = process.env.npm_config_dump const dump = process.env.npm_config_dump
const lineends = /(?:\r\n|\r|\n)/g
const handle_slash = (() => {
if (path.sep == '\\') {
return str => str.replace(/\\/g,'/')
} else {
return str => str
}
})()
// Unit tests // Unit tests
@ -17,7 +25,7 @@ const dump = process.env.npm_config_dump
// the --dump switch does nothing here // the --dump switch does nothing here
what = what ? what.split(',') : false what = what ? what.split(',') : false
for (const unit of glob.sync(path.join(__dirname, 'unit', '*.js'))) { for (const unit of glob.sync(handle_slash(path.join(__dirname, 'unit', '*.js')))) {
const base = path.basename(unit, '.js') const base = path.basename(unit, '.js')
if (what && !what.includes(base)) continue if (what && !what.includes(base)) continue
require(`./unit/${base}.js`) require(`./unit/${base}.js`)
@ -30,6 +38,19 @@ for (const unit of glob.sync(path.join(__dirname, 'unit', '*.js'))) {
// as well as individual tests using slash-notation (like `points/default`) // as well as individual tests using slash-notation (like `points/default`)
// the --dump switch can output the new results, overriding the old reference // the --dump switch can output the new results, overriding the old reference
const dump_structure = (obj, depth=-1, prefix='', breadcrumbs=[]) => {
if (a.type(obj)() != 'object') {
console.log(prefix + breadcrumbs.join('_'))
return
}
if (depth == 0) return
for (const [key, val] of Object.entries(obj)) {
breadcrumbs.push(key)
dump_structure(val, depth-1, prefix, breadcrumbs)
breadcrumbs.pop()
}
}
const cap = s => s.charAt(0).toUpperCase() + s.slice(1) const cap = s => s.charAt(0).toUpperCase() + s.slice(1)
const test = function(input_path) { const test = function(input_path) {
@ -37,27 +58,52 @@ const test = function(input_path) {
this.slow(120000) this.slow(120000)
title = path.basename(input_path, '.yaml').split('_').join(' ') title = path.basename(input_path, '.yaml').split('_').join(' ')
it(title, async function() { it(title, async function() {
const input = yaml.load(fs.readFileSync(input_path).toString()) const input = yaml.load(fs.readFileSync(input_path).toString())
const base = path.join(path.dirname(input_path), path.basename(input_path, '.yaml'))
const references = glob.sync(handle_slash(base) + '___*')
// handle deliberately wrong inputs
const exception = base + '___EXCEPTION.txt'
if (fs.existsSync(exception)) {
const exception_snippet = fs.readFileSync(exception).toString()
return await ergogen.process(input, true).should.be.rejectedWith(exception_snippet)
}
const output = await ergogen.process(input, true) const output = await ergogen.process(input, true)
// compare output vs. reference // compare output vs. reference
const base = path.join(path.dirname(input_path), path.basename(input_path, '.yaml')) if (references.length) {
for (const expected_path of glob.sync(base + '___*')) { for (const expected_path of references) {
let expected = fs.readFileSync(expected_path).toString() let expected = fs.readFileSync(expected_path).toString()
if (expected_path.endsWith('.json')) { if (expected_path.endsWith('.json')) {
expected = JSON.parse(expected) expected = JSON.parse(expected)
} }
const comp_path = expected_path.split('___')[1].split('.')[0].split('_').join('.') const comp_path = expected_path.split('___')[1].split('.')[0].split('_').join('.')
const output_part = u.deep(output, comp_path) const output_part = u.deep(output, comp_path)
if (dump) { if (dump) {
if (a.type(output_part)() == 'string') { if (a.type(output_part)() == 'string') {
fs.writeFileSync(expected_path, output_part) fs.writeFileSync(expected_path, output_part)
} else { } else {
fs.writeJSONSync(expected_path, output_part, {spaces: 4}) fs.writeJSONSync(expected_path, output_part, {spaces: 4})
}
} else {
if (a.type(output_part)() == 'string') {
const parse_out = output_part.replace(lineends, '\n')
const parse_exp = expected.replace(lineends, '\n')
parse_out.should.deep.equal(parse_exp)
} else {
// JSON can hide negative zeroes, for example, so we canonical-ize first
const canonical_part = JSON.parse(JSON.stringify(output_part))
canonical_part.should.deep.equal(expected)
}
} }
} else {
output_part.should.deep.equal(expected)
} }
// explicit dump-ing above only works, if there are already files with the right name
// if there aren't, dump now outputs a list of candidates that could be referenced
} else if (dump) {
dump_structure(output, 3, base + '___')
} }
}) })
} }
@ -74,7 +120,7 @@ if (what) {
regex = path.join(__dirname, w, '*.yaml') regex = path.join(__dirname, w, '*.yaml')
} }
describe(title, function() { describe(title, function() {
for (const i of glob.sync(regex)) { for (const i of glob.sync(handle_slash(regex))) {
test.call(this, i) test.call(this, i)
} }
}) })
@ -82,7 +128,7 @@ if (what) {
} else { } else {
for (const part of ['points', 'outlines', 'cases', 'pcbs', 'footprints']) { for (const part of ['points', 'outlines', 'cases', 'pcbs', 'footprints']) {
describe(cap(part), function() { describe(cap(part), function() {
for (const i of glob.sync(path.join(__dirname, part, '*.yaml'))) { for (const i of glob.sync(handle_slash(path.join(__dirname, part, '*.yaml')))) {
test.call(this, i) test.call(this, i)
} }
}) })
@ -109,7 +155,7 @@ for (let w of cli_what) {
describe('CLI', function() { describe('CLI', function() {
this.timeout(120000) this.timeout(120000)
this.slow(120000) this.slow(120000)
for (const t of glob.sync(path.join(__dirname, w))) { for (const t of glob.sync(handle_slash(path.join(__dirname, w)))) {
it(path.basename(t).split('_').join(' '), function() { it(path.basename(t).split('_').join(' '), function() {
const command = read(t, 'command') const command = read(t, 'command')
const output_path = exists(t, 'path') ? read(t, 'path') : 'output' const output_path = exists(t, 'path') ? read(t, 'path') : 'output'
@ -133,14 +179,19 @@ for (let w of cli_what) {
ref_path = path.resolve(path.join(t, read(ref_path).trim())) ref_path = path.resolve(path.join(t, read(ref_path).trim()))
} }
const comp_res = dircompare.compareSync(output_path, ref_path, { const comp_res = dircompare.compareSync(output_path, ref_path, {
compareContent: true compareContent: true,
ignoreLineEnding: true,
compareFileSync: dircompare.fileCompareHandlers.lineBasedFileCompare.compareSync,
compareFileAsync: dircompare.fileCompareHandlers.lineBasedFileCompare.compareAsync
}) })
if (dump) { if (dump) {
fs.moveSync(output_path, ref_path, {overwrite: true}) fs.moveSync(output_path, ref_path, {overwrite: true})
} else { } else {
fs.removeSync(output_path) fs.removeSync(output_path)
} }
actual_log.should.equal(ref_log) const parse_act_log = actual_log.replace(lineends, '\n')
const parse_ref_log = ref_log.replace(lineends, '\n')
parse_act_log.should.equal(parse_ref_log)
comp_res.same.should.be.true comp_res.same.should.be.true
// deliberately incorrect execution // deliberately incorrect execution
} else { } else {
@ -162,4 +213,4 @@ for (let w of cli_what) {
}) })
} }
}) })
} }

View file

@ -0,0 +1,18 @@
points:
zones:
matrix:
mirror:
ref: matrix_only_first
distance: 30
columns:
only.rows:
first.bind: 0
second.bind: [0,10,0,10]
third.bind: [10,0,10,0]
fourth.bind: [u, u/2, u/3, u/4]
outlines:
bound:
- what: rectangle
where: true
size: 20
bound: true

View file

@ -0,0 +1,338 @@
0
SECTION
2
HEADER
9
$INSUNITS
70
4
0
ENDSEC
0
SECTION
2
TABLES
0
TABLE
2
LTYPE
0
LTYPE
72
65
70
64
2
CONTINUOUS
3
______
73
0
40
0
0
ENDTAB
0
TABLE
2
LAYER
0
ENDTAB
0
ENDSEC
0
SECTION
2
ENTITIES
0
LINE
8
0
10
-10
20
-10
11
10
21
-10
0
LINE
8
0
10
10
20
-10
11
10
21
9
0
LINE
8
0
10
-10
20
9
11
-10
21
-10
0
LINE
8
0
10
10
20
29
11
20
21
29
0
LINE
8
0
10
20
20
9
11
10
21
9
0
LINE
8
0
10
-10
20
9
11
-20
21
9
0
LINE
8
0
10
-20
20
9
11
-20
21
29
0
LINE
8
0
10
-20
20
29
11
-10
21
29
0
LINE
8
0
10
10
20
29
11
10
21
40.6666667
0
LINE
8
0
10
-10
20
29
11
-10
21
40.6666667
0
LINE
8
0
10
-14.75
20
86
11
44.75
21
86
0
LINE
8
0
10
10
20
40.6666667
11
20
21
40.6666667
0
LINE
8
0
10
-10
20
40.6666667
11
-14.75
21
40.6666667
0
LINE
8
0
10
-14.75
20
40.6666667
11
-14.75
21
86
0
LINE
8
0
10
20
20
-10
11
40
21
-10
0
LINE
8
0
10
40
20
-10
11
40
21
9
0
LINE
8
0
10
20
20
9
11
20
21
-10
0
LINE
8
0
10
40
20
29
11
50
21
29
0
LINE
8
0
10
50
20
9
11
50
21
29
0
LINE
8
0
10
50
20
9
11
40
21
9
0
LINE
8
0
10
40
20
29
11
40
21
40.6666667
0
LINE
8
0
10
20
20
29
11
20
21
40.6666667
0
LINE
8
0
10
44.75
20
40.6666667
11
44.75
21
86
0
LINE
8
0
10
44.75
20
40.6666667
11
40
21
40.6666667
0
ENDSEC
0
EOF

46
test/outlines/expand.yaml Normal file
View file

@ -0,0 +1,46 @@
points:
zones:
matrix: {}
outlines:
base:
- what: rectangle
where: true
size: 20
bound: false
sh_beveled:
- what: outline
name: base
expand: "5]"
sh_round:
- what: outline
name: base
expand: "6)"
sh_pointy:
- what: outline
name: base
expand: "7>"
shorthand-combo:
- "sh_pointy"
- "-sh_round"
- "+sh_beveled"
- "-base"
jnt_beveled:
- what: outline
name: base
expand: 8
joints: beveled
jnt_round:
- what: outline
name: base
expand: 9
joints: round
jnt_pointy:
- what: outline
name: base
expand: 10
joints: pointy
joint-name-combo:
- "jnt_pointy"
- "-jnt_round"
- "+jnt_beveled"
- "-base"

View file

@ -0,0 +1,346 @@
0
SECTION
2
HEADER
9
$INSUNITS
70
4
0
ENDSEC
0
SECTION
2
TABLES
0
TABLE
2
LTYPE
0
LTYPE
72
65
70
64
2
CONTINUOUS
3
______
73
0
40
0
0
ENDTAB
0
TABLE
2
LAYER
0
ENDTAB
0
ENDSEC
0
SECTION
2
ENTITIES
0
LINE
8
0
10
-20
20
-20
11
20
21
-20
0
LINE
8
0
10
20
20
-20
11
20
21
20
0
LINE
8
0
10
-20
20
20
11
20
21
20
0
LINE
8
0
10
-20
20
-20
11
-20
21
20
0
LINE
8
0
10
-10
20
-19
11
10
21
-19
0
ARC
8
0
10
10
20
-10
40
9
50
270
51
360
0
LINE
8
0
10
19
20
-10
11
19
21
10
0
ARC
8
0
10
10
20
10
40
9
50
0
51
90
0
LINE
8
0
10
10
20
19
11
-10
21
19
0
ARC
8
0
10
-10
20
10
40
9
50
90
51
180
0
LINE
8
0
10
-19
20
10
11
-19
21
-10
0
ARC
8
0
10
-10
20
-10
40
9
50
180
51
270
0
LINE
8
0
10
-13.3137085
20
-18
11
13.3137085
21
-18
0
LINE
8
0
10
13.3137085
20
-18
11
18
21
-13.3137085
0
LINE
8
0
10
18
20
-13.3137085
11
18
21
13.3137085
0
LINE
8
0
10
13.3137085
20
18
11
18
21
13.3137085
0
LINE
8
0
10
-13.3137085
20
18
11
13.3137085
21
18
0
LINE
8
0
10
-18
20
13.3137085
11
-13.3137085
21
18
0
LINE
8
0
10
-18
20
-13.3137085
11
-18
21
13.3137085
0
LINE
8
0
10
-18
20
-13.3137085
11
-13.3137085
21
-18
0
LINE
8
0
10
-10
20
-10
11
10
21
-10
0
LINE
8
0
10
10
20
-10
11
10
21
10
0
LINE
8
0
10
10
20
10
11
-10
21
10
0
LINE
8
0
10
-10
20
10
11
-10
21
-10
0
ENDSEC
0
EOF

View file

@ -0,0 +1,346 @@
0
SECTION
2
HEADER
9
$INSUNITS
70
4
0
ENDSEC
0
SECTION
2
TABLES
0
TABLE
2
LTYPE
0
LTYPE
72
65
70
64
2
CONTINUOUS
3
______
73
0
40
0
0
ENDTAB
0
TABLE
2
LAYER
0
ENDTAB
0
ENDSEC
0
SECTION
2
ENTITIES
0
LINE
8
0
10
-17
20
-17
11
17
21
-17
0
LINE
8
0
10
17
20
-17
11
17
21
17
0
LINE
8
0
10
-17
20
17
11
17
21
17
0
LINE
8
0
10
-17
20
-17
11
-17
21
17
0
LINE
8
0
10
-10
20
-16
11
10
21
-16
0
ARC
8
0
10
10
20
-10
40
6
50
270
51
360
0
LINE
8
0
10
16
20
-10
11
16
21
10
0
ARC
8
0
10
10
20
10
40
6
50
0
51
90
0
LINE
8
0
10
10
20
16
11
-10
21
16
0
ARC
8
0
10
-10
20
10
40
6
50
90
51
180
0
LINE
8
0
10
-16
20
10
11
-16
21
-10
0
ARC
8
0
10
-10
20
-10
40
6
50
180
51
270
0
LINE
8
0
10
-12.0710678
20
-15
11
12.0710678
21
-15
0
LINE
8
0
10
12.0710678
20
-15
11
15
21
-12.0710678
0
LINE
8
0
10
15
20
-12.0710678
11
15
21
12.0710678
0
LINE
8
0
10
12.0710678
20
15
11
15
21
12.0710678
0
LINE
8
0
10
-12.0710678
20
15
11
12.0710678
21
15
0
LINE
8
0
10
-15
20
12.0710678
11
-12.0710678
21
15
0
LINE
8
0
10
-15
20
-12.0710678
11
-15
21
12.0710678
0
LINE
8
0
10
-15
20
-12.0710678
11
-12.0710678
21
-15
0
LINE
8
0
10
-10
20
-10
11
10
21
-10
0
LINE
8
0
10
10
20
-10
11
10
21
10
0
LINE
8
0
10
10
20
10
11
-10
21
10
0
LINE
8
0
10
-10
20
10
11
-10
21
-10
0
ENDSEC
0
EOF

View file

@ -16,11 +16,22 @@ outlines:
where: true where: true
size: cy size: cy
bound: true bound: true
adjust:
- what: circle
where: true
radius: 2
# adjust works, and it can use shape-specific units
adjust.shift: [0, r]
fillet: fillet:
- what: outline - name: base
name: base
fillet: 2 fillet: 2
scale: scale:
- what: outline - name: fillet
name: fillet scale: 0.5
scale: 0.5 combination:
- "base"
- "-scale"
- "~fillet"
expand:
- name: combination
expand: 1

View file

@ -0,0 +1,90 @@
0
SECTION
2
HEADER
9
$INSUNITS
70
4
0
ENDSEC
0
SECTION
2
TABLES
0
TABLE
2
LTYPE
0
LTYPE
72
65
70
64
2
CONTINUOUS
3
______
73
0
40
0
0
ENDTAB
0
TABLE
2
LAYER
0
ENDTAB
0
ENDSEC
0
SECTION
2
ENTITIES
0
CIRCLE
8
0
10
0
20
2
40
2
0
CIRCLE
8
0
10
0
20
19
40
2
0
CIRCLE
8
0
10
19
20
2
40
2
0
CIRCLE
8
0
10
19
20
19
40
2
0
ENDSEC
0
EOF

View file

@ -0,0 +1,514 @@
0
SECTION
2
HEADER
9
$INSUNITS
70
4
0
ENDSEC
0
SECTION
2
TABLES
0
TABLE
2
LTYPE
0
LTYPE
72
65
70
64
2
CONTINUOUS
3
______
73
0
40
0
0
ENDTAB
0
TABLE
2
LAYER
0
ENDTAB
0
ENDSEC
0
SECTION
2
ENTITIES
0
LINE
8
0
10
8.6
20
-6.6
11
8.6
21
-4.3
0
LINE
8
0
10
8.6
20
12.8
11
8.6
21
23.6
0
LINE
8
0
10
-6.6
20
-8.6
11
6.6
21
-8.6
0
LINE
8
0
10
-8.6
20
-6.6
11
-8.6
21
23.6
0
LINE
8
0
10
-6.6
20
25.6
11
6.6
21
25.6
0
LINE
8
0
10
27.6
20
-6.6
11
27.6
21
23.6
0
LINE
8
0
10
12.4
20
-8.6
11
25.6
21
-8.6
0
LINE
8
0
10
10.4
20
-6.6
11
10.4
21
-4.3
0
LINE
8
0
10
10.4
20
12.8
11
10.4
21
23.6
0
LINE
8
0
10
12.4
20
25.6
11
25.6
21
25.6
0
LINE
8
0
10
4.3
20
-3.3
11
4.3
21
11.8
0
LINE
8
0
10
-3.3
20
-4.3
11
3.3
21
-4.3
0
LINE
8
0
10
-4.3
20
-3.3
11
-4.3
21
11.8
0
LINE
8
0
10
-3.3
20
12.8
11
3.3
21
12.8
0
LINE
8
0
10
13.8
20
-3.3
11
13.8
21
11.8
0
LINE
8
0
10
6.2
20
-4.3
11
8.6
21
-4.3
0
LINE
8
0
10
10.4
20
-4.3
11
12.8
21
-4.3
0
LINE
8
0
10
5.2
20
-3.3
11
5.2
21
11.8
0
LINE
8
0
10
6.2
20
12.8
11
8.6
21
12.8
0
LINE
8
0
10
10.4
20
12.8
11
12.8
21
12.8
0
ARC
8
0
10
3.3
20
11.8
40
1
50
0
51
90
0
ARC
8
0
10
-3.3
20
11.8
40
1
50
90
51
180
0
ARC
8
0
10
-3.3
20
-3.3
40
1
50
180
51
270
0
ARC
8
0
10
3.3
20
-3.3
40
1
50
270
51
0
0
ARC
8
0
10
12.8
20
11.8
40
1
50
0
51
90
0
ARC
8
0
10
6.2
20
11.8
40
1
50
90
51
180
0
ARC
8
0
10
6.2
20
-3.3
40
1
50
180
51
270
0
ARC
8
0
10
12.8
20
-3.3
40
1
50
270
51
0
0
ARC
8
0
10
6.6
20
23.6
40
2
50
0
51
90
0
ARC
8
0
10
-6.6
20
23.6
40
2
50
90
51
180
0
ARC
8
0
10
-6.6
20
-6.6
40
2
50
180
51
270
0
ARC
8
0
10
6.6
20
-6.6
40
2
50
270
51
0
0
ARC
8
0
10
25.6
20
23.6
40
2
50
0
51
90
0
ARC
8
0
10
12.4
20
23.6
40
2
50
90
51
180
0
ARC
8
0
10
12.4
20
-6.6
40
2
50
180
51
270
0
ARC
8
0
10
25.6
20
-6.6
40
2
50
270
51
0
0
ENDSEC
0
EOF

View file

@ -0,0 +1,410 @@
0
SECTION
2
HEADER
9
$INSUNITS
70
4
0
ENDSEC
0
SECTION
2
TABLES
0
TABLE
2
LTYPE
0
LTYPE
72
65
70
64
2
CONTINUOUS
3
______
73
0
40
0
0
ENDTAB
0
TABLE
2
LAYER
0
ENDTAB
0
ENDSEC
0
SECTION
2
ENTITIES
0
LINE
8
0
10
-6.6
20
-9.6
11
6.6
21
-9.6
0
ARC
8
0
10
6.6
20
-6.6
40
3
50
270
51
345.164888
0
ARC
8
0
10
12.4
20
-6.6
40
3
50
194.835112
51
270
0
LINE
8
0
10
12.4
20
-9.6
11
25.6
21
-9.6
0
ARC
8
0
10
25.6
20
-6.6
40
3
50
270
51
360
0
LINE
8
0
10
28.6
20
-6.6
11
28.6
21
23.6
0
ARC
8
0
10
25.6
20
23.6
40
3
50
0
51
90
0
LINE
8
0
10
12.4
20
26.6
11
25.6
21
26.6
0
ARC
8
0
10
12.4
20
23.6
40
3
50
90
51
165.164888
0
ARC
8
0
10
6.6
20
23.6
40
3
50
14.835112
51
90
0
LINE
8
0
10
-6.6
20
26.6
11
6.6
21
26.6
0
ARC
8
0
10
-6.6
20
23.6
40
3
50
90
51
180
0
LINE
8
0
10
-9.6
20
-6.6
11
-9.6
21
23.6
0
ARC
8
0
10
-6.6
20
-6.6
40
3
50
180
51
270
0
LINE
8
0
10
12.8
20
-3.3
11
12.8
21
11.8
0
LINE
8
0
10
10.4
20
11.8
11
12.8
21
11.8
0
ARC
8
0
10
10.4
20
12.8
40
1
50
205.8419331
51
270
0
ARC
8
0
10
8.6
20
12.8
40
1
50
270
51
334.1580669
0
LINE
8
0
10
6.2
20
11.8
11
8.6
21
11.8
0
LINE
8
0
10
6.2
20
-3.3
11
6.2
21
11.8
0
LINE
8
0
10
6.2
20
-3.3
11
8.6
21
-3.3
0
ARC
8
0
10
8.6
20
-4.3
40
1
50
25.8419331
51
90
0
ARC
8
0
10
10.4
20
-4.3
40
1
50
90
51
154.1580669
0
LINE
8
0
10
10.4
20
-3.3
11
12.8
21
-3.3
0
LINE
8
0
10
3.3
20
-3.3
11
3.3
21
11.8
0
LINE
8
0
10
-3.3
20
11.8
11
3.3
21
11.8
0
LINE
8
0
10
-3.3
20
-3.3
11
-3.3
21
11.8
0
LINE
8
0
10
-3.3
20
-3.3
11
3.3
21
-3.3
0
ENDSEC
0
EOF

View file

@ -17,6 +17,7 @@ outlines:
- mirror_matrix - mirror_matrix
shift: [0, sy/2] shift: [0, sy/2]
size: [20, 40] size: [20, 40]
corner: 5
outside_rects: outside_rects:
what: rectangle what: rectangle
where: where:

View file

@ -67,7 +67,7 @@ LINE
11 11
10 10
21 21
0 5
0 0
LINE LINE
8 8
@ -135,7 +135,7 @@ LINE
10 10
30 30
20 20
0 5
11 11
30 30
21 21
@ -145,14 +145,28 @@ LINE
8 8
0 0
10 10
10 15
20 20
0 0
11 11
30 25
21 21
0 0
0 0
ARC
8
0
10
25
20
5
40
5
50
270
51
360
0
LINE LINE
8 8
0 0
@ -163,32 +177,74 @@ LINE
11 11
30 30
21 21
35
0
ARC
8
0
10
25
20
35
40 40
5
50
0
51
90
0 0
LINE LINE
8 8
0 0
10 10
30 25
20 20
40 40
11 11
10 15
21 21
40 40
0 0
ARC
8
0
10
15
20
35
40
5
50
90
51
180
0
LINE LINE
8 8
0 0
10 10
10 10
20 20
40 35
11 11
10 10
21 21
10 10
0 0
ARC
8
0
10
15
20
5
40
5
50
180
51
270
0
LINE LINE
8 8
0 0

View file

@ -1,5 +1,7 @@
points.zones.matrix: points.zones.matrix:
mirror: 10 mirror: 10
key:
magic_value: 5
outlines: outlines:
edge: edge:
- what: rectangle - what: rectangle
@ -18,6 +20,7 @@ pcbs:
shift: [1, 1] shift: [1, 1]
rotate: 30 rotate: 30
params: params:
width: u/40
side: F side: F
mirror: mirror:
side: B side: B
@ -28,9 +31,25 @@ pcbs:
rotate: 30 rotate: 30
dyn: dyn:
what: dynamic_net_test what: dynamic_net_test
anc: anc1:
what: anchor_test what: anchor_test
params: params:
end: end:
ref: matrix ref: matrix
shift: [10, 10] shift: [10, 10]
anc2:
what: anchor_test
params:
end: matrix
arrobj:
what: arrobj_test
params:
start: {x: 5, y: 5}
end: [[6, 6], [7, 7]]
arrobj_templated:
what: arrobj_test
where:
ref: matrix
params:
start: '{x: {{magic_value}}, y: {{magic_value}}}'
end: '[[6, 6], [7, {{magic_value}}]]'

View file

@ -94,9 +94,9 @@
(net 0 "") (net 0 "")
(net 1 "P1") (net 1 "P1")
(net 2 "T6_1") (net 2 "T4_1")
(net 3 "T6_2") (net 3 "T4_2")
(net 4 "T6_3") (net 4 "T4_3")
(net_class Default "This is the default net class." (net_class Default "This is the default net class."
(clearance 0.2) (clearance 0.2)
@ -107,9 +107,9 @@
(uvia_drill 0.1) (uvia_drill 0.1)
(add_net "") (add_net "")
(add_net "P1") (add_net "P1")
(add_net "T6_1") (add_net "T4_1")
(add_net "T6_2") (add_net "T4_2")
(add_net "T6_3") (add_net "T4_3")
) )
@ -126,7 +126,7 @@
) )
(segment (start 1 -1) (end 7.830127 0.8301270000000001) (width 0.25) (layer F.Cu) (net 1)) (segment (start 1 -1) (end 7.830127 0.8301270000000001) (width 0.475) (layer F.Cu) (net 1))
@ -143,41 +143,7 @@
) )
(segment (start 19 -1) (end 12.169872999999999 0.8301270000000001) (width 0.25) (layer B.Cu) (net 1)) (segment (start 19 -1) (end 12.169872999999999 0.8301270000000001) (width 0.475) (layer B.Cu) (net 1))
(module trace_test (layer B.Cu) (tedit 5CF31DEF)
(at 19 -1 -30)
(pad 1 smd rect (at 0 0 -30) (size 1 1) (layers B.Cu B.Paste B.Mask)
(net 1 "P1") (solder_mask_margin 0.2))
(pad 2 smd rect (at -5 5 -30) (size 1 1) (layers B.Cu B.Paste B.Mask)
(net 1 "P1") (solder_mask_margin 0.2))
)
(segment (start 19 -1) (end 12.169872999999999 0.8301270000000001) (width 0.25) (layer B.Cu) (net 1))
(module trace_test (layer F.Cu) (tedit 5CF31DEF)
(at 1 -1 30)
(pad 1 smd rect (at 0 0 30) (size 1 1) (layers F.Cu F.Paste F.Mask)
(net 1 "P1") (solder_mask_margin 0.2))
(pad 2 smd rect (at 5 5 30) (size 1 1) (layers F.Cu F.Paste F.Mask)
(net 1 "P1") (solder_mask_margin 0.2))
)
(segment (start 1 -1) (end 7.830127 0.8301270000000001) (width 0.25) (layer F.Cu) (net 1))
@ -209,13 +175,13 @@
(at 0 0 0) (at 0 0 0)
(pad 1 smd rect (at 0 0 0) (size 1 1) (layers F.Cu F.Paste F.Mask) (pad 1 smd rect (at 0 0 0) (size 1 1) (layers F.Cu F.Paste F.Mask)
(net 2 "T6_1") (solder_mask_margin 0.2)) (net 2 "T4_1") (solder_mask_margin 0.2))
(pad 1 smd rect (at 0 0 0) (size 1 1) (layers F.Cu F.Paste F.Mask) (pad 1 smd rect (at 0 0 0) (size 1 1) (layers F.Cu F.Paste F.Mask)
(net 3 "T6_2") (solder_mask_margin 0.2)) (net 3 "T4_2") (solder_mask_margin 0.2))
(pad 1 smd rect (at 0 0 0) (size 1 1) (layers F.Cu F.Paste F.Mask) (pad 1 smd rect (at 0 0 0) (size 1 1) (layers F.Cu F.Paste F.Mask)
(net 4 "T6_3") (solder_mask_margin 0.2)) (net 4 "T4_3") (solder_mask_margin 0.2))
) )
@ -231,6 +197,43 @@
) )
(module anchor_test (layer F.Cu) (tedit 5CF31DEF)
(at 0 0 0)
(fp_line (start 0 0) (end 0 0) (layer Dwgs.User) (width 0.05))
)
(module arrobj_test (layer F.Cu) (tedit 5CF31DEF)
(at 0 0 0)
(fp_line (start 5 5) (end 6 6) (layer Dwgs.User) (width 0.05))
(fp_line (start 5 5) (end 7 7) (layer Dwgs.User) (width 0.05))
)
(module arrobj_test (layer F.Cu) (tedit 5CF31DEF)
(at 0 0 0)
(fp_line (start 5 5) (end 6 6) (layer Dwgs.User) (width 0.05))
(fp_line (start 5 5) (end 7 5) (layer Dwgs.User) (width 0.05))
)
(gr_line (start -9.5 9.5) (end 9.5 9.5) (angle 90) (layer Edge.Cuts) (width 0.15)) (gr_line (start -9.5 9.5) (end 9.5 9.5) (angle 90) (layer Edge.Cuts) (width 0.15))
(gr_line (start 9.5 9.5) (end 9.5 -9.5) (angle 90) (layer Edge.Cuts) (width 0.15)) (gr_line (start 9.5 9.5) (end 9.5 -9.5) (angle 90) (layer Edge.Cuts) (width 0.15))
(gr_line (start 9.5 -9.5) (end -9.5 -9.5) (angle 90) (layer Edge.Cuts) (width 0.15)) (gr_line (start 9.5 -9.5) (end -9.5 -9.5) (angle 90) (layer Edge.Cuts) (width 0.15))

34
test/pcbs/outlines.yaml Normal file
View file

@ -0,0 +1,34 @@
points.zones.matrix:
columns:
left:
right:
rows.only:
outlines:
left:
out:
what: rectangle
where: matrix_left_only
size: u
fillet: u/5
in:
what: circle
where: matrix_left_only
radius: u/4
operation: subtract
right:
out:
what: rectangle
where: matrix_right_only
size: u
bevel: u/5
in:
what: rectangle
where: matrix_right_only
size: u/2
bevel: u/4
operation: subtract
pcbs:
main:
outlines:
- outline: 'left'
- outline: 'right'

Some files were not shown because too many files have changed in this diff Show more