cqparts package

Submodules

cqparts.assembly module

class cqparts.assembly.Assembly(*largs, **kwargs)

Bases: cqparts.component.Component

An assembly is a group of parts, and other assemblies (called components)

build(recursive=True)

Building an assembly buffers the components() and constraints().

Running build() is optional, it’s automatically run when requesting components() or constraints().

Mostly it’s used to test that there aren’t any critical runtime issues with its construction, but doing anything like displaying or exporting will ultimately run a build anyway.

Parameters:recursive (bool) – if set, iterates through child components and builds those as well.
components

Returns full dict of Component instances, after a successful build()

Returns:dict of named Component instances
Return type:dict

For more information read about the Assembly Build Cycle .

constraints

Returns full list of Constraint instances, after a successful build()

Returns:list of named Constraint instances
Return type:list

For more information read about the Assembly Build Cycle .

find(keys, _index=0)
Parameters:keys (str or list) – key path. 'a.b' is equivalent to ['a', 'b']

Find a nested Component by a “.” separated list of names. for example:

>>> motor.find('bearing.outer_ring')

would return the Part instance of the motor bearing’s outer ring.

>>> bearing = motor.find('bearing')
>>> ring = bearing.find('inner_ring')  # equivalent of 'bearing.inner_ring'

the above code does much the same thing, bearing is an Assembly, and ring is a Part.

Note

For a key path of a.b.c the c key can referernce any Component type.

Everything prior (in this case a and b) must reference an Assembly.

make_alterations()

Make necessary changes to components after the constraints solver has completed.

Tip

This can be overridden in inheriting class, read:

make_components()

Create and return dict of Component instances.

Tip

This must be overridden in inheriting class, read:

Returns:{<name>: <Component>, …}
Return type:dict of Component instances
make_constraints()

Create and return list of Constraint instances

Tip

This must be overridden in inheriting class, read:

Returns:constraints for assembly children’s placement
Return type:list of Constraint instances

Default behaviour returns an empty list; assumes assembly is entirely unconstrained.

solve()

Run the solver and assign the solution’s CoordSystem instances as the corresponding part’s world coordinates.

tree_str(name=None, prefix='', add_repr=False, _depth=0)

Return string listing recursively the assembly hierarchy

Parameters:
  • name (str) – if set, names the tree’s trunk, otherwise the object’s repr() names the tree
  • prefix (str) – string prefixed to each line, can be used to indent
  • add_repr (bool) – if set, component repr() is put after their names
Returns:

Printable string of an assembly’s component hierarchy.

Return type:

str

Example output from block_tree.py

>>> log = logging.getLogger(__name__)
>>> isinstance(block_tree, Assembly)
True
>>> log.info(block_tree.tree_str(name="block_tree"))
block_tree
 ├○ branch_lb
 ├○ branch_ls
 ├─ branch_r
 │   ├○ L
 │   ├○ R
 │   ├○ branch
 │   ├─ house
 │   │   ├○ bar
 │   │   └○ foo
 │   └○ split
 ├○ trunk
 └○ trunk_split

Where:

  • denotes an Assembly, and
  • denotes a Part
static verify_components(components)

Verify values returned from make_components().

Used internally during the build() process.

Parameters:components (dict) – value returned from make_components()
Raises:ValueError – if verification fails
static verify_constraints(constraints)

Verify values returned from make_constraints().

Used internally during the build() process.

Parameters:constraints (list) – value returned from make_constraints()
Raises:ValueError – if verification fails

cqparts.component module

class cqparts.component.Component(*largs, **kwargs)

Bases: cqparts.params.parametric_object.ParametricObject

Note

Both the Part and Assembly classes inherit from Component.

Wherever the term “component” is used, it is in reference to an instance of either Part or Assembly.

build(recursive=True)
Raises:NotImplementedError – must be overridden by inheriting classes to function
exporter(exporter_name=None)

Get an exporter instance to write the component’s content to file.

Parameters:exporter_name (str) – registered name of exporter to use, see register_exporter() for more information.

For example, to get a ThreejsJSONExporter instance to import a json file:

>>> from cqparts_misc.basic.primatives import Box
>>> box = Box()
>>> json_exporter = box.exporter('json')

>>> # then each exporter will behave differently
>>> json_exporter('out.json')  

To learn more: Import / Export

classmethod importer(importer_name=None)

Get an importer instance to instantiate a component from file.

Parameters:importer_name (str) – registered name of importer to use, see register_importer() for more information.

For example, to get an importer to instantiate a Part from a STEP file:

