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:
Florian Festi 2019-02-08 22:56:19 +01:00
parent 8640514daf
commit 0a73e929ec
18 changed files with 735 additions and 473 deletions

View File

@ -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

View File

@ -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."

View File

@ -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.

View File

@ -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**.

View File

@ -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

View File

@ -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.

View File

@ -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

View File

@ -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.

View File

@ -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()

View File

@ -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.

View File

@ -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

View File

@ -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.

120
documentation/src/boxes.rst Normal file
View File

@ -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:

56
documentation/src/boxes2rst Executable file
View File

@ -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])

View File

@ -0,0 +1,9 @@
All Box Generators
==================
Generators are organized in several Groups
.. contents::
:local:
.. include:: generators.inc

View File

@ -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
==================

View File

@ -0,0 +1,9 @@
:orphan:
boxes
=====
.. toctree::
:maxdepth: 4
boxes