cqparts.codec package

Submodules

cqparts.codec.amf module

class cqparts.codec.amf.AMFExporter(obj)

Bases: cqparts.codec.Exporter

Export shape to AMF format.

Name amf
Exports Part

Note

Object is passed to cadquery.freecad_impl.exporters.exportShape() for exporting.

cqparts.codec.gltf module

class cqparts.codec.gltf.GLTFExporter(*args, **kwargs)

Bases: cqparts.codec.Exporter

Export Part or Assembly to a glTF 2.0 format.

Name gltf
Exports Part & Assembly
Spec glTF 2.0

Exporting a Box:

For this example we’ll instantiate an existing Part class, a simple Box:

>>> import cpqarts
>>> from cqparts_misc.basic.primatives import Box
>>> box = Box()
>>> box.exporter('gltf')('box.gltf', embed=True)

Will export a single file box.gltf with mesh data encoded into it as a string.

Embedding vs .bin Files: default generates .bin files

If embed is True when calling, then all data is stored in the output .gltf file. However this is very inefficient, for larger, more complex models when loading on a web-interface.

When not embedded, all geometry will be stored as binary .bin files in the same directory as the root .gltf file.

For example, if we use the car from Make your own Assembly, with the hierarchy:

>>> car = Car()
>>> print(car.tree_str(name='car'))
car
├○ chassis
├─ front_axle
│   ├○ axle
│   ├○ left_wheel
│   └○ right_wheel
└─ rear_axle
    ├○ axle
    ├○ left_wheel
    └○ right_wheel
>>> car.exporter('gltf')('car.gltf', embed=False)

When exported, a .bin file will be created for each Part (denoted by a ).

So the following files will be generated:

car.gltf
car.chassis.bin
car.front_axle.axle.bin
car.front_axle.left_wheel.bin
car.front_axle.right_wheel.bin
car.rear_axle.axle.bin
car.rear_axle.left_wheel.bin
car.rear_axle.right_wheel.bin

The car.gltf will reference each of the .bin files.

The car.gltf and all .bin files should be web-hosted to serve the scene correctly.

Todo

In this example, all wheels and axles are the same, they should only generate a single buffer.

But how to definitively determine Part instance equality?

TEMPLATE = {'accessors': [], 'materials': [], 'meshes': [], 'asset': {'version': '2.0', 'generator': 'cqparts_0.2.1'}, 'nodes': [{'children': [], 'matrix': [0.001, 0.0, 0.0, 0.0, 0.0, 0.0, -0.001, 0.0, 0.0, 0.001, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0]}], 'bufferViews': [], 'scene': 0, 'buffers': [], 'scenes': [{'nodes': [0]}]}
__call__(filename='out.gltf', embed=False)
Parameters:
  • filename (str) – name of .gltf file to export
  • embed (bool) – if True, binary content is embedded in json object.
add_part(part, filename=None, name=None, origin=None, parent_idx=0)

Adds the given part to self.gltf_dict.

Parameters:
  • part (Part) – part to add to gltf export
  • filename (str) – name of binary file to store buffer, if None, binary data is embedded in the buffer’s ‘uri’
  • name (str) – name given to exported mesh (optional)
  • parent_idx (int) – index of parent node (everything is added to a hierarchy)
Returns:

information about additions to the gltf dict

Return type:

dict

Return Format:

The returned dict is an account of what objects were added to the gltf dict, and the index they may be referenced:

<return format> = {
    'buffers':     [(<index>, <object>), ... ],
    'bufferViews': [(<index>, <object>), ... ],
    'accessors':   [(<index>, <object>), ... ],
    'materials':   [(<index>, <object>), ... ],
    'meshes':      [(<index>, <object>), ... ],
    'nodes':       [(<index>, <object>), ... ],
}

Note

The format of the returned dict looks similar to the gltf format, but it is not.

classmethod coordsys_dict(coord_sys, matrix=True)

Return coordinate system as gltf node transform

Parameters:coord_sys (CoordSystem) – Coordinate system to transform
Returns:node transform keys & values
Return type:dict
classmethod part_buffer(part)

Export part’s geometry as a glTF 2.0 asset binary stream.