>>> from cqparts import Part
>>> step_importer = Part.importer('step')

>>> # then each importer will behave differently
>>> my_part = step_importer('my_file.step')  

To learn more: Import / Export

mate_origin
Returns:mate at object’s origin
Return type:Mate
world_coords

Component’s placement in word coordinates (CoordSystem)

Returns:coordinate system in the world, None if not set.
Return type:CoordSystem

cqparts.errors module

exception cqparts.errors.AssemblyFindError

Bases: exceptions.Exception

Raised when an assembly element cannot be found

exception cqparts.errors.MakeError

Bases: exceptions.Exception

Raised when there are issues during the make() process of a Part or Assembly

exception cqparts.errors.ParameterError

Bases: exceptions.Exception

Raised when an invalid parameter is specified

exception cqparts.errors.SearchError

Bases: exceptions.Exception

Raised by search algithms, for example cqparts.search.find()

Parent of both SearchNoneFoundError & SearchMultipleFoundError

>>> from cqparts.errors import SearchError
>>> from cqparts.search import find

>>> try:
...     part_a_class = find(a='common', b='criteria')  # multiple results
...     part_b_class = find(a="doesn't exist")  # no results
... except SearchError:
...     # error handling?
...     pass
exception cqparts.errors.SearchMultipleFoundError

Bases: cqparts.errors.SearchError

Raised when multiple results are found by cqparts.search.find()

exception cqparts.errors.SearchNoneFoundError

Bases: cqparts.errors.SearchError

Raised when no results are found by cqparts.search.find()

exception cqparts.errors.SolidValidityError

Bases: exceptions.Exception

Raised when an unrecoverable issue occurs with a solid

cqparts.part module

class cqparts.part.Part(*largs, **kwargs)

Bases: cqparts.component.Component

bounding_box

Generate a bounding box based on the full complexity part.

Returns:bounding box of part
Return type:cadquery.BoundBox
build(recursive=False)

Building a part buffers the local_obj attribute.

Running .build() is optional, it’s mostly used to test that there aren’t any critical runtime issues with it’s construction.

Parameters:recursive – (Part has no children, parameter ignored)
local_obj

Buffered result of make() which is (probably) a cadquery.Workplane instance. If _simple is True, then make_simple() is returned instead.

Note

This is usually the correct way to get your part’s object for rendering, exporting, or measuring.

Only call cqparts.Part.make() directly if you explicitly intend to re-generate the model from scratch, then dispose of it.

make()

Create and return solid part

Returns:cadquery.Workplane of the part in question
Return type:subclass of cadquery.CQ, usually a cadquery.Workplane

Important

This must be overridden in your Part

The outcome of this function should be accessed via cqparts.Part.object

make_simple()

Create and return simplified solid part.

The simplified representation of a Part is to lower the export quality of an Assembly or Part for rendering.

Overriding this is optional, but highly recommended.

The default behaviour returns the full complexity object’s bounding box. But to do this, theh full complexity object must be generated first.

There are 2 main problems with this:

  1. building the full complexity part is not efficient.
  2. a bounding box may not be a good representation of the part.

Bolts

A good example of this is a bolt.

  • building a bolt’s thread is not a trivial task; it can take some time to generate.
  • a box is not a good visual representation of a bolt

So for the Fastener parts, all make_simple methods are overridden to provide 2 cylinders, one for the bolt’s head, and another for the thread.

world_obj

The local_obj object in the world_coords coordinate system.

Note

This is automatically generated when called, and world_coords is not Null.

cqparts.search module

cqparts.search.common_criteria(**common)

Wrap a function to always call with the given common named parameters.

Property common:
 criteria common to your function call
Returns:decorator function
Return type:function
>>> import cqparts
>>> from cqparts.search import register, search, find
>>> from cqparts.search import common_criteria

>>> # Somebody elses (boring) library may register with...
>>> @register(a='one', b='two')
... class BoringThing(cqparts.Part):
...     pass

>>> # But your library is awesome; only registering with unique criteria...
>>> lib_criteria = {
...     'author': 'your_name',
...     'libname': 'awesome_things',
... }

>>> awesome_register = common_criteria(**lib_criteria)(register)

>>> @awesome_register(a='one', b='two')  # identical to BoringThing
... class AwesomeThing(cqparts.Part):
...     pass

>>> # So lets try a search
>>> len(search(a='one', b='two')) 
2
>>> # oops, that returned both classes

>>> # To narrow it down, we add something unique:
>>> len(search(a='one', b='two', libname='awesome_things'))  # finds only yours 
1

