renamed folders to standard ones

This commit is contained in:
Dave Cowden 2013-04-15 21:22:54 -04:00
parent 911d00bfd7
commit 8943b8dd10
45 changed files with 3803 additions and 34 deletions

View File

@ -21,8 +21,48 @@ try:
import xml.etree.cElementTree as ET
except ImportError:
import xml.etree.ElementTree as ET
class ExportFormats:
STL = "STL"
BREP = "BREP"
STEP = "STEP"
AMF = "AMF"
IGES = "IGES"
class AMFWriter(object):
class UNITS:
MM = "mm"
IN = "in"
def guessUnitOfMeasure(shape):
"""
Guess the unit of measure of a shape.
"""
bb = shape.BoundBox
dimList = [ bb.XLength, bb.YLength,bb.ZLength ]
#no real part would likely be bigger than 10 inches on any side
if max(dimList) > 10:
return UNITS.MM
#no real part would likely be smaller than 0.1 mm on all dimensions
if min(dimList) < 0.1:
return UNITS.IN
#no real part would have the sum of its dimensions less than about 5mm
if sum(dimList) < 10:
return UNITS.IN
return UNITS.MM
class Exporter(object):
def export(self):
"""
return a string representing the model exported in the specified format
"""
raise NotImplementedError()
class AMFExporter(Exporter):
def __init__(self,tessellation):
self.units = "mm"
@ -65,7 +105,7 @@ class AMFWriter(object):
three.js JSON object notation
https://github.com/mrdoob/three.js/wiki/JSON-Model-format-3.0
"""
class JsonMesh(object):
class JsonExporter(Exporter):
def __init__(self):
self.vertices = [];
@ -95,31 +135,8 @@ class JsonMesh(object):
'nFaces' : self.nFaces
};
class SVGExporter(Exporter):
class UNITS:
MM = "mm"
IN = "in"
def guessUnitOfMeasure(shape):
"""
Guess the unit of measure of a shape.
"""
bb = shape.BoundBox
dimList = [ bb.XLength, bb.YLength,bb.ZLength ]
#no real part would likely be bigger than 10 inches on any side
if max(dimList) > 10:
return UNITS.MM
#no real part would likely be smaller than 0.1 mm on all dimensions
if min(dimList) < 0.1:
return UNITS.IN
#no real part would have the sum of its dimensions less than about 5mm
if sum(dimList) < 10:
return UNITS.IN
return UNITS.MM
def getPaths(freeCadSVG):
"""

View File

@ -49,14 +49,6 @@
"""
class ExportFormats:
STL = "STL"
BREP = "BREP"
STEP = "STEP"
AMF = "AMF"
IGES = "IGES"
class Shape(object):
"""
Represents a shape in the system.

153
doc/Makefile Normal file
View File