Parameters:world (bool) – if True, use world coordinates, otherwise use local
Returns:byte sream of exported geometry
Return type:BytesIO

To embed binary model data into a ‘uri’, you can:

>>> import cqparts
>>> from cqparts_misc.basic.primatives import Cube

>>> cube = Cube()
>>> buff = cube.exporter('gltf').part_buffer(cube)

>>> import base64
>>> {'uri': "data:{mimetype};base64,{data}".format(
...     mimetype="application/octet-stream",
...     data=base64.b64encode(buff.read()).decode('ascii'),
... )}
{'uri': 'data:application/octet-stream;base64,AAAAvwAAAD8AAAA/AAAAvwAAAD8AAAC/AAAAvwAAAL8AAAA/AAAAvwAAAL8AAAC/AAAAPwAAAL8AAAA/AAAAPwAAAD8AAAC/AAAAPwAAAD8AAAA/AAAAPwAAAL8AAAC/AAECAQMCBAUGBAcFAwcCAgcEAAUBBgUAAwEHBwEFBAACBgAE'}
classmethod part_mesh(part)

Convert a part’s object to a mesh.

Parameters:
  • part (Part) – part being converted to a mesh
  • world (bool) – if True, world coordinates are used
Returns:

list of (<vertices>, <indexes>)

Return type:

tuple

Returned mesh format:

<return value> = (
    [FreeCAD.Base.Vector(x, y, z), ... ],  # list of vertices
    [(i, j, k), ... ],  # indexes of vertices making a polygon
)
scale = 0.001
tolerance = 0.01
class cqparts.codec.gltf.ShapeBuffer(max_index=255)

Bases: object

Write byte buffer for a set of polygons

To create a buffer for a single polygon:

>>> from cqparts.codec.gltf import ShapeBuffer
>>> sb = ShapeBuffer()

>>> # Populate data
>>> sb.add_vertex(0, 0, 0)  # [0]
>>> sb.add_vertex(1, 0, 0)  # [1]
>>> sb.add_vertex(0, 1, 0)  # [2]
>>> sb.add_poly_index(0, 1, 2)

>>> # write to file
>>> with open('single-poly.bin', 'wb') as fh:  
...     for chunk in sb.buffer_iter():  
...         fh.write(chunk)  

>>> # get sizes (relevant for bufferViews, and accessors)
>>> (sb.vert_len, sb.vert_offset, sb.vert_size)
(36L, 0, 3L)
>>> (sb.idx_len, sb.idx_offset, sb.idx_size)
(3L, 36L, 3L)
__init__(max_index=255)
Parameters:max_index (long) – maximum index number, if > 65535, 4-byte integers are used
add_poly_index(i, j, k)

Add 3 SCALAR of uint to the idx_data buffer.

add_vertex(x, y, z)

Add a VEC3 of floats to the vert_data buffer

buffer_iter(block_size=1024)

Iterate through chunks of the vertices, and indices buffers seamlessly.

Note

To see a usage example, look at the ShapeBuffer description.

idx_len

Number of bytes in idx_data buffer.

idx_offset

Offset (in bytes) of the idx_data buffer.

idx_size

Number of idx_data elements. (ie: number of 2 or 4 byte groups)

See Accessor Element Size in the glTF docs for clarification.

read()

Read buffer out as a single stream.

Warning

Avoid using this function!

Why? This is a convenience function; it doesn’t encourage good memory management.

All memory required for a mesh is duplicated, and returned as a single str. So at best, using this function will double the memory required for a single model.

Instead: Wherever possible, please use buffer_iter().

vert_len

Number of bytes in vert_data buffer.

vert_offset

Offset (in bytes) of the vert_data buffer.

vert_size

Size of vert_data in groups of 3 floats (ie: number of \(3 \times 4\) byte groups)

See Accessor Element Size in the glTF docs for clarification.

class cqparts.codec.gltf.WebGL

Enumeration container (nothing special).

>>> from cqparts.codec.gltf import WebGL
>>> WebGL.ARRAY_BUFFER
34962

This class purely exists to make the code more readable.

All enumerations transcribed from the spec’ where needed.

