Updated cadquery lib
This commit is contained in:
parent
8062976bc4
commit
4dc437e44a
|
@ -23,12 +23,16 @@ before_install:
|
||||||
pip install -r requirements-dev.txt;
|
pip install -r requirements-dev.txt;
|
||||||
pip install travis-sphinx;
|
pip install travis-sphinx;
|
||||||
pip install sphinx_rtd_theme;
|
pip install sphinx_rtd_theme;
|
||||||
|
pip install readme_renderer;
|
||||||
fi
|
fi
|
||||||
|
|
||||||
install:
|
install:
|
||||||
- python setup.py install;
|
- python setup.py install;
|
||||||
|
|
||||||
script:
|
script:
|
||||||
|
- if [[ "$TRAVIS_PYTHON_VERSION" == "2.7" ]]; then
|
||||||
|
python setup.py check -r -s;
|
||||||
|
fi
|
||||||
- coverage run runtests.py
|
- coverage run runtests.py
|
||||||
- if [[ "$TRAVIS_PYTHON_VERSION" == "2.7" ]]; then
|
- if [[ "$TRAVIS_PYTHON_VERSION" == "2.7" ]]; then
|
||||||
travis-sphinx build --nowarn --source=doc;
|
travis-sphinx build --nowarn --source=doc;
|
||||||
|
|
|
@ -34,7 +34,7 @@ RUN mkdir -p $CQ_HOME
|
||||||
RUN mkdir -p $CQ_HOME/build_data
|
RUN mkdir -p $CQ_HOME/build_data
|
||||||
VOLUME $CQ_HOME/build_data
|
VOLUME $CQ_HOME/build_data
|
||||||
|
|
||||||
COPY requirements-dev.txt runtests.py cq_cmd.py cq_cmd.sh setup.py README.md MANIFEST setup.cfg $CQ_HOME/
|
COPY requirements-dev.txt runtests.py cq_cmd.py cq_cmd.sh setup.py README.rst MANIFEST setup.cfg $CQ_HOME/
|
||||||
COPY cadquery $CQ_HOME/cadquery
|
COPY cadquery $CQ_HOME/cadquery
|
||||||
COPY examples $CQ_HOME/examples
|
COPY examples $CQ_HOME/examples
|
||||||
COPY tests $CQ_HOME/tests
|
COPY tests $CQ_HOME/tests
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
README.txt
|
README.rst
|
||||||
README.md
|
|
||||||
setup.cfg
|
setup.cfg
|
||||||
setup.py
|
setup.py
|
||||||
cadquery\cq.py
|
cadquery\cq.py
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
include README.md
|
include README.rst LICENSE
|
||||||
|
|
|
@ -1,264 +0,0 @@
|
||||||
<p align="center">
|
|
||||||
<img src="http://dcowden.github.io/cadquery/_static/cadquery_logo_dark.svg" width="100"/>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
What is a CadQuery?
|
|
||||||
========================================
|
|
||||||
|
|
||||||
[](https://travis-ci.org/dcowden/cadquery?branch=master)
|
|
||||||
[](https://ci.appveyor.com/project/jmwright/cadquery/branch/master)
|
|
||||||
[](https://coveralls.io/github/dcowden/cadquery?branch=master)
|
|
||||||
[](https://github.com/dcowden/cadquery/releases/tag/v1.2.0)
|
|
||||||
[](https://github.com/dcowden/cadquery/blob/master/LICENSE)
|
|
||||||
|
|
||||||
CadQuery is an intuitive, easy-to-use python based language for building parametric 3D CAD models. CadQuery is for 3D CAD what jQuery is for javascript. Imagine selecting Faces of a 3d object the same way you select DOM objects with JQuery!
|
|
||||||
|
|
||||||
CadQuery has several goals:
|
|
||||||
|
|
||||||
* Build lD 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 (loss-less) 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
|
|
||||||
|
|
||||||
Using CadQuery, you can write short, simple scripts that produce high quality CAD models. It is easy to make many different objects using a single script that can be customized.
|
|
||||||
|
|
||||||
Full Documentation and a Welcoming Community
|
|
||||||
============================
|
|
||||||
You can find the full cadquery documentation at http://dcowden.github.io/cadquery
|
|
||||||
|
|
||||||
We also have a Google Group to make it easy to get help from other CadQuery users. We want you to feel welcome and encourage you to join the group and introduce yourself. We would also love to hear what you are doing with CadQuery. https://groups.google.com/forum/#!forum/cadquery
|
|
||||||
|
|
||||||
Getting Started With CadQuery
|
|
||||||
========================================
|
|
||||||
|
|
||||||
Installation instructions for all following use cases can be found [here](http://dcowden.github.io/cadquery/installation.html).
|
|
||||||
|
|
||||||
It is currently possible to use CadQuery for your own projects in 4 different ways:
|
|
||||||
* as a plugin for FreeCAD
|
|
||||||
* using the Docker Image to operate CadQuery as a CLI
|
|
||||||
* as a plugin running on a Jupyter Notebook server
|
|
||||||
* a standalone installation
|
|
||||||
|
|
||||||
## I just want to try things out!
|
|
||||||
|
|
||||||
If you are interested in trying CadQuery without installing anything, your best option is to experiment with CadQuery scripts running on a Jupyter server.
|
|
||||||
|
|
||||||
[](https://mybinder.org/v2/gh/RustyVermeer/tryCQ/master)
|
|
||||||
|
|
||||||
That button will launch a Jupyter Server pre-configured with CadQuery and its dependencies. It contains a folder with many useful examples to showcase CadQuery's features.
|
|
||||||
|
|
||||||
## I'd like to use CadQuery on my own setup
|
|
||||||
|
|
||||||
The easiest way to get started with CadQuery is to Install FreeCAD (version 16+) (http://www.freecadweb.org/), and then to use our great CadQuery-FreeCAD plugin here: https://github.com/jmwright/cadquery-freecad-module
|
|
||||||
|
|
||||||
It includes the latest version of cadquery already bundled, and has super-easy installation on Mac, Windows, and Unix.
|
|
||||||
|
|
||||||
It has tons of awesome features like integration with FreeCAD so you can see your objects, code-autocompletion, an examples bundle, and script saving/loading. Its definitely the best way to kick the tires!
|
|
||||||
|
|
||||||
## I have other ideas and want to run things my own way
|
|
||||||
|
|
||||||
Awesome! CadQuery is built with this attitude in mind. If none of the existing usage methods work for you, you are more than welcome to forge your own path. You'll probably find the most success using the Docker image. You can alternatively install CadQuery as a standalone package.
|
|
||||||
|
|
||||||
Getting Started with the docker image
|
|
||||||
=======================================
|
|
||||||
The CadQuery docker image (https://hub.docker.com/r/dcowden/cadquery/) includes cadquery and all of its dependencies. It can be used to run cadquery scripts without any installation required ( other than docker, of course)
|
|
||||||
|
|
||||||
Examples:
|
|
||||||
|
|
||||||
Display the Documentation::
|
|
||||||
|
|
||||||
docker run dcowden/cadquery:latest
|
|
||||||
|
|
||||||
Build a local model using stdin/stdout::
|
|
||||||
|
|
||||||
cat Ex001_Simple_Block.py | docker run -i dcowden/cadquery:latest build --in_spec stdin --format STEP --out_spec stdout
|
|
||||||
|
|
||||||
... STEP output on the console
|
|
||||||
|
|
||||||
Build local models and output to the same directory:
|
|
||||||
|
|
||||||
docker run -v $PWD:/home/cq -i dcowden/cadquery:latest build --in_spec Ex001_Simple_Block.py --format STEP
|
|
||||||
INFO: Reading from file 'Ex001_Simple_Block.py'
|
|
||||||
INFO: Parsed Script 'Ex001_Simple_Block.py'.
|
|
||||||
INFO: This script provides parameters length,thickness,height, which can be customized at build time.
|
|
||||||
INFO: The script will run with default variable values
|
|
||||||
INFO: use --param_file to provide a json file that contains values to override the defaults
|
|
||||||
INFO: Output Format is 'STEP'. Use --output-format to change it.
|
|
||||||
INFO: Output Path is './cqobject-%(counter)d.%(format)s'. Use --out_spec to change it.
|
|
||||||
INFO: Script Generated 1 result Objects
|
|
||||||
INFO: Writing STEP Output to './cqobject-1.STEP'
|
|
||||||
|
|
||||||
Projects Using CadQuery
|
|
||||||
=========================
|
|
||||||
|
|
||||||
This resin mold was modeled using cadquery and then created on a CNC machine:
|
|
||||||
|
|
||||||
<p align="center">
|
|
||||||
<img src="doc/_static/hyOzd-cablefix.png" width="350"/>
|
|
||||||
<img src="doc/_static/hyOzd-finished.jpg" width="350"/>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
The cadquery script is surprisingly short, and allows easily customizing any of the variables::
|
|
||||||
|
|
||||||
```python
|
|
||||||
import cadquery as cq
|
|
||||||
from Helpers import show
|
|
||||||
BS = cq.selectors.BoxSelector
|
|
||||||
|
|
||||||
# PARAMETERS
|
|
||||||
mount_holes = True
|
|
||||||
|
|
||||||
# mold size
|
|
||||||
mw = 40
|
|
||||||
mh = 13
|
|
||||||
ml = 120
|
|
||||||
|
|
||||||
# wire and fix size
|
|
||||||
wd = 6 # wire diameter
|
|
||||||
rt = 7 # resin thickness
|
|
||||||
rl = 50 # resin length
|
|
||||||
rwpl = 10 # resin to wire pass length
|
|
||||||
|
|
||||||
# pocket fillet
|
|
||||||
pf = 18
|
|
||||||
|
|
||||||
# mount holes
|
|
||||||
mhd = 7 # hole diameter
|
|
||||||
mht = 3 # hole distance from edge
|
|
||||||
|
|
||||||
# filling hole
|
|
||||||
fhd = 6
|
|
||||||
|
|
||||||
# DRAWING
|
|
||||||
|
|
||||||
# draw base
|
|
||||||
base = cq.Workplane("XY").box(ml, mw, mh, (True, True, False))
|
|
||||||
|
|
||||||
# draw wire
|
|
||||||
pocket = cq.Workplane("XY", (0, 0, mh)).moveTo(-ml/2., 0).line(0, wd/2.)\
|
|
||||||
.line((ml-rl)/2.-rwpl, 0).line(rwpl, rt).line(rl, 0)\
|
|
||||||
.line(rwpl, -rt).line((ml-rl)/2.-rwpl, 0)\
|
|
||||||
.line(0, -(wd/2.)).close().revolve(axisEnd=(1, 0))\
|
|
||||||
.edges(BS((-rl/2.-rwpl-.1, -100, -100), (rl/2.+rwpl+.1, 100, 100)))\
|
|
||||||
.fillet(pf)
|
|
||||||
|
|
||||||
r = base.cut(pocket)
|
|
||||||
|
|
||||||
# mount holes
|
|
||||||
if mount_holes:
|
|
||||||
px = ml/2.-mht-mhd/2.
|
|
||||||
py = mw/2.-mht-mhd/2
|
|
||||||
r = r.faces("<Z").workplane().pushPoints([
|
|
||||||
(px, py),
|
|
||||||
(-px, py),
|
|
||||||
(-px, -py),
|
|
||||||
(px, -py)
|
|
||||||
]).hole(mhd)
|
|
||||||
|
|
||||||
# fill holes
|
|
||||||
r = r.faces("<Y").workplane().center(0, mh/2.).pushPoints([
|
|
||||||
(-rl/2., 0),
|
|
||||||
(0, 0),
|
|
||||||
(rl/2., 0)
|
|
||||||
]).hole(fhd, mw/2.)
|
|
||||||
|
|
||||||
show(r)
|
|
||||||
```
|
|
||||||
|
|
||||||
Thanks go to cadquery contributor hyOzd ( Altu Technology ) for the example!
|
|
||||||
|
|
||||||
|
|
||||||
KiCad uses cadquery to build high quality models of electrictronic components. ( https://github.com/KiCad/packages3D )
|
|
||||||
|
|
||||||
<p align="center">
|
|
||||||
<img src="https://forum.freecadweb.org/download/file.php?id=33797&sid=b8584f80928497722e9ee9d582a3fa43" width="350"/>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
This Prusa i3 extruder support uses cadquery to build the model (https://github.com/adam-urbanczyk/cadquery-models) :
|
|
||||||
|
|
||||||
<p align="center">
|
|
||||||
<img src="https://github.com/adam-urbanczyk/cadquery-models/raw/master/extruder_support.png" width="350"/>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
The mach30 project used cadquery to develop a tool that will create a rocket thruster directly from the appropriate equations (https://opendesignengine.net/projects/yavin-thruster/wiki):
|
|
||||||
<p align="center">
|
|
||||||
<img src="http://opendesignengine.net/dmsf_files/480?download=" width="700"/>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
This example uses Jupyter notebook to produce a really cool web-based scripting environment ( https://github.com/RustyVermeer/avnb/blob/master/readme.md ) :
|
|
||||||
|
|
||||||
<p align="center">
|
|
||||||
<img src="https://github.com/RustyVermeer/cqnb/raw/master/showcase.gif" width="350"/>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
We would love to link to your cadquery based project. Just let us know and we'll add it here.
|
|
||||||
|
|
||||||
|
|
||||||
Where does the name CadQuery come from?
|
|
||||||
========================================
|
|
||||||
|
|
||||||
CadQuery is inspired by jQuery, a popular framework that
|
|
||||||
revolutionized web development involving javascript.
|
|
||||||
|
|
||||||
If you are familiar with jQuery, you will probably recognize several jQuery features that CadQuery uses:
|
|
||||||
|
|
||||||
* A fluent api to create clean, easy to read code
|
|
||||||
* Language features that make selection and iteration incredibly easy
|
|
||||||
*
|
|
||||||
* Ability to use the library along side other python libraries
|
|
||||||
* Clear and complete documentation, with plenty of samples.
|
|
||||||
|
|
||||||
Why CadQuery instead of OpenSCAD?
|
|
||||||
========================================
|
|
||||||
|
|
||||||
CadQuery is based on OpenCasCade. CadQuery shares 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 libraries that exist already. So why not simply use OpenSCAD?
|
|
||||||
|
|
||||||
CadQuery scripts have several key advantages over OpenSCAD:
|
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
License
|
|
||||||
========
|
|
||||||
|
|
||||||
CadQuery is licensed under the terms of the Apache Public License, version 2.0.
|
|
||||||
A copy of the license can be found at http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Ongoing and Future Work
|
|
||||||
============
|
|
||||||
|
|
||||||
### CadQuery GUI (under development)
|
|
||||||
Work is underway on a stand-alone gui here: https://github.com/jmwright/cadquery-gui
|
|
||||||
|
|
||||||
### CadQuery Parts / Assembly Handling
|
|
||||||
Work by Fragmuffin is ongoing with the [cqparts](https://github.com/fragmuffin/cqparts) repo.
|
|
||||||
|
|
||||||
### Moving to Python3 and away from FreeCAD as a dependency
|
|
||||||
Adam Urbańczyk has been working hard on his own [CQ fork](https://github.com/adam-urbanczyk/cadquery) which uses only PythonOCC instead of FreeCAD.
|
|
||||||
|
|
||||||
Work has begun on Cadquery 2.0, which will feature:
|
|
||||||
|
|
||||||
1. Feature trees, for more powerful selection
|
|
||||||
2. Direct use of OpenCascade Community Edition (OCE), so that it is no longer required to install FreeCAD
|
|
||||||
|
|
||||||
The project page can be found here: https://github.com/dcowden/cadquery/projects/1
|
|
||||||
|
|
||||||
A more detailed description of the plan for CQ 2.0 is here: https://docs.google.com/document/d/1cXuxBkVeYmGOo34MGRdG7E3ILypQqkrJ26oVf3CUSPQ
|
|
315
Libs/cadquery/README.rst
Normal file
315
Libs/cadquery/README.rst
Normal file
|
@ -0,0 +1,315 @@
|
||||||
|
.. image:: http://dcowden.github.io/cadquery/_static/cadquery_logo_dark.svg
|
||||||
|
|
||||||
|
|
||||||
|
ANNOUNCEMENT! CadQuery is Moving to https://github.com/CadQuery/cadquery!
|
||||||
|
============================================================
|
||||||
|
|
||||||
|
Version 2.0 development is under way It uses pythonOCC instead of FreeCAD, and has tons of cool features
|
||||||
|
|
||||||
|
*BUT DONT WORRY!* Version 1.x (this repository ) will be suported until all features are comfortably implemented in the 2.x stream.
|
||||||
|
|
||||||
|
We're happy to be moving to a more open organization, but we're sad we're starting over with our stars. Please give us one at our new home!
|
||||||
|
|
||||||
|
|
||||||
|
What is CadQuery?
|
||||||
|
========================================
|
||||||
|
|
||||||
|
|TRAVIS| |APPVEYOR| |COVERALLS| |VERSION| |LICENSE|
|
||||||
|
|
||||||
|
.. |TRAVIS| image:: https://travis-ci.org/dcowden/cadquery.svg?branch=master
|
||||||
|
:alt: Travis Build Status
|
||||||
|
:target: https://travis-ci.org/dcowden/cadquery?branch=master
|
||||||
|
|
||||||
|
.. |APPVEYOR| image:: https://ci.appveyor.com/api/projects/status/c7u4yjl8xxlokrw0/branch/master?svg=true
|
||||||
|
:alt: Build status
|
||||||
|
:target: https://ci.appveyor.com/project/jmwright/cadquery/branch/master
|
||||||
|
|
||||||
|
.. |COVERALLS| image:: https://coveralls.io/repos/github/dcowden/cadquery/badge.svg?branch=master
|
||||||
|
:alt: Coverage Status
|
||||||
|
:target: https://coveralls.io/github/dcowden/cadquery?branch=master
|
||||||
|
|
||||||
|
.. |VERSION| image:: https://d25lcipzij17d.cloudfront.net/badge.svg?id=gh&type=6&v=1.2.0&x2=0
|
||||||
|
:alt: GitHub version
|
||||||
|
:target: https://github.com/dcowden/cadquery/releases/tag/v1.2.0
|
||||||
|
|
||||||
|
.. |LICENSE| image:: https://img.shields.io/badge/license-Apache2-blue.svg
|
||||||
|
:alt: License
|
||||||
|
:target: https://github.com/dcowden/cadquery/blob/master/LICENSE
|
||||||
|
|
||||||
|
CadQuery is an intuitive, easy-to-use python based language for building parametric 3D CAD models. CadQuery is for 3D CAD what jQuery is for javascript. Imagine selecting Faces of a 3d object the same way you select DOM objects with JQuery!
|
||||||
|
|
||||||
|
CadQuery has several goals:
|
||||||
|
|
||||||
|
* Build 3d 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 (loss-less) 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
|
||||||
|
|
||||||
|
Using CadQuery, you can write short, simple scripts that produce high quality CAD models. It is easy to make many different objects using a single script that can be customized.
|
||||||
|
|
||||||
|
|
||||||
|
Full Documentation and a Welcoming Community
|
||||||
|
===============================================
|
||||||
|
You can find the full cadquery documentation at `https://dcowden.github.io/cadquery <https://dcowden.github.io/cadquery>`_
|
||||||
|
|
||||||
|
We also have a Google Group to make it easy to get help from other CadQuery users. We want you to feel welcome and encourage you to join the group and introduce yourself. We would also love to hear what you are doing with CadQuery. https://groups.google.com/forum/#!forum/cadquery
|
||||||
|
|
||||||
|
Getting Started With CadQuery
|
||||||
|
========================================
|
||||||
|
|
||||||
|
Installation instructions for all following use cases can be found `here <http://dcowden.github.io/cadquery/installation.html>`_.
|
||||||
|
|
||||||
|
It is currently possible to use CadQuery for your own projects in 4 different ways:
|
||||||
|
* as a plugin for FreeCAD
|
||||||
|
* using the Docker Image to operate CadQuery as a CLI
|
||||||
|
* as a plugin running on a Jupyter Notebook server
|
||||||
|
* a standalone installation
|
||||||
|
|
||||||
|
I just want to try things out!
|
||||||
|
--------------------------------------------------
|
||||||
|
|
||||||
|
If you are interested in trying CadQuery without installing anything, your best option is to experiment with CadQuery scripts running on a Jupyter server.
|
||||||
|
|
||||||
|
|BINDER|
|
||||||
|
|
||||||
|
.. |BINDER| image:: https://mybinder.org/badge.svg
|
||||||
|
:alt: Binder
|
||||||
|
:target: https://mybinder.org/v2/gh/RustyVermeer/tryCQ/master
|
||||||
|
|
||||||
|
That button will launch a Jupyter Server pre-configured with CadQuery and its dependencies. It contains a folder with many useful examples to showcase CadQuery's features.
|
||||||
|
|
||||||
|
I'd like to use CadQuery on my own setup
|
||||||
|
--------------------------------------------------
|
||||||
|
|
||||||
|
The easiest way to get started with CadQuery is to Install FreeCAD (version 16+) (`http://www.freecadweb.org/ <http://www.freecadweb.org/>`_), and then to use our great CadQuery-FreeCAD plugin here: `https://github.com/jmwright/cadquery-freecad-module <https://github.com/jmwright/cadquery-freecad-module>`_
|
||||||
|
|
||||||
|
It includes the latest version of cadquery already bundled, and has super-easy installation on Mac, Windows, and Unix.
|
||||||
|
|
||||||
|
It has tons of awesome features like integration with FreeCAD so you can see your objects, code-autocompletion, an examples bundle, and script saving/loading. Its definitely the best way to kick the tires!
|
||||||
|
|
||||||
|
I have other ideas and want to run things my own way
|
||||||
|
-----------------------------------------------------------
|
||||||
|
|
||||||
|
Awesome! CadQuery is built with this attitude in mind. If none of the existing usage methods work for you, you are more than welcome to forge your own path. You'll probably find the most success using the Docker image. You can alternatively install CadQuery as a standalone package.
|
||||||
|
|
||||||
|
|
||||||
|
Getting Started with the docker image
|
||||||
|
=======================================
|
||||||
|
|
||||||
|
The CadQuery docker image (`https://hub.docker.com/r/dcowden/cadquery/ <https://hub.docker.com/r/dcowden/cadquery/>`_) includes cadquery and all of its dependencies. It can be used to run cadquery scripts without any installation required ( other than docker, of course)
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
|
||||||
|
Display the Documentation:
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
docker run dcowden/cadquery:latest
|
||||||
|
|
||||||
|
Build a local model using stdin/stdout:
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
cat Ex001_Simple_Block.py | docker run -i dcowden/cadquery:latest build --in_spec stdin --format STEP --out_spec stdout
|
||||||
|
|
||||||
|
... STEP output on the console
|
||||||
|
|
||||||
|
Build local models and output to the same directory::
|
||||||
|
|
||||||
|
docker run -v $PWD:/home/cq -i dcowden/cadquery:latest build --in_spec Ex001_Simple_Block.py --format STEP
|
||||||
|
INFO: Reading from file 'Ex001_Simple_Block.py'
|
||||||
|
INFO: Parsed Script 'Ex001_Simple_Block.py'.
|
||||||
|
INFO: This script provides parameters length,thickness,height, which can be customized at build time.
|
||||||
|
INFO: The script will run with default variable values
|
||||||
|
INFO: use --param_file to provide a json file that contains values to override the defaults
|
||||||
|
INFO: Output Format is 'STEP'. Use --output-format to change it.
|
||||||
|
INFO: Output Path is './cqobject-%(counter)d.%(format)s'. Use --out_spec to change it.
|
||||||
|
INFO: Script Generated 1 result Objects
|
||||||
|
INFO: Writing STEP Output to './cqobject-1.STEP'
|
||||||
|
|
||||||
|
|
||||||
|
Projects Using CadQuery
|
||||||
|
=========================
|
||||||
|
|
||||||
|
This resin mold was modeled using cadquery and then created on a CNC machine:
|
||||||
|
|
||||||
|
|HY0ZD_CABLEFIX| |HY0ZD_FINISHED|
|
||||||
|
|
||||||
|
.. |HY0ZD_CABLEFIX| image:: http://dcowden.github.io/cadquery/_static/hyOzd-cablefix.png
|
||||||
|
:alt: Cable-fix resin mold: Rendered
|
||||||
|
|
||||||
|
.. |HY0ZD_FINISHED| image:: http://dcowden.github.io/cadquery/_static/hyOzd-finished_thumb.jpg
|
||||||
|
:alt: Cable-fix resin mold: Finised
|
||||||
|
:target: http://dcowden.github.io/cadquery/_static/hyOzd-finished_thumb.jpg
|
||||||
|
|
||||||
|
|
||||||
|
The cadquery script is surprisingly short, and allows easily customizing any of the variables:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
import cadquery as cq
|
||||||
|
from Helpers import show
|
||||||
|
BS = cq.selectors.BoxSelector
|
||||||
|
|
||||||
|
# PARAMETERS
|
||||||
|
mount_holes = True
|
||||||
|
|
||||||
|
# mold size
|
||||||
|
mw = 40
|
||||||
|
mh = 13
|
||||||
|
ml = 120
|
||||||
|
|
||||||
|
# wire and fix size
|
||||||
|
wd = 6 # wire diameter
|
||||||
|
rt = 7 # resin thickness
|
||||||
|
rl = 50 # resin length
|
||||||
|
rwpl = 10 # resin to wire pass length
|
||||||
|
|
||||||
|
# pocket fillet
|
||||||
|
pf = 18
|
||||||
|
|
||||||
|
# mount holes
|
||||||
|
mhd = 7 # hole diameter
|
||||||
|
mht = 3 # hole distance from edge
|
||||||
|
|
||||||
|
# filling hole
|
||||||
|
fhd = 6
|
||||||
|
|
||||||
|
# DRAWING
|
||||||
|
|
||||||
|
# draw base
|
||||||
|
base = cq.Workplane("XY").box(ml, mw, mh, (True, True, False))
|
||||||
|
|
||||||
|
# draw wire
|
||||||
|
pocket = cq.Workplane("XY", (0, 0, mh)).moveTo(-ml/2., 0).line(0, wd/2.)\
|
||||||
|
.line((ml-rl)/2.-rwpl, 0).line(rwpl, rt).line(rl, 0)\
|
||||||
|
.line(rwpl, -rt).line((ml-rl)/2.-rwpl, 0)\
|
||||||
|
.line(0, -(wd/2.)).close().revolve(axisEnd=(1, 0))\
|
||||||
|
.edges(BS((-rl/2.-rwpl-.1, -100, -100), (rl/2.+rwpl+.1, 100, 100)))\
|
||||||
|
.fillet(pf)
|
||||||
|
|
||||||
|
r = base.cut(pocket)
|
||||||
|
|
||||||
|
# mount holes
|
||||||
|
if mount_holes:
|
||||||
|
px = ml/2.-mht-mhd/2.
|
||||||
|
py = mw/2.-mht-mhd/2
|
||||||
|
r = r.faces("<Z").workplane().pushPoints([
|
||||||
|
(px, py),
|
||||||
|
(-px, py),
|
||||||
|
(-px, -py),
|
||||||
|
(px, -py)
|
||||||
|
]).hole(mhd)
|
||||||
|
|
||||||
|
# fill holes
|
||||||
|
r = r.faces("<Y").workplane().center(0, mh/2.).pushPoints([
|
||||||
|
(-rl/2., 0),
|
||||||
|
(0, 0),
|
||||||
|
(rl/2., 0)
|
||||||
|
]).hole(fhd, mw/2.)
|
||||||
|
|
||||||
|
show(r)
|
||||||
|
|
||||||
|
|
||||||
|
Thanks go to cadquery contributor hyOzd ( Altu Technology ) for the example!
|
||||||
|
|
||||||
|
|
||||||
|
KiCad uses cadquery to build high quality models of electronic components. (`https://github.com/KiCad/packages3D <https://github.com/KiCad/packages3D>`_)
|
||||||
|
|
||||||
|
.. image:: http://dcowden.github.io/cadquery/_static/KiCad_Capacitors_SMD_thumb.jpg
|
||||||
|
:target: http://dcowden.github.io/cadquery/_static/KiCad_Capacitors_SMD.jpg
|
||||||
|
:alt: Surface mount capacitors rendered in KiCad
|
||||||
|
|
||||||
|
This Prusa i3 extruder support uses cadquery to build the model (`https://github.com/adam-urbanczyk/cadquery-models <https://github.com/adam-urbanczyk/cadquery-models>`_):
|
||||||
|
|
||||||
|
.. image:: http://dcowden.github.io/cadquery/_static/extruder_support.png
|
||||||
|
:alt: Prusa i3 extruder support - FreeCAD model render
|
||||||
|
|
||||||
|
The mach30 project used cadquery to develop a tool that will create a rocket thruster directly from the appropriate equations (`https://opendesignengine.net/projects/yavin-thruster/wiki <https://opendesignengine.net/projects/yavin-thruster/wiki>`_):
|
||||||
|
|
||||||
|
.. image:: http://dcowden.github.io/cadquery/_static/march30_landing_page.png
|
||||||
|
:target: https://opendesignengine.net/projects/yavin-thruster/wiki
|
||||||
|
:alt: mach30 project landing page
|
||||||
|
|
||||||
|
This example uses Jupyter notebook to produce a really cool web-based scripting environment (`https://github.com/RustyVermeer/avnb/blob/master/readme.md <https://github.com/RustyVermeer/avnb/blob/master/readme.md>`_):
|
||||||
|
|
||||||
|
.. image:: http://dcowden.github.io/cadquery/_static/jupyter_showcase_thumb.png
|
||||||
|
:alt: Jupyter notebook showcased as animation
|
||||||
|
:target: https://github.com/RustyVermeer/cqnb
|
||||||
|
|
||||||
|
We would love to link to your cadquery based project. Just let us know and we'll add it here.
|
||||||
|
|
||||||
|
|
||||||
|
Where does the name CadQuery come from?
|
||||||
|
========================================
|
||||||
|
|
||||||
|
CadQuery is inspired by jQuery, a popular framework that
|
||||||
|
revolutionized web development involving javascript.
|
||||||
|
|
||||||
|
If you are familiar with jQuery, you will probably recognize several jQuery features that CadQuery uses:
|
||||||
|
|
||||||
|
* A fluent API to create clean, easy to read code
|
||||||
|
* Language features that make selection and iteration incredibly easy
|
||||||
|
* Ability to use the library along side other python libraries
|
||||||
|
* Clear and complete documentation, with plenty of samples.
|
||||||
|
|
||||||
|
|
||||||
|
Why CadQuery instead of OpenSCAD?
|
||||||
|
========================================
|
||||||
|
|
||||||
|
CadQuery is based on OpenCasCade. CadQuery shares 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 libraries that exist already. So why not simply use OpenSCAD?
|
||||||
|
|
||||||
|
CadQuery scripts have several key advantages over OpenSCAD:
|
||||||
|
|
||||||
|
#. **The scripts use a standard programming language**, Python, and thus can benefit from the associated infrastructure.
|
||||||
|
This includes many standard libraries and IDEs
|
||||||
|
#. **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
|
||||||
|
#. **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
|
||||||
|
#. **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.
|
||||||
|
#. **Better Performance** CadQuery scripts can build STL, STEP, and AMF faster than OpenSCAD.
|
||||||
|
|
||||||
|
|
||||||
|
License
|
||||||
|
====================
|
||||||
|
|
||||||
|
CadQuery is licensed under the terms of the `Apache Public License, version 2.0 <http://www.apache.org/licenses/LICENSE-2.0>`_.
|
||||||
|
|
||||||
|
Ongoing and Future Work
|
||||||
|
=============================
|
||||||
|
|
||||||
|
CadQuery 2.0 (And future versions)
|
||||||
|
-----------------------------------
|
||||||
|
|
||||||
|
Cadquery 2.0 is under way. 2.0 is based on pythonOCC directly ( rather than FreeCAD ), and is under heavy development.
|
||||||
|
Beginning with version 2.0, CadQuery has moved to a new home at `https://github.com/CadQuery/cadquery` CadQuery/cadquery
|
||||||
|
|
||||||
|
|
||||||
|
CadQuery GUI (under development)
|
||||||
|
-------------------------------------------
|
||||||
|
|
||||||
|
Work is underway on a stand-alone gui here: `https://github.com/jmwright/cadquery-gui <https://github.com/jmwright/cadquery-gui>`_
|
||||||
|
|
||||||
|
CadQuery Parts / Assembly Handling
|
||||||
|
-------------------------------------------
|
||||||
|
|
||||||
|
Work by Fragmuffin is ongoing with the `cqparts <https://github.com/fragmuffin/cqparts>`_ repo.
|
||||||
|
|
||||||
|
Moving to Python3 and away from FreeCAD as a dependency
|
||||||
|
-------------------------------------------------------------
|
||||||
|
|
||||||
|
Adam Urbańczyk has been working hard on his own `CQ fork <https://github.com/adam-urbanczyk/cadquery>`_ which uses only PythonOCC instead of FreeCAD.
|
||||||
|
|
||||||
|
Work has begun on Cadquery 2.0, which will feature:
|
||||||
|
|
||||||
|
#. Feature trees, for more powerful selection
|
||||||
|
#. Direct use of OpenCascade Community Edition (OCE), so that it is no longer required to install FreeCAD
|
||||||
|
|
||||||
|
The project page can be found here: `https://github.com/dcowden/cadquery/projects/1 <https://github.com/dcowden/cadquery/projects/1>`_
|
||||||
|
|
||||||
|
A more detailed description of `the plan for CQ 2.0 <https://docs.google.com/document/d/1cXuxBkVeYmGOo34MGRdG7E3ILypQqkrJ26oVf3CUSPQ>`_
|
0
Libs/cadquery/build_docker.sh
Executable file → Normal file
0
Libs/cadquery/build_docker.sh
Executable file → Normal file
|
@ -719,7 +719,7 @@ class CQ(object):
|
||||||
Future Enhancements:
|
Future Enhancements:
|
||||||
* A version of this method that returns a transformed copy, rather than modifying
|
* A version of this method that returns a transformed copy, rather than modifying
|
||||||
the originals
|
the originals
|
||||||
* This method doesnt expose a very good interface, because the axis of rotation
|
* This method doesn't expose a very good interface, because the axis of rotation
|
||||||
could be inconsistent between multiple objects. This is because the beginning
|
could be inconsistent between multiple objects. This is because the beginning
|
||||||
of the axis is variable, while the end is fixed. This is fine when operating on
|
of the axis is variable, while the end is fixed. This is fine when operating on
|
||||||
one object, but is not cool for multiple.
|
one object, but is not cool for multiple.
|
||||||
|
@ -1082,6 +1082,45 @@ class Workplane(CQ):
|
||||||
|
|
||||||
return self.pushPoints(lpoints)
|
return self.pushPoints(lpoints)
|
||||||
|
|
||||||
|
def polarArray(self, radius, startAngle, angle, count, fill=True):
|
||||||
|
"""
|
||||||
|
Creates an polar array of points and pushes them onto the stack.
|
||||||
|
The 0 degree reference angle is located along the local X-axis.
|
||||||
|
|
||||||
|
:param radius: Radius of the array.
|
||||||
|
:param startAngle: Starting angle (degrees) of array. 0 degrees is
|
||||||
|
situated along local X-axis.
|
||||||
|
:param angle: The angle (degrees) to fill with elements. A positive
|
||||||
|
value will fill in the counter-clockwise direction. If fill is
|
||||||
|
false, angle is the angle between elements.
|
||||||
|
:param count: Number of elements in array. ( > 0 )
|
||||||
|
"""
|
||||||
|
|
||||||
|
if count <= 0:
|
||||||
|
raise ValueError("No elements in array")
|
||||||
|
|
||||||
|
# First element at start angle, convert to cartesian coords
|
||||||
|
x = radius * math.cos(math.radians(startAngle))
|
||||||
|
y = radius * math.sin(math.radians(startAngle))
|
||||||
|
points = [(x, y)]
|
||||||
|
|
||||||
|
# Calculate angle between elements
|
||||||
|
if fill:
|
||||||
|
if angle % 360 == 0:
|
||||||
|
angle = angle / count
|
||||||
|
elif count > 1:
|
||||||
|
# Inclusive start and end
|
||||||
|
angle = angle / (count - 1)
|
||||||
|
|
||||||
|
# Add additional elements
|
||||||
|
for i in range(1, count):
|
||||||
|
phi = math.radians(startAngle + (angle * i))
|
||||||
|
x = radius * math.cos(phi)
|
||||||
|
y = radius * math.sin(phi)
|
||||||
|
points.append((x, y))
|
||||||
|
|
||||||
|
return self.pushPoints(points)
|
||||||
|
|
||||||
def pushPoints(self, pntList):
|
def pushPoints(self, pntList):
|
||||||
"""
|
"""
|
||||||
Pushes a list of points onto the stack as vertices.
|
Pushes a list of points onto the stack as vertices.
|
||||||
|
@ -1220,6 +1259,35 @@ class Workplane(CQ):
|
||||||
p = self._findFromPoint(True)
|
p = self._findFromPoint(True)
|
||||||
return self.lineTo(xCoord, p.y, forConstruction)
|
return self.lineTo(xCoord, p.y, forConstruction)
|
||||||
|
|
||||||
|
def polarLine(self, distance, angle, forConstruction=False):
|
||||||
|
"""
|
||||||
|
Make a line of the given length, at the given angle from the current point
|
||||||
|
|
||||||
|
:param float distance: distance of the end of the line from the current point
|
||||||
|
:param float angle: angle of the vector to the end of the line with the x-axis
|
||||||
|
:return: the Workplane object with the current point at the end of the new line
|
||||||
|
"""
|
||||||
|
x = math.cos(math.radians(angle)) * distance
|
||||||
|
y = math.sin(math.radians(angle)) * distance
|
||||||
|
|
||||||
|
return self.line(x, y, forConstruction)
|
||||||
|
|
||||||
|
def polarLineTo(self, distance, angle, forConstruction=False):
|
||||||
|
"""
|
||||||
|
Make a line from the current point to the given polar co-ordinates
|
||||||
|
|
||||||
|
Useful if it is more convenient to specify the end location rather than
|
||||||
|
the distance and angle from the current point
|
||||||
|
|
||||||
|
:param float distance: distance of the end of the line from the origin
|
||||||
|
:param float angle: angle of the vector to the end of the line with the x-axis
|
||||||
|
:return: the Workplane object with the current point at the end of the new line
|
||||||
|
"""
|
||||||
|
x = math.cos(math.radians(angle)) * distance
|
||||||
|
y = math.sin(math.radians(angle)) * distance
|
||||||
|
|
||||||
|
return self.lineTo(x, y, forConstruction)
|
||||||
|
|
||||||
#absolute move in current plane, not drawing
|
#absolute move in current plane, not drawing
|
||||||
def moveTo(self, x=0, y=0):
|
def moveTo(self, x=0, y=0):
|
||||||
"""
|
"""
|
||||||
|
@ -1443,7 +1511,7 @@ class Workplane(CQ):
|
||||||
Produces a flat, heart shaped object
|
Produces a flat, heart shaped object
|
||||||
|
|
||||||
Future Enhancements:
|
Future Enhancements:
|
||||||
mirrorX().mirrorY() should work but doesnt, due to some FreeCAD weirdness
|
mirrorX().mirrorY() should work but doesn't, due to some FreeCAD weirdness
|
||||||
"""
|
"""
|
||||||
tm = Matrix()
|
tm = Matrix()
|
||||||
tm.rotateY(math.pi)
|
tm.rotateY(math.pi)
|
||||||
|
@ -1461,7 +1529,7 @@ class Workplane(CQ):
|
||||||
Typically used to make creating wires with symmetry easier.
|
Typically used to make creating wires with symmetry easier.
|
||||||
|
|
||||||
Future Enhancements:
|
Future Enhancements:
|
||||||
mirrorX().mirrorY() should work but doesnt, due to some FreeCAD weirdness
|
mirrorX().mirrorY() should work but doesn't, due to some FreeCAD weirdness
|
||||||
"""
|
"""
|
||||||
tm = Matrix()
|
tm = Matrix()
|
||||||
tm.rotateX(math.pi)
|
tm.rotateX(math.pi)
|
||||||
|
@ -1852,7 +1920,7 @@ class Workplane(CQ):
|
||||||
ctxSolid.wrapped = s.wrapped
|
ctxSolid.wrapped = s.wrapped
|
||||||
return self.newObject([s])
|
return self.newObject([s])
|
||||||
|
|
||||||
#but parameter list is different so a simple function pointer wont work
|
#but parameter list is different so a simple function pointer won't work
|
||||||
def cboreHole(self, diameter, cboreDiameter, cboreDepth, depth=None, clean=True):
|
def cboreHole(self, diameter, cboreDiameter, cboreDepth, depth=None, clean=True):
|
||||||
"""
|
"""
|
||||||
Makes a counterbored hole for each item on the stack.
|
Makes a counterbored hole for each item on the stack.
|
||||||
|
@ -1904,7 +1972,7 @@ class Workplane(CQ):
|
||||||
return self.cutEach(_makeCbore, True, clean)
|
return self.cutEach(_makeCbore, True, clean)
|
||||||
|
|
||||||
#TODO: almost all code duplicated!
|
#TODO: almost all code duplicated!
|
||||||
#but parameter list is different so a simple function pointer wont work
|
#but parameter list is different so a simple function pointer won't work
|
||||||
def cskHole(self, diameter, cskDiameter, cskAngle, depth=None, clean=True):
|
def cskHole(self, diameter, cskDiameter, cskAngle, depth=None, clean=True):
|
||||||
"""
|
"""
|
||||||
Makes a countersunk hole for each item on the stack.
|
Makes a countersunk hole for each item on the stack.
|
||||||
|
@ -1955,7 +2023,7 @@ class Workplane(CQ):
|
||||||
return self.cutEach(_makeCsk, True, clean)
|
return self.cutEach(_makeCsk, True, clean)
|
||||||
|
|
||||||
#TODO: almost all code duplicated!
|
#TODO: almost all code duplicated!
|
||||||
#but parameter list is different so a simple function pointer wont work
|
#but parameter list is different so a simple function pointer won't work
|
||||||
def hole(self, diameter, depth=None, clean=True):
|
def hole(self, diameter, depth=None, clean=True):
|
||||||
"""
|
"""
|
||||||
Makes a hole for each item on the stack.
|
Makes a hole for each item on the stack.
|
||||||
|
@ -2146,7 +2214,7 @@ class Workplane(CQ):
|
||||||
|
|
||||||
:param path: A wire along which the pending wires will be swept
|
:param path: A wire along which the pending wires will be swept
|
||||||
:param boolean sweepAlongWires:
|
:param boolean sweepAlongWires:
|
||||||
False to create mutliple swept from wires on the chain along path
|
False to create multiple swept from wires on the chain along path
|
||||||
True to create only one solid swept along path with shape following the list of wires on the chain
|
True to create only one solid swept along path with shape following the list of wires on the chain
|
||||||
:param boolean combine: True to combine the resulting solid with parent solids if found.
|
:param boolean combine: True to combine the resulting solid with parent solids if found.
|
||||||
:param boolean clean: call :py:meth:`clean` afterwards to have a clean shape
|
:param boolean clean: call :py:meth:`clean` afterwards to have a clean shape
|
||||||
|
@ -2473,7 +2541,7 @@ class Workplane(CQ):
|
||||||
|
|
||||||
:param path: A wire along which the pending wires will be swept
|
:param path: A wire along which the pending wires will be swept
|
||||||
:param boolean sweepAlongWires:
|
:param boolean sweepAlongWires:
|
||||||
False to create mutliple swept from wires on the chain along path
|
False to create multiple swept from wires on the chain along path
|
||||||
True to create only one solid swept along path with shape following the list of wires on the chain
|
True to create only one solid swept along path with shape following the list of wires on the chain
|
||||||
:return:a FreeCAD solid, suitable for boolean operations
|
:return:a FreeCAD solid, suitable for boolean operations
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -30,7 +30,7 @@ class CQModel(object):
|
||||||
|
|
||||||
After construction, the metadata property contains
|
After construction, the metadata property contains
|
||||||
a ScriptMetaData object, which describes the model in more detail,
|
a ScriptMetaData object, which describes the model in more detail,
|
||||||
and can be used to retrive the parameters defined by the model.
|
and can be used to retrieve the parameters defined by the model.
|
||||||
|
|
||||||
the build method can be used to generate a 3d model
|
the build method can be used to generate a 3d model
|
||||||
"""
|
"""
|
||||||
|
@ -44,7 +44,7 @@ class CQModel(object):
|
||||||
self.script_source = script_source
|
self.script_source = script_source
|
||||||
self._find_vars()
|
self._find_vars()
|
||||||
|
|
||||||
# TODO: pick up other scirpt metadata:
|
# TODO: pick up other script metadata:
|
||||||
# describe
|
# describe
|
||||||
# pick up validation methods
|
# pick up validation methods
|
||||||
self._find_descriptions()
|
self._find_descriptions()
|
||||||
|
@ -58,7 +58,7 @@ class CQModel(object):
|
||||||
#are only at the top level of the script. IE, we'll ignore any
|
#are only at the top level of the script. IE, we'll ignore any
|
||||||
#variable definitions at lower levels of the script
|
#variable definitions at lower levels of the script
|
||||||
|
|
||||||
#we dont want to use the visit interface because here we excplicitly
|
#we don't want to use the visit interface because here we explicitly
|
||||||
#want to walk only the top level of the tree.
|
#want to walk only the top level of the tree.
|
||||||
assignment_finder = ConstantAssignmentFinder(self.metadata)
|
assignment_finder = ConstantAssignmentFinder(self.metadata)
|
||||||
|
|
||||||
|
@ -85,7 +85,7 @@ class CQModel(object):
|
||||||
:param build_parameters: a dictionary of variables. The variables must be
|
:param build_parameters: a dictionary of variables. The variables must be
|
||||||
assignable to the underlying variable type. These variables override default values in the script
|
assignable to the underlying variable type. These variables override default values in the script
|
||||||
:param build_options: build options for how to build the model. Build options include things like
|
:param build_options: build options for how to build the model. Build options include things like
|
||||||
timeouts, tesselation tolerances, etc
|
timeouts, tessellation tolerances, etc
|
||||||
:raises: Nothing. If there is an exception, it will be on the exception property of the result.
|
:raises: Nothing. If there is an exception, it will be on the exception property of the result.
|
||||||
This is the interface so that we can return other information on the result, such as the build time
|
This is the interface so that we can return other information on the result, such as the build time
|
||||||
:return: a BuildResult object, which includes the status of the result, and either
|
:return: a BuildResult object, which includes the status of the result, and either
|
||||||
|
@ -308,7 +308,7 @@ class ScriptCallback(object):
|
||||||
"""
|
"""
|
||||||
return an object to the executing environment, with options
|
return an object to the executing environment, with options
|
||||||
:param shape: a cadquery object
|
:param shape: a cadquery object
|
||||||
:param options: a dictionary of options that will be made available to the executing envrionment
|
:param options: a dictionary of options that will be made available to the executing environment
|
||||||
"""
|
"""
|
||||||
o = ShapeResult()
|
o = ShapeResult()
|
||||||
o.options=options
|
o.options=options
|
||||||
|
@ -326,7 +326,7 @@ class ScriptCallback(object):
|
||||||
|
|
||||||
def describe_parameter(self,var_data ):
|
def describe_parameter(self,var_data ):
|
||||||
"""
|
"""
|
||||||
Do Nothing-- we parsed the ast ahead of exection to get what we need.
|
Do Nothing-- we parsed the ast ahead of execution to get what we need.
|
||||||
"""
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
|
@ -63,7 +63,7 @@ def _fc_path():
|
||||||
|
|
||||||
# Try to guess if using Anaconda
|
# Try to guess if using Anaconda
|
||||||
if 'env' in sys.prefix:
|
if 'env' in sys.prefix:
|
||||||
if sys.platform.startswith('linux'):
|
if sys.platform.startswith('linux') or sys.platform.startswith('darwin'):
|
||||||
_PATH = os.path.join(sys.prefix,'lib')
|
_PATH = os.path.join(sys.prefix,'lib')
|
||||||
# return PATH if FreeCAD.[so,pyd] is present
|
# return PATH if FreeCAD.[so,pyd] is present
|
||||||
if len(glob.glob(os.path.join(_PATH,'FreeCAD.so'))) > 0:
|
if len(glob.glob(os.path.join(_PATH,'FreeCAD.so'))) > 0:
|
||||||
|
|
|
@ -102,7 +102,7 @@ def disable():
|
||||||
"""
|
"""
|
||||||
Disables logging to FreeCAD console (or STDOUT).
|
Disables logging to FreeCAD console (or STDOUT).
|
||||||
Note, logging may be enabled by another imported module, so this isn't a
|
Note, logging may be enabled by another imported module, so this isn't a
|
||||||
guarentee; this function undoes logging_enable(), nothing more.
|
guarantee; this function undoes logging_enable(), nothing more.
|
||||||
"""
|
"""
|
||||||
global _logging_handler
|
global _logging_handler
|
||||||
if _logging_handler:
|
if _logging_handler:
|
||||||
|
|
|
@ -78,7 +78,7 @@ def exportShape(shape,exportType,fileLike,tolerance=0.1):
|
||||||
#weird, but we need to close this file. the next step is going to write to
|
#weird, but we need to close this file. the next step is going to write to
|
||||||
#it from c code, so it needs to be closed.
|
#it from c code, so it needs to be closed.
|
||||||
#FreeCAD junks up stdout with a bunch of messages, so this context
|
#FreeCAD junks up stdout with a bunch of messages, so this context
|
||||||
#manager supresses that stuff in the case we're trying to write to stdout
|
#manager suppresses that stuff in the case we're trying to write to stdout
|
||||||
os.close(h)
|
os.close(h)
|
||||||
with suppress_stdout_stderr():
|
with suppress_stdout_stderr():
|
||||||
if exportType == ExportTypes.STEP:
|
if exportType == ExportTypes.STEP:
|
||||||
|
|
|
@ -192,7 +192,7 @@ class Vector(object):
|
||||||
"""Return the vector itself
|
"""Return the vector itself
|
||||||
|
|
||||||
The center of myself is myself.
|
The center of myself is myself.
|
||||||
Provided so that vectors, vertexes, and other shapes all support a
|
Provided so that vectors, vertices, and other shapes all support a
|
||||||
common interface, when Center() is requested for all objects on the
|
common interface, when Center() is requested for all objects on the
|
||||||
stack.
|
stack.
|
||||||
"""
|
"""
|
||||||
|
@ -216,7 +216,7 @@ class Vector(object):
|
||||||
def __bool__(self):
|
def __bool__(self):
|
||||||
return any(coord != 0 for coord in self.toTuple())
|
return any(coord != 0 for coord in self.toTuple())
|
||||||
|
|
||||||
__nonzero__ = __bool__ # python 2.x compatability
|
__nonzero__ = __bool__ # python 2.x compatibility
|
||||||
|
|
||||||
def __add__(self, v):
|
def __add__(self, v):
|
||||||
return self.add(v)
|
return self.add(v)
|
||||||
|
@ -433,7 +433,7 @@ class Plane(object):
|
||||||
**Non-orthogonal vectors**
|
**Non-orthogonal vectors**
|
||||||
|
|
||||||
If the ``xDir`` and ``normal`` vectors are not orthogonal, the ``normal``
|
If the ``xDir`` and ``normal`` vectors are not orthogonal, the ``normal``
|
||||||
(or ``z`` axis) vector direction is preserved, and truely orthogonal
|
(or ``z`` axis) vector direction is preserved, and truly orthogonal
|
||||||
``x`` and ``y`` axes are calculated with cross products.
|
``x`` and ``y`` axes are calculated with cross products.
|
||||||
|
|
||||||
* ``y = z.cross(x)``, and
|
* ``y = z.cross(x)``, and
|
||||||
|
|
|
@ -39,12 +39,16 @@ def importStep(fileName):
|
||||||
try:
|
try:
|
||||||
rshape = Part.read(fileName)
|
rshape = Part.read(fileName)
|
||||||
|
|
||||||
#Make sure that we extract all the solids
|
# Extract all solids and surfaces
|
||||||
solids = []
|
geometry = []
|
||||||
for solid in rshape.Solids:
|
for solid in rshape.Solids:
|
||||||
solids.append(Shape.cast(solid))
|
geometry.append(Shape.cast(solid))
|
||||||
|
|
||||||
|
for shell in rshape.Shells:
|
||||||
|
geometry.append(Shape.cast(shell))
|
||||||
|
|
||||||
|
return cadquery.Workplane("XY").newObject(geometry)
|
||||||
|
|
||||||
return cadquery.Workplane("XY").newObject(solids)
|
|
||||||
except:
|
except:
|
||||||
raise ValueError("STEP File Could not be loaded")
|
raise ValueError("STEP File Could not be loaded")
|
||||||
|
|
||||||
|
@ -64,13 +68,7 @@ def importStepFromURL(url):
|
||||||
webFile.close()
|
webFile.close()
|
||||||
tempFile.close()
|
tempFile.close()
|
||||||
|
|
||||||
rshape = Part.read(tempFile.name)
|
# Read saved file and return CQ Workplane object
|
||||||
|
return importStep(tempFile.name)
|
||||||
#Make sure that we extract all the solids
|
|
||||||
solids = []
|
|
||||||
for solid in rshape.Solids:
|
|
||||||
solids.append(Shape.cast(solid))
|
|
||||||
|
|
||||||
return cadquery.Workplane("XY").newObject(solids)
|
|
||||||
except:
|
except:
|
||||||
raise ValueError("STEP File from the URL: " + url + " Could not be loaded")
|
raise ValueError("STEP File from the URL: " + url + " Could not be loaded")
|
||||||
|
|
|
@ -105,7 +105,7 @@ class Shape(object):
|
||||||
return tr
|
return tr
|
||||||
|
|
||||||
# TODO: all these should move into the exporters folder.
|
# TODO: all these should move into the exporters folder.
|
||||||
# we dont need a bunch of exporting code stored in here!
|
# we don't need a bunch of exporting code stored in here!
|
||||||
#
|
#
|
||||||
def exportStl(self, fileName, tolerance=0.1):
|
def exportStl(self, fileName, tolerance=0.1):
|
||||||
self.wrapped.exportStl(fileName, tolerance)
|
self.wrapped.exportStl(fileName, tolerance)
|
||||||
|
@ -354,7 +354,7 @@ class Shape(object):
|
||||||
def transformShape(self, tMatrix):
|
def transformShape(self, tMatrix):
|
||||||
"""
|
"""
|
||||||
tMatrix is a matrix object.
|
tMatrix is a matrix object.
|
||||||
returns a copy of the ojbect, transformed by the provided matrix,
|
returns a copy of the object, transformed by the provided matrix,
|
||||||
with all objects keeping their type
|
with all objects keeping their type
|
||||||
"""
|
"""
|
||||||
tmp = self.wrapped.copy()
|
tmp = self.wrapped.copy()
|
||||||
|
@ -367,14 +367,14 @@ class Shape(object):
|
||||||
"""
|
"""
|
||||||
tMatrix is a matrix object.
|
tMatrix is a matrix object.
|
||||||
|
|
||||||
returns a copy of the object, but with geometry transformed insetad of just
|
returns a copy of the object, but with geometry transformed instead of just
|
||||||
rotated.
|
rotated.
|
||||||
|
|
||||||
WARNING: transformGeometry will sometimes convert lines and circles to splines,
|
WARNING: transformGeometry will sometimes convert lines and circles to splines,
|
||||||
but it also has the ability to handle skew and stretching transformations.
|
but it also has the ability to handle skew and stretching transformations.
|
||||||
|
|
||||||
If your transformation is only translation and rotation, it is safer to use transformShape,
|
If your transformation is only translation and rotation, it is safer to use transformShape,
|
||||||
which doesnt change the underlying type of the geometry, but cannot handle skew transformations
|
which doesn't change the underlying type of the geometry, but cannot handle skew transformations
|
||||||
"""
|
"""
|
||||||
tmp = self.wrapped.copy()
|
tmp = self.wrapped.copy()
|
||||||
tmp = tmp.transformGeometry(tMatrix)
|
tmp = tmp.transformGeometry(tMatrix)
|
||||||
|
@ -449,7 +449,7 @@ class Edge(Shape):
|
||||||
def startPoint(self):
|
def startPoint(self):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
:return: a vector representing the start poing of this edge
|
:return: a vector representing the start point of this edge
|
||||||
|
|
||||||
Note, circles may have the start and end points the same
|
Note, circles may have the start and end points the same
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -155,7 +155,7 @@ class BaseDirSelector(Selector):
|
||||||
#no really good way to avoid a switch here, edges and faces are simply different!
|
#no really good way to avoid a switch here, edges and faces are simply different!
|
||||||
|
|
||||||
if type(o) == Face:
|
if type(o) == Face:
|
||||||
# a face is only parallell to a direction if it is a plane, and its normal is parallel to the dir
|
# a face is only parallel to a direction if it is a plane, and its normal is parallel to the dir
|
||||||
normal = o.normalAt(None)
|
normal = o.normalAt(None)
|
||||||
|
|
||||||
if self.test(normal):
|
if self.test(normal):
|
||||||
|
@ -392,7 +392,7 @@ class SumSelector(BinarySelector):
|
||||||
|
|
||||||
class SubtractSelector(BinarySelector):
|
class SubtractSelector(BinarySelector):
|
||||||
"""
|
"""
|
||||||
Difference selector. Substract results of a selector from another
|
Difference selector. Subtract results of a selector from another
|
||||||
selectors results.
|
selectors results.
|
||||||
"""
|
"""
|
||||||
def filterResults(self, r_left, r_right):
|
def filterResults(self, r_left, r_right):
|
||||||
|
@ -630,7 +630,7 @@ class StringSyntaxSelector(Selector):
|
||||||
***axisStrings*** are: ``X,Y,Z,XY,YZ,XZ`` or ``(x,y,z)`` which defines an arbitrary direction
|
***axisStrings*** are: ``X,Y,Z,XY,YZ,XZ`` or ``(x,y,z)`` which defines an arbitrary direction
|
||||||
|
|
||||||
It is possible to combine simple selectors together using logical operations.
|
It is possible to combine simple selectors together using logical operations.
|
||||||
The following operations are suuported
|
The following operations are supported
|
||||||
|
|
||||||
:and:
|
:and:
|
||||||
Logical AND, e.g. >X and >Y
|
Logical AND, e.g. >X and >Y
|
||||||
|
|
BIN
Libs/cadquery/doc/_static/KiCad_Capacitors_SMD.jpg
vendored
Normal file
BIN
Libs/cadquery/doc/_static/KiCad_Capacitors_SMD.jpg
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 258 KiB |
BIN
Libs/cadquery/doc/_static/KiCad_Capacitors_SMD_thumb.jpg
vendored
Normal file
BIN
Libs/cadquery/doc/_static/KiCad_Capacitors_SMD_thumb.jpg
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 18 KiB |
BIN
Libs/cadquery/doc/_static/extruder_support.png
vendored
Normal file
BIN
Libs/cadquery/doc/_static/extruder_support.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 52 KiB |
BIN
Libs/cadquery/doc/_static/hyOzd-finished_thumb.jpg
vendored
Normal file
BIN
Libs/cadquery/doc/_static/hyOzd-finished_thumb.jpg
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 20 KiB |
BIN
Libs/cadquery/doc/_static/jupyter_showcase_thumb.png
vendored
Normal file
BIN
Libs/cadquery/doc/_static/jupyter_showcase_thumb.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 59 KiB |
BIN
Libs/cadquery/doc/_static/march30_landing_page.png
vendored
Normal file
BIN
Libs/cadquery/doc/_static/march30_landing_page.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 90 KiB |
|
@ -146,7 +146,7 @@ Selectors
|
||||||
------------------------
|
------------------------
|
||||||
|
|
||||||
Objects that filter and select CAD objects. Selectors are used to select existing geometry
|
Objects that filter and select CAD objects. Selectors are used to select existing geometry
|
||||||
as a basis for futher operations.
|
as a basis for further operations.
|
||||||
|
|
||||||
.. currentmodule:: cadquery
|
.. currentmodule:: cadquery
|
||||||
|
|
||||||
|
|
|
@ -108,7 +108,7 @@ If a parameter called 'param' is defined in the model, it will be assigned the v
|
||||||
An error will occur if a value is provided that is not defined in the model, or if the value provided cannot
|
An error will occur if a value is provided that is not defined in the model, or if the value provided cannot
|
||||||
be assigned to a variable with the given name.
|
be assigned to a variable with the given name.
|
||||||
|
|
||||||
build_options is used to set server-side settings like timeouts, tesselation tolerances, and other details about
|
build_options is used to set server-side settings like timeouts, tessellation tolerances, and other details about
|
||||||
how the model should be built.
|
how the model should be built.
|
||||||
|
|
||||||
|
|
||||||
|
@ -141,7 +141,7 @@ You can list the variables defined in the model by using the return value of the
|
||||||
The key of the dictionary is a string , and the value is a :py:class:`cadquery.cqgi.InputParameter` object
|
The key of the dictionary is a string , and the value is a :py:class:`cadquery.cqgi.InputParameter` object
|
||||||
See the CQGI API docs for more details.
|
See the CQGI API docs for more details.
|
||||||
|
|
||||||
Future enhancments will include a safer sandbox to prevent malicious scripts.
|
Future enhancements will include a safer sandbox to prevent malicious scripts.
|
||||||
|
|
||||||
Important CQGI Methods
|
Important CQGI Methods
|
||||||
-------------------------
|
-------------------------
|
||||||
|
|
|
@ -38,7 +38,7 @@ If you have experience with 3D CAD systems, you also know that there is a key de
|
||||||
After the base block is created, how the hole is located is key. If it is located from one edge, changing the block
|
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.
|
size will have a different affect than if the hole is located from the center.
|
||||||
|
|
||||||
Many scripting langauges do not provide a way to capture design intent-- because they require that you always work in
|
Many scripting languages do 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
|
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.
|
the design intent just like a human would when creating a drawing or building an object.
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,7 @@ Items introduced in the example are marked with a **!**
|
||||||
You may want to work through these examples by pasting the text into a scratchpad on the live website.
|
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:
|
If you do, make sure to take these steps so that they work:
|
||||||
|
|
||||||
1. paste the content into the build() method, properly intented, and
|
1. paste the content into the build() method, properly indented, and
|
||||||
2. add the line 'return result' at the end. The samples below are autogenerated, but they use a different
|
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.
|
syntax than the models on the website need to be.
|
||||||
|
|
||||||
|
@ -29,7 +29,7 @@ Items introduced in the example are marked with a **!**
|
||||||
|
|
||||||
.. warning::
|
.. warning::
|
||||||
|
|
||||||
* You have to have an svg capable browser to view these!
|
* You have to have an SVG capable browser to view these!
|
||||||
|
|
||||||
.. contents:: List of Examples
|
.. contents:: List of Examples
|
||||||
:backlinks: entry
|
:backlinks: entry
|
||||||
|
@ -199,7 +199,7 @@ like :py:meth:`Workplane.circle` and :py:meth:`Workplane.rect`, will operate on
|
||||||
Polygons
|
Polygons
|
||||||
-------------------------
|
-------------------------
|
||||||
|
|
||||||
You can create polygons for each stack point if you would like. Useful in 3d printers whos firmware does not
|
You can create polygons for each stack point if you would like. Useful in 3d printers whose firmware does not
|
||||||
correct for small hole sizes.
|
correct for small hole sizes.
|
||||||
|
|
||||||
.. cq_plot::
|
.. cq_plot::
|
||||||
|
@ -604,6 +604,35 @@ Here we fillet all of the edges of a simple plate.
|
||||||
* :py:meth:`Workplane.edges`
|
* :py:meth:`Workplane.edges`
|
||||||
* :py:meth:`Workplane`
|
* :py:meth:`Workplane`
|
||||||
|
|
||||||
|
A reinforced junction between two pieces with Fillet
|
||||||
|
-----------------------------------------
|
||||||
|
|
||||||
|
The fillet can also be used to reinfoce a junction between two pieces.
|
||||||
|
|
||||||
|
.. cq_plot::
|
||||||
|
|
||||||
|
s = cq.Workplane("XY")
|
||||||
|
|
||||||
|
horizontalPart = s.box(10, 5, 1)
|
||||||
|
verticalPart = s.box(10, 1, 5).translate((0, 0, 1 + 5/2))
|
||||||
|
|
||||||
|
result = horizontalPart.union(verticalPart) \
|
||||||
|
.faces(">Z[1]").edges("not(<X or >X or <Y or >Y)").fillet(1)
|
||||||
|
|
||||||
|
show_object(result)
|
||||||
|
|
||||||
|
.. topic:: Api References
|
||||||
|
|
||||||
|
.. hlist::
|
||||||
|
:columns: 2
|
||||||
|
|
||||||
|
* :py:meth:`Workplane`
|
||||||
|
* :py:meth:`Workplane.box`
|
||||||
|
* :py:meth:`Workplane.faces`
|
||||||
|
* :py:meth:`Workplane.edges`
|
||||||
|
* :ref:`selector_reference`
|
||||||
|
* :py:meth:`Workplane.fillet`
|
||||||
|
|
||||||
A Parametric Bearing Pillow Block
|
A Parametric Bearing Pillow Block
|
||||||
------------------------------------
|
------------------------------------
|
||||||
|
|
||||||
|
@ -621,7 +650,6 @@ with just a few lines of code.
|
||||||
|
|
||||||
show_object(result)
|
show_object(result)
|
||||||
|
|
||||||
|
|
||||||
Splitting an Object
|
Splitting an Object
|
||||||
---------------------
|
---------------------
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@ Extending CadQuery
|
||||||
======================
|
======================
|
||||||
|
|
||||||
|
|
||||||
If you find that CadQuery doesnt suit your needs, you can easily extend it. CadQuery provides several extension
|
If you find that CadQuery doesn't suit your needs, you can easily extend it. CadQuery provides several extension
|
||||||
methods:
|
methods:
|
||||||
|
|
||||||
* You can load plugins others have developed. This is by far the easiest way to access other code
|
* You can load plugins others have developed. This is by far the easiest way to access other code
|
||||||
|
@ -25,7 +25,7 @@ is actually equivalent to::
|
||||||
return Part.makeBox(1.0,2.0,3.0)
|
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
|
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::
|
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)
|
box = Part.makeBox(1.0,2.0,3.0)
|
||||||
cq = CQ(box).faces(">Z").size() # returns 6
|
cq = CQ(box).faces(">Z").size() # returns 6
|
||||||
|
@ -108,7 +108,7 @@ are designed to aid in plugin creation:
|
||||||
* :py:meth:`cadquery.Workplane.plane` provides a reference to the workplane, which allows you to convert between workplane
|
* :py:meth:`cadquery.Workplane.plane` provides a reference to the workplane, which allows you to convert between workplane
|
||||||
coordinates and global coordinates:
|
coordinates and global coordinates:
|
||||||
* :py:meth:`cadquery.freecad_impl.geom.Plane.toWorldCoords` will convert local coordinates to global ones
|
* :py:meth:`cadquery.freecad_impl.geom.Plane.toWorldCoords` will convert local coordinates to global ones
|
||||||
* :py:meth:`cadquery.freecad_impl.geom.Plane.toLocalCoords` will convet from global coordinates to local coordinates
|
* :py:meth:`cadquery.freecad_impl.geom.Plane.toLocalCoords` will convert from global coordinates to local coordinates
|
||||||
|
|
||||||
Coordinate Systems
|
Coordinate Systems
|
||||||
-----------------------
|
-----------------------
|
||||||
|
@ -140,7 +140,7 @@ That's it!
|
||||||
|
|
||||||
CadQueryExample Plugins
|
CadQueryExample Plugins
|
||||||
-----------------------
|
-----------------------
|
||||||
Some core cadquery code is intentionally written exactly like a plugin.
|
Some core CadQuery code is intentionally written exactly like a plugin.
|
||||||
If you are writing your own plugins, have a look at these methods for inspiration:
|
If you are writing your own plugins, have a look at these methods for inspiration:
|
||||||
|
|
||||||
* :py:meth:`cadquery.Workplane.polygon`
|
* :py:meth:`cadquery.Workplane.polygon`
|
||||||
|
@ -177,4 +177,3 @@ This ultra simple plugin makes cubes of the specified size for each stack point.
|
||||||
.rect(4.0,4.0,forConstruction=True).vertices() \
|
.rect(4.0,4.0,forConstruction=True).vertices() \
|
||||||
.makeCubes(1.0).combineSolids()
|
.makeCubes(1.0).combineSolids()
|
||||||
show_object(result)
|
show_object(result)
|
||||||
|
|
||||||
|
|
|
@ -10,8 +10,11 @@ Prerequisites--FreeCAD and Python 2.6 or 2.7
|
||||||
----------------------------------------------
|
----------------------------------------------
|
||||||
CadQuery requires FreeCAD and Python version 2.6.x or 2.7.x *Python 3.x is NOT supported*
|
CadQuery requires FreeCAD and Python version 2.6.x or 2.7.x *Python 3.x is NOT supported*
|
||||||
|
|
||||||
Ubuntu Command Line Installation
|
Installation
|
||||||
------------------------------------------
|
-------------------
|
||||||
|
|
||||||
|
Ubuntu
|
||||||
|
^^^^^^^^^^^^^^
|
||||||
|
|
||||||
On Ubuntu, you can type::
|
On Ubuntu, you can type::
|
||||||
|
|
||||||
|
@ -21,22 +24,37 @@ On Ubuntu, you can type::
|
||||||
This `Unix Installation Video <http://youtu.be/InZu8jgaYCA>`_ will walk you through the installation
|
This `Unix Installation Video <http://youtu.be/InZu8jgaYCA>`_ will walk you through the installation
|
||||||
|
|
||||||
|
|
||||||
Installation: Other Platforms
|
Windows & Mac
|
||||||
------------------------------------------
|
^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
1. Install FreeCAD using the appropriate installer for your platform, on `www.freecadweb.org <http://www.freecadweb.org/wiki/?title=Download>`_
|
1. Install FreeCAD using the appropriate installer for your platform, on `www.freecadweb.org <http://www.freecadweb.org/wiki/?title=Download>`_
|
||||||
2. pip install cadquery
|
2. pip install cadquery
|
||||||
|
|
||||||
This `Windows Installation video <https://www.youtube.com/watch?v=dWw4Y_ah-8k>`_ will walk you through the installation on Windows
|
This `Windows Installation video <https://www.youtube.com/watch?v=dWw4Y_ah-8k>`_ will walk you through the installation on Windows
|
||||||
|
|
||||||
|
|
||||||
|
Anaconda (cross-platform)
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
Alternatively you can use Anaconda's package management system to install
|
||||||
|
cadquery and its dependencies, including FreeCAD.
|
||||||
|
|
||||||
|
1. Install `Anaconda <https://www.anaconda.com/download>`_
|
||||||
|
2. Open an anaconda prompt and run:
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
conda install -c conda-forge cadquery
|
||||||
|
|
||||||
|
|
||||||
Test Your Installation
|
Test Your Installation
|
||||||
------------------------
|
------------------------
|
||||||
|
|
||||||
If all has gone well, you can open a command line/prompt, and type::
|
If all has gone well, you can open a command line/prompt, and type::
|
||||||
|
|
||||||
$python
|
$ python
|
||||||
$import cadquery
|
>>> import cadquery
|
||||||
$cadquery.Workplane('XY').box(1,2,3).toSvg()
|
>>> cadquery.Workplane('XY').box(1,2,3).toSvg()
|
||||||
|
|
||||||
Adding a Nicer GUI via the cadquery-freecad-module
|
Adding a Nicer GUI via the cadquery-freecad-module
|
||||||
--------------------------------------------------------
|
--------------------------------------------------------
|
||||||
|
|
|
@ -19,7 +19,7 @@ CadQuery is an intuitive, easy-to-use python library for building parametric 3D
|
||||||
* Provide a non-proprietary, plain text model format that can be edited and executed with only a web browser
|
* Provide a non-proprietary, plain text model format that can be edited and executed with only a web browser
|
||||||
|
|
||||||
CadQuery is based on
|
CadQuery is based on
|
||||||
`FreeCAD <http://sourceforge.net/apps/mediawiki/free-cad/index.php?title=Main_Page>`_,
|
`FreeCAD <https://www.freecadweb.org/>`_,
|
||||||
which is turn based on the open-source `OpenCascade <http://www.opencascade.com/>`_ modelling kernel.
|
which is turn based on the open-source `OpenCascade <http://www.opencascade.com/>`_ modelling kernel.
|
||||||
|
|
||||||
Using CadQuery, you can build fully parametric models with a very small amount of code. For example, this simple script
|
Using CadQuery, you can build fully parametric models with a very small amount of code. For example, this simple script
|
||||||
|
|
|
@ -63,7 +63,7 @@ See :ref:`2dOperations` to learn more.
|
||||||
3D Construction
|
3D Construction
|
||||||
---------------------------
|
---------------------------
|
||||||
|
|
||||||
You can construct 3D primatives such as boxes, spheres, wedges, and cylinders directly. You can also sweep, extrude,
|
You can construct 3D primitives 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.
|
and loft 2D geometry to form 3D features. Of course the basic primitive operations are also available.
|
||||||
|
|
||||||
See :ref:`3doperations` to learn more.
|
See :ref:`3doperations` to learn more.
|
||||||
|
@ -74,7 +74,7 @@ Selectors
|
||||||
---------------------------
|
---------------------------
|
||||||
|
|
||||||
Selectors allow you to select one or more features, for use to define new features. As an example, you might
|
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
|
extrude a box, and then select the top face as the location for a new feature. Or, you might extrude a box, and
|
||||||
then select all of the vertical edges so that you can apply a fillet to them.
|
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.
|
You can select Vertices, Edges, Faces, Solids, and Wires using selectors.
|
||||||
|
|
|
@ -11,14 +11,14 @@ Want a quick glimpse of what CadQuery can do? This quickstart will demonstrate
|
||||||
Prerequisites: FreeCAD + cadQuery-freeCAD-module in FreeCAD
|
Prerequisites: FreeCAD + cadQuery-freeCAD-module in FreeCAD
|
||||||
==============================================================
|
==============================================================
|
||||||
|
|
||||||
If you have not already done so, follow the :ref:`installation`, and to install cadquery, FreeCAD,
|
If you have not already done so, follow the :ref:`installation`, and to install CadQuery, FreeCAD,
|
||||||
and the cadquery-freecad-module
|
and the cadquery-freecad-module
|
||||||
|
|
||||||
After installation, open the CadQuery workbench:
|
After installation, open the CadQuery workbench:
|
||||||
|
|
||||||
.. image:: _static/quickstart/001.png
|
.. image:: _static/quickstart/001.png
|
||||||
|
|
||||||
You'll see that we start out with a single block. Find the cadquery Code Window, at the bottom left.
|
You'll see that we start out with a single block. Find the CadQuery Code Window, at the bottom left.
|
||||||
|
|
||||||
If you want check out a couple of the examples in the CadQuery->Examples menu.
|
If you want check out a couple of the examples in the CadQuery->Examples menu.
|
||||||
|
|
||||||
|
@ -170,7 +170,7 @@ There are a couple of things to note about this line:
|
||||||
tells CadQuery that this rectangle will not form a part of the solid,
|
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.
|
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
|
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
|
3. Unless you specify 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
|
this case, the center of the top face of the block. So this rectangle will be centered on the face
|
||||||
|
|
||||||
|
|
||||||
|
@ -236,7 +236,7 @@ with < 20 lines of code.
|
||||||
Want to learn more?
|
Want to learn more?
|
||||||
====================
|
====================
|
||||||
|
|
||||||
* Use the CadQuery->Examples menu of the cadquery workbench to explore a lot of other examples.
|
* Use the CadQuery->Examples menu of the CadQuery workbench to explore a lot of other examples.
|
||||||
* The :ref:`examples` contains lots of examples demonstrating cadquery features
|
* The :ref:`examples` contains lots of examples demonstrating CadQuery features
|
||||||
* The :ref:`apireference` is a good overview of language features grouped by function
|
* 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.
|
* The :ref:`classreference` is the hard-core listing of all functions available.
|
|
@ -8,10 +8,10 @@ width = 2.2 # Nominal x dimension of the part
|
||||||
height = 0.5 # Height from bottom top to the top of the top :P
|
height = 0.5 # Height from bottom top to the top of the top :P
|
||||||
length = 1.5 # Nominal y dimension of the part
|
length = 1.5 # Nominal y dimension of the part
|
||||||
trapezoidFudge = 0.7 # ratio of trapezoid bases. set to 1.0 for cube
|
trapezoidFudge = 0.7 # ratio of trapezoid bases. set to 1.0 for cube
|
||||||
xHoleOffset = 0.500 # Holes are distributed symetrically about each axis
|
xHoleOffset = 0.500 # Holes are distributed symmetrically about each axis
|
||||||
yHoleOffset = 0.500
|
yHoleOffset = 0.500
|
||||||
zFilletRadius = 0.50 # Fillet radius of corners perp. to Z axis.
|
zFilletRadius = 0.50 # Fillet radius of corners perp. to Z axis.
|
||||||
yFilletRadius = 0.250 # Fillet readius of the top edge of the case
|
yFilletRadius = 0.250 # Fillet radius of the top edge of the case
|
||||||
lipHeight = 0.1 # The height of the lip on the inside of the cover
|
lipHeight = 0.1 # The height of the lip on the inside of the cover
|
||||||
wallThickness = 0.06 # Wall thickness for the case
|
wallThickness = 0.06 # Wall thickness for the case
|
||||||
coverThickness = 0.2 # Thickness of the cover plate
|
coverThickness = 0.2 # Thickness of the cover plate
|
||||||
|
@ -23,7 +23,7 @@ yzplane = cq.Workplane("YZ")
|
||||||
|
|
||||||
|
|
||||||
def trapezoid(b1, b2, h):
|
def trapezoid(b1, b2, h):
|
||||||
"Defines a symetrical trapezoid in the XY plane."
|
"Defines a symmetrical trapezoid in the XY plane."
|
||||||
|
|
||||||
y = h / 2
|
y = h / 2
|
||||||
x1 = b1 / 2
|
x1 = b1 / 2
|
||||||
|
|
|
@ -104,7 +104,7 @@ res = res.vLine(-support_depth).\
|
||||||
res = res.extrude(main_plate_size_x/2, both=True, clean=True) # extrude the triangle, now the bridge has a nice support making it much more stiff
|
res = res.extrude(main_plate_size_x/2, both=True, clean=True) # extrude the triangle, now the bridge has a nice support making it much more stiff
|
||||||
|
|
||||||
# Start cutting out a slot for hotend mounting
|
# Start cutting out a slot for hotend mounting
|
||||||
face = res.faces('>Y') # select the most extreme face in Y direction, i.e. top ot the "bridge"
|
face = res.faces('>Y') # select the most extreme face in Y direction, i.e. top of the "bridge"
|
||||||
res = move_to_center(face.workplane(), face.edges('>Z').val()) # shift the workplane to the center of the most extreme edge of the bridge
|
res = move_to_center(face.workplane(), face.edges('>Z').val()) # shift the workplane to the center of the most extreme edge of the bridge
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
import cadquery as cq
|
||||||
|
from cadquery import selectors
|
||||||
|
|
||||||
|
# This exemple demonstrates the use of a fillet to reinforce a junction between two parts.
|
||||||
|
# It relies on the selection of an edge of the weak junction, and the use of fillet.
|
||||||
|
|
||||||
|
# 1 - The construction of the model : a pipe connector
|
||||||
|
# In that model, the junction surface between the box and the cylinder is small.
|
||||||
|
# This makes the junction between the two too weak.
|
||||||
|
model = cq.Workplane("XY").box(15.0, 15.0, 2.0)\
|
||||||
|
.faces(">Z").rect(10.0, 10.0, forConstruction=True)\
|
||||||
|
.vertices().cskHole(2.0, 4.0, 82)\
|
||||||
|
.faces(">Z").circle(4.0).extrude(10.0)\
|
||||||
|
.faces(">Z").hole(6)
|
||||||
|
|
||||||
|
# 2 - Reinforcement of the junction
|
||||||
|
# Two steps here :
|
||||||
|
# - select the edge to reinforce. Here we search the closest edge from the center on the top face of the box.
|
||||||
|
# - apply a fillet or a chamfer to that edge
|
||||||
|
result = model.faces('<Z[1]').edges(selectors.NearestToPointSelector((0.0, 0.0))).fillet(1)
|
||||||
|
|
||||||
|
# Additional note :
|
||||||
|
# Using a type selector to select circles on the face would have returned all the circles, including the one to reinforce,
|
||||||
|
# but also the ones for the countersunk holes.
|
||||||
|
# The order of the edges returned by the selector is not guaranteed, so selecting the circle in the stack would not be reliable.
|
||||||
|
# If there was only one circle on the face, then this would have worked perfectly :
|
||||||
|
# result = model.faces('<Z[1]').edges('%Circle').fillet(1)
|
||||||
|
|
||||||
|
show_object(result)
|
|
@ -0,0 +1,2 @@
|
||||||
|
[metadata]
|
||||||
|
license_file = LICENSE
|
|
@ -18,9 +18,7 @@ from setuptools import setup
|
||||||
|
|
||||||
#if we are building in travis, use the build number as the sub-minor version
|
#if we are building in travis, use the build number as the sub-minor version
|
||||||
version = '1.2.0'
|
version = '1.2.0'
|
||||||
if 'TRAVIS_TAG' in list(os.environ.keys()):
|
version = os.environ.get('TRAVIS_TAG', None) or version
|
||||||
version= os.environ['TRAVIS_TAG']
|
|
||||||
|
|
||||||
|
|
||||||
setup(
|
setup(
|
||||||
name='cadquery',
|
name='cadquery',
|
||||||
|
@ -30,7 +28,7 @@ setup(
|
||||||
author='David Cowden',
|
author='David Cowden',
|
||||||
author_email='dave.cowden@gmail.com',
|
author_email='dave.cowden@gmail.com',
|
||||||
description='CadQuery is a parametric scripting language for creating and traversing CAD models',
|
description='CadQuery is a parametric scripting language for creating and traversing CAD models',
|
||||||
long_description=codecs.open('README.md', 'rb', 'UTF-8').read(),
|
long_description=codecs.open('README.rst', 'rb', 'UTF-8').read(),
|
||||||
packages=['cadquery','cadquery.contrib','cadquery.freecad_impl','cadquery.plugins','tests'],
|
packages=['cadquery','cadquery.contrib','cadquery.freecad_impl','cadquery.plugins','tests'],
|
||||||
install_requires=['pyparsing'],
|
install_requires=['pyparsing'],
|
||||||
include_package_data=True,
|
include_package_data=True,
|
||||||
|
|
|
@ -107,7 +107,7 @@ class TestCQGI(BaseTest):
|
||||||
def test_that_invalid_syntax_in_script_fails_immediately(self):
|
def test_that_invalid_syntax_in_script_fails_immediately(self):
|
||||||
badscript = textwrap.dedent(
|
badscript = textwrap.dedent(
|
||||||
"""
|
"""
|
||||||
this doesnt even compile
|
this doesn't even compile
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -519,6 +519,35 @@ class TestCadQuery(BaseTest):
|
||||||
self.saveModel(s)
|
self.saveModel(s)
|
||||||
self.assertEqual(6+NUMX*NUMY*2,s.faces().size()) #6 faces for the box, 2 faces for each cylinder
|
self.assertEqual(6+NUMX*NUMY*2,s.faces().size()) #6 faces for the box, 2 faces for each cylinder
|
||||||
|
|
||||||
|
def testPolarArray(self):
|
||||||
|
radius = 10
|
||||||
|
|
||||||
|
# Test for proper number of elements
|
||||||
|
s = Workplane("XY").polarArray(radius, 0, 180, 1)
|
||||||
|
self.assertEqual(1, s.size())
|
||||||
|
s = Workplane("XY").polarArray(radius, 0, 180, 6)
|
||||||
|
self.assertEqual(6, s.size())
|
||||||
|
|
||||||
|
# Test for proper placement when fill == True
|
||||||
|
s = Workplane("XY").polarArray(radius, 0, 180, 3)
|
||||||
|
self.assertAlmostEqual(0, s.objects[1].x)
|
||||||
|
self.assertAlmostEqual(radius, s.objects[1].y)
|
||||||
|
|
||||||
|
# Test for proper placement when angle to fill is multiple of 360 deg
|
||||||
|
s = Workplane("XY").polarArray(radius, 0, 360, 4)
|
||||||
|
self.assertAlmostEqual(0, s.objects[1].x)
|
||||||
|
self.assertAlmostEqual(radius, s.objects[1].y)
|
||||||
|
|
||||||
|
# Test for proper placement when fill == False
|
||||||
|
s = Workplane("XY").polarArray(radius, 0, 90, 3, fill=False)
|
||||||
|
self.assertAlmostEqual(0, s.objects[1].x)
|
||||||
|
self.assertAlmostEqual(radius, s.objects[1].y)
|
||||||
|
|
||||||
|
# Test for proper operation of startAngle
|
||||||
|
s = Workplane("XY").polarArray(radius, 90, 180, 3)
|
||||||
|
self.assertAlmostEqual(0, s.objects[0].x)
|
||||||
|
self.assertAlmostEqual(radius, s.objects[0].y)
|
||||||
|
|
||||||
def testNestedCircle(self):
|
def testNestedCircle(self):
|
||||||
s = Workplane("XY").box(40,40,5).pushPoints([(10,0),(0,10)]).circle(4).circle(2).extrude(4)
|
s = Workplane("XY").box(40,40,5).pushPoints([(10,0),(0,10)]).circle(4).circle(2).extrude(4)
|
||||||
self.saveModel(s)
|
self.saveModel(s)
|
||||||
|
@ -608,7 +637,7 @@ class TestCadQuery(BaseTest):
|
||||||
self.assertEqual(0,s.faces().size() ) # the original workplane does not, because it did not have a solid initially
|
self.assertEqual(0,s.faces().size() ) # the original workplane does not, because it did not have a solid initially
|
||||||
|
|
||||||
t = r.faces(">Z").workplane().rect(0.25,0.25).extrude(0.5,False)
|
t = r.faces(">Z").workplane().rect(0.25,0.25).extrude(0.5,False)
|
||||||
self.assertEqual(6,t.faces().size()) #result has 6 faces, becuase it was not combined with the original
|
self.assertEqual(6,t.faces().size()) #result has 6 faces, because it was not combined with the original
|
||||||
self.assertEqual(6,r.faces().size()) #original is unmodified as well
|
self.assertEqual(6,r.faces().size()) #original is unmodified as well
|
||||||
#subseuent opertions use that context solid afterwards
|
#subseuent opertions use that context solid afterwards
|
||||||
|
|
||||||
|
@ -799,7 +828,7 @@ class TestCadQuery(BaseTest):
|
||||||
s = Workplane(Plane.XY())
|
s = Workplane(Plane.XY())
|
||||||
|
|
||||||
#TODO: extrude() should imply wire() if not done already
|
#TODO: extrude() should imply wire() if not done already
|
||||||
#most users dont understand what a wire is, they are just drawing
|
#most users don't understand what a wire is, they are just drawing
|
||||||
|
|
||||||
r = s.lineTo(1.0,0).lineTo(0,1.0).close().wire().extrude(0.25)
|
r = s.lineTo(1.0,0).lineTo(0,1.0).close().wire().extrude(0.25)
|
||||||
with suppress_stdout_stderr():
|
with suppress_stdout_stderr():
|
||||||
|
@ -881,6 +910,23 @@ class TestCadQuery(BaseTest):
|
||||||
assert(a1.edges().first().val().Length() == a2.edges().first().val().Length())
|
assert(a1.edges().first().val().Length() == a2.edges().first().val().Length())
|
||||||
assert(a3.edges().first().val().Length() == a4.edges().first().val().Length())
|
assert(a3.edges().first().val().Length() == a4.edges().first().val().Length())
|
||||||
|
|
||||||
|
def testPolarLines(self):
|
||||||
|
"""
|
||||||
|
Draw some polar lines and check expected results
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Test the PolarLine* functions
|
||||||
|
s = Workplane(Plane.XY())
|
||||||
|
r = s.polarLine(10, 45) \
|
||||||
|
.polarLineTo(10, -45) \
|
||||||
|
.polarLine(10, -180) \
|
||||||
|
.polarLine(-10, -90) \
|
||||||
|
.close()
|
||||||
|
|
||||||
|
# a single wire, 5 edges
|
||||||
|
self.assertEqual(1, r.wires().size())
|
||||||
|
self.assertEqual(5, r.wires().edges().size())
|
||||||
|
|
||||||
def testLargestDimension(self):
|
def testLargestDimension(self):
|
||||||
"""
|
"""
|
||||||
Tests the largestDimension function when no solids are on the stack and when there are
|
Tests the largestDimension function when no solids are on the stack and when there are
|
||||||
|
@ -1488,7 +1534,7 @@ class TestCadQuery(BaseTest):
|
||||||
return cup
|
return cup
|
||||||
"""
|
"""
|
||||||
|
|
||||||
#for some reason shell doesnt work on this simple shape. how disappointing!
|
#for some reason shell doesn't work on this simple shape. how disappointing!
|
||||||
td = 50.0
|
td = 50.0
|
||||||
bd = 20.0
|
bd = 20.0
|
||||||
h = 10.0
|
h = 10.0
|
||||||
|
|
|
@ -43,7 +43,7 @@ def toTuple(v):
|
||||||
elif type(v) == Vector:
|
elif type(v) == Vector:
|
||||||
return v.toTuple()
|
return v.toTuple()
|
||||||
else:
|
else:
|
||||||
raise RuntimeError("dont know how to convert type %s to tuple" % str(type(v)) )
|
raise RuntimeError("don't know how to convert type %s to tuple" % str(type(v)) )
|
||||||
|
|
||||||
|
|
||||||
class BaseTest(unittest.TestCase):
|
class BaseTest(unittest.TestCase):
|
||||||
|
|
Loading…
Reference in New Issue
Block a user