@ -0,0 +1,153 @@
# Makefile for Sphinx documentation
#
# You can set these variables from the command line.
SPHINXOPTS =
SPHINXBUILD = sphinx-build
PAPER =
BUILDDIR = _build
# Internal variables.
PAPEROPT_a4 = -D latex_paper_size=a4
PAPEROPT_letter = -D latex_paper_size=letter
ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
# the i18n builder cannot share the environment and doctrees with the others
I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext
help:
@echo "Please use \`make <target>' where <target> is one of"
@echo " html to make standalone HTML files"
@echo " dirhtml to make HTML files named index.html in directories"
@echo " singlehtml to make a single large HTML file"
@echo " pickle to make pickle files"
@echo " json to make JSON files"
@echo " htmlhelp to make HTML files and a HTML help project"
@echo " qthelp to make HTML files and a qthelp project"
@echo " devhelp to make HTML files and a Devhelp project"
@echo " epub to make an epub"
@echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
@echo " latexpdf to make LaTeX files and run them through pdflatex"
@echo " text to make text files"
@echo " man to make manual pages"
@echo " texinfo to make Texinfo files"
@echo " info to make Texinfo files and run them through makeinfo"
@echo " gettext to make PO message catalogs"
@echo " changes to make an overview of all changed/added/deprecated items"
@echo " linkcheck to check all external links for integrity"
@echo " doctest to run all doctests embedded in the documentation (if enabled)"
clean:
-rm -rf $(BUILDDIR)/*
html:
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
@echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
dirhtml:
$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
@echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
singlehtml:
$(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
@echo
@echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
pickle:
$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
@echo
@echo "Build finished; now you can process the pickle files."
json:
$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
@echo
@echo "Build finished; now you can process the JSON files."
htmlhelp:
$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
@echo
@echo "Build finished; now you can run HTML Help Workshop with the" \
".hhp project file in $(BUILDDIR)/htmlhelp."
qthelp:
$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
@echo
@echo "Build finished; now you can run "qcollectiongenerator" with the" \
".qhcp project file in $(BUILDDIR)/qthelp, like this:"
@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/CadQuery.qhcp"
@echo "To view the help file:"
@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/CadQuery.qhc"
devhelp:
$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
@echo
@echo "Build finished."
@echo "To view the help file:"
@echo "# mkdir -p $$HOME/.local/share/devhelp/CadQuery"
@echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/CadQuery"
@echo "# devhelp"
epub:
$(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
@echo
@echo "Build finished. The epub file is in $(BUILDDIR)/epub."
latex:
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@echo
@echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
@echo "Run \`make' in that directory to run these through (pdf)latex" \
"(use \`make latexpdf' here to do that automatically)."
latexpdf:
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@echo "Running LaTeX files through pdflatex..."
$(MAKE) -C $(BUILDDIR)/latex all-pdf
@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
text:
$(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
@echo
@echo "Build finished. The text files are in $(BUILDDIR)/text."
man:
$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
@echo
@echo "Build finished. The manual pages are in $(BUILDDIR)/man."
texinfo:
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
@echo
@echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
@echo "Run \`make' in that directory to run these through makeinfo" \
"(use \`make info' here to do that automatically)."
info:
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
@echo "Running Texinfo files through makeinfo..."
make -C $(BUILDDIR)/texinfo info
@echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
gettext:
$(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
@echo
@echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
changes:
$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
@echo
@echo "The overview file is in $(BUILDDIR)/changes."
linkcheck:
$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
@echo
@echo "Link check complete; look for any errors in the above output " \
"or in $(BUILDDIR)/linkcheck/output.txt."
doctest:
$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
@echo "Testing of doctests in the sources finished, look at the " \
"results in $(BUILDDIR)/doctest/output.txt."

BIN
doc/_static/ParametricPulley.PNG vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

BIN
doc/_static/PillowBlock.PNG vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

BIN
doc/_static/block.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

BIN
doc/_static/new_badge.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

BIN
doc/_static/parametric-cup-screencap.PNG vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

BIN
doc/_static/quickstart-1.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

BIN
doc/_static/quickstart-2.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

BIN
doc/_static/quickstart-3.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

BIN
doc/_static/quickstart-4.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

BIN
doc/_static/quickstart-5.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

BIN
doc/_static/quickstart.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

139
doc/apireference.rst Normal file
View File

@ -0,0 +1,139 @@
.. _apireference:
***********************
CadQuery API Reference
***********************
.. automodule:: cadfile.cadutils.cadquery
.. seealso::
This page lists api methods grouped by functional area.
Use :ref:`classreference` to see methods alphabetically by class.
Don't see a method you want? see :ref:`extending`
Primary Objects
----------------
The CadQuery API is made up of 3 main objects:
* **CQ** - Basic Selection, and 3d operations
* **Workplane** -- Draw in 2-d to make 3d features
* **Selector** -- Filter and select things
The sections below list methods of these objects grouped by **functional area**
Initialization
----------------
Creating new workplanes and object chains
.. autosummary::
CQ
Workplane
CQ.workplane
.. _2dOperations:
2-d Operations
-----------------
Creating 2-d constructs that can be used to create 3 d features
.. autosummary::
Workplane.center
Workplane.lineTo
Workplane.line
Workplane.vLine
Workplane.vLineTo
Workplane.hLine
Workplane.moveTo
Workplane.move
Workplane.spline
Workplane.threePointArc
Workplane.rotateAndCopy
Workplane.mirrorY
Workplane.mirrorX
Workplane.wire
Workplane.rect
Workplane.circle
Workplane.polyline
Workplane.close
Workplane.rarray
.. _3doperations:
3-d Operations
-----------------
Methods that create 3d features
.. autosummary::
Workplane.cboreHole
Workplane.cskHole
Workplane.hole
Workplane.extrude
Workplane.cut
Workplane.cutBlind
Workplane.cutThruAll
Workplane.box
Workplane.union
Workplane.combine
CQ.shell
CQ.fillet
CQ.split
CQ.rotateAboutCenter
CQ.translate
Iteration Methods
------------------
Methods that allow iteration over the stack or objects
.. autosummary::
Workplane.each
Workplane.eachpoint
.. _stackMethods:
Stack Methods
-----------------
CadQuery methods that operate on the stack
.. autosummary::
CQ.all
CQ.size
CQ.vals
CQ.add
CQ.val
CQ.first
CQ.item
CQ.last
CQ.end
CQ.vertices
CQ.faces
CQ.edges
CQ.wires
CQ.solids
CQ.shells
CQ.compounds
.. _selectors:
Selectors
------------------------
Objects that filter and select CAD objects
.. autosummary::
NearestToPointSelector
ParallelDirSelector
DirectionSelector
PerpendicularDirSelector
TypeSelector
DirectionMinMaxSelector
StringSyntaxSelector

243
doc/cadquerybasics.rst Normal file
View File

@ -0,0 +1,243 @@
.. _cadquerybasics:
.. automodule:: cadfile.cadutils.cadquery
*************************
Introduction to CadQuery
*************************
This page describes basic CadQuery concepts and goals. CadQuery is still under development, but already offers a lot.
======================
Goals and Principles
======================
Principle 1: Intuitive Construction
====================================
CadQuery aims to make building models using python scripting easy and intuitive.
CadQuery strives to allow scripts to read roughly as a human would describe an object verbally.
For example, consider this object:
.. image:: quickstart.png
A human would describe this as:
"A block 80mm square x 30mm thick , with countersunk holes for M2 socket head cap screws
at the corners, and a circular pocket 22mm in diameter in the middle for a bearing"
The goal is to have the CadQuery script that produces this object be as close as possible to the english phrase
a human would use.
Principle 2: Capture Design Intent
====================================
The features that are **not** part of the part description above are just as important as those that are. For example, most
humans will assume that:
* The countersunk holes are spaced a uniform distance from the edges
* The circular pocket is in the center of the block, no matter how big the block is
If you have experience with 3D CAD systems, you also know that there is a key design intent built into this object.
After the base block is created, how the hole is located is key. If it is located from one edge, changing the block
size will have a different affect than if the hole is located from the center.
Many scripting langauges to not provide a way to capture design intent-- because they require that you always work in
global coordinates. CadQuery is different-- you can locate features relative to others in a relative way-- preserving
the design intent just like a human would when creating a drawing or building an object.
In fact, though many people know how to use 3D CAD systems, few understand how important the way that an object is built
impact its maintainability and resiliency to design changes.
Principle 3: Plugins as first class citizens
============================================
Any system for building 3D models will evolve to contain an immense number of libraries and feature builders. It is
important that these can be seamlessly included into the core and used alongside the built in libraries. Plugins
should be easy to install and familiar to use.
Principle 4: CAD models as source code makes sense
==================================================================
It is surprising that the world of 3D CAD is primarily dominated by systems that create opaque binary files.
Just like the world of software, CAD models are very complex.
CAD models have many things in common with software, and would benefit greatly from the use of tools that are standard
in the software industry, such as:
1. Easily re-using features between objects
2. Storing objects using version control systems
3. Computing the differences between objects by using source control tools
4. Share objects on the internet
5. Automate testing and generation by allowing objects to be built from within libraries
CadQuery is designed to make 3D content creation easy enough that the above benefits can be attained without more work
than using existing 'opaque', 'point and click' solutions.
======================
3D Topology Primer
======================
Before talking about CadQuery, it makes sense to talk a little about 3D CAD Topology. CadQuery is based upon the
OpenCascade kernel, which is uses Boundary Representations ( BREP ) for objects. This just means that objects
are defined by their enclosing surfaces.
When working in a BREP system, these fundamental constructs exist to define a shape ( working up the food chain):
:vertex: a single point in space
:edge: a connection between two or more vertices along a particular path ( called a curve )
:wire: a collection of edges that are connected together.
:face: a set of edges or wires that enclose a surface
:shell: a collection of faces that are connected together along some of their edges
:solid: a shell that has a closed interior
:compound: a collection of solids
When using CadQuery, all of these objects are created, hopefully with the least possible work. In the actual CAD
kernel, there are another set of Geometrical constructs involved as well. For example, an arc-shaped edge will
hold a reference to an underlying curve that is a full cricle, and each linear edge holds underneath it the equation
for a line. CadQuery shields you from these constructs.
======================
CadQuery Concepts
======================
CadQuery provides functions several key areas. As you would expect, many are devoted to easy creation of
2D and 3D features. But just as many, if not more, are for navigating and selecting objects.
* CQ, the CadQuery object
* Workplanes
* Selection
* 2D Construction
* 3D Construction
* construction geometry
* easy iteration
CQ, the CadQuery Object
========================
The CadQuery object wraps a BREP feature, and provides functionality around it. Typical examples include rotating,
transforming, combining objects, and creating workplanes.
See :ref:`apireference` to learn more.
Workplanes
======================
Workplanes represent a plane in space, from which other features can be located. They have a center point and a local
coordinate system.
The most common way to create a workplane is to locate one on the face of a solid. You can also create new workplanes
in space, or relative to other planes using offsets or rotations.
The most powerful feature of workplanes is that they allow you to work in 2D space in the coordinate system of the
workplane, and then build 3D features based on local coordinates. This makes scripts much easier to create and maintain.
See :py:class:`Workplane` to learn more
2D Construction
======================
Once you create a workplane, you can work in 2D, and then later use the features you create to make 3D objects.
You'll find all of the 2D constructs you expect-- circles, lines, arcs, mirroring, points, etc.
See :ref:`2dOperations` to learn more.
3D Construction
======================
You can construct 3D primatives such as boxes, spheres, wedges, and cylinders directly. You can also sweep, extrude,
and loft 2D geometry to form 3D features. Of course the basic primitive operations are also available.
See :ref:`3doperations` to learn more.
Selectors
======================
Selectors allow you to select one or more features, for use to define new features. As an example, you might
extrude a box, and then select the top face as the location for a new feture. Or, you might extrude a box, and
then select all of the vertical edges so that you can apply a fillet to them.
You can select Vertices, Edges, Faces, Solids, and Wires using selectors.
Think of selectors as the equivalent of your hand and mouse, were you to build an object using a conventional CAD system.
You can learn more about selectors :ref:`selectors`
Construction Geometry
======================
Construction geometry are features that are not part of the object, but are only defined to aid in building the object.
A common example might be to define a rectangle, and then use the corners to define a the location of a set of holes.
Most CadQuery construction methods provide a forConstruction keyword, which creates a feature that will only be used
to locate other features
The Stack
======================
As you work in CadQuery, each operation returns a new CadQuery object with the result of that operations. Each CadQuery
object has a list of objects, and a reference to its parent.
You can always go backwards to older operations by removing the current object from the stack. For example::
CQ(someObject).faces(">Z").first().vertices()
returns a CadQuery object that contains all of the vertices on highest face of someObject. But you can always move
backwards in the stack to get the face as well::
CQ(someObject).faces(">Z").first().vertices().end() #returns the same as CQ(someObject).faces(">Z").first()
You can browse stack access methods here :ref:`stackMethods`
Chaining
======================
All CadQuery methods return another CadQuery object, so that you can chain the methods together fluently. Use
the core CQ methods to get at the objects that were created.
The Context Solid
======================
Most of the time, you are building a single object, and adding features to that single object. CadQuery watches
your operations, and defines the first solid object created as the 'context solid'. After that, any features
you create are automatically combined ( unless you specify otherwise) with that solid. This happens even if the
solid was created a long way up in the stack. For example::
Workplane('XY').box(1,2,3).faces(">Z").circle(0.25).extrude()
Will create a 1x2x3 box, with a cylindrical boss extending from the top face. It was not necessary to manually
combine the cylinder created by extruding the circle with the box, because the default behavior for extrude is
to combine the result with the context solid. The hole() method works similarly-- CadQuery presumes that you want
to subtract the hole from the context solid.
If you want to avoid this, you can specified combine=False, and CadQuery will create the solid separately.
Iteration
======================
CAD models often have repeated geometry, and its really annoying to resort to for loops to construct features.
Many CadQuery methods operate automatically on each element on the stack, so that you don't have to write loops.
For example, this::
Workplane('XY').box(1,2,3).faces(">Z").vertices().circle(0.5)
Will actually create 4 circles, because vertices() selects 4 vertices of a rectangular face, and the circle() method
iterates on each member of the stack.
This is really useful to remember when you author your own plugins. :py:meth:`Workplane.each` is useful for this purpose.

71
doc/classreference.rst Normal file
View File

@ -0,0 +1,71 @@
.. _classreference:
*************************
CadQuery Class Reference
*************************
This page documents all of the methods and functions of the CadQuery classes, organized alphabatically.
.. seealso::
For a listing organized by functional area, see the :ref:`apireference`
.. automodule:: cadfile.cadutils.cadquery
Core Classes
---------------------
.. autosummary::
CQ
Plane
Workplane
Selectors
---------------------
.. autosummary::
NearestToPointSelector
ParallelDirSelector
DirectionSelector
PerpendicularDirSelector
TypeSelector
DirectionMinMaxSelector
StringSyntaxSelector
Classes
------------------------
.. autoclass:: CQ
:members:
.. autoclass:: Plane
:members:
.. autoclass:: Workplane
:members:
:inherited-members:
.. autoclass:: Selector
:members:
.. autoclass:: NearestToPointSelector
:members:
.. autoclass:: ParallelDirSelector
:members:
.. autoclass:: DirectionSelector
:members:
.. autoclass:: PerpendicularDirSelector
:members:
.. autoclass:: TypeSelector
:members:
.. autoclass:: DirectionMinMaxSelector
:members:
.. autoclass:: StringSyntaxSelector
:members:

272
doc/conf.py Normal file
View File

@ -0,0 +1,272 @@
# -*- coding: utf-8 -*-
#
# CadQuery documentation build configuration file, created by
# sphinx-quickstart on Sat Aug 25 21:10:53 2012.
#
# This file is execfile()d with the current directory set to its containing dir.
#
# Note that not all possible configuration values are present in this
# autogenerated file.
#
# All configuration values have a default; values that are commented out
# serve to show the default.
import sys, os
import cadquery
settings._target = None
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
#sys.path.insert(0, os.path.abspath('.'))
# -- General configuration -----------------------------------------------------
# If your documentation needs a minimal Sphinx version, state it here.
#needs_sphinx = '1.0'
# Add any Sphinx extension module names here, as strings. They can be extensions
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
extensions = ['sphinx.ext.autodoc', 'sphinx.ext.viewcode', 'sphinx.ext.autosummary','cadfile.cadutils.cq_directive']
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
# The suffix of source filenames.
source_suffix = '.rst'
# The encoding of source files.
#source_encoding = 'utf-8-sig'
# The master toctree document.
master_doc = 'index'
# General information about the project.
project = u'CadQuery'
copyright = u'Parametric Products Intellectual Holdings LLC, All Rights Reserved'
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
# built documents.
#
# The short X.Y version.
version = '0.1'
# The full version, including alpha/beta/rc tags.
release = '0.1'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
#language = None
# There are two options for replacing |today|: either, you set today to some
# non-false value, then it is used:
#today = ''
# Else, today_fmt is used as the format for a strftime call.
#today_fmt = '%B %d, %Y'
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
exclude_patterns = ['_build']
# The reST default role (used for this markup: `text`) to use for all documents.
#default_role = None
# If true, '()' will be appended to :func: etc. cross-reference text.
#add_function_parentheses = True
# If true, the current module name will be prepended to all description
# unit titles (such as .. function::).
#add_module_names = True
# If true, sectionauthor and moduleauthor directives will be shown in the
# output. They are ignored by default.
#show_authors = False
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'sphinx'
# A list of ignored prefixes for module index sorting.
#modindex_common_prefix = []
# -- Options for HTML output ---------------------------------------------------
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
#html_theme = 'timlinux-linfiniti-sphinx'
html_theme = 'pparts'
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
# documentation.
#html_theme_options = {
# "headerfont": "'Open Sans',Arial,sans-serif",
# #"bodyfont:": "'Open Sans',Arial,sans-serif",
# #"headerbg" : "{image: url('/img/bg/body.jpg');color:#000000;}",
# "headerbg" : "color:black;",
# "footerbg" : "{color:#13171A;}",
# "linkcolor": "#84B51E;",
## "headercolor1": "#13171A;",
# "headercolor2": "#444;",
# "headerlinkcolor" : "#13171A;",
#}
#agogo options
"""
bodyfont (CSS font family): Font for normal text.
headerfont (CSS font family): Font for headings.
pagewidth (CSS length): Width of the page content, default 70em.
documentwidth (CSS length): Width of the document (without sidebar), default 50em.
sidebarwidth (CSS length): Width of the sidebar, default 20em.
bgcolor (CSS color): Background color.
headerbg (CSS value for background): background for the header area, default a grayish gradient.
footerbg (CSS value for background): background for the footer area, default a light gray gradient.
linkcolor (CSS color): Body link color.
headercolor1, headercolor2 (CSS color): colors for <h1> and <h2> headings.
headerlinkcolor (CSS color): Color for the backreference link in headings.
textalign (CSS text-align value): Text alignment for the body, default is justify.
"""
# Add any paths that contain custom themes here, relative to this directory.
#html_theme_path = []
# The name for this set of Sphinx documents. If None, it defaults to
# "<project> v<release> documentation".
html_title = "Documentation"
# A shorter title for the navigation bar. Default is the same as html_title.
#html_short_title = None
# The name of an image file (relative to this directory) to place at the top
# of the sidebar.
html_logo = "logo.png"
# The name of an image file (within the static path) to use as favicon of the
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
# pixels large.
#html_favicon = None
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static']
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
# using the given strftime format.
#html_last_updated_fmt = '%b %d, %Y'
# If true, SmartyPants will be used to convert quotes and dashes to
# typographically correct entities.
#html_use_smartypants = True
# Custom sidebar templates, maps document names to template names.
#html_sidebars = {}
# Additional templates that should be rendered to pages, maps page names to
# template names.
#html_additional_pages = {}
# If false, no module index is generated.
#html_domain_indices = True
# If false, no index is generated.
#html_use_index = True
# If true, the index is split into individual pages for each letter.
#html_split_index = False
# If true, links to the reST sources are added to the pages.
html_show_sourcelink = False
# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
html_show_sphinx = False
# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
#html_show_copyright = True
# If true, an OpenSearch description file will be output, and all pages will
# contain a <link> tag referring to it. The value of this option must be the
# base URL from which the finished HTML is served.
#html_use_opensearch = ''
# This is the file name suffix for HTML files (e.g. ".xhtml").
#html_file_suffix = None
# Output file base name for HTML help builder.
htmlhelp_basename = 'CadQuerydoc'
# -- Options for LaTeX output --------------------------------------------------
latex_elements = {
# The paper size ('letterpaper' or 'a4paper').
#'papersize': 'letterpaper',
# The font size ('10pt', '11pt' or '12pt').
#'pointsize': '10pt',
# Additional stuff for the LaTeX preamble.
#'preamble': '',
}
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title, author, documentclass [howto/manual]).
latex_documents = [
('index', 'CadQuery.tex', u'CadQuery Documentation',
u'David Cowden', 'manual'),
]
# The name of an image file (relative to this directory) to place at the top of
# the title page.
#latex_logo = None
# For "manual" documents, if this is true, then toplevel headings are parts,
# not chapters.
#latex_use_parts = False
# If true, show page references after internal links.
#latex_show_pagerefs = False
# If true, show URL addresses after external links.
#latex_show_urls = False
# Documents to append as an appendix to all manuals.
#latex_appendices = []
# If false, no module index is generated.
#latex_domain_indices = True
# -- Options for manual page output --------------------------------------------
# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
man_pages = [
('index', 'cadquery', u'CadQuery Documentation',
[u'David Cowden'], 1)
]
# If true, show URL addresses after external links.
#man_show_urls = False
# -- Options for Texinfo output ------------------------------------------------
# Grouping the document tree into Texinfo files. List of tuples
# (source start file, target name, title, author,
# dir menu entry, description, category)
texinfo_documents = [
('index', 'CadQuery', u'CadQuery Documentation',
u'David Cowden', 'CadQuery', 'One line description of project.',
'Miscellaneous'),
]
# Documents to append as an appendix to all manuals.
#texinfo_appendices = []
# If false, no module index is generated.
#texinfo_domain_indices = True
# How to display URL addresses: 'footnote', 'no', or 'inline'.
#texinfo_show_urls = 'footnote'

688
doc/examples.rst Normal file
View File

@ -0,0 +1,688 @@
.. _examples:
*********************************
CadQuery Examples
*********************************
.. automodule:: cadfile.cadutils.cadquery
.. automodule:: cadfile.cadutils.cad
The examples on this page can help you learn how to build objects with CadQuery.
They are organized from simple to complex, so working through them in order is the best way to absorb them.
Each example lists the api elements used in the example for easy reference.
Items introduced in the example are marked with a **!**
.. note::
You may want to work through these examples by pasting the text into a scratchpad on the live website.
If you do, make sure to take these steps so that they work:
1. paste the content into the build() method, properly intented, and
2. add the line 'return result' at the end. The samples below are autogenerated, but they use a different
syntax than the models on the website need to be.
.. warning::
* You have to have an svg capable browser to view these!
* For brevity, these examples do not include the MetaData and Header sections required for a
fully functional parametric part. See the :ref:`quickstart` for a guide that includes those portions
.. contents:: List of Examples
:backlinks: entry
Simple Rectangular Plate
------------------------
Just about the simplest possible example, a rectangular box
.. cq_plot::
result = Workplane("front").box(2.0,2.0,0.5)
.. topic:: Api References
.. hlist::
:columns: 2
* :py:meth:`Workplane` **!**
* :py:meth:`Workplane.box` **!**
Plate with Hole
------------------------
A rectangular box, but with a hole added.
"\>Z" selects the top most face of the resulting box. The hole is located in the center because the default origin
of a working plane is at the center of the face. The default hole depth is through the entire part.
.. cq_plot::
result = Workplane("front").box(2.0,2.0,0.5).faces(">Z").hole(0.5)
.. topic:: Api References
.. hlist::
:columns: 2
* :py:meth:`Workplane.hole` **!**
* :py:meth:`Workplane.box`
* :py:meth:`Workplane.box`
An extruded prismatic solid
-------------------------------
Build a prismatic solid using extrusion. After a drawing operation, the center of the previous object
is placed on the stack, and is the reference for the next operation. So in this case, the rect() is drawn
centered on the previously draw circle.
By default, rectangles and circles are centered around the previous working point.
.. cq_plot::
result = Workplane("front").circle(2.0).rect(0.5,0.75).extrude(0.5)
.. topic:: Api References
.. hlist::
:columns: 2
* :py:meth:`Workplane.circle` **!**
* :py:meth:`Workplane.rect` **!**
* :py:meth:`Workplane.extrude` **!**
* :py:meth:`Workplane`
Building Profiles using lines and arcs
--------------------------------------
Sometimes you need to build complex profiles using lines and arcs. This example builds a prismatic
solid from 2-d operations.
2-d operations maintain a current point, which is initially at the origin. Use close() to finish a
closed curve.
.. cq_plot::
result = Workplane("front").lineTo(2.0,0).lineTo(2.0,1.0).threePointArc((1.0,1.5),(0.0,1.0))\
.close().extrude(0.25)
.. topic:: Api References
.. hlist::
:columns: 2
* :py:meth:`Workplane.threePointArc` **!**
* :py:meth:`Workplane.lineTo` **!**
* :py:meth:`Workplane.extrude`
* :py:meth:`Workplane`
Moving The Current working point
---------------------------------
In this example, a closed profile is required, with some interior features as well.
This example also demonstrates using multiple lines of code instead of longer chained commands,
though of course in this case it was possible to do it in one long line as well.
A new work plane center can be established at any point.
.. cq_plot::
result = Workplane("front").circle(3.0) #current point is the center of the circle, at (0,0)
result = result.center(1.5,0.0).rect(0.5,0.5) # new work center is (1.5,0.0)
result = result.center(-1.5,1.5).circle(0.25) # new work center is ( 0.0,1.5).
#the new center is specified relative to the previous center, not global coordinates!
result = result.extrude(0.25)
.. topic:: Api References
.. hlist::
:columns: 2
* :py:meth:`Workplane.center` **!**
* :py:meth:`Workplane`
* :py:meth:`Workplane.circle`
* :py:meth:`Workplane.rect`
* :py:meth:`Workplane.extrude`
Using Point Lists
---------------------------
Sometimes you need to create a number of features at various locations, and using :py:meth:`Workplane.center`
is too cumbersome.
You can use a list of points to construct multiple objects at once. Most construction methods,
like :py:meth:`Workplane.circle` and :py:meth:`Workplane.rect`, will operate on multiple points if they are on the stack
.. cq_plot::
r = Workplane("front").circle(2.0) # make base
r = r.pushPoints( [ (1.5,0),(0,1.5),(-1.5,0),(0,-1.5) ] ) # now four points are on the stack
r = r.circle( 0.25 ) # circle will operate on all four points
result = r.extrude(0.125 ) # make prism
.. topic:: Api References
.. hlist::
:columns: 2
* :py:meth:`Workplane.points` **!**
* :py:meth:`Workplane`
* :py:meth:`Workplane.circle`
* :py:meth:`Workplane.extrude`
Polygons
-------------------------
You can create polygons for each stack point if you would like. Useful in 3d printers whos firmware does not
correct for small hole sizes.
.. cq_plot::
result = Workplane("front").box(3.0,4.0,0.25).pushPoints ( [ ( 0,0.75 ),(0,-0.75) ]) \
.polygon(6,1.0).cutThruAll()
.. topic:: Api References
.. hlist::
:columns: 2
* :py:meth:`Workplane.polygon` **!**
* :py:meth:`Workplane.pushPoints`
* :py:meth:`Workplane.box`
Polylines
-------------------------
:py:meth:`Workplane.polyline` allows creating a shape from a large number of chained points connected by lines.
This example uses a polyline to create one half of an i-beam shape, which is mirrored to create the final profile.
.. cq_plot::
(L,H,W,t) = ( 100.0,20.0,20.0,1.0)
pts = [
(0,H/2.0),
(W/2.0,H/2.0),
(W/2.0,(H/2.0 - t)),
(t/2.0,(H/2.0-t)),
(t/2.0,(t - H/2.0)),
(W/2.0,(t -H/2.0)),
(W/2.0,H/-2.0),
(0,H/-2.0)
]
result = Workplane("front").polyline(pts).mirrorY().extrude(L)
.. topic:: Api References
.. hlist::
:columns: 2
* :py:meth:`Workplane.polyline` **!**
* :py:meth:`Workplane`
* :py:meth:`Workplane.mirrorY`
* :py:meth:`Workplane.extrude`
Defining an Edge with a Spline
------------------------------
This example defines a side using a spline curve through a collection of points. Useful when you have an edge that
needs a complex profile
.. cq_plot::
s = Workplane("XY")
sPnts = [
(2.75,1.5),
(2.5,1.75),
(2.0,1.5),
(1.5,1.0),
(1.0,1.25),
(0.5,1.0),
(0,1.0)
]
r = s.lineTo(3.0,0).lineTo(3.0,1.0).spline(sPnts).close()
result = r.extrude(0.5)
.. topic:: Api References
.. hlist::
:columns: 2
* :py:meth:`Workplane.spline` **!**
* :py:meth:`Workplane`
* :py:meth:`Workplane.close`
* :py:meth:`Workplane.lineTo`
* :py:meth:`Workplane.extrude`
Mirroring Symmetric Geometry
-----------------------------
You can mirror 2-d geometry when your shape is symmetric. In this example we also
introduce horizontal and vertical lines, which make for slightly easier coding.
.. cq_plot::
r = Workplane("front").hLine(1.0) # 1.0 is the distance, not coordinate
r = r.vLine(0.5).hLine(-0.25).vLine(-0.25).hLineTo(0.0) # hLineTo allows using xCoordinate not distance
result =r.mirrorY().extrude(0.25 ) # mirror the geometry and extrude
.. topic:: Api References
.. hlist::
:columns: 2
* :py:meth:`Workplane.hLine` **!**
* :py:meth:`Workplane.vLine` **!**
* :py:meth:`Workplane.hLineTo` **!**
* :py:meth:`Workplane.mirrorY` **!**
* :py:meth:`Workplane.mirrorX` **!**
* :py:meth:`Workplane`
* :py:meth:`Workplane.extrude`
Creating Workplanes on Faces
-----------------------------
This example shows how to locate a new workplane on the face of a previously created feature.
.. note::
Using workplanes in this way are a key feature of CadQuery. Unlike typical 3d scripting language,
using work planes frees you from tracking the position of various features in variables, and
allows the model to adjust itself with removing redundant dimensions
The :py:meth:`Workplane.faces()` method allows you to select the faces of a resulting solid. It accepts
a selector string or object, that allows you to target a single face, and make a workplane oriented on that
face.
Keep in mind that the origin of new workplanes are located at the center of a face by default.
.. cq_plot::
result = Workplane("front").box(2,3,0.5) #make a basic prism
result = result.faces(">Z").workplane().hole(0.5) #find the top-most face and make a hole
.. topic:: Api References
.. hlist::
:columns: 2
* :py:meth:`Workplane.faces` **!**
* :py:meth:`StringSyntaxSelector` **!**
* :ref:`selector_reference` **!**
* :py:meth:`Workplane.workplane`
* :py:meth:`Workplane.box`
* :py:meth:`Workplane`
Locating a Workplane on a vertex
---------------------------------
Normally, the :py:meth:`Workplane.workplane` method requires a face to be selected. But if a vertex is selected
**immediately after a face**, :py:meth:`Workplane.workplane` will locate the workplane on the face, with the origin at the vertex instead
of at the center of the face
The example also introduces :py:meth:`Workplane.cutThruAll`, which makes a cut through the entire part, no matter
how deep the part is
.. cq_plot::
result = Workplane("front").box(3,2,0.5) #make a basic prism
result = result.faces(">Z").vertices("<XY").workplane() #select the lower left vertex and make a workplane
result = result.circle(1.0).cutThruAll() #cut the corner out
.. topic:: Api References
.. hlist::
:columns: 2
* :py:meth:`Workplane.cutThruAll` **!**
* :ref:`selector_reference` **!**
* :py:meth:`Workplane.vertices` **!**
* :py:meth:`Workplane.box`
* :py:meth:`Workplane`
* :py:meth:`StringSyntaxSelector` **!**
Offset Workplanes
--------------------------
Workplanes do not have to lie exactly on a face. When you make a workplane, you can define it at an offset
from an existing face.
This example uses an offset workplane to make a compound object, which is perfectly valid!
.. cq_plot::
result = Workplane("front").box(3,2,0.5) #make a basic prism
result = result.faces("<X").workplane(offset=0.75) #workplane is offset from the object surface
result = result.circle(1.0).extrude(0.5) #disc
.. topic:: Api References
.. hlist::
:columns: 2
* :py:meth:`Workplane.extrude`
* :ref:`selector_reference` **!**
* :py:meth:`Workplane.box`
* :py:meth:`Workplane`
Rotated Workplanes
--------------------------
You can create a rotated work plane by specifying angles of rotation relative to another workplane
.. cq_plot::
result = Workplane("front").box(4.0,4.0,0.25).faces(">Z").workplane() \
.transformed(offset=cad.Vector(0,-1.5,1.0),rotate=cad.Vector(60,0,0)) \
.rect(1.5,1.5,forConstruction=True).vertices().hole(0.25)
.. topic:: Api References
.. hlist::
:columns: 2
* :py:meth:`Workplane.transformed` **!**
* :py:meth:`Workplane.box`
* :py:meth:`Workplane.rect`
* :py:meth:`Workplane.faces`
Using construction Geometry
---------------------------
You can draw shapes to use the vertices as points to locate other features. Features that are used to
locate other features, rather than to create them, are called ``Construction Geometry``
In the example below, a rectangle is drawn, and its vertices are used to locate a set of holes.
.. cq_plot::
result = Workplane("front").box(2,2,0.5).faces(">Z").workplane() \
.rect(1.5,1.5,forConstruction=True).vertices().hole(0.125 )
.. topic:: Api References
.. hlist::
:columns: 2
* :py:meth:`Workplane.rect` (forConstruction=True)
* :ref:`selector_reference`
* :py:meth:`Workplane.workplane`
* :py:meth:`Workplane.box`
* :py:meth:`Workplane.hole`
* :py:meth:`Workplane`
Shelling To Create Thin features
--------------------------------
Shelling converts a solid object into a shell of uniform thickness. To shell an object, one or more faces
are removed, and then the inside of the solid is 'hollowed out' to make the shell.
.. cq_plot::
result = Workplane("front").box(2,2,2).faces("+Z").shell(0.05)
.. topic:: Api References
.. hlist::
:columns: 2
* :py:meth:`Workplane.shell` **!**
* :py:meth:`Workplane.box`
* :py:meth:`Workplane.faces`
* :py:meth:`Workplane`
Making Lofts
--------------------------------------------
A loft is a solid swept through a set of wires. This example creates lofted section between a rectangle
and a circular section.
.. cq_plot::
result = Workplane("front").box(4.0,4.0,0.25).faces(">Z").circle(1.5) \
.workplane(offset=3.0).rect(0.75,0.5).loft(combine=True)
.. topic:: Api References
.. hlist::
:columns: 2
* :py:meth:`Workplane.loft` **!**
* :py:meth:`Workplane.box`
* :py:meth:`Workplane.faces`
* :py:meth:`Workplane.circle`
* :py:meth:`Workplane.rect`
Making Counter-bored and counter-sunk holes
----------------------------------------------
Counterbored and countersunk holes are so common that CadQuery creates macros to create them in a single step.
Similar to :py:meth:`Workplane.hole` , these functions operate on a list of points as well as a single point.
.. cq_plot::
result = Workplane(Plane.XY()).box(4,2,0.5).faces(">Z").workplane().rect(3.5,1.5,forConstruction=True)\
.vertices().cboreHole(0.125, 0.25,0.125,depth=None)
.. topic:: Api References
.. hlist::
:columns: 2
* :py:meth:`Workplane.cboreHole` **!**
* :py:meth:`Workplane.cskHole` **!**
* :py:meth:`Workplane.box`
* :py:meth:`Workplane.rect`
* :py:meth:`Workplane.workplane`
* :py:meth:`Workplane.vertices`
* :py:meth:`Workplane.faces`
* :py:meth:`Workplane`
Rounding Corners with Fillet
-----------------------------
Filleting is done by selecting the edges of a solid, and using the fillet function.
Here we fillet all of the edges of a simple plate.
.. cq_plot::
result = Workplane("XY" ).box(3,3,0.5).edges("|Z").fillet(0.125)
.. topic:: Api References
.. hlist::
:columns: 2
* :py:meth:`Workplane.fillet` **!**
* :py:meth:`Workplane.box`
* :py:meth:`Workplane.edges`
* :py:meth:`Workplane`
Splitting an Object
---------------------
You can split an object using a workplane, and retain either or both halves
.. cq_plot::
c = Workplane("XY").box(1,1,1).faces(">Z").workplane().circle(0.25).cutThruAll()
#now cut it in half sideways
result = c.faces(">Y").workplane(-0.5).split(keepTop=True)
.. topic:: Api References
.. hlist::
:columns: 2
* :py:meth:`Workplane.split` **!**
* :py:meth:`Workplane.box`
* :py:meth:`Workplane.circle`
* :py:meth:`Workplane.cutThruAll`
* :py:meth:`Workplane.workplane`
* :py:meth:`Workplane`
The Classic OCC Bottle
----------------------
CadQuery is based on the OpenCascade.org (OCC) modeling Kernel. Those who are familiar with OCC know about the
famous 'bottle' example. http://www.opencascade.org/org/gettingstarted/appli/
A pythonOCC version is listed here
http://code.google.com/p/pythonocc/source/browse/trunk/src/examples/Tools/InteractiveViewer/scripts/Bottle.py?r=1046
Of course one difference between this sample and the OCC version is the length. This sample is one of the longer
ones at 13 lines, but that's very short compared to the pythonOCC version, which is 10x longer!
.. cq_plot::
(L,w,t) = (20.0,6.0,3.0)
s = Workplane("XY")
#draw half the profile of the bottle and extrude it
p = s.center(-L/2.0,0).vLine(w/2.0) \
.threePointArc((L/2.0, w/2.0 + t),(L,w/2.0)).vLine(-w/2.0) \
.mirrorX().extrude(30.0,True)
#make the neck
p.faces(">Z").workplane().circle(3.0).extrude(2.0,True)
#make a shell
result = p.faces(">Z").shell(0.3)
.. topic:: Api References
.. hlist::
:columns: 2
* :py:meth:`Workplane.extrude`
* :py:meth:`Workplane.mirrorX`
* :py:meth:`Workplane.threePointArc`
* :py:meth:`Workplane.workplane`
* :py:meth:`Workplane.vertices`
* :py:meth:`Workplane.vLine`
* :py:meth:`Workplane.faces`
* :py:meth:`Workplane`
A Parametric Enclosure
-----------------------
.. cq_plot::
:height: 400
#parameter definitions
p_outerWidth = 100.0 #Outer width of box enclosure
p_outerLength = 150.0 #Outer length of box enclosure
p_outerHeight = 50.0 #Outer height of box enclosure
p_thickness = 3.0 #Thickness of the box walls
p_sideRadius = 10.0 #Radius for the curves around the sides of the bo
p_topAndBottomRadius = 2.0 #Radius for the curves on the top and bottom edges of the box
p_screwpostInset = 12.0 #How far in from the edges the screwposts should be place.
p_screwpostID = 4.0 #nner Diameter of the screwpost holes, should be roughly screw diameter not including threads
p_screwpostOD = 10.0 #Outer Diameter of the screwposts.\nDetermines overall thickness of the posts
p_boreDiameter = 8.0 #Diameter of the counterbore hole, if any
p_boreDepth = 1.0 #Depth of the counterbore hole, if
p_countersinkDiameter = 0.0 #Outer diameter of countersink. Should roughly match the outer diameter of the screw head
p_countersinkAngle = 90.0 #Countersink angle (complete angle between opposite sides, not from center to one side)
p_flipLid = True #Whether to place the lid with the top facing down or not.
p_lipHeight = 1.0 #Height of lip on the underside of the lid.\nSits inside the box body for a snug fit.
#outer shell
oshell = Workplane("XY").rect(p_outerWidth,p_outerLength).extrude(p_outerHeight + p_lipHeight)
#weird geometry happens if we make the fillets in the wrong order
if p_sideRadius > p_topAndBottomRadius:
oshell.edges("|Z").fillet(p_sideRadius)
oshell.edges("#Z").fillet(p_topAndBottomRadius)
else:
oshell.edges("#Z").fillet(p_topAndBottomRadius)
oshell.edges("|Z").fillet(p_sideRadius)
#inner shell
ishell = oshell.faces("<Z").workplane(p_thickness,True)\
.rect((p_outerWidth - 2.0* p_thickness),(p_outerLength - 2.0*p_thickness))\
.extrude((p_outerHeight - 2.0*p_thickness),False) #set combine false to produce just the new boss
ishell.edges("|Z").fillet(p_sideRadius - p_thickness)
#make the box outer box
box = oshell.cut(ishell)
#make the screwposts
POSTWIDTH = (p_outerWidth - 2.0*p_screwpostInset)
POSTLENGTH = (p_outerLength -2.0*p_screwpostInset)
postCenters = box.faces(">Z").workplane(-p_thickness)\
.rect(POSTWIDTH,POSTLENGTH,forConstruction=True)\
.vertices()
for v in postCenters.all():
v.circle(p_screwpostOD/2.0).circle(p_screwpostID/2.0)\
.extrude((-1.0)*(p_outerHeight + p_lipHeight -p_thickness ),True)
#split lid into top and bottom parts
(lid,bottom) = box.faces(">Z").workplane(-p_thickness -p_lipHeight ).split(keepTop=True,keepBottom=True).all() #splits into two solids
#translate the lid, and subtract the bottom from it to produce the lid inset
lowerLid = lid.translate((0,0,-p_lipHeight))
cutlip = lowerLid.cut(bottom).translate((p_outerWidth + p_thickness ,0,p_thickness - p_outerHeight + p_lipHeight))
#compute centers for counterbore/countersink or counterbore
topOfLidCenters = cutlip.faces(">Z").workplane().rect(POSTWIDTH,POSTLENGTH,forConstruction=True).vertices()
#add holes of the desired type
if p_boreDiameter > 0 and p_boreDepth > 0:
topOfLid = topOfLidCenters.cboreHole(p_screwpostID,p_boreDiameter,p_boreDepth,(2.0)*p_thickness)
elif p_countersinkDiameter > 0 and p_countersinkAngle > 0:
topOfLid = topOfLidCenters.cskHole(p_screwpostID,p_countersinkDiameter,p_countersinkAngle,(2.0)*p_thickness)
else:
topOfLid= topOfLidCenters.hole(p_screwpostID,(2.0)*p_thickness)
#flip lid upside down if desired
if p_flipLid:
topOfLid.rotateAboutCenter((1,0,0),180)
#return the combined result
result =topOfLid.combineSolids(bottom)
.. topic:: Api References
.. hlist::
:columns: 3
* :py:meth:`Workplane.circle`
* :py:meth:`Workplane.rect`
* :py:meth:`Workplane.extrude`
* :py:meth:`Workplane.box`
* :py:meth:`CQ.all`
* :py:meth:`CQ.faces`
* :py:meth:`CQ.vertices`
* :py:meth:`CQ.edges`
* :py:meth:`CQ.workplane`
* :py:meth:`Workplane.fillet`
* :py:meth:`Workplane.cut`
* :py:meth:`Workplane.combineSolids`
* :py:meth:`Workplane.rotateAboutCenter`
* :py:meth:`Workplane.cboreHole`
* :py:meth:`Workplane.cskHole`
* :py:meth:`Workplane.hole`

178
doc/extending.rst Normal file
View File

@ -0,0 +1,178 @@
.. _extending:
******************
Extending CadQuery
******************
.. automodule:: cadfile.cadutils.cadquery
If you find that CadQuery doesnt suit your needs, you can easily extend it. CadQuery provides several extension
methods:
* You can load plugins others have developed. This is by far the easiest way to access other code
* you can define your own plugins.
* you can use FreeCAD script directly
Loading external Plugins
-----------------------
You can load a plugin using the tools.loadScript(*URL*) directive in your script.
Using FreeCAD Script
--------------------
The easiest way to extend CadQuery is to simply use FreeCAD script inside of your build method. Just about
any valid FreeCAD script will execute just fine. For example, this simple CadQuery script::
return Workplane("XY").box(1.0,2.0,3.0).val()
is actually equivalent to::
return Part.makeBox(1.0,2.0,3.0)
As long as you return a valid FreeCAD Shape, you can use any FreeCAD methods you like. You can even mix and match the
two. For example, consider this script, which creates a FreeCAD box, but then uses cadquery to select its faces::
box = Part.makeBox(1.0,2.0,3.0)
cq = CQ(box).faces(">Z").size() # returns 6
Extending CadQuery: Plugins
----------------------------
Though you can get a lot done with FreeCAD, the code gets pretty nasty in a hurry. CadQuery shields you from
a lot of the complexity of the FreeCAD api.
You can get the best of both worlds by wrapping your freecad script into a CadQuery plugin.
A CadQuery plugin is simply a function that is attached to the CadQuery :py:meth:`CQ` or :py:meth:`Workplane` class.
When connected, your plugin can be used in the chain just like the built-in functions.
There are a few key concepts important to understand when building a plugin
The Stack
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Every CadQuery object has a local stack, which contains a list of items. The items on the stack will be
one of these types:
* **A CadQuery SolidReference object**, which holds a reference to a FreeCAD solid
* **A FreeCAD object**, a Vertex, Edge, Wire, Face, Shell, Solid, or Compound
The stack is available by using self.objects, and will always contain at least one object.
.. note::
Objects and points on the stack are **always** in global coordinates. Similarly, any objects you
create must be created in terms of global coordinates as well!
Preserving the Chain
^^^^^^^^^^^^^^^^^^^^^^^^^
CadQuery's fluent api relies on the ability to chain calls together one after another. For this to work,
you must return a valid CadQuery object as a return value. If you choose not to return a CadQuery object,
then your plugin will end the chain. Sometimes this is desired for example :py:meth:`CQ.size`
There are two ways you can safely continue the chain:
1. **return self** If you simply wish to modify the stack contents, you can simply return a reference to
self. This approach is destructive, because the contents of the stack are modified, but it is also the
simplest.
2. :py:meth:`CQ.newObject` Most of the time, you will want to return a new object. Using newObject will
return a new CQ or Workplane object having the stack you specify, and will link this object to the
previous one. This preserves the original object and its stack.
Helper Methods
^^^^^^^^^^^^^^^^^^^^^^^^^
When you implement a CadQuery plugin, you are extending CadQuery's base objects. As a result, you can call any
CadQuery or Workplane methods from inside of your extension. You can also call a number of internal methods that
are designed to aid in plugin creation:
* :py:meth:`Workplane._pointsOnStack` returns a FreeCAD Vector ( a point ) for each item on the stack. Useful if you
are writing a plugin that you'd like to operate on all values on the stack, like :py:meth:`Workplane.circle` and
most other built-ins do
* :py:meth:`Workplane._makeWireAtPoints` will invoke a factory function you supply for all points on the stack,
and return a properly constructed cadquery object. This function takes care of registering wires for you
and everything like that
* :py:meth:`Workplane.newObject` returns a new Workplane object with the provided stack, and with its parent set
to the current object. The preferred way to continue the chain
* :py:meth:`Workplane.findSolid` returns the first Solid found in the chain, working from the current object upwards
in the chain. commonly used when your plugin will modify an existing solid, or needs to create objects and
then combine them onto the 'main' part that is in progress
* :py:meth:`Workplane._addWire` must be called if you add a wire. This allows the base class to track all the wires
that are created, so that they can be managed when extrusion occurs.
* :py:meth:`Workplane.wire` gathers up all of the edges that have been drawn ( eg, by line, vline, etc ), and
attempts to combine them into a single wire, which is returned. This should be used when your plugin creates
2-d edges, and you know it is time to collect them into a single wire.
* :py:meth:`Workplane.plane` provides a reference to the workplane, which allows you to convert between workplane
coordinates and global coordinates:
* :py:meth:`Plane.toWorldCoords` will convert local coordinates to global ones
* :py:meth:`Plane.toLocalCoords` will convet from global coordinates to local coordinates
Coordinate Systems
^^^^^^^^^^^^^^^^^^^^^^
Keep in mind that the user may be using a work plane that has created a local coordinate system. Consequently,
the orientation of shapes that you create are often implicitly defined by the user's workplane.
Any objects that you create must be fully defined in *global coordinates*, even though some or all of the users'
inputs may be defined in terms of local coordinates.
Linking in your plugin
^^^^^^^^^^^^^^^^^^^^^^^
Your plugin is a single method, which is attached to the main Workplane or CadQuery object.
Your plugin method's first parameter should be 'self', which will provide a reference to base class functionality.
You can also accept other arguments.
To install it, simply attach it to the CadQuery or Workplane object, like this::
def _yourFunction(self,arg1,arg):
do stuff
return whatever_you_want
Workplane.yourPlugin = _yourFunction
That's it!
Plugin Example
^^^^^^^^^^^^^^^
This ultra simple plugin makes cubes of the specified size for each stack point.
(The cubes are off-center because the boxes have their lower left corner at the reference points.)
.. cq_plot::
def makeCubes(self,length):
#self refers to the CQ or Workplane object
#inner method that creates a cube
def _singleCube(pnt):
#pnt is a location in local coordinates
#since we're using eachpoint with useLocalCoordinates=True
return Solid.makeBox(length,length,length,pnt)
#use CQ utility method to iterate over the stack, call our
#method, and convert to/from local coordinates.
return self.eachpoint(_singleCube,True)
#link the plugin into cadQuery
Workplane.makeCubes = makeCubes
#use the plugin
result = Workplane("XY").box(6.0,8.0,0.5).faces(">Z").rect(4.0,4.0,forConstruction=True).vertices() \
.makeCubes(1.0).combineSolids()

202
doc/fileformat.rst Normal file
View File

@ -0,0 +1,202 @@
.. _cadquery_reference:
********************************
ModelScript Format Reference
********************************
ParametricParts ModelScripts define a parametric 3D model that can be executed and customized by an end user.
CadQuery scripts are pure python scripts that follow a standard format. Each script contains these main components:
:MetaData:
*(Mandatory)* Defines the attributes that describe the model, such as version and unit of measure
:Parameters:
*(Optional)* Defines parameters and their default values, which can be
manipulated by users to customize the object. Parameters are defined by creating local variables
of a particular class type. Presets and groups organize parameters to make them easier to use
:build script:
*(Mandatory)* Constructs the model once parameter values are collected and the model is validated.
The script must return a solid object, or a cadquery solid
The Script Life-cycle
----------------------
CadQuery scripts have the following lifecycle when they are executed by a user via the web interface:
1. **Load Script** If it is valid, the parameters and MetaData
are loaded. A number of special objects are automatically available to your script
2. **Display Model to User** The parameters and default values are displayed to the user.
The model is rendered and displayed to the user using the default values
3. **User selects new parameter values** , either by selecting
preset combinations, or by providing values for each parameter
4. **Build the model** If validation is successful, the model is re-built, and the preview window is updated
5. **User downloads** If the user chooses to download the model as STL, STEP, or AMF, the model is re-built
again for download.
A Full Example Script
----------------------
This script demonstrates all of the model elements available. Each is briefly introduced in the sample text,
and then described in more detail after the sample::
"""
Comments and Copyright Statement
"""
#
# metadata describes your model
#
UOM = "mm"
VERSION = 1.0
#
# parameter definitions. Valid parameter types are FloatParam,IntParam,and BooleanParam
# each paraemter can have min and max values, a description, and a set of named preset values
#
p_diam = FloatParam(min=1.0,max=500.0,presets={'default':40.0,'small':2.0,'big':200.0},group="Basics", desc="Diameter");
#
# build the model based on user selected parameter values.
# Must return a FreeCAD solid before exiting.
#
def build():
return Part.makeSphere(p_diam.value);
Each section of the script is described in more detail below
Metadata
----------------
Model metadata is provided by setting a dictionary variable called METADATA in the script. You can provide
any metadata you choose, but only these values are currently used:
:UOM:
The unit of measure of your model. in and mm are common values, but others are allowed.
Some model formats like AMF can accept units of measure, which streamlines the printing process. **[OPTIONAL]**
:VERSION:
The script format version. Valid versions are established by ParametricParts, currently only version 1.0 is
valid. If omitted, the latest version is assumed. **[OPTIONAL]**
Other metadata fields may be added in the future.
Parameters
----------------
Model parameters provide the flexibility users need to customize your model. Parameters are optional, but most
users will expect at least a couple of parameters for your model to qualify as 'parametric'.
Parameters can be named whatever you would like. By convention, it is common to name them *p_<name>*, indicating
"parameter".
Each parameter has a particular type ( Float, Integer, Boolean ). Parameters also have optional attributes, which are
provided as keyword arguments:
:desc:
A description of the parameter, displayed to the user if help is needed [Optional]
:min:
The minimum value ( not applicable to Boolean ) [Optional]
:max:
The maximum value ( not applicable to Boolean ) [Optional]
:presets:
A dictionary containing key-value pairs. Each key is the name of a preset, and the value is the value the
parameter will take when the preset is selected by the user.
When a model defines presets, the user is presented with a choice of available presets in a drop-down-list.
Selecting a preset changes the values of all parameters to their associated values.
If it exists, the special preset named 'default' will be used to populate the default values when the user
is initially presented with the model.
When the model is built, the parameters are checked to ensure they meet the constraints. If they do not,
an error occurs.
:group:
If provided, parameters will be grouped together when displayed to the user. Any ungrouped parameters
will display in a special group named `default`. Groups help divide a long list of parameters to make
them easier to understand. Examples might include 'basics' and 'advanced'
Build Method
-----------------------
The heart of your model is the build method. Your build method must be called 'build'::
def build():
return Workplane("XY").box(1,1,1)
Your build method use any combination of FreeCAD, python, and CadQuery to construct objects.
You must return one of two things:
1. A CadQuery object, or
2. A FreeCAD object
In your build script,you retrieve the values of the parameters by using ``<parameter_name>.value``.
The following modules are available when your script runs:
Scripts Using CadQuery Syntax
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
:python syntax:
Python loops, dictionaries, lists, and other standard language structures are available.
:math:
Python's math package is imported for you to use
:FloatParam,IntegerParam,BooleanParam:
Parameter types used to declare parameters
:Workplane:
The CadQuery workplane object, which is the typical starting point for most scripts
:CQ:
The CadQuery object, in case you need to decorate a normal FreeCAD object
:Plane:
The CadQuery Plane object, in case you need to create non-standard planes
.. warning::
Though your script is a standard python script, it does **not** run in a standard python environment.
For security reasons, most python packages, like sys, os, import, and urllib are restricted.
FreeCAD Build Scripts
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
It is recommended that you use CadQuery for your model scripts-- the syntax is much shorter and more convienient.
But if you are willing to write more code, you can get access to all of the features that the FreeCAD library provides.
When your script executes, these FreeCAD objects are in scope as well:
:Part:
FreeCAD.Part
:Vector:
FreeCAD.Base.Vector
:Base:
FreeCAD.Base
**If you use a FreeCAD build script, your build method must return a FreeCAD shape object.**
Should you choose to write your model with the lower-level FreeCAD scripts, you may find this documentation useful:
http://sourceforge.net/apps/mediawiki/free-cad/index.php?title=FreeCAD_API

43
doc/index.rst Normal file
View File

@ -0,0 +1,43 @@
.. CadQuery documentation master file, created by
sphinx-quickstart on Sat Aug 25 21:10:53 2012.
You can adapt this file completely to your liking, but it should at least
contain the root `toctree` directive.
Parametric Parts Documentation Home
===================================
Parametric Parts is a technology platform that offers:
* **For Users**: Customize, download, and print models easily using only a web browser. Every model is parametric.
* **For Designers**: Create models with an easy to use, fluent API called CadQuery. ( See :ref:`examples` )
* **For Developers**: :ref:`buildservice` allows other technology platforms to build models while controlling the user
experience
Contents
==================
.. toctree::
:maxdepth: 2
intro.rst
quickstart.rst
fileformat.rst
cadquerybasics.rst
examples.rst
apireference.rst
primitiveref.rst
selectors.rst
classreference.rst
restservice.rst
roadmap.rst
Indices and tables
==================
* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`

70
doc/intro.rst Normal file
View File

@ -0,0 +1,70 @@
.. _what_is_cadquery:
*********************
Introduction
*********************
What is a ParametricParts Model Script?
========================================
A Model Script is a python script that builds a 3d model in response to user inputs.
Model Scripts are written in python. They can use two different APIs:
1. FreeCAD Scripts, or
2. a new, fluent-api called CadQuery.
CadQuery is an intuitive, easy-to-use language for building parametric 3D CAD models. It has several goals:
* Build models with scripts that are as close as possible to how you'd describe the object to a human.
* Create parametric models that can be very easily customized by end users
* Output high quality CAD formats like STEP and AMF in addition to traditional STL
* Provide a non-proprietary, plain text model format that can be edited and executed with only a web browser
CadQuery is a Python module that provides a high-level wrapper around the
(`FreeCAD <http://sourceforge.net/apps/mediawiki/free-cad/index.php?title=Main_Page>`_) python libraries.
Where does the name CadQuery come from?
===============================
CadQuery is inspired by ( `jQuery <http://www.jquery.com>`_ ), a popular framework that
revolutionized web development involving javascript.
CadQuery is for 3D CAD what jQuery is for javascript.
If you are familiar with how jQuery, you will probably recognize several jQuery features that CadQuery uses:
* A fluent api to create clean, easy to read code
* Ability to use the library along side other python libraries
* Clear and complete documentation, with plenty of samples.
Why ParametricParts instead of OpenSCAD?
==================================
CadQuery is based on FreeCAD,which is in turn based on the OpenCascade modelling kernel. CadQuery/FreeCAD scripts
share many features with OpenSCAD, another open source, script based, parametric model generator.
The primary advantage of OpenSCAD is the large number of already existing model libaries that exist already. So why not simply use OpenSCAD?
CadQuery scripts run from ParametricParts.com have several key advantages over OpenSCAD ( including the various web-based SCAD solutions):
1. **The scripts use a standard programming language**, python, and thus can benefit from the associated infrastructure.
This includes many standard libraries and IDEs
2. **More powerful CAD kernel** OpenCascade is much more powerful than CGAL. Features supported natively
by OCC include NURBS, splines, surface sewing, STL repair, STEP import/export, and other complex operations,
in addition to the standard CSG operations supported by CGAL
3. **Ability to import/export STEP** We think the ability to begin with a STEP model, created in a CAD package,
and then add parametric features is key. This is possible in OpenSCAD using STL, but STL is a lossy format
4. **Less Code and easier scripting** CadQuery scripts require less code to create most objects, because it is possible to locate
features based on the position of other features, workplanes, vertices, etc.
5. **Better Performance** CadQuery scripts can build STL, STEP, and AMF faster than OpenSCAD.

190
doc/make.bat Normal file
View File

@ -0,0 +1,190 @@
@ECHO OFF
REM Command file for Sphinx documentation
if "%SPHINXBUILD%" == "" (
set SPHINXBUILD=sphinx-build
)
set BUILDDIR=_build
set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% .
set I18NSPHINXOPTS=%SPHINXOPTS% .
if NOT "%PAPER%" == "" (
set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS%
set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS%
)
if "%1" == "" goto help
if "%1" == "help" (
:help
echo.Please use `make ^<target^>` where ^<target^> is one of
echo. html to make standalone HTML files
echo. dirhtml to make HTML files named index.html in directories
echo. singlehtml to make a single large HTML file
echo. pickle to make pickle files
echo. json to make JSON files
echo. htmlhelp to make HTML files and a HTML help project
echo. qthelp to make HTML files and a qthelp project
echo. devhelp to make HTML files and a Devhelp project
echo. epub to make an epub
echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter
echo. text to make text files
echo. man to make manual pages
echo. texinfo to make Texinfo files
echo. gettext to make PO message catalogs
echo. changes to make an overview over all changed/added/deprecated items
echo. linkcheck to check all external links for integrity
echo. doctest to run all doctests embedded in the documentation if enabled
goto end
)
if "%1" == "clean" (
for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i
del /q /s %BUILDDIR%\*
goto end
)
if "%1" == "html" (
%SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The HTML pages are in %BUILDDIR%/html.
goto end
)
if "%1" == "dirhtml" (
%SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml.
goto end
)
if "%1" == "singlehtml" (
%SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml.
goto end
)
if "%1" == "pickle" (
%SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle
if errorlevel 1 exit /b 1
echo.
echo.Build finished; now you can process the pickle files.
goto end
)
if "%1" == "json" (
%SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json
if errorlevel 1 exit /b 1
echo.
echo.Build finished; now you can process the JSON files.
goto end
)
if "%1" == "htmlhelp" (
%SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp
if errorlevel 1 exit /b 1
echo.
echo.Build finished; now you can run HTML Help Workshop with the ^
.hhp project file in %BUILDDIR%/htmlhelp.
goto end
)
if "%1" == "qthelp" (
%SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp
if errorlevel 1 exit /b 1
echo.
echo.Build finished; now you can run "qcollectiongenerator" with the ^
.qhcp project file in %BUILDDIR%/qthelp, like this:
echo.^> qcollectiongenerator %BUILDDIR%\qthelp\CadQuery.qhcp
echo.To view the help file:
echo.^> assistant -collectionFile %BUILDDIR%\qthelp\CadQuery.ghc
goto end
)
if "%1" == "devhelp" (
%SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp
if errorlevel 1 exit /b 1
echo.
echo.Build finished.
goto end
)
if "%1" == "epub" (
%SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The epub file is in %BUILDDIR%/epub.
goto end
)
if "%1" == "latex" (
%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
if errorlevel 1 exit /b 1
echo.
echo.Build finished; the LaTeX files are in %BUILDDIR%/latex.
goto end
)
if "%1" == "text" (
%SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The text files are in %BUILDDIR%/text.
goto end
)
if "%1" == "man" (
%SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The manual pages are in %BUILDDIR%/man.
goto end
)
if "%1" == "texinfo" (
%SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo.
goto end
)
if "%1" == "gettext" (
%SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The message catalogs are in %BUILDDIR%/locale.
goto end
)
if "%1" == "changes" (
%SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes
if errorlevel 1 exit /b 1
echo.
echo.The overview file is in %BUILDDIR%/changes.
goto end
)
if "%1" == "linkcheck" (
%SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck
if errorlevel 1 exit /b 1
echo.
echo.Link check complete; look for any errors in the above output ^
or in %BUILDDIR%/linkcheck/output.txt.
goto end
)
if "%1" == "doctest" (
%SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest
if errorlevel 1 exit /b 1
echo.
echo.Testing of doctests in the sources finished, look at the ^
results in %BUILDDIR%/doctest/output.txt.
goto end
)
:end

9
doc/primer.rst Normal file
View File

@ -0,0 +1,9 @@
.. _3d_cad_primer:
***********************
3D CAD Primer
***********************
This section provides a basic introduction to 3D modeling. It will get you started with the basics. After that,
you may want to do some heavier reading on the subject (PUT LINKS HERE )

57
doc/primitiveref.rst Normal file
View File

@ -0,0 +1,57 @@
.. _primreference:
***********************
Primitive Class Reference
***********************
.. automodule:: cadfile.cadutils.cad
.. autosummary::
Plane
Vector
Solid
Shell
Wire
Edge
Vertex
Geometry Classes
------------------
.. autoclass:: Vector
:members:
.. autoclass:: Plane
:members:
Shape Base Class
-------------------
All objects inherit from Shape, which as basic manipulation methods:
.. autoclass:: Shape
:members:
Primitive Classes
--------------------
.. autoclass:: Solid
:members:
.. autoclass:: Shell
:members:
.. autoclass:: Wire
:members:
.. autoclass:: Edge
:members:
.. autoclass:: Vertex
:members:

305
doc/quickstart.rst Normal file
View File

@ -0,0 +1,305 @@
.. module:: cadfile.cadutils.cadquery
.. _quickstart:
***********************
ModelScript QuickStart
***********************
Want a quick glimpse of Parametric Parts ModelScripts? You're at the right place!
This quickstart will demonstrate the basics of ModelScripts using a simple example
Prerequisites
=============
**WebGL Capable Browser**
CadQuery renders models in your browser using WebGL-- which is supported by most browsers *except for IE*
You can follow along without IE, but you will not be able to see the model dynamically rendered
What we'll accomplish
=====================
Our finished object will look like this:
.. image:: quickstart.png
**We would like our block to have these features:**
1. It should be sized to hold a single 608 ( 'skate' ) bearing, in the center of the block.
2. It should have counter sunk holes for M2 socket head cap screws at the corners
3. The length and width of the block should be configurable by the user to any reasonable size.
A human would describe this as:
"A rectangular block 80mm x 60mm x 30mm , with countersunk holes for M2 socket head cap screws
at the corners, and a circular pocket 22mm in diameter in the middle for a bearing"
Human descriptions are very elegant, right?
Hopefully our finished script will not be too much more complex than this human-oriented description.
Let's see how we do.
Start a new Model
==================================
CadQuery comes with an online, interactive default model as a starting point. Lets open up that tool
`here <http://www.parametricparts.com/parts/create>`_
You should see the dynamic model creator page, which will display a sample model:
.. image:: quickstart-1.png
Take a minute to play with this model. Here are a few things to try:
1. Use the mouse to rotate the block
2. Play with the view controls under the image
3. change the length ( the only available parameter),
and use the preview button to re-display the updated model
4. Change the preset value to `short`
5. Edit the model script itself. Change the hard-coded width and thickness values and click 'update script'
to re-display the model.
At this point, you should have some idea how to interact with the sample model, so lets get to work on the project.
Modify MetaData and Parameters
==============================
Each model has metadata that describes the model's properties. The default Unit of Measure (UOM) will work:
.. code-block:: python
:linenos:
:emphasize-lines: 1
UOM = "mm"
Next, lets set up the parameters. Parameters are `placeholders` that users can modify separately from the script itself.
The default model has a single parameter, ``length``. Lets add a ``height`` parameter too
.. code-block:: python
:linenos:
:emphasize-lines: 4
UOM = "mm"
length = FloatParam(min=30.0,max=200.0,presets={'default':80.0,'short':30.0},desc="Length of the block")
height = FloatParam(min=30.0,max=200.0,presets={'default':60.0,'short':30.0},desc="Height of the block")
thickness = 10.0
def build():
return Workplane("XY").box(length.value,height.value,thickness)
We've set the minimum values to 30 mm, since that's about as small as it could be while having room for a bearing 22mm
in diameter. We've also set the default values to be those we'd like to start with: 80mm for the length and 60mm for the
height.
Now, modify the build script to use your width value to make the block by changing ``height`` to
``height.value``
.. code-block:: python
:linenos:
:emphasize-lines: 3
...
def build():
return Workplane("XY").box(length.value,height.value,thickness)
The value property always returns the ``user-adjusted`` value of the parameter. That's good enough for now.
Click "Save Changes" and you should see your 80x60x10mm base plate, like this:
.. image:: quickstart-2.png
If you'd like to come back to this model later, the url bar links to the newly created part.
Now lets move on and make this boring plate into a pillow block.
Add the Holes
================
Our pillow block needs to have a 22mm diameter hole in the center of this block to hold the bearing.
This modification will do the trick:
.. code-block:: python
:linenos:
:emphasize-lines: 3
...
def build():
return Workplane("XY").box(length.value,height.value,thickness).faces(">Z").workplane().hole(22.0)
Rebuild your model by clicking "Save Model" at the bottom. Your block should look like this:
.. image:: quickstart-3.png
The code is pretty compact, and works like this:
* :py:meth:`Workplane.faces` selects the top-most face in the Z direction, and
* :py:meth:`Workplane.workplane` begins a new workplane located on this face
* :py:meth:`Workplane.hole` drills a hole through the part 22mm in diamter
.. note::
Don't worry about the CadQuery syntax now.. you can learn all about it in the :ref:`apireference` later.
More Holes
============
Ok, that hole was not too hard, but what about the counter-bored holes in the corners?
An M2 Socket head cap screw has these dimensions:
* **Head Diameter** : 3.8 mm
* **Head height** : 2.0 mm
* **Clearance Hole** : 2.4 mm
* **CounterBore diameter** : 4.4 mm
The centers of these holes should be 4mm from the edges of the block. And,
we want the block to work correctly even when the block is re-sized by the user.
**Don't tell me** we'll have to repeat the steps above 8 times to get counter-bored holes?
Good news!-- we can get the job done with just two lines of code. Here's the code we need:
.. code-block:: python
:linenos:
:emphasize-lines: 4-5
...
def build():
return Workplane("XY").box(length.value,height.value,thickness).faces(">Z").workplane().hole(22.0) \
.faces(">Z").workplane() \
.rect(length.value-8.0,height.value-8.0,forConstruction=True) \
.vertices().cboreHole(2.4,4.4,2.1)
You should see something like this:
.. image:: quickstart-4.png
Lets Break that down a bit
^^^^^^^^^^^^^^^^^^^^^^^^^^
**Line 4** selects the top-most face of the block, and creates a workplane on the top that face, which we'll use to
define the centers of the holes in the corners:
.. code-block:: python
:linenos:
:emphasize-lines: 4
...
def build():
return Workplane("XY").box(length.value,height.value,thickness).faces(">Z").workplane().hole(22.0) \
.faces(">Z").workplane() \
.rect(length.value-8.0,width.value-8.0,forConstruction=True) \
.vertices().cboreHole(2.4,4.4,2.1)
**Line 5** draws a rectangle 8mm smaller than the overall length and width of the block,which we will use to
locate the corner holes:
.. code-block:: python
:linenos:
:emphasize-lines: 5
...
def build():
return Workplane("XY").box(length.value,height.value,thickness).faces(">Z").workplane().hole(22.0) \
.faces(">Z").workplane() \
.rect(length.value-8.0,width.value-8.0,forConstruction=True) \
.vertices().cboreHole(2.4,4.4,2.1)
There are a couple of things to note about this line:
1. The :py:meth:`Workplane.rect` function draws a rectangle. **forConstruction=True**
tells CadQuery that this rectangle will not form a part of the solid,
but we are just using it to help define some other geometry.
2. The center point of a workplane on a face is always at the center of the face, which works well here
3. Unless you specifiy otherwise, a rectangle is drawn with its center on the current workplane center-- in
this case, the center of the top face of the block. So this rectangle will be centered on the face
**Line 6** selects the corners of the rectangle, and makes the holes:
.. code-block:: python
:linenos:
:emphasize-lines: 6
...
def build():
return Workplane("XY").box(length.value,height.value,thickness).faces(">Z").workplane().hole(22.0) \
.faces(">Z").workplane() \
.rect(length.value-8.0,width.value-8.0,forConstruction=True) \
.vertices().cboreHole(2.4,4.4,2.1)
Notes about this line:
1. The :py:meth:`CQ.vertices` function selects the corners of the rectangle
2. The :py:meth:`Workplane.cboreHole` function is a handy CadQuery function that makes a counterbored hole
3. ``cboreHole``, like most other CadQuery functions, operate on the values on the stack. In this case, since
selected the four vertices before calling the function, the function operates on each of the four points--
which results in a counterbore hole at the corners.
Presets
===========
Almost done. This model is pretty easy to configure, but we can make it even easier by providing users with a few
'out of the box' options to choose from. Lets provide two preset options:
* **Small** : 30 mm x 40mm
* **Square-Medium** : 50 mm x 50mm
We can do that using the preset dictionaries in the parameter definition:
.. code-block:: python
:linenos:
:emphasize-lines: 2-3
...
length = FloatParam(min=10.0,max=500.0,presets={'default':100.0,'small':30.0,'square-medium':50},desc="Length of the box")
height = FloatParam(min=30.0,max=200.0,presets={'default':60.0,'small':40.0,'square-medium':50},desc="Height of the block")
Now save the model and have a look at the preset DDLB-- you'll see that you can easily switch between these
configurations:
.. image:: quickstart-5.png
Done!
============
And... We're done! Congratulations, you just made a parametric, 3d model with 15 lines of code.Users can use this
model to generate pillow blocks in any size they would like
For completeness, Here's a copy of the finished model:
.. code-block:: python
:linenos:
UOM = "mm"
length = FloatParam(min=10.0,max=500.0,presets={'default':100.0,'small':30.0,'square-medium':50},desc="Length of the box")
height = FloatParam(min=30.0,max=200.0,presets={'default':60.0,'small':40.0,'square-medium':50},desc="Height of the block")
width = 40.0
thickness = 10.0
def build():
return Workplane("XY").box(length.value,height.value,thickness).faces(">Z").workplane().hole(22.0) \
.faces(">Z").workplane() \
.rect(length.value-8.0,height.value-8.0,forConstruction=True) \
.vertices().cboreHole(2.4,4.4,2.1)
Want to learn more?
====================
* The :ref:`examples` contains lots of examples demonstrating cadquery features
* The :ref:`cadquery_reference` describes the file format in detail
* The :ref:`apireference` is a good overview of language features grouped by function
* The :ref:`classreference` is the hard-core listing of all functions available.

114
doc/restservice.rst Normal file
View File

@ -0,0 +1,114 @@
.. _buildservice:
******************************************
The Parametric Parts Build Service
******************************************
If you have registered for an account, you can use the REST api to build models from your website or platform.
Each request to the service will construct a model in the format you choose.
Using the Build Service
-------------------------
The Build Service endpoint is `<https://parametricparts.com/parts/build>`_
In each request, you provide four main things via either a GET or a POST :
1. **An API Key**, to identify yourself.
2. **A ModelScript to build**, either by providing the entire script, or the id of a model stored on
parametricparts.com,
3. **The type of output** you want,
4. **The Model parameters** that should be supplied to the model.
.. note::
GET or POSTs are allowed, but be aware that URLs for GET requests are limited to 4K,
so POSTs are advised if you are sending your modelScript via the URL
The output streamed in the format you have requested.
Errors are provided using standard HTTP error codes:
:200: if the build is a success
:403: if the APIKey is invalid, or if your account cannot execute any more downloads
:404: if the requested model cannot be found
:50X: if there is a problem generating the model
Build Service Parameters
--------------------------
All parameters must be URL encoded:
:key:
(Required) Your API Key. See :ref:`gettingakey` If you do not have one.
:id:
(Either id or s is Required) The id of the ParametricParts.com ModelScript to build. The id is the last part of the url
when viewing the model: http://parametricparts.com/parts/<modelId>. Model ids are between 7 and 9
characters, for example '4hskpb69'.
:s:
(Either id or s is Required) The ModelScript to build. This should be a valid parametricparts.com ModelScript.
If both id and s are provided, s takes precedence.
:type:
(Required) ("STL" | "STEP" | "AMF" | "TJS" ). The type of output you want to receive. STL, STEP,
and AMF return the corresponding industry standard format.
TJS will return JSON content suitable for display in a Three.js scene.
:preset:
(Optional) The name of a preset defined in the ModelScript. If omitted, other parameters are used.
If a preset is provided in addition to parameters, then the preset is applied first, and then
parameters are set afterwards.
:<params>:
(Optional) Remaining URL parameters are mapped onto ModelScript parameters of the same name. Each
parameter value must have the datatype corresponding to the parameter in the ModelScript. To supply multiple
parameters, send an HTTP parameter for each desired value, having name matching the name of the ModelScript
parameter, and value having the value for that parameter. If no
parameters are provided, output is generated using ModelScript defaults.
Example
--------------------------
This example builds STEP for a trivial model, without supplying any model parameters or presets::
POST https://parametricparts.com/parts/build HTTP/1.1
key:259cd575c9a2998420ac65f21b2d6b2a
s:def+build%28%29%3A%0D%0A++++return+Part.makeBox%281%2C2%2C3%29%0D%0A++++++++
type:AMF
This example selects an existing model (2qus7a32 ) on the server, and requests
preset 'short', as well as adjusting parameter 'p_length' to value 120::
POST https://parametricparts.com/parts/build HTTP/1.1
key:259cd575c9a2998420ac65f21b2d6b2a
id:2qus7a32
type:STL
preset:short
p_length:120
.. _gettingakey:
Signing Up
-----------------------
In order to use the API, you first need to have an API key. To get one:
1. `Sign Up <https://parametricparts.com/account/signup>`_ for a ParametricParts account
2. `Contact ParametricParts Support <http://support.parametricparts.com/customer/portal/emails/new>`_ to request API key access.
API keys usually require an enterprise license, but are available for free evaluation if you request access
3. Log onto your ParametricParts account, and generate an API Key using the `API Keys <https://localhost:8080/key/keys>`_ link.
4. Test your api key using the api key tester `Here <https://parametricparts.com/apitester>`_
If the test goes well, you'll see STL output from the sample script.
Now you are ready to make REST requests to build models.
.. warning::
Make sure to keep your API Key secret, as any requests that use your key will be charged to your account.
You can disable or generate a new API Key from your account page.

172
doc/roadmap.rst Normal file
View File

@ -0,0 +1,172 @@
.. _roadmap:
**************************
RoadMap: Planned Features
**************************
**CadQuery is not even close to finished!!!**
Many features are planned for later versions. This page tracks them. If you find that you need features
not listed here, let us know!
Core
--------------------
end(n)
allows moving backwards a fixed number of parents in the chain, eg end(3) is same as end().end().end()
FreeCAD object wrappers
return CQ wrappers for FreeCAD shapes instead of the native FreeCAD objects.
Improved iteration tools for plugin developers
make it easier to iterate over points and wires for plugins
More parameter types (String? )
face.outerWire
allow selecting the outerWire of a face, so that it can be used for reference geometry or offsets
Selectors
--------------------
Chained Selectors
Space delimited selectors should be unioned to allow multiple selections. For example ">Z >X"
Ad-hoc axes
for example, >(1,2,1) would select a face with normal in the 1,2,1 direction
logic inversion
! or not to invert logic, such as "!(>Z)" to select faces _other_ than the most z facing
closest to point
support faces, points, or edges closest to a provided point
tagged entities
support tagging entities when they are created, so they can be selected later on using that tag.
ideally, tags are propagated to features that are created from these features ( ie, an edge tagged with 'foo'
that is later extruded into a face means that face would be tagged with 'foo' as well )
Workplanes
--------------------
rotated workplanes
support creation of workplanes at an angle to another plane or face
workplane local rotations
rotate the coordinate system of a workplane by an angle.
make a workplane from a wire
useful to select outer wire and then operate from there, to allow offsets
2-d operations
-------------------
offsets
offset profiles, including circles, rects, and other profiles.
ellipses
create elipses and portions of elipses
regular polygons
several construction methods:
* number of sides and side length
* number of sides inscribed in circle
* number of sides circumscribed by circle
arc construction using relative measures
instead of forcing use of absolute workplane coordinates
tangent arcs
after a line
centerpoint arcs
including portions of arcs as well as with end points specified
trimming
ability to use construction geometry to trim other entities
construction lines
especially centerlines
2-d fillets
for a rectangle, or for consecutive selected lines
2-d chamfers
based on rectangles, polygons, polylines, or adjacent selected lines
mirror around centerline
using centerline construction geometry
rectangular array
automate creation of equally spread points
polar array
create equally spaced copies of a feature around a circle
perhaps based on a construction circle?
midpoint selection
select midpoints of lines, arcs
face center
explicit selection of face center
manipulate spline control points
so that the shape of a spline can be more accurately controlled
feature snap
project geometry in the rest of the part into the work plane, so that
they can be selected and used as references for other features.
polyline edges
allow polyline to be combined with other edges/curves
create text
ideally, in various fonts.
3-d operations
---------------------
rotation/transform that return a copy
The current rotateAboutCenter and translate method modify the object, rather than returning a copy
primitive creation
Need primitive creation for:
* cone
* sphere
* cylinder
* torus
* wedge
extrude/cut up to surface
allow a cut or extrude to terminate at another surface ,rather than either through all or a fixed distance
extrude along a path
rather than just normal to the plane. This would include
loft
create a feature between two or more wire sections
revolve
revolve a wire around an axis to create a solid
STEP import
allow embedding and importing step solids created in other tools, which
can then be further manipulated parametrically
Dome
very difficult to do otherwise
primitive boolean operations
* intersect
* union
* subtract
Algorithms
---------------------
Wire Discretization
Sample wires at point interval to improve closet wire computations

103
doc/selectors.rst Normal file
View File

@ -0,0 +1,103 @@
.. _selector_reference:
*************************
CadQuery String Selectors
*************************
.. automodule:: cadfile.cadutils.cadquery
CadQuery selector strings allow filtering various types of object lists. Most commonly, Edges, Faces, and Vertices are
used, but all objects types can be filtered.
String selectors are used as arguments to the various selection methods:
* :py:meth:`CQ.faces`
* :py:meth:`CQ.edges`
* :py:meth:`CQ.vertices`
* :py:meth:`CQ.solids`
* :py:meth:`CQ.shells`
.. note::
String selectors are shortcuts to concrete selector classes, which you can use or extend. See
:ref:`classreference` for more details
If you find that the built-in selectors are not sufficient, you can easily plug in your own.
See :ref:`extending` to see how.
.. _filteringfaces:
Filtering Faces
----------------
All types of filters work on faces. In most cases, the selector refers to the direction of the **normal vector**
of the face.
.. warning::
If a face is not planar, selectors are evaluated at the center of mass of the face. This can lead
to results that are quite unexpected.
The axis used in the listing below are for illustration: any axis would work similarly in each case.
========= ==================================== ====================================== ==========================
Selector Selector Class Selects # objects returned
========= ==================================== ====================================== ==========================
+Z :py:class:`DirectionSelector` Faces with normal in +z direction 0 or 1
\|Z :py:class:`ParallelDirSelector` Faces parallel to xy plane 0..many
-X :py:class:`DirectionSelector` Faces with normal in neg x direction 0..many
#Z :py:class:`PerpendicularDirSelector` Faces perpendicular to z direction 0..many
%Plane :py:class:`TypeSelector` Faces of type plane 0..many
>Y :py:class:`DirectionMinMaxSelector` Face farthest in the positive y dir 0 or 1
<Y :py:class:`DirectionMinMaxSelector` Face farthest in the negative y dir 0 or 1
========= ==================================== ====================================== ==========================
.. _filteringedges:
Filtering Edges
----------------
Some filter types are not supported for edges. The selector usually refers to the **direction** of the edge.
.. warning::
Non-linear edges are not selected for any selectors except type (%). Non-linear edges are never returned
when these filters are applied.
The axis used in the listing below are for illustration: any axis would work similarly in each case.
========= ==================================== ===================================== ==========================
Selector Selector Class Selects # objects returned
========= ==================================== ===================================== ==========================
+Z :py:class:`DirectionSelector` Edges aligned in the Z direction 0..many
\|Z :py:class:`ParallelDirSelector` Edges parallel to z direction 0..many
-X :py:class:`DirectionSelector` Edges aligned in neg x direction 0..many
#Z :py:class:`PerpendicularDirSelector` Edges perpendicular to z direction 0..many
%Line :py:class:`TypeSelector` Edges type line 0..many
>Y :py:class:`DirectionMinMaxSelector` Edges farthest in the positive y dir 0 or 1
<Y :py:class:`DirectionMinMaxSelector` Edges farthest in the negative y dir 0 or 1
========= ==================================== ===================================== ==========================
.. _filteringvertices:
Filtering Vertices
-------------------
Only a few of the filter types apply to vertices. The location of the vertex is the subject of the filter
========= ==================================== ===================================== ==========================
Selector Selector Class Selects # objects returned
========= ==================================== ===================================== ==========================
>Y :py:class:`DirectionMinMaxSelector` Edges farthest in the positive y dir 0 or 1
<Y :py:class:`DirectionMinMaxSelector` Edges farthest in the negative y dir 0 or 1
========= ==================================== ===================================== ==========================
Future Enhancements
--------------------
* Support direct vectors inline, such as \|(x,y,z)
* Support multiple selectors separated by spaces, which unions the results, such as "+Z +Y to select both z and y-most faces

43
doc/themes/pparts/layout.html vendored Normal file
View File

@ -0,0 +1,43 @@
{% extends "basic/layout.html" %}
{%- block extrahead %}
<link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Neuton&amp;subset=latin" type="text/css" media="screen" charset="utf-8" />
<link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Nobile:regular,italic,bold,bolditalic&amp;subset=latin" type="text/css" media="screen" charset="utf-8" />
<link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Open+Sans:400,800">
<!--[if lte IE 6]>
<link rel="stylesheet" href="{{ pathto('_static/ie6.css', 1) }}" type="text/css" media="screen" charset="utf-8" />
<script type="text/javascript">
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-37657197-1']);
_gaq.push(['_setDomainName', 'none']);
_gaq.push(['_setAllowLinker', 'true']);
_gaq.push(['_trackPageview']);
(function() {
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})();
</script>
<![endif]-->
{% endblock %}
{% block header %}
{%- if logo %}
<div class="header">
<a href="{{ pathto(master_doc) }}">
<div class="logo">
<img class="logo" src="{{ pathto('_static/' + logo, 1) }}" alt="Logo"/>
</div>
</a>
</div>
{%- endif %}
{% endblock %}
{%- block sidebarlogo %}{%- endblock %}
{%- block sidebarsourcelink %}{%- endblock %}

BIN
doc/themes/pparts/static/body.jpg vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 126 KiB

BIN
doc/themes/pparts/static/dialog-note.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

310
doc/themes/pparts/static/epub.css vendored Normal file
View File

@ -0,0 +1,310 @@
/*
* default.css_t
* ~~~~~~~~~~~~~
*
* Sphinx stylesheet -- default theme.
*
* :copyright: Copyright 2007-2010 by the Sphinx team, see AUTHORS.
* :license: BSD, see LICENSE for details.
*
*/
@import url("basic.css");
/* -- page layout ----------------------------------------------------------- */
body {
font-family: {{ theme_bodyfont }};
font-size: 100%;
background-color: {{ theme_footerbgcolor }};
color: #000;
margin: 0;
padding: 0;
}
div.document {
background-color: {{ theme_sidebarbgcolor }};
}
div.documentwrapper {
float: left;
width: 100%;
}
div.bodywrapper {
margin: 0 0 0 230px;
}
div.body {
background-color: {{ theme_bgcolor }};
color: {{ theme_textcolor }};
padding: 0 20px 30px 20px;
}
{%- if theme_rightsidebar|tobool %}
div.bodywrapper {
margin: 0 230px 0 0;
}
{%- endif %}
div.footer {
color: {{ theme_footertextcolor }};
width: 100%;
padding: 9px 0 9px 0;
text-align: center;
font-size: 75%;
}
div.footer a {
color: {{ theme_footertextcolor }};
text-decoration: underline;
}
div.related {
background-color: {{ theme_relbarbgcolor }};
line-height: 30px;
color: {{ theme_relbartextcolor }};
}
div.related a {
color: {{ theme_relbarlinkcolor }};
}
div.sphinxsidebar {
{%- if theme_stickysidebar|tobool %}
top: 30px;
bottom: 0;
margin: 0;
position: fixed;
overflow: auto;
height: auto;
{%- endif %}
{%- if theme_rightsidebar|tobool %}
float: right;
{%- if theme_stickysidebar|tobool %}
right: 0;
{%- endif %}
{%- endif %}
}
{%- if theme_stickysidebar|tobool %}
/* this is nice, but it it leads to hidden headings when jumping
to an anchor */
/*
div.related {
position: fixed;
}
div.documentwrapper {
margin-top: 30px;
}
*/
{%- endif %}
div.sphinxsidebar h3 {
font-family: {{ theme_headfont }};
color: {{ theme_sidebartextcolor }};
font-size: 1.4em;
font-weight: normal;
margin: 0;
padding: 0;
}
div.sphinxsidebar h3 a {
color: {{ theme_sidebartextcolor }};
}
div.sphinxsidebar h4 {
font-family: {{ theme_headfont }};
color: {{ theme_sidebartextcolor }};
font-size: 1.3em;
font-weight: normal;
margin: 5px 0 0 0;
padding: 0;
}
div.sphinxsidebar p {
color: {{ theme_sidebartextcolor }};
}
div.sphinxsidebar p.topless {
margin: 5px 10px 10px 10px;
}
div.sphinxsidebar ul {
margin: 10px;
padding: 0;
color: {{ theme_sidebartextcolor }};
}
div.sphinxsidebar a {
color: {{ theme_sidebarlinkcolor }};
}
div.sphinxsidebar input {
border: 1px solid {{ theme_sidebarlinkcolor }};
font-family: sans-serif;
font-size: 1em;
}
{% if theme_collapsiblesidebar|tobool %}
/* for collapsible sidebar */
div#sidebarbutton {
background-color: {{ theme_sidebarbtncolor }};
}
{% endif %}
/* -- hyperlink styles ------------------------------------------------------ */
a {
color: {{ theme_linkcolor }};
text-decoration: none;
}
a:visited {
color: {{ theme_visitedlinkcolor }};
text-decoration: none;
}
a:hover {
text-decoration: underline;
}
{% if theme_externalrefs|tobool %}
a.external {
text-decoration: none;
border-bottom: 1px dashed {{ theme_linkcolor }};
}
a.external:hover {
text-decoration: none;
border-bottom: none;
}
a.external:visited {
text-decoration: none;
border-bottom: 1px dashed {{ theme_visitedlinkcolor }};
}
{% endif %}
/* -- body styles ----------------------------------------------------------- */
div.body h1,
div.body h2,
div.body h3,
div.body h4,
div.body h5,
div.body h6 {
font-family: {{ theme_headfont }};
background-color: {{ theme_headbgcolor }};
font-weight: normal;
color: {{ theme_headtextcolor }};
border-bottom: 1px solid #ccc;
margin: 20px -20px 10px -20px;
padding: 3px 0 3px 10px;
}
div.body h1 { margin-top: 0; font-size: 200%; }
div.body h2 { font-size: 160%; }
div.body h3 { font-size: 140%; }
div.body h4 { font-size: 120%; }
div.body h5 { font-size: 110%; }
div.body h6 { font-size: 100%; }
a.headerlink {
color: {{ theme_headlinkcolor }};
font-size: 0.8em;
padding: 0 4px 0 4px;
text-decoration: none;
}
a.headerlink:hover {
background-color: {{ theme_headlinkcolor }};
color: white;
}
div.body p, div.body dd, div.body li {
text-align: justify;
line-height: 130%;
}
div.admonition p.admonition-title + p {
display: inline;
}
div.admonition p {
margin-bottom: 5px;
}
div.admonition pre {
margin-bottom: 5px;
}
div.admonition ul, div.admonition ol {
margin-bottom: 5px;
}
div.note {
background-color: #eee;
border: 1px solid #ccc;
}
div.seealso {
background-color: #ffc;
border: 1px solid #ff6;
}
div.topic {
background-color: #eee;
}
div.warning {
background-color: #ffe4e4;
border: 1px solid #f66;
}
p.admonition-title {
display: inline;
}
p.admonition-title:after {
content: ":";
}
pre {
padding: 5px;
background-color: {{ theme_codebgcolor }};
color: {{ theme_codetextcolor }};
line-height: 120%;
border: 1px solid #ac9;
border-left: none;
border-right: none;
}
tt {
background-color: #ecf0f3;
padding: 0 1px 0 1px;
font-size: 0.95em;
}
th {
background-color: #ede;
}
.warning tt {
background: #efc2c2;
}
.note tt {
background: #d6d6d6;
}
.viewcode-back {
font-family: {{ theme_bodyfont }};
}
div.viewcode-block:target {
background-color: #f4debf;
border-top: 1px solid #ac9;
border-bottom: 1px solid #ac9;
}