ARRAY_BUFFER = 34962
BYTE = 5120
ELEMENT_ARRAY_BUFFER = 34963
FLOAT = 5126
LINES = 1
LINE_LOOP = 2
LINE_STRIP = 3
POINTS = 0
SHORT = 5122
TRIANGLES = 4
TRIANGLE_FAN = 6
TRIANGLE_STRIP = 5
UNSIGNED_BYTE = 5121
UNSIGNED_INT = 5125
UNSIGNED_SHORT = 5123

cqparts.codec.step module

class cqparts.codec.step.STEPAssemblyImporter(cls)

Bases: cqparts.codec.step.STEPPartImporter

Import a shape from a STEP formatted file.

Name step
Imports Assembly

Note

Step file is passed to cadquery.freecad_impl.importers.importShape() to do the hard work of extracting geometry.

Multi-part STEP

This importer is intended for STEP files with multiple separated meshes defined.

Each mesh is imported into a nested Part component.

class cqparts.codec.step.STEPExporter(obj)

Bases: cqparts.codec.Exporter

Export shape to STEP format.

Name step
Exports Part

Note

Object is passed to cadquery.freecad_impl.exporters.exportShape() for exporting.

class cqparts.codec.step.STEPPartImporter(cls)

Bases: cqparts.codec.step.STEPPartImporter

Import a shape from a STEP formatted file.

Name step
Imports Part

Note

Step file is passed to cadquery.freecad_impl.importers.importShape() to do the hard work of extracting geometry.

Multi-part STEP

If the STEP file has multiple parts, all parts are unioned together to form a single Part.

cqparts.codec.stl module

class cqparts.codec.stl.STLExporter(obj)

Bases: cqparts.codec.Exporter

Export shape to STL format.

Name stl
Exports Part

Note

Object is passed to cadquery.freecad_impl.exporters.exportShape() for exporting.

cqparts.codec.svg module

class cqparts.codec.svg.SVGExporter(obj)

Bases: cqparts.codec.Exporter

Export shape to AMF format.

Name svg
Exports Part

Note

Object is passed to cadquery.freecad_impl.exporters.exportShape() for exporting.

cqparts.codec.threejs_json module

class cqparts.codec.threejs_json.ThreejsJSONAssemblyExporter(obj)

Bases: cqparts.codec.Exporter

Export an Assembly into multiple json files.

Name json
Exports Assembly
Spec three.js JSON model format v3 specification

Warning

The three.js JSON v3 format does not support multiple models (or, at least, not as far as I can tell).

So this exporter will create multiple files, one per part.

If you’re after a more modern WebGL supported export, consider using GLTFExporter instead.

class cqparts.codec.threejs_json.ThreejsJSONExporter(obj)

Bases: cqparts.codec.Exporter

Export the Part to a three.js JSON v3 file format.

Name json
Exports Part
Spec three.js JSON model format v3 specification

For information on how to load in a webpage, look to your WebGL framework of choice:

__call__(filename='out.json', world=False)

Write to file.

Parameters:
  • filename (str) – file to write
  • world (bool) – if True, use world coordinates, otherwise use local
get_dict(world=False)

Get the part’s geometry as a dict

Parameters:world (bool) – if True, use world coordinates, otherwise use local
Returns:JSON model format
Return type:dict
get_str(*args, **kwargs)

Get file string.

(same arguments as get_export_gltf_dict())

Returns:JSON string
Return type:str

Module contents

class cqparts.codec.Exporter(obj)

Bases: object

cqparts.codec.register_exporter(name, base_class)

Register an exporter to use for a Part, Assembly, or both (with Component).

Registration is necessary to use with Component.exporter().

Parameters:
  • name (str) – name (or ‘key’) of exporter
  • base_class (type) – class of Component to export
>>> from cqparts import Part
>>> from cqparts.codec import Exporter, register_exporter

>>> @register_exporter('my_type', Part)
... class MyExporter(Exporter):
...     def __call__(self, filename='out.mytype'):
...         print("export %r to %s" % (self.obj, filename))

