renamed folders to standard ones
|
@ -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):
|
||||
"""
|
||||
|
|
|
@ -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
|
@ -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
After Width: | Height: | Size: 58 KiB |
BIN
doc/_static/PillowBlock.PNG
vendored
Normal file
After Width: | Height: | Size: 58 KiB |
BIN
doc/_static/block.png
vendored
Normal file
After Width: | Height: | Size: 41 KiB |
BIN
doc/_static/new_badge.png
vendored
Normal file
After Width: | Height: | Size: 3.1 KiB |
BIN
doc/_static/parametric-cup-screencap.PNG
vendored
Normal file
After Width: | Height: | Size: 65 KiB |
BIN
doc/_static/quickstart-1.png
vendored
Normal file
After Width: | Height: | Size: 6.0 KiB |
BIN
doc/_static/quickstart-2.png
vendored
Normal file
After Width: | Height: | Size: 6.0 KiB |
BIN
doc/_static/quickstart-3.png
vendored
Normal file
After Width: | Height: | Size: 6.9 KiB |
BIN
doc/_static/quickstart-4.png
vendored
Normal file
After Width: | Height: | Size: 6.9 KiB |
BIN
doc/_static/quickstart-5.png
vendored
Normal file
After Width: | Height: | Size: 11 KiB |
BIN
doc/_static/quickstart.png
vendored
Normal file
After Width: | Height: | Size: 18 KiB |
139
doc/apireference.rst
Normal 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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -0,0 +1,43 @@
|
|||
{% extends "basic/layout.html" %}
|
||||
|
||||
{%- block extrahead %}
|
||||
<link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Neuton&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&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
After Width: | Height: | Size: 126 KiB |
BIN
doc/themes/pparts/static/dialog-note.png
vendored
Normal file
After Width: | Height: | Size: 1.5 KiB |
BIN
doc/themes/pparts/static/dialog-seealso.png
vendored
Normal file
After Width: | Height: | Size: 1.5 KiB |
BIN
doc/themes/pparts/static/dialog-topic.png
vendored
Normal file
After Width: | Height: | Size: 1.9 KiB |
BIN
doc/themes/pparts/static/dialog-warning.png
vendored
Normal file
After Width: | Height: | Size: 1.4 KiB |
310
doc/themes/pparts/static/epub.css
vendored
Normal 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
After Width: | Height: | Size: 333 B |
BIN
doc/themes/pparts/static/headerbg.png
vendored
Normal file
After Width: | Height: | Size: 203 B |
7
doc/themes/pparts/static/ie6.css
vendored
Normal 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
After Width: | Height: | Size: 8.7 KiB |
BIN
doc/themes/pparts/static/middlebg.png
vendored
Normal file
After Width: | Height: | Size: 2.7 KiB |
387
doc/themes/pparts/static/pparts.css_t
vendored
Normal 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
After Width: | Height: | Size: 49 B |
4
doc/themes/pparts/theme.conf
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
[theme]
|
||||
inherit = basic
|
||||
stylesheet = pparts.css
|
||||
pygments_style = friendly
|