>>> # or, we could use common_criteria again...
>>> awesome_search = common_criteria(**lib_criteria)(search)
>>> awesome_find = common_criteria(**lib_criteria)(find)
>>> len(awesome_search(a='one', b='two')) 
1
>>> awesome_find(a='one', b='two').__name__
'AwesomeThing'

A good universal way to apply unique criteria is with

import cadquery, cqparts
from cqparts.search import register, common_criteria
_register = common_criteria(module=__name__)(register)

@_register(shape='cube', scale='unit')
class Cube(cqparts.Part):
    # just an example...
    def make(self):
        return cadquery.Workplane('XY').box(1, 1, 1)
cqparts.search.find(**criteria)

Find a single component class with the given criteria.

Finds classes indexed with register()

Raises:
from cqparts.search import find
import cqparts_motors  # example of a 3rd party lib

# get a specific motor class
motor_class = find(type='motor', part_number='ABC123X')
motor = motor_class(shaft_diameter=6.0)
cqparts.search.register(**criteria)

class decorator to add Part or Assembly to the cqparts search index:

import cqparts
from cqparts.params import *

# Created Part or Assembly
@cqparts.search.register(
    type='motor',
    current_class='dc',
    part_number='ABC123X',
)
class SomeMotor(cqparts.Assembly):
    shaft_diam = PositiveFloat(5)
    def make_components(self):
        return {}  # build assembly content

motor_class = cqparts.search.find(part_number='ABC123X')
motor = motor_class(shaft_diam=6.0)

Then use find() &/or search() to instantiate it.

Warning

Multiple classes can be registered with identical criteria, but should be avoided.

If multiple classes share the same criteria, find() will never yield the part you want.

Try adding unique criteria, such as make, model, part number, library name, &/or author.

To avoid this, learn more in Component Index.

cqparts.search.search(**criteria)

Search registered component classes matching the given criteria.

Parameters:criteria – search criteria of the form: a='1', b='x'
Returns:parts registered with the given criteria
Return type:set

Will return an empty set if nothing is found.

from cqparts.search import search
import cqparts_motors  # example of a 3rd party lib

# Get all DC motor classes
dc_motors = search(type='motor', current_class='dc')

# For more complex queries:
air_cooled = search(cooling='air')
non_aircooled_dcmotors = dc_motors - air_cooled
# will be all DC motors that aren't air-cooled

Module contents

Copyright 2018 Peter Boin

Licensed under the Apache License, Version 2.0 (the “License”); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

class cqparts.Component(*largs, **kwargs)

Bases: cqparts.params.parametric_object.ParametricObject

Note

Both the Part and Assembly classes inherit from Component.

Wherever the term “component” is used, it is in reference to an instance of either Part or Assembly.

build(recursive=True)
Raises:NotImplementedError – must be overridden by inheriting classes to function
exporter(exporter_name=None)

Get an exporter instance to write the component’s content to file.

Parameters:exporter_name (str) – registered name of exporter to use, see register_exporter() for more information.

For example, to get a ThreejsJSONExporter instance to import a json file:

>>> from cqparts_misc.basic.primatives import Box
>>> box = Box()
>>> json_exporter = box.exporter('json')

>>> # then each exporter will behave differently
>>> json_exporter('out.json')  

To learn more: Import / Export

classmethod importer(importer_name=None)

Get an importer instance to instantiate a component from file.

Parameters:importer_name (str) – registered name of importer to use, see register_importer() for more information.

For example, to get an importer to instantiate a Part from a STEP file:

>>> from cqparts import Part
>>> step_importer = Part.importer('step')

>>> # then each importer will behave differently
>>> my_part = step_importer('my_file.step')  

To learn more: Import / Export

mate_origin
Returns:mate at object’s origin
Return type:Mate
world_coords

Component’s placement in word coordinates (CoordSystem)

Returns:coordinate system in the world, None if not set.
Return type:CoordSystem
class cqparts.Part(*largs, **kwargs)

Bases: cqparts.component.Component

bounding_box

Generate a bounding box based on the full complexity part.

Returns:bounding box of part
Return type:cadquery.BoundBox
build(recursive=False)

Building a part buffers the local_obj attribute.

Running .build() is optional, it’s mostly used to test that there aren’t any critical runtime issues with it’s construction.

Parameters:recursive – (Part has no children, parameter ignored)
local_obj

Buffered result of make() which is (probably) a cadquery.Workplane instance. If _simple is True, then make_simple() is returned instead.

Note

This is usually the correct way to get your part’s object for rendering, exporting, or measuring.

