Restructure API docs and generate module index
Automatically generate docs for generators. Semiautomatically generate doc for all other modules. This should create the - until now - missing module index
This commit is contained in:
parent
8640514daf
commit
0a73e929ec
|
@ -1,221 +0,0 @@
|
|||
|
||||
==========================
|
||||
The boxes.Boxes main class
|
||||
==========================
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
There is basically one class that takes care of everything. You are
|
||||
supposed to sub class it and implement the ``.__init__()`` and
|
||||
``.render()`` method. This Boxes class keeps a cairo canvas object
|
||||
(self.ctx) that all drawing is made on. In addition it keeps a couple
|
||||
of global settings used for various drawing operations. See the
|
||||
``.__init__()`` method for the details.
|
||||
|
||||
.. autoclass:: boxes.Boxes
|
||||
|
||||
And easier way to get started is using the
|
||||
``boxes/generators/_template.py`` as a basis for your own generators.
|
||||
|
||||
Basic operation
|
||||
---------------
|
||||
.. automethod:: boxes.Boxes.__init__
|
||||
|
||||
.. automethod:: boxes.Boxes.parseArgs
|
||||
.. automethod:: boxes.Boxes.render
|
||||
|
||||
.. automethod:: boxes.Boxes.open
|
||||
.. automethod:: boxes.Boxes.close
|
||||
|
||||
|
||||
Generating Parts
|
||||
----------------
|
||||
|
||||
A couple of commands can create whole parts like walls. Typically the
|
||||
sizes given are the inner dimmensions not including additional space
|
||||
needed for burn compensation or joints.
|
||||
|
||||
Currently there are the following parts:
|
||||
|
||||
.. automethod:: boxes.Boxes.rectangularWall
|
||||
.. automethod:: boxes.Boxes.flangedWall
|
||||
.. automethod:: boxes.Boxes.rectangularTriangle
|
||||
.. automethod:: boxes.Boxes.regularPolygonWall
|
||||
.. automethod:: boxes.Boxes.roundedPlate
|
||||
.. automethod:: boxes.Boxes.surroundingWall
|
||||
|
||||
Parts Class
|
||||
...........
|
||||
|
||||
More parts are available in a separete class. An instance is available as
|
||||
**Boxes.parts**
|
||||
|
||||
.. automethod:: boxes.parts.Parts.disc
|
||||
.. automethod:: boxes.parts.Parts.waivyKnob
|
||||
.. automethod:: boxes.parts.Parts.concaveKnob
|
||||
.. automethod:: boxes.parts.Parts.ringSegment
|
||||
|
||||
|
||||
There are a few parameter shared by many of those parts:
|
||||
|
||||
The callback parameter
|
||||
......................
|
||||
|
||||
The callback parameter can take on of the following forms:
|
||||
|
||||
* A function (or bound method) that expects one parameter: the number of the side the callback is currently called for.
|
||||
* A dict with some of the numbers of the sides as keys and functions without parameters as values.
|
||||
* A list of functions without parameters. The list may contain None as place holder and be shorter than the number of sides.
|
||||
|
||||
The callback functions are called with the side of the part at the
|
||||
positive x and y axis. If the edge uses up space this space is below
|
||||
the x axis. You do not have to restore the coordinate settings in the
|
||||
callback.
|
||||
|
||||
Instead of functions it can be handy to use a lambda expression
|
||||
calling the one building block funtion you need (e.g. fingerHolesAt).
|
||||
|
||||
For your own parts you can use this helper function:
|
||||
|
||||
.. automethod:: boxes.Boxes.cc
|
||||
|
||||
For finding the right piece to the *callback* parameter this function is used:
|
||||
|
||||
.. automethod:: boxes.Boxes.getEntry
|
||||
|
||||
|
||||
The move parameter
|
||||
..................
|
||||
|
||||
For placing the parts the ``move`` parameter can be used. It is string
|
||||
with space separated words - at most one of each of those options:
|
||||
|
||||
* left / right
|
||||
* up / down
|
||||
* only
|
||||
|
||||
If "only" is given the part is not drawn but only the move is
|
||||
done. This can be useful to go in one direction after having placed
|
||||
multiple parts in the other and have returned with ``.ctx.restore()``.
|
||||
|
||||
For implementing parts the following helper function can be used to
|
||||
implement a ``move`` parameter:
|
||||
|
||||
.. automethod:: boxes.Boxes.move
|
||||
|
||||
It needs to be called before and after drawing the actual part with
|
||||
the proper ``before`` paramter set.
|
||||
|
||||
The edges parameter
|
||||
...................
|
||||
|
||||
The ``edges`` parameter needs to be an iterable of Edge instances to be
|
||||
used as edges of the part. Instead of instances it is possible to pass
|
||||
a single character that is looked up in the ``.edges`` dict. This
|
||||
allows to pass a string with the desired characters per edge. By
|
||||
default the following character are supported:
|
||||
|
||||
* e : straight edge
|
||||
* E : as above but extended outside by one thickness
|
||||
* f, F : finger joints
|
||||
* h : edge with holes for finger joints
|
||||
* d, D : dove tail joints
|
||||
|
||||
Generators can register their own Edges by putting them into the
|
||||
``.edges`` dictionary.
|
||||
|
||||
Same applies to the parameters of ``.surroundingWall`` although they
|
||||
denominate single edge (types) only.
|
||||
|
||||
PartsMatrix
|
||||
-----------
|
||||
|
||||
To place many of the same part partMatrix can used:
|
||||
|
||||
.. automethod:: boxes.Boxes.partsMatrix
|
||||
|
||||
It creates one big block of parts. The move param treat this block like on big
|
||||
part.
|
||||
|
||||
Navigation
|
||||
----------
|
||||
.. automethod:: boxes.Boxes.moveTo
|
||||
.. automethod:: boxes.Boxes.moveArc
|
||||
|
||||
**Boxes.ctx.save()** allows to save (among other things) the current position.
|
||||
**Boxes.ctx.restore()** restores the previously saved state. Always make sure
|
||||
to have balanced calls to those two functions.
|
||||
|
||||
Turtle Graphics commands
|
||||
------------------------
|
||||
|
||||
These commands all move the coordinate system with them.
|
||||
|
||||
.. automethod:: boxes.Boxes.edge
|
||||
.. automethod:: boxes.Boxes.corner
|
||||
.. automethod:: boxes.Boxes.curveTo
|
||||
.. automethod:: boxes.Boxes.polyline
|
||||
|
||||
Special Functions
|
||||
.................
|
||||
|
||||
.. automethod:: boxes.Boxes.bedBoltHole
|
||||
|
||||
Latch and Grip
|
||||
..............
|
||||
|
||||
These should probably be Edge classes. But right now they are still functions.
|
||||
|
||||
.. automethod:: boxes.Boxes.grip
|
||||
.. automethod:: boxes.Boxes.latch
|
||||
.. automethod:: boxes.Boxes.handle
|
||||
|
||||
Draw Commands
|
||||
-------------
|
||||
|
||||
These commands do not change the coordinate system but get the
|
||||
coordinates passed as parameters. All of them are either som sort of
|
||||
hole or text. These artefacts are placed somewhere independently of
|
||||
some continuous outline of the part their on.
|
||||
|
||||
.. automethod:: boxes.Boxes.hole
|
||||
.. automethod:: boxes.Boxes.rectangularHole
|
||||
.. automethod:: boxes.Boxes.dHole
|
||||
.. automethod:: boxes.Boxes.flatHole
|
||||
.. automethod:: boxes.Boxes.text
|
||||
.. automethod:: boxes.Boxes.NEMA
|
||||
.. automethod:: boxes.Boxes.TX
|
||||
.. automethod:: boxes.Boxes.flex2D
|
||||
.. py:class:: NutHole
|
||||
|
||||
An instance is available as **boxes.Boxes.nutHole()**
|
||||
|
||||
An instance of
|
||||
|
||||
.. autoclass:: boxes.edges.FingerHoles
|
||||
:noindex:
|
||||
|
||||
is accessible as **Boxes.fingerHolesAt**.
|
||||
|
||||
|
||||
Hexagonal Hole patterns
|
||||
.......................
|
||||
|
||||
Hexagonal hole patterns are one way to have some ventilation for
|
||||
housings maded with Boxes.py. Right now both ``.rectangularWall()``
|
||||
and ``.roundedPlate()`` do supports this pattern directly by passing
|
||||
the parameters to the calls. For other use cases these more low level
|
||||
methods can be used.
|
||||
|
||||
For now this is the only supported pattern for ventilation slots. More
|
||||
may be added in the future.
|
||||
|
||||
There is a global Boxes.hexHolesSettings object that is used if no settings are
|
||||
passed. It currently is just a tuple of (r, dist, style) defualting to
|
||||
(5, 3, 'circle') but might be replace by a Settings instance in the future.
|
||||
|
||||
.. automethod:: boxes.Boxes.hexHolesRectangle
|
||||
.. automethod:: boxes.Boxes.hexHolesCircle
|
||||
.. automethod:: boxes.Boxes.hexHolesPlate
|
||||
.. automethod:: boxes.Boxes.hexHolesHex
|
|
@ -50,7 +50,8 @@ clean:
|
|||
rm -rf $(BUILDDIR)/*
|
||||
|
||||
html:
|
||||
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
|
||||
./boxes2rst generators.inc
|
||||
$(SPHINXBUILD) --color -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html 2>&1 | grep -v "WARNING: duplicate object description"
|
||||
cp index.html $(BUILDDIR)/
|
||||
@echo
|
||||
@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
|
||||
|
|
|
@ -0,0 +1,95 @@
|
|||
Architecture
|
||||
------------
|
||||
|
||||
Boxes.py it structured into several distinct tiers.
|
||||
|
||||
User Interfaces
|
||||
...............
|
||||
|
||||
User interfaces allow users to render the different generators. They
|
||||
handle the parameters of Generators and convert them to a readable
|
||||
form. The user interfaces are located in `scripts/`. Currently there is
|
||||
|
||||
* scripts/boxes -- the command line interface
|
||||
* scripts/boxesserver -- the web interface
|
||||
* scripts/boxes2inx -- generates Inkscape extensions
|
||||
* scripts/boxes_example.ipynb -- Jupyter notebook
|
||||
|
||||
|
||||
Generators
|
||||
..........
|
||||
|
||||
A (box) generator is an sub class of boxes.Boxes. It generates one
|
||||
drawing. The sub classes over load .__init__() to set their parameters
|
||||
and implement .render() that does the actual drawing.
|
||||
|
||||
Generators are found in ``boxes/generators/``. They are included into
|
||||
the web UI and the CLI tool by the name of their class. So whenever
|
||||
you copy either an existing generator or the sceleton in
|
||||
``boxes/generators/_template.py`` you need to change the name of the
|
||||
main class first.
|
||||
|
||||
Parts
|
||||
.....
|
||||
|
||||
Parts are a single call that draws something according to a set of parameters.
|
||||
There is a number of standard parts. Their typical params are
|
||||
explained in the API docs.
|
||||
|
||||
Only real requirement for a part it supporting the move parameter for
|
||||
placement.
|
||||
|
||||
Part Callbacks
|
||||
++++++++++++++
|
||||
|
||||
Most parts support callbacks - either one in the middle for round
|
||||
parts or one for each edge. They allow placing holes or other features
|
||||
on the part.
|
||||
|
||||
Navigation and Turtle Graphics
|
||||
..............................
|
||||
|
||||
Many drawing commands in Boxes.py are Turtle Graphics commands. They
|
||||
start at the current position and in the current direction and move
|
||||
the coordinate system with them. This way the absolute coordinates are
|
||||
never used and placement and movement is always relative to the
|
||||
current position.
|
||||
|
||||
There are a few functions to move the origin to a convenient position
|
||||
or to return to a previously saved position.
|
||||
|
||||
Edges
|
||||
.....
|
||||
|
||||
Edges are turtle graphic commands. But they have been elevated to
|
||||
proper Classes to handle outsets. They can be passed as parameters to parts.
|
||||
There is a set of standard edges found in ``.edges``. They are
|
||||
acciociated with a single char which can be used instead of the
|
||||
Edge object itself at most places. This allows passing the edge
|
||||
description of a part as a string.
|
||||
|
||||
Turtle graphics
|
||||
...............
|
||||
|
||||
There are a few turtle graphics commands that do the actual
|
||||
drawing. Corners with an positive angle (going counter clockwise)
|
||||
close the part while negative angles (going clockwise) create protrusions.
|
||||
This is inversed for holes which need to be drawn clockwise.
|
||||
|
||||
Getting this directions right is important to make the burn correction
|
||||
(aka kerf) work properly.
|
||||
|
||||
Simple drawing commands
|
||||
.......................
|
||||
|
||||
These also are simple drawing commands. Some of them get ``x``, ``y`` and
|
||||
``angle`` parameters to draw somewhere specific. Some just draw right
|
||||
at the current coordinate origin. Often these commands create holes or
|
||||
hole patterns.
|
||||
|
||||
Cairo
|
||||
.....
|
||||
|
||||
Boxes.py uses cairo as graphics library. It is not fully encapsulated
|
||||
within the drawing methods of the Boxes class. Although this is the
|
||||
long term goal. Boxes.ctx is the cairo context all drawing is made on.
|
|
@ -0,0 +1,76 @@
|
|||
Generator Arguments
|
||||
-------------------
|
||||
|
||||
Boxes.py uses the ``argparse`` standard library for handling the
|
||||
arguments for the generators. It is used directly for the ``boxes``
|
||||
command line tool. But it also handles -- with some additional code --
|
||||
the web interface and the Inkscape extensions. To make this work one
|
||||
has to limit the kind of parameters used. Boxes.py supports the
|
||||
following types:
|
||||
|
||||
* ``int``
|
||||
* ``float``
|
||||
* ``str``
|
||||
* ``boxes.boolarg`` -- an alternative to ``bool`` that works with the
|
||||
web interface
|
||||
* ``boxes.argparseSections`` -- multiple lengths e.g. for dividing up
|
||||
a box in one direction
|
||||
|
||||
and
|
||||
|
||||
.. autoclass:: boxes.ArgparseEdgeType
|
||||
|
||||
For the standard types there is code to create HTML and Inkscape
|
||||
extensions. The other types can have ``.html()`` and ``.inx()``
|
||||
methods.
|
||||
|
||||
The argument parser need to be built in the ``.__init__()`` method
|
||||
after calling the method of the super class. Have a look at
|
||||
|
||||
.. automethod:: boxes.generators._template.BOX.__init__
|
||||
|
||||
As many arguments are used over and over there is a function that can
|
||||
add the most common ones:
|
||||
|
||||
.. automethod:: boxes.Boxes.buildArgParser
|
||||
|
||||
Check the source for details about the single arguments.
|
||||
|
||||
Other arguments can be added with the normal argparser API - namely
|
||||
|
||||
.. automethod:: argparse.ArgumentParser.add_argument
|
||||
|
||||
of the ``Boxes.argparser`` attribute.
|
||||
|
||||
Edge style arguments
|
||||
....................
|
||||
|
||||
Edges that work together share a Settings class (and object). These
|
||||
classes can create ``argparse`` groups:
|
||||
|
||||
.. automethod:: boxes.edges.Settings.parserArguments
|
||||
|
||||
See
|
||||
|
||||
.. automethod:: boxes.generators._template.BOX.__init__
|
||||
|
||||
for a list of possible edge settings. These regular settings are used
|
||||
in the standard edge instances used everywhere. For special edge
|
||||
instances you can call them with a ``prefix`` parameter. But you then
|
||||
need to deal with the results on your own.
|
||||
|
||||
Default Arguments
|
||||
.................
|
||||
|
||||
The :ref:`default-args` get added automatically by the super class's
|
||||
constructor.
|
||||
|
||||
Accessing the Arguments
|
||||
.......................
|
||||
|
||||
For convenience content of the arguments are written to attributes of
|
||||
the Boxes instance before ``.render()`` is called. This is done by
|
||||
``Boxes.parseArgs``. But most people won't need to care as this is
|
||||
handled by the frame work. Be careful to **not overwrite important
|
||||
methods or attributes by using conflicting argument names**.
|
||||
|
|
@ -0,0 +1,76 @@
|
|||
Drawing commands
|
||||
================
|
||||
|
||||
|
||||
Turtle Graphics commands
|
||||
------------------------
|
||||
|
||||
These commands all move the coordinate system with them.
|
||||
|
||||
.. automethod:: boxes.Boxes.edge
|
||||
.. automethod:: boxes.Boxes.corner
|
||||
.. automethod:: boxes.Boxes.curveTo
|
||||
.. automethod:: boxes.Boxes.polyline
|
||||
|
||||
Special Functions
|
||||
.................
|
||||
|
||||
.. automethod:: boxes.Boxes.bedBoltHole
|
||||
|
||||
Latch and Grip
|
||||
..............
|
||||
|
||||
These should probably be Edge classes. But right now they are still functions.
|
||||
|
||||
.. automethod:: boxes.Boxes.grip
|
||||
.. automethod:: boxes.Boxes.latch
|
||||
.. automethod:: boxes.Boxes.handle
|
||||
|
||||
Draw Commands
|
||||
-------------
|
||||
|
||||
These commands do not change the coordinate system but get the
|
||||
coordinates passed as parameters. All of them are either som sort of
|
||||
hole or text. These artefacts are placed somewhere independently of
|
||||
some continuous outline of the part their on.
|
||||
|
||||
.. automethod:: boxes.Boxes.hole
|
||||
.. automethod:: boxes.Boxes.rectangularHole
|
||||
.. automethod:: boxes.Boxes.dHole
|
||||
.. automethod:: boxes.Boxes.flatHole
|
||||
.. automethod:: boxes.Boxes.text
|
||||
.. automethod:: boxes.Boxes.NEMA
|
||||
.. automethod:: boxes.Boxes.TX
|
||||
.. automethod:: boxes.Boxes.flex2D
|
||||
.. py:class:: NutHole
|
||||
|
||||
An instance is available as **boxes.Boxes.nutHole()**
|
||||
|
||||
An instance of
|
||||
|
||||
.. autoclass:: boxes.edges.FingerHoles
|
||||
:noindex:
|
||||
|
||||
is accessible as **Boxes.fingerHolesAt**.
|
||||
|
||||
|
||||
Hexagonal Hole patterns
|
||||
.......................
|
||||
|
||||
Hexagonal hole patterns are one way to have some ventilation for
|
||||
housings maded with Boxes.py. Right now both ``.rectangularWall()``
|
||||
and ``.roundedPlate()`` do supports this pattern directly by passing
|
||||
the parameters to the calls. For other use cases these more low level
|
||||
methods can be used.
|
||||
|
||||
For now this is the only supported pattern for ventilation slots. More
|
||||
may be added in the future.
|
||||
|
||||
There is a global Boxes.hexHolesSettings object that is used if no settings are
|
||||
passed. It currently is just a tuple of (r, dist, style) defualting to
|
||||
(5, 3, 'circle') but might be replace by a Settings instance in the future.
|
||||
|
||||
.. automethod:: boxes.Boxes.hexHolesRectangle
|
||||
.. automethod:: boxes.Boxes.hexHolesCircle
|
||||
.. automethod:: boxes.Boxes.hexHolesPlate
|
||||
.. automethod:: boxes.Boxes.hexHolesHex
|
|
@ -0,0 +1,97 @@
|
|||
Examples
|
||||
--------
|
||||
|
||||
Decide whether you want to start from scratch or want to rework an
|
||||
existing generator.
|
||||
|
||||
You should go over the arguments first. Get at least the most basic
|
||||
arguments done. For things you are still unsure you can just use a
|
||||
attribute set in the .__init__() method and turn it into a proper
|
||||
argument later on.
|
||||
|
||||
Depending on what you want to do you can work on the different levels
|
||||
of the API. You can either use what is there and combine it into
|
||||
something new or you can implements new things in the appropriate level.
|
||||
|
||||
Here are some examples:
|
||||
|
||||
Housing for some electronics
|
||||
............................
|
||||
|
||||
You can use the ElectronicsBox or the ClosedBox as a basis. Write some
|
||||
callbacks to place holes in the walls to allow accessing the ports of
|
||||
the electronics boards. Place some holes to screw spacers into the
|
||||
bottom to mount the PBC on.
|
||||
|
||||
NemaMount
|
||||
.........
|
||||
|
||||
This is a good non box example to look at.
|
||||
|
||||
.. autoclass:: boxes.generators.nemamount.NemaMount
|
||||
|
||||
Note that although it produces a cube like object it uses separate
|
||||
variables (``x``, ``y``, ``h``) for the different axis. Probably
|
||||
because it started as a copy of another generator like ``ClosedBox``.
|
||||
|
||||
DisplayShelf
|
||||
............
|
||||
|
||||
.. autoclass:: boxes.generators.displayshelf.DisplayShelf
|
||||
|
||||
The DisplayShelf is completely made out of rectangularWalls(). It uses
|
||||
a callback to place all the fingerHolesAt() right places on the sides.
|
||||
While the use of the Boxes.py API is pretty straight forward the
|
||||
calculations needed are a bit more tricky. You can use the ``debug``
|
||||
default param to check if you got things right when attempting
|
||||
something like this yourself.
|
||||
|
||||
Note that the front walls and the shelfs form a 90° angle so they work
|
||||
with the default FingerJoints.
|
||||
|
||||
BinTray
|
||||
.......
|
||||
|
||||
.. autoclass:: boxes.generators.bintray.BinTray
|
||||
|
||||
The BinTray is based on the TypeTray generator:
|
||||
|
||||
.. autoclass:: boxes.generators.typetray.TypeTray
|
||||
|
||||
TypeTray is an already pretty complicated generator.
|
||||
|
||||
BinTray replaces the now vertical front (former top) edges with a
|
||||
special purpose one that does add the triangles:
|
||||
|
||||
.. autoclass:: boxes.generators.bintray.BinFrontEdge
|
||||
|
||||
The ``hi`` (height of inner walls) argument was removed although the
|
||||
variable is still used internally - out of lazyness.
|
||||
|
||||
To complete the bin the front walls are added. Follow up patches then
|
||||
switched the slots between the vertical and horizontal walls to have
|
||||
better support for the now bottoms of the bins. Another patch adds
|
||||
angled finger joints for connecting the front walls with the bottoms
|
||||
of the bins.
|
||||
|
||||
The TrafficLight generator uses a similar technique implementing its
|
||||
own Edge class. But it uses its own code to generate all the wall needed.
|
||||
|
||||
Stachel
|
||||
.......
|
||||
|
||||
.. autoclass:: boxes.generators.stachel.Stachel
|
||||
|
||||
Stachel allows mounting a monopod to a bass recorder. It is basically
|
||||
just one part repeated with different parameters. It can't really make
|
||||
use of much of the Boxes.py library. It implements this one part
|
||||
including the ``move`` parameter and draws everything using the
|
||||
``.polyline()`` method. This is pretty painful as lots of angles and
|
||||
distances need to be calculated by hand.
|
||||
|
||||
For symmetric sections it passes the parameters to ``.polyline`` twice
|
||||
-- first in normal order and then reversed to get the mirrored section.
|
||||
|
||||
This generator is beyond what Boxes.py is designed for. If you need
|
||||
something similar you may want to use another tool like OpenScad or a
|
||||
traditional CAD program.
|
|
@ -0,0 +1,26 @@
|
|||
Existing Parts
|
||||
--------------
|
||||
|
||||
A couple of commands can create whole parts like walls. Typically the
|
||||
sizes given are the inner dimmensions not including additional space
|
||||
needed for burn compensation or joints.
|
||||
|
||||
Currently there are the following parts:
|
||||
|
||||
.. automethod:: boxes.Boxes.rectangularWall
|
||||
.. automethod:: boxes.Boxes.flangedWall
|
||||
.. automethod:: boxes.Boxes.rectangularTriangle
|
||||
.. automethod:: boxes.Boxes.regularPolygonWall
|
||||
.. automethod:: boxes.Boxes.roundedPlate
|
||||
.. automethod:: boxes.Boxes.surroundingWall
|
||||
|
||||
Parts Class
|
||||
...........
|
||||
|
||||
More parts are available in a separete class. An instance is available as
|
||||
**Boxes.parts**
|
||||
|
||||
.. automethod:: boxes.parts.Parts.disc
|
||||
.. automethod:: boxes.parts.Parts.waivyKnob
|
||||
.. automethod:: boxes.parts.Parts.concaveKnob
|
||||
.. automethod:: boxes.parts.Parts.ringSegment
|
|
@ -0,0 +1,45 @@
|
|||
|
||||
Generators
|
||||
==========
|
||||
|
||||
Generators are sub classes of
|
||||
|
||||
.. autoclass:: boxes.Boxes
|
||||
|
||||
Most code is directly in this class. Sub class are supposed to over
|
||||
write the ``.__init__()`` and ``.render()`` method.
|
||||
|
||||
The Boxes class keeps a cairo canvas object (self.ctx) that all
|
||||
drawing is made on. In addition it keeps a couple of global settings
|
||||
used for various drawing operations. See the ``.__init__()`` method
|
||||
for the details.
|
||||
|
||||
For implementing a new generator forking an existing one or using the
|
||||
``boxes/generators/_template.py`` is probably easier than starting
|
||||
from scratch.
|
||||
|
||||
Many methods and attributes are for use of the sub classes. These
|
||||
methods are the interface for the user interfaces to interact with the
|
||||
generators:
|
||||
|
||||
.. automethod:: boxes.Boxes.__init__
|
||||
|
||||
.. automethod:: boxes.Boxes.parseArgs
|
||||
.. automethod:: boxes.Boxes.render
|
||||
|
||||
.. automethod:: boxes.Boxes.open
|
||||
.. automethod:: boxes.Boxes.close
|
||||
|
||||
Handling Generators
|
||||
-------------------
|
||||
|
||||
To handle the generators there is code in the ``boxes.generators``
|
||||
package.
|
||||
|
||||
.. automodule:: boxes.generators
|
||||
:members:
|
||||
:undoc-members:
|
||||
|
||||
This adds generators to the user interfaces automatically. For this to
|
||||
work it is important that the class names are unique. So whenever you
|
||||
start a new generator please change the class name right away.
|
|
@ -0,0 +1,12 @@
|
|||
Navigation
|
||||
----------
|
||||
.. automethod:: boxes.Boxes.moveTo
|
||||
.. automethod:: boxes.Boxes.moveArc
|
||||
|
||||
**Boxes.ctx.save()** allows to save (among other things) the current position.
|
||||
**Boxes.ctx.restore()** restores the previously saved state. Always make sure
|
||||
to have balanced calls to those two functions.
|
||||
|
||||
XXX
|
||||
|
||||
.. automethod:: boxes.Boxes.saved_context()
|
|
@ -0,0 +1,86 @@
|
|||
Parts
|
||||
-----
|
||||
|
||||
|
||||
|
||||
|
||||
There are a few parameter shared by many of those parts:
|
||||
|
||||
The callback parameter
|
||||
......................
|
||||
|
||||
The callback parameter can take on of the following forms:
|
||||
|
||||
* A function (or bound method) that expects one parameter: the number of the side the callback is currently called for.
|
||||
* A dict with some of the numbers of the sides as keys and functions without parameters as values.
|
||||
* A list of functions without parameters. The list may contain None as place holder and be shorter than the number of sides.
|
||||
|
||||
The callback functions are called with the side of the part at the
|
||||
positive x and y axis. If the edge uses up space this space is below
|
||||
the x axis. You do not have to restore the coordinate settings in the
|
||||
callback.
|
||||
|
||||
Instead of functions it can be handy to use a lambda expression
|
||||
calling the one building block funtion you need (e.g. fingerHolesAt).
|
||||
|
||||
For your own parts you can use this helper function:
|
||||
|
||||
.. automethod:: boxes.Boxes.cc
|
||||
|
||||
For finding the right piece to the *callback* parameter this function is used:
|
||||
|
||||
.. automethod:: boxes.Boxes.getEntry
|
||||
|
||||
|
||||
The move parameter
|
||||
..................
|
||||
|
||||
For placing the parts the ``move`` parameter can be used. It is string
|
||||
with space separated words - at most one of each of those options:
|
||||
|
||||
* left / right
|
||||
* up / down
|
||||
* only
|
||||
|
||||
If "only" is given the part is not drawn but only the move is
|
||||
done. This can be useful to go in one direction after having placed
|
||||
multiple parts in the other and have returned with ``.ctx.restore()``.
|
||||
|
||||
For implementing parts the following helper function can be used to
|
||||
implement a ``move`` parameter:
|
||||
|
||||
.. automethod:: boxes.Boxes.move
|
||||
|
||||
It needs to be called before and after drawing the actual part with
|
||||
the proper ``before`` paramter set.
|
||||
|
||||
The edges parameter
|
||||
...................
|
||||
|
||||
The ``edges`` parameter needs to be an iterable of Edge instances to be
|
||||
used as edges of the part. Instead of instances it is possible to pass
|
||||
a single character that is looked up in the ``.edges`` dict. This
|
||||
allows to pass a string with the desired characters per edge. By
|
||||
default the following character are supported:
|
||||
|
||||
* e : straight edge
|
||||
* E : as above but extended outside by one thickness
|
||||
* f, F : finger joints
|
||||
* h : edge with holes for finger joints
|
||||
* d, D : dove tail joints
|
||||
|
||||
Generators can register their own Edges by putting them into the
|
||||
``.edges`` dictionary.
|
||||
|
||||
Same applies to the parameters of ``.surroundingWall`` although they
|
||||
denominate single edge (types) only.
|
||||
|
||||
PartsMatrix
|
||||
...........
|
||||
|
||||
To place many of the same part partMatrix can used:
|
||||
|
||||
.. automethod:: boxes.Boxes.partsMatrix
|
||||
|
||||
It creates one big block of parts. The move param treat this block like on big
|
||||
part.
|
|
@ -0,0 +1,19 @@
|
|||
Using the Boxes.py API
|
||||
======================
|
||||
|
||||
If there is no generator fitting your needs you can either adjust an
|
||||
existing one (may be by copying it to another name first) or writing a
|
||||
new one from scratch.
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
api_architecture
|
||||
api_generator
|
||||
api_arguments
|
||||
api_navigation
|
||||
api_parts
|
||||
api_existing_parts
|
||||
api_edges
|
||||
api_drawing
|
||||
api_examples
|
|
@ -1,245 +0,0 @@
|
|||
==========================
|
||||
Using the Boxes.py library
|
||||
==========================
|
||||
|
||||
If there is no generator fitting your needs you can either adjust an
|
||||
existing one (may be by copying it to another name first) or writing a
|
||||
new one from scratch.
|
||||
|
||||
Generators are found in ``boxes/generators/``. They are included into
|
||||
the web UI and the CLI tool by the name of their class. So whenever
|
||||
you copy either an existing generator or the sceleton in
|
||||
``boxes/generators/_template.py`` you need to change the name of the
|
||||
main class first.
|
||||
|
||||
Generator Arguments
|
||||
-------------------
|
||||
|
||||
Boxes.py uses the ``argparse`` standard library for handling the
|
||||
arguments for the generators. It is used directly for the ``boxes``
|
||||
command line tool. But it also handles -- with some additional code --
|
||||
the web interface and the Inkscape extensions. To make this work one
|
||||
has to limit the kind of parameters used. Boxes.py supports the
|
||||
following types:
|
||||
|
||||
* ``int``
|
||||
* ``float``
|
||||
* ``str``
|
||||
* ``boxes.boolarg`` -- an alternative to ``bool`` that works with the
|
||||
web interface
|
||||
* ``boxes.argparseSections`` -- multiple lengths e.g. for dividing up
|
||||
a box in one direction
|
||||
|
||||
and
|
||||
|
||||
.. autoclass:: boxes.ArgparseEdgeType
|
||||
|
||||
For the standard types there is code to create HTML and Inkscape
|
||||
extensions. The other types can have ``.html()`` and ``.inx()``
|
||||
methods.
|
||||
|
||||
The argument parser need to be built in the ``.__init__()`` method
|
||||
after calling the method of the super class. Have a look at
|
||||
|
||||
.. automethod:: boxes.generators._template.BOX.__init__
|
||||
|
||||
As many arguments are used over and over there is a function that can
|
||||
add the most common ones:
|
||||
|
||||
.. automethod:: boxes.Boxes.buildArgParser
|
||||
|
||||
Check the source for details about the single arguments.
|
||||
|
||||
Other arguments can be added with the normal argparser API - namely
|
||||
|
||||
.. automethod:: argparse.ArgumentParser.add_argument
|
||||
|
||||
of the ``Boxes.argparser`` attribute.
|
||||
|
||||
Edge style arguments
|
||||
....................
|
||||
|
||||
Edges that work together share a Settings class (and object). These
|
||||
classes can create ``argparse`` groups:
|
||||
|
||||
.. automethod:: boxes.edges.Settings.parserArguments
|
||||
|
||||
See
|
||||
|
||||
.. automethod:: boxes.generators._template.BOX.__init__
|
||||
|
||||
for a list of possible edge settings. These regular settings are used
|
||||
in the standard edge instances used everywhere. For special edge
|
||||
instances you can call them with a ``prefix`` parameter. But you then
|
||||
need to deal with the results on your own.
|
||||
|
||||
Default Arguments
|
||||
.................
|
||||
|
||||
The :ref:`default-args` get added automatically by the super class's
|
||||
constructor.
|
||||
|
||||
Accessing the Arguments
|
||||
.......................
|
||||
|
||||
For convenience content of the arguments are written to attributes of
|
||||
the Boxes instance before ``.render()`` is called. This is done by
|
||||
``Boxes.parseArgs``. But most people won't need to care as this is
|
||||
handled by the frame work. Be careful to **not overwrite important
|
||||
methods or attributes by using conflicting argument names**.
|
||||
|
||||
API Levels
|
||||
----------
|
||||
|
||||
For actual drawing there are multiple levels of abscractions thta can
|
||||
be used. From the simplest to the more powerful they are the following:
|
||||
|
||||
Simple drawing commands
|
||||
.......................
|
||||
|
||||
These are simple drawing commands. Some of them get ``x``, ``y`` and
|
||||
``angle`` parameters to draw somewhere specific. Some just draw right
|
||||
at the current coordinate origin. Often these commands create holes or
|
||||
hole patterns.
|
||||
|
||||
Moving the coordinate system
|
||||
............................
|
||||
|
||||
Boxes.py moves the coordinate system around a lot. You basically never have to
|
||||
deal with the global position on the sheet but only with coordnates
|
||||
relative to where you are. There are a few functions to move the
|
||||
origin to a convenient position.
|
||||
|
||||
Turtle graphics
|
||||
...............
|
||||
|
||||
To draw parts turtle graphic commands are used. The always start at
|
||||
the current origin following the X axis. The move the origin with
|
||||
them. The inside of the part is above the X axis and the outside
|
||||
below. Corners with an positive angle (going counter clockwise) close
|
||||
the part while negative angles (going clockwise) create protrusions.
|
||||
This is inversed for holes which need to be drawn clockwise.
|
||||
|
||||
Getting this directions right is important to make the burn correction
|
||||
(aka kerf) work properly. The burn correction is implemented by
|
||||
increasing the radius of positive corners and decresing the radius of
|
||||
negative corners. (TODO: nice pictures)
|
||||
|
||||
Edges
|
||||
.....
|
||||
|
||||
Edges are also turtle graphic commands. But they have been elevated to
|
||||
proper Classes.
|
||||
|
||||
Parts
|
||||
.....
|
||||
|
||||
There are a couple of standard parts that can be drawn with a single
|
||||
command. Their typical params are explained in the API docs.
|
||||
|
||||
|
||||
Part Callbacks
|
||||
..............
|
||||
|
||||
Most parts support callbacks - either one in the middle for round
|
||||
parts or one for each edge. They allow placing holes or other features
|
||||
on the part.
|
||||
|
||||
|
||||
How to get things done
|
||||
----------------------
|
||||
|
||||
Decide whether you want to start from scratch or want to rework an
|
||||
existing generator.
|
||||
|
||||
You should go over the arguments first. Get at least the most basic
|
||||
arguments done. For things you are still unsure you can just use a
|
||||
attribute set in the .__init__() method and turn it into a proper
|
||||
argument later on.
|
||||
|
||||
Depending on what you want to do you can work on the different levels
|
||||
of the API. You can either use what is there and combine it into
|
||||
something new or you can implements new things in the appropriate level.
|
||||
|
||||
Here are some examples:
|
||||
|
||||
Housing for some electronics
|
||||
............................
|
||||
|
||||
You can use the ElectronicsBox or the ClosedBox as a basis. Write some
|
||||
callbacks to place holes in the walls to allow accessing the ports of
|
||||
the electronics boards. Place some holes to screw spacers into the
|
||||
bottom to mount the PBC on.
|
||||
|
||||
NemaMount
|
||||
.........
|
||||
|
||||
This is a good non box example to look at.
|
||||
|
||||
.. autoclass:: boxes.generators.nemamount.NemaMount
|
||||
|
||||
Note that although it produces a cube like object it uses separate
|
||||
variables (``x``, ``y``, ``h``) for the different axis. Probably
|
||||
because it started as a copy of another generator like ``ClosedBox``.
|
||||
|
||||
DisplayShelf
|
||||
............
|
||||
|
||||
.. autoclass:: boxes.generators.displayshelf.DisplayShelf
|
||||
|
||||
The DisplayShelf is completely made out of rectangularWalls(). It uses
|
||||
a callback to place all the fingerHolesAt() right places on the sides.
|
||||
While the use of the Boxes.py API is pretty straight forward the
|
||||
calculations needed are a bit more tricky. You can use the ``debug``
|
||||
default param to check if you got things right when attempting
|
||||
something like this yourself.
|
||||
|
||||
Note that the front walls and the shelfs form a 90° angle so they work
|
||||
with the default FingerJoints.
|
||||
|
||||
BinTray
|
||||
.......
|
||||
|
||||
.. autoclass:: boxes.generators.bintray.BinTray
|
||||
|
||||
The BinTray is based on the TypeTray generator:
|
||||
|
||||
.. autoclass:: boxes.generators.typetray.TypeTray
|
||||
|
||||
TypeTray is an already pretty complicated generator.
|
||||
|
||||
BinTray replaces the now vertical front (former top) edges with a
|
||||
special purpose one that does add the triangles:
|
||||
|
||||
.. autoclass:: boxes.generators.bintray.BinFrontEdge
|
||||
|
||||
The ``hi`` (height of inner walls) argument was removed although the
|
||||
variable is still used internally - out of lazyness.
|
||||
|
||||
To complete the bin the front walls are added. Follow up patches then
|
||||
switched the slots between the vertical and horizontal walls to have
|
||||
better support for the now bottoms of the bins. Another patch adds
|
||||
angled finger joints for connecting the front walls with the bottoms
|
||||
of the bins.
|
||||
|
||||
The TrafficLight generator uses a similar technique implementing its
|
||||
own Edge class. But it uses its own code to generate all the wall needed.
|
||||
|
||||
Stachel
|
||||
.......
|
||||
|
||||
.. autoclass:: boxes.generators.stachel.Stachel
|
||||
|
||||
Stachel allows mounting a monopod to a bass recorder. It is basically
|
||||
just one part repeated with different parameters. It can't really make
|
||||
use of much of the Boxes.py library. It implements this one part
|
||||
including the ``move`` parameter and draws everything using the
|
||||
``.polyline()`` method. This is pretty painful as lots of angles and
|
||||
distances need to be calculated by hand.
|
||||
|
||||
For symmetric sections it passes the parameters to ``.polyline`` twice
|
||||
-- first in normal order and then reversed to get the mirrored section.
|
||||
|
||||
This generator is beyond what Boxes.py is designed for. If you need
|
||||
something similar you may want to use another tool like OpenScad or a
|
||||
traditional CAD program.
|
|
@ -0,0 +1,120 @@
|
|||
boxes package
|
||||
=============
|
||||
|
||||
Subpackage boxes.generators
|
||||
---------------------------
|
||||
|
||||
.. automodule:: boxes.generators
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
:doc:`generators`
|
||||
|
||||
Submodules
|
||||
----------
|
||||
|
||||
boxes.Color module
|
||||
------------------
|
||||
|
||||
.. automodule:: boxes.Color
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
boxes.edges module
|
||||
------------------
|
||||
|
||||
.. automodule:: boxes.edges
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
boxes.formats module
|
||||
--------------------
|
||||
|
||||
.. automodule:: boxes.formats
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
boxes.gears module
|
||||
------------------
|
||||
|
||||
.. automodule:: boxes.gears
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
boxes.lids module
|
||||
-----------------
|
||||
|
||||
.. automodule:: boxes.lids
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
boxes.mounts module
|
||||
-------------------
|
||||
|
||||
.. automodule:: boxes.mounts
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
boxes.parts module
|
||||
------------------
|
||||
|
||||
.. automodule:: boxes.parts
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
boxes.pulley module
|
||||
-------------------
|
||||
|
||||
.. automodule:: boxes.pulley
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
boxes.robot module
|
||||
------------------
|
||||
|
||||
.. automodule:: boxes.robot
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
boxes.servos module
|
||||
-------------------
|
||||
|
||||
.. automodule:: boxes.servos
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
boxes.svgutil module
|
||||
--------------------
|
||||
|
||||
.. automodule:: boxes.svgutil
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
boxes.vectors module
|
||||
--------------------
|
||||
|
||||
.. automodule:: boxes.vectors
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
|
||||
Module contents
|
||||
---------------
|
||||
|
||||
.. automodule:: boxes
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
|
@ -0,0 +1,56 @@
|
|||
#!/usr/bin/env python3
|
||||
# Copyright (C) 2017 Florian Festi
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import sys
|
||||
import os.path
|
||||
|
||||
try:
|
||||
import boxes.generators
|
||||
except ImportError:
|
||||
sys.path.append(os.path.dirname(__file__) + "/../..")
|
||||
import boxes.generators
|
||||
|
||||
class Boxes2rst:
|
||||
def __init__(self):
|
||||
self.boxes = {b.__name__ : b() for b in boxes.generators.getAllBoxGenerators().values() if b.webinterface}
|
||||
self.groups = boxes.generators.ui_groups
|
||||
self.groups_by_name = boxes.generators.ui_groups_by_name
|
||||
|
||||
for name, box in self.boxes.items():
|
||||
self.groups_by_name.get(box.ui_group,
|
||||
self.groups_by_name["Misc"]).add(box)
|
||||
|
||||
def write(self, path):
|
||||
with open(path, "w") as f:
|
||||
for name, group in self.groups_by_name.items():
|
||||
f.write(name + """
|
||||
----------------
|
||||
|
||||
""")
|
||||
for box in group.generators:
|
||||
f.write(box.__class__.__name__)
|
||||
f.write("\n..........................................\n\n")
|
||||
f.write("\n\n.. autoclass:: %s.%s" % (
|
||||
box.__class__.__module__, box.__class__.__name__))
|
||||
f.write("\n\n")
|
||||
if os.path.exists("../../static/samples/"+ box.__class__.__name__+".jpg"):
|
||||
f.write(".. image:: ../../static/samples/" + box.__class__.__name__+".jpg\n\n")
|
||||
|
||||
if __name__=="__main__":
|
||||
if len(sys.argv) != 2:
|
||||
print("Usage: boxes2inksacpe TARGETPATH")
|
||||
b = Boxes2rst()
|
||||
b.write(sys.argv[1])
|
|
@ -0,0 +1,9 @@
|
|||
All Box Generators
|
||||
==================
|
||||
|
||||
Generators are organized in several Groups
|
||||
|
||||
.. contents::
|
||||
:local:
|
||||
|
||||
.. include:: generators.inc
|
|
@ -3,21 +3,22 @@
|
|||
You can adapt this file completely to your liking, but it should at least
|
||||
contain the root `toctree` directive.
|
||||
|
||||
Welcome to boxes.py's documentation!
|
||||
====================================
|
||||
Boxes.py
|
||||
========
|
||||
|
||||
Create boxes and more with a laser cutter!
|
||||
|
||||
Contents:
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
:maxdepth: 1
|
||||
|
||||
README
|
||||
install
|
||||
usermanual
|
||||
CONTRIBUTING.rst
|
||||
apiintro
|
||||
Boxes
|
||||
edges
|
||||
apidoc
|
||||
generators
|
||||
|
||||
Indices and tables
|
||||
==================
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
:orphan:
|
||||
|
||||
boxes
|
||||
=====
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 4
|
||||
|
||||
boxes
|
Loading…
Reference in New Issue