BIN
doc/themes/pparts/static/footerbg.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 333 B

BIN
doc/themes/pparts/static/headerbg.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 203 B

7
doc/themes/pparts/static/ie6.css vendored Normal file
View File

@ -0,0 +1,7 @@
* html img,
* html .png{position:relative;behavior:expression((this.runtimeStyle.behavior="none")&&(this.pngSet?this.pngSet=true:(this.nodeName == "IMG" && this.src.toLowerCase().indexOf('.png')>-1?(this.runtimeStyle.backgroundImage = "none",
this.runtimeStyle.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='" + this.src + "',sizingMethod='image')",
this.src = "_static/transparent.gif"):(this.origBg = this.origBg? this.origBg :this.currentStyle.backgroundImage.toString().replace('url("','').replace('")',''),
this.runtimeStyle.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='" + this.origBg + "',sizingMethod='crop')",
this.runtimeStyle.backgroundImage = "none")),this.pngSet=true)
);}

BIN
doc/themes/pparts/static/logo.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.7 KiB

BIN
doc/themes/pparts/static/middlebg.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

387
doc/themes/pparts/static/pparts.css_t vendored Normal file
View File

@ -0,0 +1,387 @@
/*
* pylons.css_t
* ~~~~~~~~~~~~
*
* Sphinx stylesheet -- pylons theme.
*
* :copyright: Copyright 2007-2010 by the Sphinx team, see AUTHORS.
* :license: BSD, see LICENSE for details.
*
*/
@import url("basic.css");
/* -- page layout ----------------------------------------------------------- */
html {background-image:url(../img/bg/html.png);}
body {color:#333;background-position:50% -400px;background-repeat:repeat-x;}
#home {background-position:50% 0;}
body, input, textarea, button {font:13px/20px Arial,sans-serif;}
/* Color for the links */
a {color:#84B51E; text-decoration:none;}
* {margin:0;}
p, ul, ol, table, form, pre {margin-bottom:20px;}
img {border:none;max-width:100%;}
ul {list-style:none;}
:focus {outline:0;}
.clear {clear:both;}
article, aside, details, figcaption, figure, footer, header, hgroup, menu, nav, section {display:block;}
.wrapper:after, #login:after {content:".";display:block;height:0;clear:both;visibility:hidden;}
/* Overall background color and image */
html, #login {background-color:#f5f5f5;}
body {background-image:url('../img/bg/body.jpg');}
/* Background and border color for drop-down navigation */
nav ul ul {background-color:#13171A;border-color:#84B51E;}
/* Footer background color */
footer, footer h3 span {background-color:#13171A;}
/* Primary navigation color */
nav>ul>li>a {color:#ddd;}
/* Header colors */
h1, h1 a {color:#13171A;}
h2, h2 a, h3, h4, .pricing thead th {color:#444;}
/* Color for the links */
p a, .wrapper ul li a {color:#84B51E;}
body {
font-family: 'Open Sans',Arial,sans-serif;
font-size: 100%;
background-color: #333;
color: #ffffff;
margin: 0;
padding: 0;
}
div.documentwrapper {
float: left;
width: 100%;
}
div.bodywrapper {
margin: 0 0 0 {{ theme_sidebarwidth }}px;
}
hr {
border: 1px solid #B1B4B6;
}
div.document {
background-color: #f5f5f5;
}
div.header {
width:100%;
height:142px;
background: #eaad32 url(body.jpg) bottom;
position:relative;
}
div.header ul > li > a{
text-decoration:none;
line-height:30px;
font-size:15px;
padding: 0 12p 0 13px;
}
div.header ul {
background:none;
}
div.logo {
text-align: left;
padding: 15px 40px;
}
div.body {
background-color: #ffffff;
color: #3E4349;
padding: 0 30px 30px 30px;
font-size: 1em;
border-left: 1px solid #333;
border-right-style: none;
overflow: auto;
}
div.footer {
color: #ffffff;
background-color:#13171A;
width: 100%;
padding: 13px 0;
text-align: center;
font-size: 75%;
background: transparent;
clear:both;
}
div.footer a {
color: #ffffff;
text-decoration: none;
}
div.footer a:hover {
color: #e88f00;
text-decoration: underline;
}
div.related {
position:absolute;
top: 52px;
width:100%;
margin:0;
list-style:none;
line-height: 30px;
color: #373839;
font-size: 15px;
background-color: transparent;
}
div.related a {
color: #1b61d6;
}
div.related h3{
display:none;
}
div.related ul {
padding-left: 450px;
}
div.related li{
display:none;
}
div.related li.right{
display:inline;
}
div.related ul > li a{
font-size: 30px;
text-decoration: none;
line-height:30px;
color: #ddd;
font-weight:bold;
display:none;
}
div.related ul > li.right a{
font-size: 15px;
font-weight:normal;
display:inline;
}
div.sphinxsidebar {
font-size: 14px;
line-height: 1.5em;
}
div.sphinxsidebarwrapper{
padding: 10px 0;
}
div.sphinxsidebar h3,
div.sphinxsidebar h4 {
color: #373839;
font-size: 15px;
font-weight: bold;
color: #444;
margin: 0;
padding: 5px 10px;
}
div.sphinxsidebar h3{
font-size: 1.3em;
}
div.sphinxsidebar h3 a {
color: #444;
}
div.sphinxsidebar p {
color: #888;
padding: 5px 20px;
}
div.sphinxsidebar p.topless {
}
div.sphinxsidebar ul {
margin: 10px 20px;
padding: 0;
color: #373839;
}
div.sphinxsidebar input {
border: 1px solid #ccc;
font-family: sans-serif;
font-size: 1em;
}
div.sphinxsidebar input[type=text]{
margin-left: 20px;
}
/* -- sidebars -------------------------------------------------------------- */
div.sidebar {
margin: 0 0 0.5em 1em;
border: 2px solid #c6d880;
background-color: #e6efc2;
width: 40%;
float: right;
border-right-style: none;
border-left-style: none;
padding: 10px 20px;
}
p.sidebar-title {
font-weight: bold;
}
/* -- body styles ----------------------------------------------------------- */
div.body h1,
div.body h2,
div.body h3,
div.body h4,
div.body h5,
div.body h6 {
font-family: 'Open Sans',Arial,sans-serif;
background-color: #ffffff;
font-weight: normal;
color: #444;
margin: 30px 0px 10px 0px;
padding: 5px 0;
}
div.body h1 { border-top: 20px solid white; margin-top: 0; font-size: 200%; }
div.body h2 { font-size: 150%; background-color: #ffffff; }
div.body h3 { font-size: 120%; background-color: #ffffff; }
div.body h4 { font-size: 110%; background-color: #ffffff; }
div.body h5 { font-size: 100%; background-color: #ffffff; }
div.body h6 { font-size: 100%; background-color: #ffffff; }
a.headerlink {
color: #1b61d6;
font-size: 0.8em;
padding: 0 4px 0 4px;
text-decoration: none;
}
a.headerlink:hover {
text-decoration: underline;
}
div.body p, div.body dd, div.body li {
line-height: 1.5em;
}
div.admonition p.admonition-title + p {
display: inline;
}
div.highlight{
background-color: white;
}
div.note {
border: 2px solid #7a9eec;
border-right-style: none;
border-left-style: none;
padding: 10px 20px 10px 60px;
background: #e1ecfe url(dialog-note.png) no-repeat 10px 8px;
}
div.seealso {
background: #fff6bf url(dialog-seealso.png) no-repeat 10px 8px;
border: 2px solid #ffd324;
border-left-style: none;
border-right-style: none;
padding: 10px 20px 10px 60px;
}
div.topic {
background: #eeeeee;
border: 2px solid #C6C9CB;
padding: 10px 20px;
border-right-style: none;
border-left-style: none;
}
div.warning {
background: #fbe3e4 url(dialog-warning.png) no-repeat 10px 8px;
border: 2px solid #fbc2c4;
border-right-style: none;
border-left-style: none;
padding: 10px 20px 10px 60px;
}
p.admonition-title {
display: none;
}
p.admonition-title:after {
content: ":";
}
pre {
padding: 10px;
background-color: #fafafa;
color: #222;
line-height: 1.2em;
border: 2px solid #C6C9CB;
font-size: 1.1em;
margin: 1.5em 0 1.5em 0;
border-right-style: none;
border-left-style: none;
}
tt {
background-color: transparent;
color: #222;
font-size: 1.1em;
font-family: monospace;
}
.viewcode-back {
font-family: "Nobile", sans-serif;
}
div.viewcode-block:target {
background-color: #fff6bf;
border: 2px solid #ffd324;
border-left-style: none;
border-right-style: none;
padding: 10px 20px;
}
table.highlighttable {
width: 100%;
}
table.highlighttable td {
padding: 0;
}
a em.std-term {
color: #007f00;
}
a:hover em.std-term {
text-decoration: underline;
}
.download {
font-family: "Nobile", sans-serif;
font-weight: normal;
font-style: normal;
}
tt.xref {
font-weight: normal;
font-style: normal;
}

BIN
doc/themes/pparts/static/transparent.gif vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 B

4
doc/themes/pparts/theme.conf vendored Normal file
View File

@ -0,0 +1,4 @@
[theme]
inherit = basic
stylesheet = pparts.css
pygments_style = friendly