Only call cqparts.Part.make() directly if you explicitly intend to re-generate the model from scratch, then dispose of it.

make()

Create and return solid part

Returns:cadquery.Workplane of the part in question
Return type:subclass of cadquery.CQ, usually a cadquery.Workplane

Important

This must be overridden in your Part

The outcome of this function should be accessed via cqparts.Part.object

make_simple()

Create and return simplified solid part.

The simplified representation of a Part is to lower the export quality of an Assembly or Part for rendering.

Overriding this is optional, but highly recommended.

The default behaviour returns the full complexity object’s bounding box. But to do this, theh full complexity object must be generated first.

There are 2 main problems with this:

  1. building the full complexity part is not efficient.
  2. a bounding box may not be a good representation of the part.

Bolts

A good example of this is a bolt.

  • building a bolt’s thread is not a trivial task; it can take some time to generate.
  • a box is not a good visual representation of a bolt

So for the Fastener parts, all make_simple methods are overridden to provide 2 cylinders, one for the bolt’s head, and another for the thread.

world_obj

The local_obj object in the world_coords coordinate system.

Note

This is automatically generated when called, and world_coords is not Null.

class cqparts.Assembly(*largs, **kwargs)

Bases: cqparts.component.Component

An assembly is a group of parts, and other assemblies (called components)

build(recursive=True)

Building an assembly buffers the components() and constraints().

Running build() is optional, it’s automatically run when requesting components() or constraints().

Mostly it’s used to test that there aren’t any critical runtime issues with its construction, but doing anything like displaying or exporting will ultimately run a build anyway.

Parameters:recursive (bool) – if set, iterates through child components and builds those as well.
components

Returns full dict of Component instances, after a successful build()

Returns:dict of named Component instances
Return type:dict

For more information read about the Assembly Build Cycle .

constraints

Returns full list of Constraint instances, after a successful build()

Returns:list of named Constraint instances
Return type:list

For more information read about the Assembly Build Cycle .

find(keys, _index=0)
Parameters:keys (str or list) – key path. 'a.b' is equivalent to ['a', 'b']

Find a nested Component by a “.” separated list of names. for example:

>>> motor.find('bearing.outer_ring')

would return the Part instance of the motor bearing’s outer ring.

>>> bearing = motor.find('bearing')
>>> ring = bearing.find('inner_ring')  # equivalent of 'bearing.inner_ring'

the above code does much the same thing, bearing is an Assembly, and ring is a Part.

Note

For a key path of a.b.c the c key can referernce any Component type.

Everything prior (in this case a and b) must reference an Assembly.

make_alterations()

Make necessary changes to components after the constraints solver has completed.

Tip

This can be overridden in inheriting class, read:

make_components()

Create and return dict of Component instances.

Tip

This must be overridden in inheriting class, read:

Returns:{<name>: <Component>, …}
Return type:dict of Component instances
make_constraints()

Create and return list of Constraint instances

Tip

This must be overridden in inheriting class, read:

Returns:constraints for assembly children’s placement
Return type:list of Constraint instances

Default behaviour returns an empty list; assumes assembly is entirely unconstrained.

solve()

Run the solver and assign the solution’s CoordSystem instances as the corresponding part’s world coordinates.

tree_str(name=None, prefix='', add_repr=False, _depth=0)

Return string listing recursively the assembly hierarchy

Parameters:
  • name (str) – if set, names the tree’s trunk, otherwise the object’s repr() names the tree
  • prefix (str) – string prefixed to each line, can be used to indent
  • add_repr (bool) – if set, component repr() is put after their names
Returns:

Printable string of an assembly’s component hierarchy.

Return type:

str

Example output from block_tree.py

>>> log = logging.getLogger(__name__)
>>> isinstance(block_tree, Assembly)
True
>>> log.info(block_tree.tree_str(name="block_tree"))
block_tree
 ├○ branch_lb
 ├○ branch_ls
 ├─ branch_r
 │   ├○ L
 │   ├○ R
 │   ├○ branch
 │   ├─ house
 │   │   ├○ bar
 │   │   └○ foo
 │   └○ split
 ├○ trunk
 └○ trunk_split

Where:

static verify_components(components)

Verify values returned from make_components().

Used internally during the build() process.

Parameters:components (dict) – value returned from make_components()
Raises:ValueError – if verification fails
static verify_constraints(constraints)

Verify values returned from make_constraints().

Used internally during the build() process.

Parameters:constraints (list) – value returned from make_constraints()
Raises:ValueError – if verification fails