>>> from cqparts_misc.basic.primatives import Sphere
>>> thing = Sphere(radius=5)
>>> thing.exporter('my_type')('some-file.mytype')
export <Sphere: radius=5.0> to some-file.mytype
cqparts.codec.get_exporter(obj, name)

Get an exporter for the

Parameters:
  • obj (Component) – object to export
  • name (str) – registered name of exporter
Returns:

an exporter instance of the given type

Return type:

Exporter

Raises:

TypeError – if exporter cannot be found

class cqparts.codec.Importer(cls)

Bases: object

cqparts.codec.register_importer(name, base_class)
cqparts.codec.get_importer(cls, name)

Get an importer for the given registered type.

Parameters:
  • cls (type) – class to import
  • name (str) – registered name of importer
Returns:

an importer instance of the given type

Return type:

Importer

Raises:

TypeError – if importer cannot be found

class cqparts.codec.AMFExporter(obj)

Bases: cqparts.codec.Exporter

Export shape to AMF format.

Name amf
Exports Part

Note

Object is passed to cadquery.freecad_impl.exporters.exportShape() for exporting.

class cqparts.codec.GLTFExporter(*args, **kwargs)

Bases: cqparts.codec.Exporter

Export Part or Assembly to a glTF 2.0 format.

Name gltf
Exports Part & Assembly
Spec glTF 2.0

Exporting a Box:

For this example we’ll instantiate an existing Part class, a simple Box:

>>> import cpqarts
>>> from cqparts_misc.basic.primatives import Box
>>> box = Box()
>>> box.exporter('gltf')('box.gltf', embed=True)

Will export a single file box.gltf with mesh data encoded into it as a string.

Embedding vs .bin Files: default generates .bin files

If embed is True when calling, then all data is stored in the output .gltf file. However this is very inefficient, for larger, more complex models when loading on a web-interface.

When not embedded, all geometry will be stored as binary .bin files in the same directory as the root .gltf file.

For example, if we use the car from Make your own Assembly, with the hierarchy:

>>> car = Car()
>>> print(car.tree_str(name='car'))
car
├○ chassis
├─ front_axle
│   ├○ axle
│   ├○ left_wheel
│   └○ right_wheel
└─ rear_axle
    ├○ axle
    ├○ left_wheel
    └○ right_wheel
>>> car.exporter('gltf')('car.gltf', embed=False)

When exported, a .bin file will be created for each Part (denoted by a ).

So the following files will be generated:

car.gltf
car.chassis.bin
car.front_axle.axle.bin
car.front_axle.left_wheel.bin
car.front_axle.right_wheel.bin
car.rear_axle.axle.bin
car.rear_axle.left_wheel.bin
car.rear_axle.right_wheel.bin

The car.gltf will reference each of the .bin files.

The car.gltf and all .bin files should be web-hosted to serve the scene correctly.

Todo

In this example, all wheels and axles are the same, they should only generate a single buffer.

But how to definitively determine Part instance equality?

TEMPLATE = {'accessors': [], 'materials': [], 'meshes': [], 'asset': {'version': '2.0', 'generator': 'cqparts_0.2.1'}, 'nodes': [{'children': [], 'matrix': [0.001, 0.0, 0.0, 0.0, 0.0, 0.0, -0.001, 0.0, 0.0, 0.001, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0]}], 'bufferViews': [], 'scene': 0, 'buffers': [], 'scenes': [{'nodes': [0]}]}
__call__(filename='out.gltf', embed=False)
Parameters:
  • filename (str) – name of .gltf file to export
  • embed (bool) – if True, binary content is embedded in json object.
add_part(part, filename=None, name=None, origin=None, parent_idx=0)

Adds the given part to self.gltf_dict.

Parameters:
  • part (Part) – part to add to gltf export
  • filename (str) – name of binary file to store buffer, if None, binary data is embedded in the buffer’s ‘uri’
  • name (str) – name given to exported mesh (optional)
  • parent_idx (int) – index of parent node (everything is added to a hierarchy)
Returns:

information about additions to the gltf dict

Return type:

dict

Return Format:

The returned dict is an account of what objects were added to the gltf dict, and the index they may be referenced:

<return format> = {
    'buffers':     [(<index>, <object>), ... ],
    'bufferViews': [(<index>, <object>), ... ],
    'accessors':   [(<index>, <object>), ... ],
    'materials':   [(<index>, <object>), ... ],
    'meshes':      [(<index>, <object>), ... ],
    'nodes':       [(<index>, <object>), ... ],
}

Note

The format of the returned dict looks similar to the gltf format, but it is not.

classmethod coordsys_dict(coord_sys, matrix=True)

Return coordinate system as gltf node transform

Parameters:coord_sys (CoordSystem) – Coordinate system to transform
Returns:node transform keys & values
Return type:dict
classmethod part_buffer(part)

Export part’s geometry as a glTF 2.0 asset binary stream.

Parameters:world (bool) – if True, use world coordinates, otherwise use local
Returns:byte sream of exported geometry
Return type:BytesIO

To embed binary model data into a ‘uri’, you can:

>>> import cqparts
>>> from cqparts_misc.basic.primatives import Cube

>>> cube = Cube()
>>> buff = cube.exporter('gltf').part_buffer(cube)

>>> import base64
>>> {'uri': "data:{mimetype};base64,{data}".format(
...     mimetype="application/octet-stream",
...     data=base64.b64encode(buff.read()).decode('ascii'),
... )}
{'uri': 'data:application/octet-stream;base64,AAAAvwAAAD8AAAA/AAAAvwAAAD8AAAC/AAAAvwAAAL8AAAA/AAAAvwAAAL8AAAC/AAAAPwAAAL8AAAA/AAAAPwAAAD8AAAC/AAAAPwAAAD8AAAA/AAAAPwAAAL8AAAC/AAECAQMCBAUGBAcFAwcCAgcEAAUBBgUAAwEHBwEFBAACBgAE'}
classmethod part_mesh(part)

Convert a part’s object to a mesh.

Parameters:
  • part (Part) – part being converted to a mesh
  • world (bool) – if True, world coordinates are used
Returns:

list of (<vertices>, <indexes>)

Return type:

tuple

Returned mesh format:

<return value> = (
    [FreeCAD.Base.Vector(x, y, z), ... ],  # list of vertices
    [(i, j, k), ... ],  # indexes of vertices making a polygon
)
scale = 0.001
tolerance = 0.01
class cqparts.codec.STEPExporter(obj)

Bases: cqparts.codec.Exporter

Export shape to STEP format.

Name step
Exports Part

Note

Object is passed to cadquery.freecad_impl.exporters.exportShape() for exporting.

class cqparts.codec.STLExporter(obj)

Bases: cqparts.codec.Exporter

Export shape to STL format.

Name stl
Exports Part

Note

Object is passed to cadquery.freecad_impl.exporters.exportShape() for exporting.

class cqparts.codec.SVGExporter(obj)

Bases: cqparts.codec.Exporter

Export shape to AMF format.

Name svg
Exports Part

Note

Object is passed to cadquery.freecad_impl.exporters.exportShape() for exporting.

class cqparts.codec.ThreejsJSONExporter(obj)

Bases: cqparts.codec.Exporter

Export the Part to a three.js JSON v3 file format.

Name json
Exports Part
Spec three.js JSON model format v3 specification

For information on how to load in a webpage, look to your WebGL framework of choice:

__call__(filename='out.json', world=False)

Write to file.

Parameters:
  • filename (str) – file to write
  • world (bool) – if True, use world coordinates, otherwise use local
get_dict(world=False)

Get the part’s geometry as a dict

Parameters:world (bool) – if True, use world coordinates, otherwise use local
Returns:JSON model format
Return type:dict
get_str(*args, **kwargs)

Get file string.

(same arguments as get_export_gltf_dict())

Returns:JSON string
Return type:str
class cqparts.codec.ThreejsJSONAssemblyExporter(obj)

Bases: cqparts.codec.Exporter

Export an Assembly into multiple json files.

Name json
Exports Assembly
Spec three.js JSON model format v3 specification

Warning

The three.js JSON v3 format does not support multiple models (or, at least, not as far as I can tell).

So this exporter will create multiple files, one per part.

If you’re after a more modern WebGL supported export, consider using GLTFExporter instead.