├── .editorconfig
├── .github
├── CODE_OF_CONDUCT.md
├── FUNDING.yml
├── ISSUE_TEMPLATE
│ ├── bug_report.md
│ └── feature_request.md
├── pull_request_template.md
└── workflows
│ ├── build.yml
│ ├── coverage.yml
│ ├── docs.yml
│ ├── ironpython.yml
│ ├── pr-checks.yml
│ ├── publish_yak.yml
│ └── release.yml
├── .gitignore
├── AUTHORS.md
├── CHANGELOG.md
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── conftest.py
├── docs
├── _images
│ ├── COMPAS.png
│ ├── extensions
│ │ ├── compas-robots.png
│ │ ├── compas_3gs.jpg
│ │ ├── compas_ags.png
│ │ ├── compas_assembly.png
│ │ ├── compas_cem.png
│ │ ├── compas_cgal.png
│ │ ├── compas_cloud.png
│ │ ├── compas_cra.png
│ │ ├── compas_fab.png
│ │ ├── compas_fea.png
│ │ ├── compas_fem.png
│ │ ├── compas_gmsh.png
│ │ ├── compas_libigl.png
│ │ ├── compas_occ.png
│ │ ├── compas_pattern1.png
│ │ ├── compas_pattern2.png
│ │ ├── compas_rbe.jpg
│ │ ├── compas_rrc.png
│ │ ├── compas_skeleton.png
│ │ ├── compas_slicer.jpg
│ │ ├── compas_tia.png
│ │ ├── compas_tna.jpg
│ │ ├── compas_triangle.png
│ │ └── compas_vol.png
│ ├── ghpython_custom.jpg
│ ├── installation.gif
│ ├── rhino_scripteditor.png
│ ├── tutorial
│ │ ├── plotters_dynamic.gif
│ │ ├── plotters_example.png
│ │ ├── plotters_line-options.png
│ │ ├── plotters_point-options.png
│ │ ├── plotters_polygon-options.png
│ │ └── plotters_vector-options.png
│ ├── userguide
│ │ ├── basics.colors_color-circle.png
│ │ ├── basics.colors_lightness.png
│ │ ├── basics.colors_maps.png
│ │ ├── basics.colors_maps_from-one-color.png
│ │ ├── basics.colors_maps_from-rgb.png
│ │ ├── basics.colors_maps_from-three-colors.png
│ │ ├── basics.colors_maps_from-two-colors.png
│ │ ├── basics.colors_saturation.png
│ │ ├── basics.datastructures.cellnetworks.example_color.png
│ │ ├── basics.datastructures.cellnetworks.example_grey.png
│ │ ├── basics.datastructures.cellnetworks.example_hull.png
│ │ ├── basics.datastructures.meshes.cycles.png
│ │ ├── basics.datastructures.meshes.edge-loop.png
│ │ ├── basics.datastructures.meshes.edge-strip.png
│ │ ├── basics.datastructures.meshes.face-neighbours.png
│ │ ├── basics.datastructures.meshes.meshgrid-column0.png
│ │ ├── basics.datastructures.meshes.meshgrid-column3.png
│ │ ├── basics.datastructures.meshes.tubemesh.png
│ │ ├── basics.datastructures.meshes.vertex-faces.png
│ │ ├── basics.datastructures.meshes.vertex-neighbours.png
│ │ ├── cad.blender.visualisation.png
│ │ ├── cad.grasshopper.gh_verify.jpg
│ │ └── cad.grasshopper.ghpython_component.jpg
│ └── vscode_git.JPG
├── _static
│ └── PLACEHOLDER
├── api
│ ├── compas.colors.html_colors.rst
│ ├── compas.colors.rst
│ ├── compas.data.rst
│ ├── compas.datastructures.Assembly.rst
│ ├── compas.datastructures.CellNetwork.rst
│ ├── compas.datastructures.Graph.rst
│ ├── compas.datastructures.Mesh.rst
│ ├── compas.datastructures.Tree.rst
│ ├── compas.datastructures.VolMesh.rst
│ ├── compas.datastructures.rst
│ ├── compas.files.rst
│ ├── compas.geometry.rst
│ ├── compas.itertools.rst
│ ├── compas.plugins.rst
│ ├── compas.rpc.rst
│ ├── compas.scene.rst
│ ├── compas.tolerance.rst
│ ├── compas_blender.conversions.rst
│ ├── compas_blender.geometry.rst
│ ├── compas_blender.scene.rst
│ ├── compas_ghpython.components.rst
│ ├── compas_ghpython.scene.rst
│ ├── compas_rhino.conversions.rst
│ ├── compas_rhino.geometry.rst
│ ├── compas_rhino.scene.rst
│ └── index.rst
├── conf.py
├── devguide
│ ├── code.rst
│ ├── documentation.rst
│ ├── dtypes.rst
│ ├── extensions.rst
│ ├── ghcomponent.rst
│ ├── index.rst
│ ├── plugins.rst
│ ├── setup.rst
│ └── workflow.rst
├── index.rst
├── sort__all__.py
├── userguide
│ ├── _plotter.py
│ ├── advanced.hashtree.rst
│ ├── advanced.pluggables.rst
│ ├── advanced.rpc.rst
│ ├── advanced.serialisation.rst
│ ├── advanced.tolerance.rst
│ ├── basics.colors.rst
│ ├── basics.datastructures.cellnetwork.rst
│ ├── basics.datastructures.cellnetworks.py
│ ├── basics.datastructures.cells.rst
│ ├── basics.datastructures.graphs.rst
│ ├── basics.datastructures.meshes.py
│ ├── basics.datastructures.meshes.rst
│ ├── basics.datastructures.rst
│ ├── basics.datastructures.trees.rst
│ ├── basics.datastructures.volmeshes.rst
│ ├── basics.datastructures.volmeshes_example-1.py
│ ├── basics.geometry.breps.rst
│ ├── basics.geometry.curves_and_surfaces.rst
│ ├── basics.geometry.distance_and_membership.rst
│ ├── basics.geometry.intersections.rst
│ ├── basics.geometry.planes_and_frames.rst
│ ├── basics.geometry.points_and_vectors.rst
│ ├── basics.geometry.polygons_and_polyhedrons.rst
│ ├── basics.geometry.rst
│ ├── basics.geometry.solids.rst
│ ├── basics.geometry.transformations.rst
│ ├── basics.visualisation.rst
│ ├── cad.blender.rst
│ ├── cad.grasshopper.rst
│ ├── cad.other.rst
│ ├── cad.rhino.rst
│ ├── cad.rhino8.rst
│ ├── citing.rst
│ ├── firststeps.rst
│ ├── index.rst
│ ├── installation.rst
│ ├── introduction.rst
│ ├── license.rst
│ ├── releases.rst
│ ├── samples
│ │ ├── colors.py
│ │ ├── colors_lightness.py
│ │ ├── colors_maps.py
│ │ ├── colors_maps_from-one-color.py
│ │ ├── colors_maps_from-rgb.py
│ │ ├── colors_maps_from-rgb_simple.py
│ │ ├── colors_maps_from-three-colors.py
│ │ ├── colors_maps_from-two-colors.py
│ │ ├── colors_saturation.py
│ │ ├── obb.py
│ │ ├── point_in_box.py
│ │ └── quadmesh_planarize.py
│ ├── scene.py
│ └── whatsnext.rst
└── write_rst.py
├── pyproject.toml
├── requirements-dev.txt
├── requirements.txt
├── src
├── compas
│ ├── __init__.py
│ ├── __main__.py
│ ├── _iotools.py
│ ├── _os.py
│ ├── colors
│ │ ├── __init__.py
│ │ ├── cmcrameri
│ │ │ ├── LICENSE
│ │ │ ├── acton.txt
│ │ │ ├── actonS.txt
│ │ │ ├── bam.txt
│ │ │ ├── bamO.txt
│ │ │ ├── bamako.txt
│ │ │ ├── bamakoS.txt
│ │ │ ├── batlow.txt
│ │ │ ├── batlowK.txt
│ │ │ ├── batlowS.txt
│ │ │ ├── batlowW.txt
│ │ │ ├── berlin.txt
│ │ │ ├── bilbao.txt
│ │ │ ├── bilbaoS.txt
│ │ │ ├── broc.txt
│ │ │ ├── brocO.txt
│ │ │ ├── buda.txt
│ │ │ ├── budaS.txt
│ │ │ ├── bukavu.txt
│ │ │ ├── cork.txt
│ │ │ ├── corkO.txt
│ │ │ ├── davos.txt
│ │ │ ├── davosS.txt
│ │ │ ├── devon.txt
│ │ │ ├── devonS.txt
│ │ │ ├── fes.txt
│ │ │ ├── grayC.txt
│ │ │ ├── grayCS.txt
│ │ │ ├── hawaii.txt
│ │ │ ├── hawaiiS.txt
│ │ │ ├── imola.txt
│ │ │ ├── imolaS.txt
│ │ │ ├── lajolla.txt
│ │ │ ├── lajollaS.txt
│ │ │ ├── lapaz.txt
│ │ │ ├── lapazS.txt
│ │ │ ├── lisbon.txt
│ │ │ ├── nuuk.txt
│ │ │ ├── nuukS.txt
│ │ │ ├── oleron.txt
│ │ │ ├── oslo.txt
│ │ │ ├── osloS.txt
│ │ │ ├── roma.txt
│ │ │ ├── romaO.txt
│ │ │ ├── tofino.txt
│ │ │ ├── tokyo.txt
│ │ │ ├── tokyoS.txt
│ │ │ ├── turku.txt
│ │ │ ├── turkuS.txt
│ │ │ ├── vanimo.txt
│ │ │ ├── vik.txt
│ │ │ └── vikO.txt
│ │ ├── color.py
│ │ ├── colordict.py
│ │ ├── colormap.py
│ │ ├── html_colors.py
│ │ └── mpl_colormap.py
│ ├── data
│ │ ├── __init__.py
│ │ ├── coercion.py
│ │ ├── data.py
│ │ ├── encoders.py
│ │ ├── exceptions.py
│ │ ├── json.py
│ │ ├── samples
│ │ │ ├── boxes.obj
│ │ │ ├── butt_model.obj
│ │ │ ├── cellnetwork_example.json
│ │ │ ├── cone.stl
│ │ │ ├── cube.off
│ │ │ ├── cube_ascii.stl
│ │ │ ├── cube_binary.stl
│ │ │ ├── cube_binary_2.stl
│ │ │ ├── doosabin.json
│ │ │ ├── faces.obj
│ │ │ ├── faces_big.obj
│ │ │ ├── faces_reversed.obj
│ │ │ ├── fink.obj
│ │ │ ├── grid_irregular.obj
│ │ │ ├── hypar.obj
│ │ │ ├── lines.json
│ │ │ ├── lines.obj
│ │ │ ├── lines_big.obj
│ │ │ ├── lines_bigger.obj
│ │ │ ├── lines_noleaves.obj
│ │ │ ├── mesh.obj
│ │ │ ├── mesh_100_faces.json
│ │ │ ├── mesh_110_faces.json
│ │ │ ├── open_edges.obj
│ │ │ ├── point.json
│ │ │ ├── quadmesh.obj
│ │ │ ├── quadmesh_planar.obj
│ │ │ ├── saddle.obj
│ │ │ ├── spline.obj
│ │ │ ├── tubemesh.json
│ │ │ ├── tubemesh.obj
│ │ │ ├── tubemesh.off
│ │ │ └── tubemesh.ply
│ │ ├── schema.py
│ │ └── validators.py
│ ├── datastructures
│ │ ├── __init__.py
│ │ ├── _mutablemapping.py
│ │ ├── assembly
│ │ │ ├── __init__.py
│ │ │ ├── assembly.py
│ │ │ ├── exceptions.py
│ │ │ └── part.py
│ │ ├── attributes.py
│ │ ├── cell_network
│ │ │ ├── __init__.py
│ │ │ └── cell_network.py
│ │ ├── datastructure.py
│ │ ├── graph
│ │ │ ├── __init__.py
│ │ │ ├── duality.py
│ │ │ ├── graph.py
│ │ │ ├── operations
│ │ │ │ ├── __init__.py
│ │ │ │ ├── join.py
│ │ │ │ └── split.py
│ │ │ ├── planarity.py
│ │ │ └── smoothing.py
│ │ ├── mesh
│ │ │ ├── __init__.py
│ │ │ ├── conway.py
│ │ │ ├── duality.py
│ │ │ ├── mesh.py
│ │ │ ├── operations
│ │ │ │ ├── __init__.py
│ │ │ │ ├── collapse.py
│ │ │ │ ├── extrude.py
│ │ │ │ ├── insert.py
│ │ │ │ ├── merge.py
│ │ │ │ ├── split.py
│ │ │ │ ├── substitute.py
│ │ │ │ ├── swap.py
│ │ │ │ └── weld.py
│ │ │ ├── remesh.py
│ │ │ ├── slice.py
│ │ │ ├── smoothing.py
│ │ │ └── subdivision.py
│ │ ├── tree
│ │ │ ├── __init__.py
│ │ │ ├── hashtree.py
│ │ │ └── tree.py
│ │ └── volmesh
│ │ │ ├── __init__.py
│ │ │ └── volmesh.py
│ ├── files
│ │ ├── __init__.py
│ │ ├── _xml
│ │ │ ├── __init__.py
│ │ │ ├── xml_cli.py
│ │ │ ├── xml_cpython.py
│ │ │ ├── xml_pre_38.py
│ │ │ └── xml_shared.py
│ │ ├── gltf
│ │ │ ├── __init__.py
│ │ │ ├── constants.py
│ │ │ ├── data_classes.py
│ │ │ ├── extensions.py
│ │ │ ├── gltf.py
│ │ │ ├── gltf_children.py
│ │ │ ├── gltf_content.py
│ │ │ ├── gltf_exporter.py
│ │ │ ├── gltf_mesh.py
│ │ │ ├── gltf_node.py
│ │ │ ├── gltf_parser.py
│ │ │ ├── gltf_reader.py
│ │ │ ├── gltf_scene.py
│ │ │ └── helpers.py
│ │ ├── obj.py
│ │ ├── off.py
│ │ ├── ply.py
│ │ ├── stl.py
│ │ └── xml.py
│ ├── geometry
│ │ ├── __init__.py
│ │ ├── _core
│ │ │ ├── __init__.py
│ │ │ ├── _algebra.py
│ │ │ ├── angles.py
│ │ │ ├── centroids.py
│ │ │ ├── distance.py
│ │ │ ├── normals.py
│ │ │ ├── nurbs.py
│ │ │ ├── predicates_2.py
│ │ │ ├── predicates_3.py
│ │ │ ├── quaternions.py
│ │ │ ├── size.py
│ │ │ ├── tangent.py
│ │ │ ├── transformations.py
│ │ │ └── transformations_numpy.py
│ │ ├── bbox.py
│ │ ├── bbox_numpy.py
│ │ ├── bestfit.py
│ │ ├── bestfit_numpy.py
│ │ ├── booleans.py
│ │ ├── booleans_shapely.py
│ │ ├── brep
│ │ │ ├── __init__.py
│ │ │ ├── brep.py
│ │ │ ├── edge.py
│ │ │ ├── errors.py
│ │ │ ├── face.py
│ │ │ ├── loop.py
│ │ │ ├── trim.py
│ │ │ └── vertex.py
│ │ ├── contours.py
│ │ ├── curves
│ │ │ ├── __init__.py
│ │ │ ├── arc.py
│ │ │ ├── bezier.py
│ │ │ ├── circle.py
│ │ │ ├── conic.py
│ │ │ ├── curve.py
│ │ │ ├── ellipse.py
│ │ │ ├── hyperbola.py
│ │ │ ├── line.py
│ │ │ ├── nurbs.py
│ │ │ ├── parabola.py
│ │ │ └── polyline.py
│ │ ├── frame.py
│ │ ├── geometry.py
│ │ ├── hull.py
│ │ ├── hull_numpy.py
│ │ ├── icp_numpy.py
│ │ ├── interpolation_barycentric.py
│ │ ├── interpolation_coons.py
│ │ ├── interpolation_tweening.py
│ │ ├── intersection.py
│ │ ├── intersections.py
│ │ ├── kdtree.py
│ │ ├── offset.py
│ │ ├── pca_numpy.py
│ │ ├── plane.py
│ │ ├── point.py
│ │ ├── pointcloud.py
│ │ ├── polygon.py
│ │ ├── polyhedron.py
│ │ ├── projection.py
│ │ ├── quadmesh_planarize.py
│ │ ├── quadmesh_planarize_none.py
│ │ ├── quaternion.py
│ │ ├── reflection.py
│ │ ├── rotation.py
│ │ ├── scale.py
│ │ ├── shapes
│ │ │ ├── __init__.py
│ │ │ ├── box.py
│ │ │ ├── capsule.py
│ │ │ ├── cone.py
│ │ │ ├── cylinder.py
│ │ │ ├── shape.py
│ │ │ ├── sphere.py
│ │ │ └── torus.py
│ │ ├── shear.py
│ │ ├── surfaces
│ │ │ ├── __init__.py
│ │ │ ├── conical.py
│ │ │ ├── cylindrical.py
│ │ │ ├── extrusion.py
│ │ │ ├── nurbs.py
│ │ │ ├── planar.py
│ │ │ ├── revolution.py
│ │ │ ├── spherical.py
│ │ │ ├── surface.py
│ │ │ └── toroidal.py
│ │ ├── transformation.py
│ │ ├── translation.py
│ │ ├── triangulation_delaunay.py
│ │ ├── triangulation_earclip.py
│ │ ├── trimesh_curvature.py
│ │ ├── trimesh_descent_numpy.py
│ │ ├── trimesh_geodistance.py
│ │ ├── trimesh_gradient_numpy.py
│ │ ├── trimesh_isolines.py
│ │ ├── trimesh_matrices.py
│ │ ├── trimesh_matrices_numpy.py
│ │ ├── trimesh_parametrisation.py
│ │ ├── trimesh_pull_points_numpy.py
│ │ ├── trimesh_remeshing.py
│ │ ├── trimesh_samplepoints_numpy.py
│ │ ├── trimesh_slicing.py
│ │ ├── trimesh_smoothing_numpy.py
│ │ └── vector.py
│ ├── itertools.py
│ ├── linalg.py
│ ├── matrices.py
│ ├── plugins.py
│ ├── rpc
│ │ ├── __init__.py
│ │ ├── __main__.py
│ │ ├── dispatcher.py
│ │ ├── errors.py
│ │ ├── proxy.py
│ │ ├── server.py
│ │ └── services
│ │ │ ├── __init__.py
│ │ │ ├── default.py
│ │ │ └── watcher.py
│ ├── scene
│ │ ├── __init__.py
│ │ ├── context.py
│ │ ├── curveobject.py
│ │ ├── descriptors
│ │ │ ├── __init__.py
│ │ │ ├── attribute.py
│ │ │ ├── color.py
│ │ │ ├── colordict.py
│ │ │ └── protocol.py
│ │ ├── exceptions.py
│ │ ├── frameobject.py
│ │ ├── geometryobject.py
│ │ ├── graphobject.py
│ │ ├── group.py
│ │ ├── meshobject.py
│ │ ├── planeobject.py
│ │ ├── scene.py
│ │ ├── sceneobject.py
│ │ ├── shapeobject.py
│ │ ├── surfaceobject.py
│ │ └── volmeshobject.py
│ ├── tolerance.py
│ ├── topology
│ │ ├── __init__.py
│ │ ├── combinatorics.py
│ │ ├── connectivity.py
│ │ ├── orientation.py
│ │ └── traversal.py
│ └── utilities
│ │ ├── __init__.py
│ │ ├── azync.py
│ │ ├── datetime.py
│ │ ├── decorators.py
│ │ ├── remote.py
│ │ └── ssh.py
├── compas_blender
│ ├── __init__.py
│ ├── collections.py
│ ├── conversions
│ │ ├── __init__.py
│ │ ├── breps.py
│ │ ├── colors.py
│ │ ├── curves.py
│ │ ├── geometry.py
│ │ ├── meshes.py
│ │ ├── surfaces.py
│ │ └── transformations.py
│ ├── data.py
│ ├── drawing.py
│ ├── geometry
│ │ ├── __init__.py
│ │ └── booleans.py
│ ├── install.py
│ ├── objects.py
│ ├── print_python_path.py
│ ├── scene
│ │ ├── __init__.py
│ │ ├── boxobject.py
│ │ ├── circleobject.py
│ │ ├── curveobject.py
│ │ ├── frameobject.py
│ │ ├── graphobject.py
│ │ ├── lineobject.py
│ │ ├── meshobject.py
│ │ ├── planeobject.py
│ │ ├── pointcloudobject.py
│ │ ├── pointobject.py
│ │ ├── polygonobject.py
│ │ ├── polyhedronobject.py
│ │ ├── polylineobject.py
│ │ ├── sceneobject.py
│ │ ├── shapeobject.py
│ │ ├── surfaceobject.py
│ │ ├── vectorobject.py
│ │ └── volmeshobject.py
│ └── utilities
│ │ └── __init__.py
├── compas_ghpython
│ ├── __init__.py
│ ├── components
│ │ ├── Compas_FromJson
│ │ │ ├── code.py
│ │ │ ├── icon.png
│ │ │ └── metadata.json
│ │ ├── Compas_Info
│ │ │ ├── code.py
│ │ │ ├── icon.png
│ │ │ └── metadata.json
│ │ ├── Compas_RpcCall
│ │ │ ├── code.py
│ │ │ ├── icon.png
│ │ │ └── metadata.json
│ │ ├── Compas_ToJson
│ │ │ ├── code.py
│ │ │ ├── icon.png
│ │ │ └── metadata.json
│ │ ├── Compas_ToRhinoGeometry
│ │ │ ├── code.py
│ │ │ ├── icon.png
│ │ │ └── metadata.json
│ │ └── __init__.py
│ ├── components_cpython
│ │ ├── Compas_FromJson
│ │ │ ├── code.py
│ │ │ ├── icon.png
│ │ │ └── metadata.json
│ │ ├── Compas_Info
│ │ │ ├── code.py
│ │ │ ├── icon.png
│ │ │ └── metadata.json
│ │ ├── Compas_RpcCall
│ │ │ ├── code.py
│ │ │ ├── icon.png
│ │ │ └── metadata.json
│ │ ├── Compas_ToJson
│ │ │ ├── code.py
│ │ │ ├── icon.png
│ │ │ └── metadata.json
│ │ └── Compas_ToRhinoGeometry
│ │ │ ├── code.py
│ │ │ ├── icon.png
│ │ │ └── metadata.json
│ ├── drawing.py
│ ├── install.py
│ ├── scene
│ │ ├── __init__.py
│ │ ├── boxobject.py
│ │ ├── brepobject.py
│ │ ├── capsuleobject.py
│ │ ├── circleobject.py
│ │ ├── coneobject.py
│ │ ├── curveobject.py
│ │ ├── cylinderobject.py
│ │ ├── ellipseobject.py
│ │ ├── frameobject.py
│ │ ├── graphobject.py
│ │ ├── lineobject.py
│ │ ├── meshobject.py
│ │ ├── planeobject.py
│ │ ├── pointobject.py
│ │ ├── polygonobject.py
│ │ ├── polyhedronobject.py
│ │ ├── polylineobject.py
│ │ ├── sceneobject.py
│ │ ├── sphereobject.py
│ │ ├── surfaceobject.py
│ │ ├── torusobject.py
│ │ ├── vectorobject.py
│ │ └── volmeshobject.py
│ ├── sets.py
│ ├── timer.py
│ ├── uninstall.py
│ └── yak_template
│ │ ├── icon.png
│ │ └── manifest.yml
└── compas_rhino
│ ├── __init__.py
│ ├── conduits
│ ├── __init__.py
│ ├── base.py
│ ├── faces.py
│ ├── labels.py
│ ├── lines.py
│ └── points.py
│ ├── conversions
│ ├── __init__.py
│ ├── breps.py
│ ├── curves.py
│ ├── docobjects.py
│ ├── exceptions.py
│ ├── extrusions.py
│ ├── geometry.py
│ ├── meshes.py
│ ├── shapes.py
│ ├── surfaces.py
│ └── transformations.py
│ ├── devtools.py
│ ├── drawing.py
│ ├── geometry
│ ├── __init__.py
│ ├── booleans.py
│ ├── brep
│ │ ├── __init__.py
│ │ ├── brep.py
│ │ ├── builder.py
│ │ ├── edge.py
│ │ ├── face.py
│ │ ├── loop.py
│ │ ├── trim.py
│ │ └── vertex.py
│ ├── curves
│ │ ├── __init__.py
│ │ ├── curve.py
│ │ └── nurbs.py
│ ├── surfaces
│ │ ├── __init__.py
│ │ ├── nurbs.py
│ │ └── surface.py
│ ├── trimesh_curvature.py
│ └── trimesh_slicing.py
│ ├── install.py
│ ├── install_plugin.py
│ ├── install_with_pip.py
│ ├── layers.py
│ ├── objects.py
│ ├── print_python_path.py
│ ├── scene
│ ├── __init__.py
│ ├── boxobject.py
│ ├── brepobject.py
│ ├── capsuleobject.py
│ ├── circleobject.py
│ ├── coneobject.py
│ ├── curveobject.py
│ ├── cylinderobject.py
│ ├── ellipseobject.py
│ ├── frameobject.py
│ ├── graphobject.py
│ ├── helpers.py
│ ├── lineobject.py
│ ├── meshobject.py
│ ├── planeobject.py
│ ├── pointobject.py
│ ├── polygonobject.py
│ ├── polyhedronobject.py
│ ├── polylineobject.py
│ ├── sceneobject.py
│ ├── sphereobject.py
│ ├── surfaceobject.py
│ ├── torusobject.py
│ ├── vectorobject.py
│ └── volmeshobject.py
│ ├── ui.py
│ ├── uninstall.py
│ ├── uninstall_plugin.py
│ └── utilities
│ └── __init__.py
├── tasks.py
└── tests
├── compas
├── colors
│ ├── test_color.py
│ └── test_colordict.py
├── compas_api.json
├── compas_api_ipy.json
├── data
│ ├── test_copy.py
│ ├── test_data.py
│ ├── test_dataschema.py
│ ├── test_json.py
│ ├── test_json_dotnet.py
│ ├── test_json_numpy.py
│ ├── test_pickle.py
│ ├── test_schema.py
│ └── test_validators.py
├── datastructures
│ ├── fixtures
│ │ ├── non-planar.obj
│ │ └── planar.obj
│ ├── test_assembly.py
│ ├── test_cell_network.py
│ ├── test_datastructure.py
│ ├── test_graph.py
│ ├── test_hashtree.py
│ ├── test_mesh.py
│ ├── test_mesh_operations.py
│ ├── test_mesh_subd.py
│ ├── test_tree.py
│ └── test_volmesh.py
├── donttest_api_completeness.py
├── donttest_api_stability.py
├── files
│ ├── fixtures
│ │ ├── bigX_sphere.ply
│ │ ├── gltf
│ │ │ ├── AnimatedMorphCube.glb
│ │ │ ├── BoxInterleaved.glb
│ │ │ ├── BoxTextured.glb
│ │ │ ├── SimpleMeshes.gltf
│ │ │ ├── SimpleMeshesEmbedded.gltf
│ │ │ ├── SimpleMorph.gltf
│ │ │ ├── SimpleSparseAccessor.gltf
│ │ │ ├── SpecGlossVsMetalRough.glb
│ │ │ ├── SpecularTest.glb
│ │ │ ├── TriangleWithoutIndices.gltf
│ │ │ └── triangle.bin
│ │ ├── stl
│ │ │ ├── ascii.stl
│ │ │ ├── binary-1.stl
│ │ │ └── binary-2.stl
│ │ ├── triangle_binary.ply
│ │ └── xml
│ │ │ ├── basic.xml
│ │ │ ├── default_nested_namespace.xml
│ │ │ └── namespaces.xml
│ ├── test_gltf.py
│ ├── test_stl.py
│ └── test_xml.py
├── fixtures
│ ├── iotools
│ │ ├── image.png
│ │ └── text.txt
│ └── topology
│ │ └── vertices_faces.json
├── geometry
│ ├── fixtures
│ │ ├── bbox_points_00.json
│ │ ├── bbox_rect_bad.obj
│ │ └── bbox_rect_good.obj
│ ├── test_bbox.py
│ ├── test_box.py
│ ├── test_capsule.py
│ ├── test_cone.py
│ ├── test_core.py
│ ├── test_core_distance.py
│ ├── test_core_predicates_2.py
│ ├── test_core_predicates_3.py
│ ├── test_core_queries.py
│ ├── test_core_tangent.py
│ ├── test_core_transformations.py
│ ├── test_core_transformations_numpy.py
│ ├── test_curves.py
│ ├── test_curves_arc.py
│ ├── test_curves_bezier.py
│ ├── test_curves_circle.py
│ ├── test_curves_ellipse.py
│ ├── test_curves_hyperbola.py
│ ├── test_curves_line.py
│ ├── test_curves_parabola.py
│ ├── test_curves_polyline.py
│ ├── test_cylinder.py
│ ├── test_frame.py
│ ├── test_intersections.py
│ ├── test_offset.py
│ ├── test_plane.py
│ ├── test_point.py
│ ├── test_pointcloud.py
│ ├── test_polygon.py
│ ├── test_polyhedron.py
│ ├── test_quaternion.py
│ ├── test_shpere.py
│ ├── test_surfaces.py
│ ├── test_surfaces_cone.py
│ ├── test_surfaces_cylinder.py
│ ├── test_surfaces_plane.py
│ ├── test_surfaces_sphere.py
│ ├── test_surfaces_torus.py
│ ├── test_transformations
│ │ ├── test_matrices.py
│ │ ├── test_projection.py
│ │ ├── test_reflection.py
│ │ ├── test_rotation.py
│ │ ├── test_scale.py
│ │ ├── test_shear.py
│ │ ├── test_transformation.py
│ │ └── test_translation.py
│ ├── test_triangulation_earclip.py
│ └── test_vector.py
├── rpc
│ └── test_rpc.py
├── scene
│ ├── test_scene.py
│ └── test_scene_serialisation.py
├── stubs.py
├── test_iotools.py
├── test_itertools.py
├── test_plugins.py
├── test_tolerance.py
├── topology
│ ├── test_traversal.py
│ └── test_unify_cycles.py
└── utilities
│ ├── test_azync.py
│ └── test_decorators.py
└── ipy_test_runner.py
/.editorconfig:
--------------------------------------------------------------------------------
1 | # EditorConfig is awesome: http://EditorConfig.org
2 | root = true
3 |
4 | [*]
5 | end_of_line = lf
6 | trim_trailing_whitespace = true
7 | insert_final_newline = true
8 | indent_style = space
9 | indent_size = 4
10 | charset = utf-8
11 | max_line_length = 179
12 |
13 | [*.{bat,cmd,ps1}]
14 | end_of_line = crlf
15 |
16 | [*.md]
17 | trim_trailing_whitespace = false
18 |
19 | [*.yml]
20 | indent_size = 2
21 |
22 | [*.rst]
23 | indent_size = 4
24 |
25 | [Makefile]
26 | indent_style = tab
27 | indent_size = 4
28 |
29 | [LICENSE]
30 | insert_final_newline = false
31 |
--------------------------------------------------------------------------------
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | # These are supported funding model platforms
2 |
3 | github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
4 | patreon: # Replace with a single Patreon username
5 | open_collective: # Replace with a single Open Collective username
6 | ko_fi: # Replace with a single Ko-fi username
7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
9 | liberapay: # Replace with a single Liberapay username
10 | issuehunt: # Replace with a single IssueHunt username
11 | otechie: # Replace with a single Otechie username
12 | custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
13 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a report to help us improve
4 |
5 | ---
6 |
7 | **Describe the bug**
8 | A clear and concise description of what the bug is.
9 |
10 | **To Reproduce**
11 | Steps to reproduce the behavior:
12 | 1. Context [e.g. ST3, Rhino, Blender, ...]
13 | 2. Sample script
14 | 3. Sample data
15 | 4. See error
16 |
17 | **Expected behavior**
18 | A clear and concise description of what you expected to happen.
19 |
20 | **Screenshots**
21 | If applicable, add screenshots to help explain your problem.
22 |
23 | **Desktop (please complete the following information):**
24 | - OS: [e.g. iOS]
25 | - Python version [e.g. 2.7]
26 | - Python package manager [e.g. macports, pip, conda]
27 |
28 | **Additional context**
29 | Add any other context about the problem here.
30 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: Suggest an idea for this project
4 |
5 | ---
6 | # Feature Request
7 |
8 | As a [role], I want [something] so that [benefit].
9 |
10 | ## Details
11 |
12 | **Is your feature request related to a problem? Please describe.**
13 | A clear and concise description of what the problem is.
14 |
15 | **Describe the solution you'd like**
16 | A clear and concise description of what you want to happen.
17 |
18 | **Describe alternatives you've considered**
19 | A clear and concise description of any alternative solutions or features you've considered.
20 |
21 | **Additional context**
22 | Add any other context or screenshots about the feature request here.
23 |
--------------------------------------------------------------------------------
/.github/pull_request_template.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | ### What type of change is this?
6 |
7 | - [ ] Bug fix in a **backwards-compatible** manner.
8 | - [ ] New feature in a **backwards-compatible** manner.
9 | - [ ] Breaking change: bug fix or new feature that involve incompatible API changes.
10 | - [ ] Other (e.g. doc update, configuration, etc)
11 |
12 | ### Checklist
13 |
14 | _Put an `x` in the boxes that apply. You can also fill these out after creating the PR. If you're unsure about any of them, don't hesitate to ask. We're here to help! This is simply a reminder of what we are going to look for before merging your code._
15 |
16 | - [ ] I added a line to the `CHANGELOG.md` file in the `Unreleased` section under the most fitting heading (e.g. `Added`, `Changed`, `Removed`).
17 | - [ ] I ran all tests on my computer and it's all green (i.e. `invoke test`).
18 | - [ ] I ran lint on my computer and there are no errors (i.e. `invoke lint`).
19 | - [ ] I added new functions/classes and made them available on a second-level import, e.g. `compas.datastructures.Mesh`.
20 | - [ ] I have added tests that prove my fix is effective or that my feature works.
21 | - [ ] I have added necessary documentation (if appropriate)
22 |
--------------------------------------------------------------------------------
/.github/workflows/build.yml:
--------------------------------------------------------------------------------
1 | name: build
2 |
3 | on:
4 | push:
5 | branches:
6 | - main
7 | pull_request:
8 | branches:
9 | - main
10 |
11 | jobs:
12 | build:
13 | if: "!contains(github.event.pull_request.labels.*.name, 'docs-only')"
14 | runs-on: ${{ matrix.os }}
15 | strategy:
16 | matrix:
17 | os: [ubuntu-latest, macos-latest, windows-latest]
18 | python: ["3.9", "3.10", "3.11", "3.12"]
19 |
20 | steps:
21 | - uses: compas-dev/compas-actions.build@v4
22 | with:
23 | invoke_lint: true
24 | invoke_test: true
25 | python: ${{ matrix.python }}
26 |
--------------------------------------------------------------------------------
/.github/workflows/coverage.yml:
--------------------------------------------------------------------------------
1 | name: coverage
2 |
3 | on:
4 | push:
5 | branches:
6 | - main
7 | pull_request:
8 | branches:
9 | - main
10 |
11 | jobs:
12 | coverage:
13 | if: "!contains(github.event.pull_request.labels.*.name, 'docs-only')"
14 | runs-on: ${{ matrix.os }}
15 | strategy:
16 | matrix:
17 | os: [ubuntu-latest]
18 | python: ["3.12"]
19 |
20 | steps:
21 | - uses: compas-dev/compas-actions.build@v4
22 | with:
23 | invoke_lint: false
24 | invoke_test: false
25 | python: ${{ matrix.python }}
26 | - name: Run tests collecting coverage reports
27 | run: pytest --cov src/compas --cov-report=html
28 | - name: Upload coverage reports to Codecov
29 | uses: codecov/codecov-action@v4.0.1
30 | with:
31 | token: ${{ secrets.CODECOV_TOKEN }}
32 |
--------------------------------------------------------------------------------
/.github/workflows/docs.yml:
--------------------------------------------------------------------------------
1 | name: docs
2 |
3 | on:
4 | push:
5 | branches:
6 | - main
7 | tags:
8 | - 'v*'
9 | pull_request_review:
10 | types: [submitted]
11 |
12 | jobs:
13 | docs:
14 | if: github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v') || (github.event_name == 'pull_request_review' && github.event.review.state == 'approved')
15 | runs-on: ubuntu-latest
16 | steps:
17 | - uses: compas-dev/compas-actions.docs@v3
18 | with:
19 | github_token: ${{ secrets.GITHUB_TOKEN }}
20 | doc_url: https://compas.dev/compas
21 |
--------------------------------------------------------------------------------
/.github/workflows/pr-checks.yml:
--------------------------------------------------------------------------------
1 | name: verify-pr-checklist
2 | on:
3 | pull_request:
4 | types: [assigned, opened, synchronize, reopened, labeled, unlabeled]
5 | branches:
6 | - main
7 | - master
8 |
9 | jobs:
10 | build:
11 | name: Check Actions
12 | runs-on: ubuntu-latest
13 | steps:
14 | - uses: actions/checkout@v1
15 | - name: Changelog check
16 | uses: Zomzog/changelog-checker@v1.2.0
17 | with:
18 | fileName: CHANGELOG.md
19 | checkNotification: Simple
20 | env:
21 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
22 |
--------------------------------------------------------------------------------
/.github/workflows/release.yml:
--------------------------------------------------------------------------------
1 | on:
2 | push:
3 | tags:
4 | - "v*"
5 |
6 | name: Create Release
7 |
8 | jobs:
9 | build:
10 | runs-on: ${{ matrix.os }}
11 | strategy:
12 | matrix:
13 | os: [ubuntu-latest, macos-latest, windows-latest]
14 | python: ["3.9", "3.10", "3.11", "3.12"]
15 |
16 | steps:
17 | - uses: compas-dev/compas-actions.build@v4
18 | with:
19 | invoke_lint: true
20 | invoke_test: true
21 | python: ${{ matrix.python }}
22 | check_import: true
23 |
24 | publish:
25 | needs: build
26 | runs-on: windows-latest
27 | steps:
28 | - uses: compas-dev/compas-actions.publish@v3
29 | with:
30 | pypi_token: ${{ secrets.PYPI }}
31 | github_token: ${{ secrets.GITHUB_TOKEN }}
32 | build_ghpython_components: true
33 | gh_source: src/compas_ghpython/components
34 | gh_target: src/compas_ghpython/components/ghuser
35 | release_name_prefix: COMPAS
36 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017-2023 COMPAS Association
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/conftest.py:
--------------------------------------------------------------------------------
1 | import math
2 |
3 | import numpy
4 | import pytest
5 |
6 | import compas
7 | from compas.geometry import allclose
8 |
9 |
10 | def pytest_ignore_collect(path):
11 | if "rhino" in str(path):
12 | return True
13 |
14 | if "blender" in str(path):
15 | return True
16 |
17 | if "ghpython" in str(path):
18 | return True
19 |
20 | if str(path).endswith("_cli.py"):
21 | return True
22 |
23 |
24 | @pytest.fixture(autouse=True)
25 | def add_compas(doctest_namespace):
26 | doctest_namespace["compas"] = compas
27 |
28 |
29 | @pytest.fixture(autouse=True)
30 | def add_math(doctest_namespace):
31 | doctest_namespace["math"] = math
32 |
33 |
34 | @pytest.fixture(autouse=True)
35 | def add_np(doctest_namespace):
36 | doctest_namespace["np"] = numpy
37 |
38 |
39 | @pytest.fixture(autouse=True)
40 | def add_allclose(doctest_namespace):
41 | doctest_namespace["allclose"] = allclose
42 |
--------------------------------------------------------------------------------
/docs/_images/COMPAS.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/compas-dev/compas/96c2ea7a5d7f799b6c8846690a19c464a6dee41e/docs/_images/COMPAS.png
--------------------------------------------------------------------------------
/docs/_images/extensions/compas-robots.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/compas-dev/compas/96c2ea7a5d7f799b6c8846690a19c464a6dee41e/docs/_images/extensions/compas-robots.png
--------------------------------------------------------------------------------
/docs/_images/extensions/compas_3gs.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/compas-dev/compas/96c2ea7a5d7f799b6c8846690a19c464a6dee41e/docs/_images/extensions/compas_3gs.jpg
--------------------------------------------------------------------------------
/docs/_images/extensions/compas_ags.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/compas-dev/compas/96c2ea7a5d7f799b6c8846690a19c464a6dee41e/docs/_images/extensions/compas_ags.png
--------------------------------------------------------------------------------
/docs/_images/extensions/compas_assembly.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/compas-dev/compas/96c2ea7a5d7f799b6c8846690a19c464a6dee41e/docs/_images/extensions/compas_assembly.png
--------------------------------------------------------------------------------
/docs/_images/extensions/compas_cem.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/compas-dev/compas/96c2ea7a5d7f799b6c8846690a19c464a6dee41e/docs/_images/extensions/compas_cem.png
--------------------------------------------------------------------------------
/docs/_images/extensions/compas_cgal.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/compas-dev/compas/96c2ea7a5d7f799b6c8846690a19c464a6dee41e/docs/_images/extensions/compas_cgal.png
--------------------------------------------------------------------------------
/docs/_images/extensions/compas_cloud.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/compas-dev/compas/96c2ea7a5d7f799b6c8846690a19c464a6dee41e/docs/_images/extensions/compas_cloud.png
--------------------------------------------------------------------------------
/docs/_images/extensions/compas_cra.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/compas-dev/compas/96c2ea7a5d7f799b6c8846690a19c464a6dee41e/docs/_images/extensions/compas_cra.png
--------------------------------------------------------------------------------
/docs/_images/extensions/compas_fab.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/compas-dev/compas/96c2ea7a5d7f799b6c8846690a19c464a6dee41e/docs/_images/extensions/compas_fab.png
--------------------------------------------------------------------------------
/docs/_images/extensions/compas_fea.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/compas-dev/compas/96c2ea7a5d7f799b6c8846690a19c464a6dee41e/docs/_images/extensions/compas_fea.png
--------------------------------------------------------------------------------
/docs/_images/extensions/compas_fem.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/compas-dev/compas/96c2ea7a5d7f799b6c8846690a19c464a6dee41e/docs/_images/extensions/compas_fem.png
--------------------------------------------------------------------------------
/docs/_images/extensions/compas_gmsh.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/compas-dev/compas/96c2ea7a5d7f799b6c8846690a19c464a6dee41e/docs/_images/extensions/compas_gmsh.png
--------------------------------------------------------------------------------
/docs/_images/extensions/compas_libigl.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/compas-dev/compas/96c2ea7a5d7f799b6c8846690a19c464a6dee41e/docs/_images/extensions/compas_libigl.png
--------------------------------------------------------------------------------
/docs/_images/extensions/compas_occ.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/compas-dev/compas/96c2ea7a5d7f799b6c8846690a19c464a6dee41e/docs/_images/extensions/compas_occ.png
--------------------------------------------------------------------------------
/docs/_images/extensions/compas_pattern1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/compas-dev/compas/96c2ea7a5d7f799b6c8846690a19c464a6dee41e/docs/_images/extensions/compas_pattern1.png
--------------------------------------------------------------------------------
/docs/_images/extensions/compas_pattern2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/compas-dev/compas/96c2ea7a5d7f799b6c8846690a19c464a6dee41e/docs/_images/extensions/compas_pattern2.png
--------------------------------------------------------------------------------
/docs/_images/extensions/compas_rbe.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/compas-dev/compas/96c2ea7a5d7f799b6c8846690a19c464a6dee41e/docs/_images/extensions/compas_rbe.jpg
--------------------------------------------------------------------------------
/docs/_images/extensions/compas_rrc.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/compas-dev/compas/96c2ea7a5d7f799b6c8846690a19c464a6dee41e/docs/_images/extensions/compas_rrc.png
--------------------------------------------------------------------------------
/docs/_images/extensions/compas_skeleton.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/compas-dev/compas/96c2ea7a5d7f799b6c8846690a19c464a6dee41e/docs/_images/extensions/compas_skeleton.png
--------------------------------------------------------------------------------
/docs/_images/extensions/compas_slicer.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/compas-dev/compas/96c2ea7a5d7f799b6c8846690a19c464a6dee41e/docs/_images/extensions/compas_slicer.jpg
--------------------------------------------------------------------------------
/docs/_images/extensions/compas_tia.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/compas-dev/compas/96c2ea7a5d7f799b6c8846690a19c464a6dee41e/docs/_images/extensions/compas_tia.png
--------------------------------------------------------------------------------
/docs/_images/extensions/compas_tna.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/compas-dev/compas/96c2ea7a5d7f799b6c8846690a19c464a6dee41e/docs/_images/extensions/compas_tna.jpg
--------------------------------------------------------------------------------
/docs/_images/extensions/compas_triangle.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/compas-dev/compas/96c2ea7a5d7f799b6c8846690a19c464a6dee41e/docs/_images/extensions/compas_triangle.png
--------------------------------------------------------------------------------
/docs/_images/extensions/compas_vol.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/compas-dev/compas/96c2ea7a5d7f799b6c8846690a19c464a6dee41e/docs/_images/extensions/compas_vol.png
--------------------------------------------------------------------------------
/docs/_images/ghpython_custom.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/compas-dev/compas/96c2ea7a5d7f799b6c8846690a19c464a6dee41e/docs/_images/ghpython_custom.jpg
--------------------------------------------------------------------------------
/docs/_images/installation.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/compas-dev/compas/96c2ea7a5d7f799b6c8846690a19c464a6dee41e/docs/_images/installation.gif
--------------------------------------------------------------------------------
/docs/_images/rhino_scripteditor.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/compas-dev/compas/96c2ea7a5d7f799b6c8846690a19c464a6dee41e/docs/_images/rhino_scripteditor.png
--------------------------------------------------------------------------------
/docs/_images/tutorial/plotters_dynamic.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/compas-dev/compas/96c2ea7a5d7f799b6c8846690a19c464a6dee41e/docs/_images/tutorial/plotters_dynamic.gif
--------------------------------------------------------------------------------
/docs/_images/tutorial/plotters_example.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/compas-dev/compas/96c2ea7a5d7f799b6c8846690a19c464a6dee41e/docs/_images/tutorial/plotters_example.png
--------------------------------------------------------------------------------
/docs/_images/tutorial/plotters_line-options.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/compas-dev/compas/96c2ea7a5d7f799b6c8846690a19c464a6dee41e/docs/_images/tutorial/plotters_line-options.png
--------------------------------------------------------------------------------
/docs/_images/tutorial/plotters_point-options.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/compas-dev/compas/96c2ea7a5d7f799b6c8846690a19c464a6dee41e/docs/_images/tutorial/plotters_point-options.png
--------------------------------------------------------------------------------
/docs/_images/tutorial/plotters_polygon-options.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/compas-dev/compas/96c2ea7a5d7f799b6c8846690a19c464a6dee41e/docs/_images/tutorial/plotters_polygon-options.png
--------------------------------------------------------------------------------
/docs/_images/tutorial/plotters_vector-options.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/compas-dev/compas/96c2ea7a5d7f799b6c8846690a19c464a6dee41e/docs/_images/tutorial/plotters_vector-options.png
--------------------------------------------------------------------------------
/docs/_images/userguide/basics.colors_color-circle.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/compas-dev/compas/96c2ea7a5d7f799b6c8846690a19c464a6dee41e/docs/_images/userguide/basics.colors_color-circle.png
--------------------------------------------------------------------------------
/docs/_images/userguide/basics.colors_lightness.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/compas-dev/compas/96c2ea7a5d7f799b6c8846690a19c464a6dee41e/docs/_images/userguide/basics.colors_lightness.png
--------------------------------------------------------------------------------
/docs/_images/userguide/basics.colors_maps.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/compas-dev/compas/96c2ea7a5d7f799b6c8846690a19c464a6dee41e/docs/_images/userguide/basics.colors_maps.png
--------------------------------------------------------------------------------
/docs/_images/userguide/basics.colors_maps_from-one-color.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/compas-dev/compas/96c2ea7a5d7f799b6c8846690a19c464a6dee41e/docs/_images/userguide/basics.colors_maps_from-one-color.png
--------------------------------------------------------------------------------
/docs/_images/userguide/basics.colors_maps_from-rgb.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/compas-dev/compas/96c2ea7a5d7f799b6c8846690a19c464a6dee41e/docs/_images/userguide/basics.colors_maps_from-rgb.png
--------------------------------------------------------------------------------
/docs/_images/userguide/basics.colors_maps_from-three-colors.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/compas-dev/compas/96c2ea7a5d7f799b6c8846690a19c464a6dee41e/docs/_images/userguide/basics.colors_maps_from-three-colors.png
--------------------------------------------------------------------------------
/docs/_images/userguide/basics.colors_maps_from-two-colors.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/compas-dev/compas/96c2ea7a5d7f799b6c8846690a19c464a6dee41e/docs/_images/userguide/basics.colors_maps_from-two-colors.png
--------------------------------------------------------------------------------
/docs/_images/userguide/basics.colors_saturation.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/compas-dev/compas/96c2ea7a5d7f799b6c8846690a19c464a6dee41e/docs/_images/userguide/basics.colors_saturation.png
--------------------------------------------------------------------------------
/docs/_images/userguide/basics.datastructures.cellnetworks.example_color.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/compas-dev/compas/96c2ea7a5d7f799b6c8846690a19c464a6dee41e/docs/_images/userguide/basics.datastructures.cellnetworks.example_color.png
--------------------------------------------------------------------------------
/docs/_images/userguide/basics.datastructures.cellnetworks.example_grey.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/compas-dev/compas/96c2ea7a5d7f799b6c8846690a19c464a6dee41e/docs/_images/userguide/basics.datastructures.cellnetworks.example_grey.png
--------------------------------------------------------------------------------
/docs/_images/userguide/basics.datastructures.cellnetworks.example_hull.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/compas-dev/compas/96c2ea7a5d7f799b6c8846690a19c464a6dee41e/docs/_images/userguide/basics.datastructures.cellnetworks.example_hull.png
--------------------------------------------------------------------------------
/docs/_images/userguide/basics.datastructures.meshes.cycles.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/compas-dev/compas/96c2ea7a5d7f799b6c8846690a19c464a6dee41e/docs/_images/userguide/basics.datastructures.meshes.cycles.png
--------------------------------------------------------------------------------
/docs/_images/userguide/basics.datastructures.meshes.edge-loop.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/compas-dev/compas/96c2ea7a5d7f799b6c8846690a19c464a6dee41e/docs/_images/userguide/basics.datastructures.meshes.edge-loop.png
--------------------------------------------------------------------------------
/docs/_images/userguide/basics.datastructures.meshes.edge-strip.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/compas-dev/compas/96c2ea7a5d7f799b6c8846690a19c464a6dee41e/docs/_images/userguide/basics.datastructures.meshes.edge-strip.png
--------------------------------------------------------------------------------
/docs/_images/userguide/basics.datastructures.meshes.face-neighbours.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/compas-dev/compas/96c2ea7a5d7f799b6c8846690a19c464a6dee41e/docs/_images/userguide/basics.datastructures.meshes.face-neighbours.png
--------------------------------------------------------------------------------
/docs/_images/userguide/basics.datastructures.meshes.meshgrid-column0.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/compas-dev/compas/96c2ea7a5d7f799b6c8846690a19c464a6dee41e/docs/_images/userguide/basics.datastructures.meshes.meshgrid-column0.png
--------------------------------------------------------------------------------
/docs/_images/userguide/basics.datastructures.meshes.meshgrid-column3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/compas-dev/compas/96c2ea7a5d7f799b6c8846690a19c464a6dee41e/docs/_images/userguide/basics.datastructures.meshes.meshgrid-column3.png
--------------------------------------------------------------------------------
/docs/_images/userguide/basics.datastructures.meshes.tubemesh.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/compas-dev/compas/96c2ea7a5d7f799b6c8846690a19c464a6dee41e/docs/_images/userguide/basics.datastructures.meshes.tubemesh.png
--------------------------------------------------------------------------------
/docs/_images/userguide/basics.datastructures.meshes.vertex-faces.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/compas-dev/compas/96c2ea7a5d7f799b6c8846690a19c464a6dee41e/docs/_images/userguide/basics.datastructures.meshes.vertex-faces.png
--------------------------------------------------------------------------------
/docs/_images/userguide/basics.datastructures.meshes.vertex-neighbours.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/compas-dev/compas/96c2ea7a5d7f799b6c8846690a19c464a6dee41e/docs/_images/userguide/basics.datastructures.meshes.vertex-neighbours.png
--------------------------------------------------------------------------------
/docs/_images/userguide/cad.blender.visualisation.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/compas-dev/compas/96c2ea7a5d7f799b6c8846690a19c464a6dee41e/docs/_images/userguide/cad.blender.visualisation.png
--------------------------------------------------------------------------------
/docs/_images/userguide/cad.grasshopper.gh_verify.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/compas-dev/compas/96c2ea7a5d7f799b6c8846690a19c464a6dee41e/docs/_images/userguide/cad.grasshopper.gh_verify.jpg
--------------------------------------------------------------------------------
/docs/_images/userguide/cad.grasshopper.ghpython_component.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/compas-dev/compas/96c2ea7a5d7f799b6c8846690a19c464a6dee41e/docs/_images/userguide/cad.grasshopper.ghpython_component.jpg
--------------------------------------------------------------------------------
/docs/_images/vscode_git.JPG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/compas-dev/compas/96c2ea7a5d7f799b6c8846690a19c464a6dee41e/docs/_images/vscode_git.JPG
--------------------------------------------------------------------------------
/docs/_static/PLACEHOLDER:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/compas-dev/compas/96c2ea7a5d7f799b6c8846690a19c464a6dee41e/docs/_static/PLACEHOLDER
--------------------------------------------------------------------------------
/docs/api/compas.colors.html_colors.rst:
--------------------------------------------------------------------------------
1 | ********************************************************************************
2 | HTML Colors
3 | ********************************************************************************
4 |
5 | .. literalinclude:: ../../src/compas/colors/html_colors.py
6 | :language: python
7 |
--------------------------------------------------------------------------------
/docs/api/compas.colors.rst:
--------------------------------------------------------------------------------
1 |
2 | ********************************************************************************
3 | compas.colors
4 | ********************************************************************************
5 |
6 | .. currentmodule:: compas.colors
7 |
8 | .. rst-class:: lead
9 |
10 |
11 | This package defines a color and color map class,
12 | that can be used to work wihth colors in a consistent way across color spaces.
13 |
14 |
15 | Classes
16 | =======
17 |
18 | .. autosummary::
19 | :toctree: generated/
20 | :nosignatures:
21 |
22 | Color
23 | ColorDict
24 | ColorMap
25 |
--------------------------------------------------------------------------------
/docs/api/compas.data.rst:
--------------------------------------------------------------------------------
1 |
2 | ********************************************************************************
3 | compas.data
4 | ********************************************************************************
5 |
6 | .. currentmodule:: compas.data
7 |
8 | .. rst-class:: lead
9 |
10 |
11 | This package defines the core infrastructure for data serialisation in the COMPAS framework.
12 | It provides a base class for data objects, a JSON encoder and decoder, serialisers and deserialisers, and schema validation.
13 |
14 |
15 | Classes
16 | =======
17 |
18 | .. autosummary::
19 | :toctree: generated/
20 | :nosignatures:
21 |
22 | Data
23 | DataDecoder
24 | DataEncoder
25 | DecoderError
26 |
27 |
28 | Functions
29 | =========
30 |
31 | .. autosummary::
32 | :toctree: generated/
33 | :nosignatures:
34 |
35 | compas_dataclasses
36 | dataclass_dataschema
37 | dataclass_jsonschema
38 | dataclass_typeschema
39 | json_dump
40 | json_dumps
41 | json_dumpz
42 | json_load
43 | json_loads
44 | json_loadz
45 |
--------------------------------------------------------------------------------
/docs/api/compas.datastructures.rst:
--------------------------------------------------------------------------------
1 |
2 | ********************************************************************************
3 | compas.datastructures
4 | ********************************************************************************
5 |
6 | .. currentmodule:: compas.datastructures
7 |
8 | .. rst-class:: lead
9 |
10 |
11 | This package defines the core data structures of the COMPAS framework.
12 | The data structures provide a structured way of storing and accessing data on individual components of both topological and geometrical objects.
13 |
14 | Classes
15 | =======
16 |
17 | .. toctree::
18 | :maxdepth: 1
19 | :titlesonly:
20 |
21 | compas.datastructures.Graph
22 | compas.datastructures.Mesh
23 | compas.datastructures.VolMesh
24 | compas.datastructures.CellNetwork
25 | compas.datastructures.Tree
26 | compas.datastructures.Assembly
27 |
28 |
29 | Exceptions
30 | ==========
31 |
32 | .. autosummary::
33 | :toctree: generated/
34 | :nosignatures:
35 |
36 | AssemblyError
37 | FeatureError
38 |
--------------------------------------------------------------------------------
/docs/api/compas.files.rst:
--------------------------------------------------------------------------------
1 |
2 | ********************************************************************************
3 | compas.files
4 | ********************************************************************************
5 |
6 | .. currentmodule:: compas.files
7 |
8 | .. rst-class:: lead
9 |
10 |
11 | This package defines a number of file formats and provides functionality for reading and writing data in these formats.
12 |
13 |
14 | Classes
15 | =======
16 |
17 | .. autosummary::
18 | :toctree: generated/
19 | :nosignatures:
20 |
21 | GLTF
22 | OBJ
23 | OFF
24 | PLY
25 | STL
26 | XML
27 |
28 |
29 | Functions
30 | =========
31 |
32 | .. autosummary::
33 | :toctree: generated/
34 | :nosignatures:
35 |
36 | prettify_string
37 |
--------------------------------------------------------------------------------
/docs/api/compas.itertools.rst:
--------------------------------------------------------------------------------
1 | ********************************************************************************
2 | compas.itertools
3 | ********************************************************************************
4 |
5 | .. currentmodule:: compas.itertools
6 |
7 | .. rst-class:: lead
8 |
9 | This package defines useful functions for working with iterable objects.
10 |
11 |
12 | Functions
13 | =========
14 |
15 | .. autosummary::
16 | :toctree: generated/
17 | :nosignatures:
18 |
19 | normalize_values
20 | remap_values
21 | meshgrid
22 | linspace
23 | flatten
24 | reshape
25 | pairwise
26 | window
27 | iterable_like
28 |
--------------------------------------------------------------------------------
/docs/api/compas.plugins.rst:
--------------------------------------------------------------------------------
1 |
2 | ********************************************************************************
3 | compas.plugins
4 | ********************************************************************************
5 |
6 | .. currentmodule:: compas.plugins
7 |
8 | .. rst-class:: lead
9 |
10 |
11 | COMPAS has an extensible architecture based on plugins that allows to
12 | customize and extend the functionality of the core framework.
13 |
14 |
15 | Classes
16 | =======
17 |
18 | .. autosummary::
19 | :toctree: generated/
20 | :nosignatures:
21 |
22 | IncompletePluginImplError
23 | PluginDefaultNotAvailableError
24 | PluginManager
25 | PluginNotInstalledError
26 | PluginValidator
27 |
28 |
29 | Functions
30 | =========
31 |
32 | .. autosummary::
33 | :toctree: generated/
34 | :nosignatures:
35 |
36 | pluggable
37 | plugin
38 | plugin_manager
39 |
--------------------------------------------------------------------------------
/docs/api/compas.rpc.rst:
--------------------------------------------------------------------------------
1 |
2 | ********************************************************************************
3 | compas.rpc
4 | ********************************************************************************
5 |
6 | .. currentmodule:: compas.rpc
7 |
8 | .. rst-class:: lead
9 |
10 |
11 | COMPAS runs in many different environments, but in some environments the availablity of libraries is limited.
12 | For example, when running COMPAS in an IronPython-based environment like Rhino/Grasshopper,
13 | plenty of CPython libraries such as `numpy` and `scipy` are not available.
14 | To workaround this limitation, COMPAS provides a mechanisms to access the functionality of a CPython environment seemlessly from any other Python environment through a "Remote Procedure Call" or RPC.
15 | Through RPC, COMPAS can be used as a server for remote clients, and as a client for remote servers.
16 | A typical use case is to run algorithms that require packages like ``numpy`` or ``scipy`` on a remote server, when working in Rhino.
17 | Or to use COMPAS in a browser application.
18 |
19 |
20 | Classes
21 | =======
22 |
23 | .. autosummary::
24 | :toctree: generated/
25 | :nosignatures:
26 |
27 | Dispatcher
28 | Proxy
29 | RPCClientError
30 | RPCServerError
31 | Server
32 |
--------------------------------------------------------------------------------
/docs/api/compas.tolerance.rst:
--------------------------------------------------------------------------------
1 |
2 | ********************************************************************************
3 | compas.tolerance
4 | ********************************************************************************
5 |
6 | .. currentmodule:: compas.tolerance
7 |
8 | .. rst-class:: lead
9 |
10 |
11 | The tolerance module provides functionality to deal with tolerances consistently across all other COMPAS packages.
12 |
13 |
14 | Classes
15 | =======
16 |
17 |
18 |
19 | .. autosummary::
20 | :toctree: generated/
21 | :nosignatures:
22 |
23 | Tolerance
24 |
25 |
26 | Functions
27 | =========
28 |
29 |
30 |
31 | .. autosummary::
32 | :toctree: generated/
33 | :nosignatures:
34 |
35 | TOL
36 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/docs/api/compas_blender.conversions.rst:
--------------------------------------------------------------------------------
1 |
2 | ********************************************************************************
3 | compas_blender.conversions
4 | ********************************************************************************
5 |
6 | .. currentmodule:: compas_blender.conversions
7 |
8 | .. rst-class:: lead
9 |
10 |
11 | This package provides functions to convert between COMPAS data/objects and Blender data/objects.
12 |
13 |
14 | Functions
15 | =========
16 |
17 | .. autosummary::
18 | :toctree: generated/
19 | :nosignatures:
20 |
21 | bmesh_to_compas
22 | circle_to_blender_curve
23 | color_to_blender_material
24 | cylinder_to_blender_mesh
25 | line_to_blender_curve
26 | mesh_to_blender
27 | mesh_to_compas
28 | meshobj_to_compas
29 | monkey_to_compas
30 | nurbscurve_to_blender_curve
31 | nurbssurface_to_blender_surface
32 | pointcloud_to_blender
33 | polygon_to_blender_mesh
34 | polyline_to_blender_curve
35 | sphere_to_blender_mesh
36 | transformation_to_blender
37 | transformation_to_compas
38 | vertices_and_faces_to_blender_mesh
39 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/docs/api/compas_blender.geometry.rst:
--------------------------------------------------------------------------------
1 |
2 | ********************************************************************************
3 | compas_blender.geometry
4 | ********************************************************************************
5 |
6 | .. currentmodule:: compas_blender.geometry
7 |
8 | .. rst-class:: lead
9 |
10 |
11 | This package provides plugins for various geometry pluggables using Blender as the backend.
12 |
13 |
14 | Plugins
15 | =======
16 |
17 | Plugins provide implementations for pluggables. You can use the plugin directly, or through the pluggable.
18 |
19 | .. autosummary::
20 | :toctree: generated/
21 | :nosignatures:
22 |
23 | boolean_difference_mesh_mesh
24 | boolean_intersection_mesh_mesh
25 | boolean_union_mesh_mesh
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/docs/api/compas_blender.scene.rst:
--------------------------------------------------------------------------------
1 |
2 | ********************************************************************************
3 | compas_blender.scene
4 | ********************************************************************************
5 |
6 | .. currentmodule:: compas_blender.scene
7 |
8 | .. rst-class:: lead
9 |
10 |
11 | This package provides scene object plugins for visualising COMPAS objects in Blender.
12 | When working in Blender, :class:`compas.scene.SceneObject` will automatically use the corresponding Blender scene object for each COMPAS object type.
13 |
14 |
15 | Classes
16 | =======
17 |
18 | .. autosummary::
19 | :toctree: generated/
20 | :nosignatures:
21 |
22 | BlenderSceneObject
23 | BoxObject
24 | CapsuleObject
25 | CircleObject
26 | ConeObject
27 | CurveObject
28 | CylinderObject
29 | FrameObject
30 | LineObject
31 | MeshObject
32 | GraphObject
33 | PointObject
34 | PointcloudObject
35 | PolygonObject
36 | PolyhedronObject
37 | PolylineObject
38 | SphereObject
39 | SurfaceObject
40 | TorusObject
41 | VectorObject
42 | VolMeshObject
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/docs/api/compas_ghpython.components.rst:
--------------------------------------------------------------------------------
1 |
2 | ********************************************************************************
3 | compas_ghpython.components
4 | ********************************************************************************
5 |
6 | .. currentmodule:: compas_ghpython.components
7 |
8 | .. rst-class:: lead
9 |
10 | This package provides a small set of functions to easily install and uninstall user-defined GH Components.
11 |
12 |
13 | Functions
14 | =========
15 |
16 | .. autosummary::
17 | :toctree: generated/
18 | :nosignatures:
19 |
20 | install_userobjects
21 | uninstall_userobjects
22 |
--------------------------------------------------------------------------------
/docs/api/compas_ghpython.scene.rst:
--------------------------------------------------------------------------------
1 |
2 | ********************************************************************************
3 | compas_ghpython.scene
4 | ********************************************************************************
5 |
6 | .. currentmodule:: compas_ghpython.scene
7 |
8 | .. rst-class:: lead
9 |
10 |
11 | This package provides scene object plugins for visualising COMPAS objects in Grasshopper.
12 | When working in GH Python components, :class:`compas.scene.SceneObject` will automatically use the corresponding GHPython scene object for each COMPAS object type.
13 |
14 |
15 | Classes
16 | =======
17 |
18 | .. autosummary::
19 | :toctree: generated/
20 | :nosignatures:
21 |
22 | BoxObject
23 | CapsuleObject
24 | CircleObject
25 | ConeObject
26 | CurveObject
27 | CylinderObject
28 | EllipseObject
29 | FrameObject
30 | GHSceneObject
31 | LineObject
32 | MeshObject
33 | GraphObject
34 | PointObject
35 | PolygonObject
36 | PolyhedronObject
37 | PolylineObject
38 | SphereObject
39 | SurfaceObject
40 | TorusObject
41 | VectorObject
42 | VolMeshObject
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/docs/api/compas_rhino.geometry.rst:
--------------------------------------------------------------------------------
1 |
2 | ********************************************************************************
3 | compas_rhino.geometry
4 | ********************************************************************************
5 |
6 | .. currentmodule:: compas_rhino.geometry
7 |
8 | .. rst-class:: lead
9 |
10 |
11 | This package provides plugins for various geometry pluggables using Rhino as the backend.
12 |
13 |
14 | Classes
15 | =======
16 |
17 | .. autosummary::
18 | :toctree: generated/
19 | :nosignatures:
20 |
21 | RhinoBrep
22 | RhinoBrepEdge
23 | RhinoBrepFace
24 | RhinoBrepLoop
25 | RhinoBrepTrim
26 | RhinoBrepVertex
27 | RhinoNurbsCurve
28 | RhinoNurbsSurface
29 |
30 |
31 | Plugins
32 | =======
33 |
34 | Plugins provide implementations for pluggables. You can use the plugin directly, or through the pluggable.
35 |
36 | .. autosummary::
37 | :toctree: generated/
38 | :nosignatures:
39 |
40 | boolean_difference_mesh_mesh
41 | boolean_intersection_mesh_mesh
42 | boolean_union_mesh_mesh
43 | trimesh_gaussian_curvature
44 | trimesh_mean_curvature
45 | trimesh_principal_curvature
46 | trimesh_slice
47 |
48 |
49 |
50 |
--------------------------------------------------------------------------------
/docs/api/compas_rhino.scene.rst:
--------------------------------------------------------------------------------
1 |
2 | ********************************************************************************
3 | compas_rhino.scene
4 | ********************************************************************************
5 |
6 | .. currentmodule:: compas_rhino.scene
7 |
8 | .. rst-class:: lead
9 |
10 |
11 | This package provides scene object plugins for visualising COMPAS objects in Rhino.
12 | When working in Rhino, :class:`compas.scene.SceneObject` will automatically use the corresponding Rhino scene object for each COMPAS object type.
13 |
14 |
15 | Classes
16 | =======
17 |
18 | .. autosummary::
19 | :toctree: generated/
20 | :nosignatures:
21 |
22 | RhinoBoxObject
23 | RhinoBrepObject
24 | RhinoCapsuleObject
25 | RhinoCircleObject
26 | RhinoConeObject
27 | RhinoCurveObject
28 | RhinoCylinderObject
29 | RhinoEllipseObject
30 | RhinoFrameObject
31 | RhinoLineObject
32 | RhinoMeshObject
33 | RhinoGraphObject
34 | RhinoPlaneObject
35 | RhinoPointObject
36 | RhinoPolygonObject
37 | RhinoPolyhedronObject
38 | RhinoPolylineObject
39 | RhinoSceneObject
40 | RhinoSphereObject
41 | RhinoSurfaceObject
42 | RhinoTorusObject
43 | RhinoVectorObject
44 | RhinoVolMeshObject
45 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/docs/devguide/documentation.rst:
--------------------------------------------------------------------------------
1 | Contributing to the Documentation
2 | =================================
3 |
--------------------------------------------------------------------------------
/docs/devguide/extensions.rst:
--------------------------------------------------------------------------------
1 | Developing an Extension
2 | =======================
3 |
--------------------------------------------------------------------------------
/docs/devguide/index.rst:
--------------------------------------------------------------------------------
1 | Developer Guide
2 | ===============
3 |
4 | This guide is intended for developers who want to contribute to the code and/or documentation of COMPAS.
5 |
6 | .. toctree::
7 | :maxdepth: 1
8 | :titlesonly:
9 | :caption: Development Basics
10 |
11 | setup
12 | workflow
13 | code
14 | documentation
15 |
16 | .. toctree::
17 | :maxdepth: 1
18 | :titlesonly:
19 | :caption: Advanced Topics
20 |
21 | extensions
22 | plugins
23 | ghcomponent
24 | dtypes
25 |
--------------------------------------------------------------------------------
/docs/devguide/plugins.rst:
--------------------------------------------------------------------------------
1 | Developing a Plugin For a Pluggable
2 | ===================================
3 |
--------------------------------------------------------------------------------
/docs/index.rst:
--------------------------------------------------------------------------------
1 | :html_theme.sidebar_secondary.remove: true
2 |
3 | ********************************************************************************
4 | COMPAS Documentation
5 | ********************************************************************************
6 |
7 | .. rst-class:: lead
8 |
9 | This is the documentation of the core infratructure of COMPAS,
10 | an open source framework for computational research and collaboration
11 | in Architecture, Engineering, Fabrication, and Construction.
12 |
13 | .. note::
14 |
15 | This is the documentation of the core Python package of COMPAS.
16 | If you are looking for the COMPAS Framework website,
17 | please go to https://compas.dev.
18 |
19 |
20 | User Guide
21 | ==========
22 |
23 | If you want to use COMPAS for your research or in one of your projects,
24 | this is the place to start.
25 |
26 | .. toctree::
27 | :maxdepth: 2
28 | :titlesonly:
29 |
30 | userguide/index
31 |
32 |
33 | Development
34 | ===========
35 |
36 | If you want to contribute to COMPAS, this is the place to start.
37 |
38 | .. toctree::
39 | :maxdepth: 2
40 | :titlesonly:
41 |
42 | devguide/index
43 |
44 |
45 | API Reference
46 | =============
47 |
48 | The reference documentation of the core package and the CAD packages.
49 |
50 | .. toctree::
51 | :maxdepth: 2
52 |
53 | api/index
54 |
55 |
56 | Indices and tables
57 | ==================
58 |
59 | * :ref:`genindex`
60 | * :ref:`modindex`
61 | * :ref:`search`
62 |
--------------------------------------------------------------------------------
/docs/sort__all__.py:
--------------------------------------------------------------------------------
1 | import compas
2 | from compas_blender import conversions as module
3 |
4 | functions = []
5 | classes = []
6 | errors = []
7 | numpy = []
8 |
9 | __newall__ = {
10 | "classes": [],
11 | "errors": [],
12 | "functions": [],
13 | "numpy": [],
14 | "pluggables": [],
15 | "plugins": [],
16 | }
17 |
18 | for name in module.__all__:
19 | obj = getattr(module, name)
20 |
21 | if name.endswith("_numpy"):
22 | numpy.append(name)
23 | continue
24 |
25 | if isinstance(obj, type):
26 | classes.append(name)
27 | else:
28 | functions.append(name)
29 |
30 | for name in sorted(classes):
31 | __newall__["classes"].append(name)
32 |
33 | for name in sorted(functions):
34 | __newall__["functions"].append(name)
35 |
36 | for name in sorted(numpy):
37 | __newall__["numpy"].append(name)
38 |
39 |
40 | compas.json_dump(__newall__, f"docs/{module.__name__}__all__.json", pretty=True)
41 |
--------------------------------------------------------------------------------
/docs/userguide/advanced.pluggables.rst:
--------------------------------------------------------------------------------
1 | ********************************************************************************
2 | Pluggables and Plugins
3 | ********************************************************************************
4 |
5 |
--------------------------------------------------------------------------------
/docs/userguide/basics.datastructures.cellnetworks.py:
--------------------------------------------------------------------------------
1 | import os
2 |
3 | from compas_viewer import Viewer
4 |
5 | import compas
6 | from compas.colors import Color
7 | from compas.datastructures import CellNetwork
8 | from compas.geometry import Line
9 | from compas.geometry import Polygon
10 |
11 | cell_network: CellNetwork = CellNetwork.from_json(compas.get("cellnetwork_example.json")) # type: ignore
12 |
13 | viewer = Viewer(show_grid=False)
14 |
15 | no_cell = cell_network.faces_without_cell()
16 |
17 | for face in cell_network.faces():
18 | if cell_network.is_face_on_boundary(face) is True:
19 | color, opacity = Color.silver(), 0.5
20 | elif face in no_cell:
21 | color, opacity = Color.azure(), 0.3
22 | else:
23 | color, opacity = Color.yellow(), 0.8
24 |
25 | viewer.scene.add(Polygon(cell_network.face_coordinates(face)), facecolor=color, opacity=opacity)
26 |
27 | for edge in cell_network.edges_without_face():
28 | line = Line(*cell_network.edge_coordinates(edge))
29 | viewer.scene.add(line, linewidth=3)
30 |
31 | graph = cell_network.cells_to_graph()
32 | viewer.scene.add(graph)
33 |
34 | viewer.show()
35 |
--------------------------------------------------------------------------------
/docs/userguide/basics.datastructures.cells.rst:
--------------------------------------------------------------------------------
1 | ********************************************************************************
2 | Cellular Meshes
3 | ********************************************************************************
4 |
--------------------------------------------------------------------------------
/docs/userguide/basics.datastructures.graphs.rst:
--------------------------------------------------------------------------------
1 | ********************************************************************************
2 | Graphs
3 | ********************************************************************************
4 |
--------------------------------------------------------------------------------
/docs/userguide/basics.datastructures.meshes.py:
--------------------------------------------------------------------------------
1 | # type: ignore
2 |
3 | from compas_viewer import Viewer
4 |
5 | from compas.colors import Color
6 | from compas.datastructures import Mesh
7 |
8 | mesh = Mesh.from_meshgrid(dx=9, nx=9)
9 |
10 | viewer = Viewer(viewmode="top", width=1600, height=900)
11 |
12 | red = Color.red()
13 |
14 | viewer.scene.add(mesh, facecolor=(0.95, 0.95, 0.95), lineswidth=2)
15 | viewer.scene.add(mesh.edge_line((30, 31)).translated([0, 0, 0.1]), linecolor=red, lineswidth=10)
16 |
17 | for edge in mesh.edge_loop((30, 31)):
18 | viewer.scene.add(mesh.edge_line(edge).translated([0, 0, 0.1]), lineswidth=10)
19 |
20 | viewer.show()
21 |
--------------------------------------------------------------------------------
/docs/userguide/basics.datastructures.rst:
--------------------------------------------------------------------------------
1 | ********************************************************************************
2 | Datastructures
3 | ********************************************************************************
4 |
5 | .. toctree::
6 | :maxdepth: 2
7 | :titlesonly:
8 | :caption: Data Structures
9 |
10 | basics.datastructures.graphs
11 | basics.datastructures.meshes
12 | basics.datastructures.cells
13 | basics.datastructures.cellnetwork
14 | basics.datastructures.trees
15 |
--------------------------------------------------------------------------------
/docs/userguide/basics.geometry.curves_and_surfaces.rst:
--------------------------------------------------------------------------------
1 | ********************************************************************************
2 | Curves and Surfaces
3 | ********************************************************************************
4 |
--------------------------------------------------------------------------------
/docs/userguide/basics.geometry.distance_and_membership.rst:
--------------------------------------------------------------------------------
1 | ******************************************************************************
2 | Distance and Membership
3 | ******************************************************************************
4 |
--------------------------------------------------------------------------------
/docs/userguide/basics.geometry.intersections.rst:
--------------------------------------------------------------------------------
1 | ********************************************************************************
2 | Intersections
3 | ********************************************************************************
4 |
--------------------------------------------------------------------------------
/docs/userguide/basics.geometry.polygons_and_polyhedrons.rst:
--------------------------------------------------------------------------------
1 | ********************************************************************************
2 | Polygons and Polyhedrons
3 | ********************************************************************************
4 |
--------------------------------------------------------------------------------
/docs/userguide/basics.geometry.rst:
--------------------------------------------------------------------------------
1 | Geometry
2 | ========
3 |
4 | .. toctree::
5 | :maxdepth: 2
6 | :titlesonly:
7 | :caption: Geometry
8 |
9 | basics.geometry.points_and_vectors
10 | basics.geometry.planes_and_frames
11 | basics.geometry.polygons_and_polyhedrons
12 | basics.geometry.curves_and_surfaces
13 | basics.geometry.solids
14 | basics.geometry.breps
15 | basics.geometry.transformations
16 |
--------------------------------------------------------------------------------
/docs/userguide/basics.geometry.solids.rst:
--------------------------------------------------------------------------------
1 | ********************************************************************************
2 | Shapes and Solids
3 | ********************************************************************************
4 |
--------------------------------------------------------------------------------
/docs/userguide/basics.geometry.transformations.rst:
--------------------------------------------------------------------------------
1 | ********************************************************************************
2 | Transformations
3 | ********************************************************************************
4 |
--------------------------------------------------------------------------------
/docs/userguide/cad.other.rst:
--------------------------------------------------------------------------------
1 | ********************************************************************************
2 | Working in Other CAD Software
3 | ********************************************************************************
4 |
5 |
--------------------------------------------------------------------------------
/docs/userguide/citing.rst:
--------------------------------------------------------------------------------
1 | ********************************************************************************
2 | Citing
3 | ********************************************************************************
4 |
5 | .. rst-class:: lead
6 |
7 | The core library of COMPAS is developed by a small team of nerds at ETH Zurich.
8 | If you use COMPAS in your work, please acknowledge their many sleepless nights
9 | and lack of social life :)
10 |
11 | ::
12 |
13 | @misc{compas-dev,
14 | title = {{COMPAS}: A framework for computational research in architecture and structures.},
15 | author = {Tom Van Mele and many others},
16 | note = {http://compas.dev},
17 | year = {2017-2021},
18 | doi = {10.5281/zenodo.2594510},
19 | url = {https://doi.org/10.5281/zenodo.2594510},
20 | }
21 |
22 |
--------------------------------------------------------------------------------
/docs/userguide/index.rst:
--------------------------------------------------------------------------------
1 | ********************************************************************************
2 | User Guide
3 | ********************************************************************************
4 |
5 | .. toctree::
6 | :maxdepth: 2
7 | :titlesonly:
8 | :caption: Getting Started
9 |
10 | introduction
11 | installation
12 | firststeps
13 | whatsnext
14 |
15 |
16 | .. toctree::
17 | :maxdepth: 2
18 | :titlesonly:
19 | :caption: Tutorial: Basics
20 |
21 | basics.geometry
22 | basics.datastructures
23 | basics.visualisation
24 | basics.colors
25 |
26 |
27 | .. toctree::
28 | :maxdepth: 2
29 | :titlesonly:
30 | :caption: Tutorial: Advanced
31 |
32 | advanced.tolerance
33 | advanced.serialisation
34 | advanced.rpc
35 | advanced.hashtree
36 |
37 |
38 | .. toctree::
39 | :maxdepth: 2
40 | :titlesonly:
41 | :caption: Tutorial: Working in CAD
42 |
43 | cad.rhino
44 | cad.rhino8
45 | cad.grasshopper
46 | cad.blender
47 |
48 |
49 | .. toctree::
50 | :maxdepth: 2
51 | :titlesonly:
52 | :caption: Miscellaneous Info
53 |
54 | releases
55 | citing
56 | license
57 |
--------------------------------------------------------------------------------
/docs/userguide/license.rst:
--------------------------------------------------------------------------------
1 | ********************************************************************************
2 | License
3 | ********************************************************************************
4 |
5 | .. rst-class:: lead
6 |
7 | COMPAS is an open source framework with a permissive license such that it can be used
8 | for research as well as for proprietary projects, in academia and in practice,
9 | or at the interface between both.
10 |
11 | .. literalinclude:: ../../LICENSE
12 | :language: none
13 |
--------------------------------------------------------------------------------
/docs/userguide/releases.rst:
--------------------------------------------------------------------------------
1 | ********************************************************************************
2 | Releases
3 | ********************************************************************************
4 |
5 | .. rst-class:: lead
6 |
7 | COMPAS releases are available on the Python Package Index (PyPI), on ``conda-forge``
8 | or directly from the Github repo.
9 |
10 | Versions are tagged following the Semantic Versioning (semver) convention of ``MAJOR.MINOR.PATCH``.
11 | For more information see `Semantic Versioning 2.0.0 `_.
12 |
13 | The API of ``COMPAS`` was under heavy development up until ``COMPAS 0.19``,
14 | the last version series before ``1.0``.
15 |
16 | Starting with ``1.0`` the API has been stabilized and the project adheres strictly to
17 | semver. In addition to the version number, major releases also have a name
18 | following the pattern `` ``, with the words
19 | forming a tautogram in which the first letter increases alphabetically on every major
20 | release and rolls back to A after reaching Z. For example: ``COMPAS 16.0: Projective Pirate``.
21 |
22 | Past and future release names
23 | =============================
24 |
25 | .. rst-class:: table table-bordered
26 |
27 | .. list-table::
28 | :widths: auto
29 | :header-rows: 1
30 |
31 | * - Version
32 | - Code name
33 | - Release date
34 | * - COMPAS 1.0
35 | - Affine Anchor
36 | - 2021-01-18
37 |
--------------------------------------------------------------------------------
/docs/userguide/samples/colors.py:
--------------------------------------------------------------------------------
1 | # type: ignore
2 |
3 | from compas_viewer import Viewer
4 |
5 | from compas.colors import Color
6 | from compas.geometry import Circle
7 | from compas.geometry import Frame
8 |
9 | viewer = Viewer(show_grid=False)
10 |
11 | viewer.scene.add(Circle(0.4, Frame([0, 0, 0])), linecolor=Color.red(), n=100)
12 | viewer.scene.add(Circle(0.4, Frame([1, 0, 0])), linecolor=Color.orange(), n=100)
13 | viewer.scene.add(Circle(0.4, Frame([2, 0, 0])), linecolor=Color.yellow(), n=100)
14 | viewer.scene.add(Circle(0.4, Frame([3, 0, 0])), linecolor=Color.lime(), n=100)
15 | viewer.scene.add(Circle(0.4, Frame([4, 0, 0])), linecolor=Color.green(), n=100)
16 | viewer.scene.add(Circle(0.4, Frame([5, 0, 0])), linecolor=Color.mint(), n=100)
17 | viewer.scene.add(Circle(0.4, Frame([6, 0, 0])), linecolor=Color.cyan(), n=100)
18 | viewer.scene.add(Circle(0.4, Frame([7, 0, 0])), linecolor=Color.azure(), n=100)
19 | viewer.scene.add(Circle(0.4, Frame([8, 0, 0])), linecolor=Color.blue(), n=100)
20 | viewer.scene.add(Circle(0.4, Frame([9, 0, 0])), linecolor=Color.violet(), n=100)
21 | viewer.scene.add(Circle(0.4, Frame([10, 0, 0])), linecolor=Color.magenta(), n=100)
22 | viewer.scene.add(Circle(0.4, Frame([11, 0, 0])), linecolor=Color.pink(), n=100)
23 | viewer.scene.add(Circle(0.4, Frame([12, 0, 0])), linecolor=Color.red(), n=100)
24 |
25 | viewer.show()
26 |
--------------------------------------------------------------------------------
/docs/userguide/samples/colors_lightness.py:
--------------------------------------------------------------------------------
1 | # type: ignore
2 |
3 | from compas_viewer import Viewer
4 |
5 | from compas.colors import Color
6 | from compas.geometry import Circle
7 | from compas.geometry import Frame
8 |
9 | viewer = Viewer(show_grid=False)
10 |
11 | colors = [
12 | Color.red(),
13 | Color.orange(),
14 | Color.yellow(),
15 | Color.lime(),
16 | Color.green(),
17 | Color.mint(),
18 | Color.cyan(),
19 | Color.azure(),
20 | Color.blue(),
21 | Color.violet(),
22 | Color.magenta(),
23 | Color.pink(),
24 | ]
25 |
26 | for up in range(5):
27 | for right, color in enumerate(colors):
28 | viewer.scene.add(Circle(0.4, Frame([right, up, 0])), linecolor=color.darkened(up * 25), n=100)
29 |
30 | for down in range(1, 5):
31 | for right, color in enumerate(colors):
32 | viewer.scene.add(Circle(0.4, Frame([right, -down, 0])), linecolor=color.lightened(down * 25), n=100)
33 |
34 | viewer.show()
35 |
--------------------------------------------------------------------------------
/docs/userguide/samples/colors_maps.py:
--------------------------------------------------------------------------------
1 | # type: ignore
2 |
3 | from compas_viewer import Viewer
4 |
5 | from compas.colors import Color
6 | from compas.colors import ColorMap
7 | from compas.datastructures import Mesh
8 | from compas.geometry import Circle
9 | from compas.geometry import Frame
10 | from compas.geometry import Pointcloud
11 | from compas.geometry import Polygon
12 |
13 | viewer = Viewer(show_grid=False)
14 |
15 | cmap = ColorMap.from_mpl("viridis")
16 | w = 16
17 | h = 10
18 | n = len(cmap.colors)
19 | d = w / n
20 | cloud = Pointcloud.from_bounds(w, h, 0, n)
21 | white = Color.white()
22 | facecolors = {}
23 | polygons = []
24 | for i, color in enumerate(cmap.colors):
25 | # c = Circle(0.1, Frame(cloud[i]))
26 | p = Polygon(
27 | [
28 | [i * d, -2, 0],
29 | [(i + 1) * d, -2, 0],
30 | [(i + 1) * d, -1, 0],
31 | [i * d, -1, 0],
32 | ]
33 | )
34 | polygons.append(p)
35 | facecolors[i] = color
36 | # viewer.add(c.to_polygon(100), facecolor=color)
37 |
38 | viewer.scene.add(Mesh.from_polygons(polygons), facecolor=facecolors, show_lines=False, show_points=False)
39 |
40 | viewer.show()
41 |
--------------------------------------------------------------------------------
/docs/userguide/samples/colors_maps_from-rgb.py:
--------------------------------------------------------------------------------
1 | # type: ignore
2 |
3 | from compas_viewer import Viewer
4 |
5 | from compas.colors import ColorMap
6 | from compas.datastructures import Mesh
7 | from compas.geometry import Bezier
8 | from compas.geometry import Point
9 | from compas.geometry import Polygon
10 | from compas.geometry import Vector
11 | from compas.itertools import linspace
12 | from compas.itertools import pairwise
13 |
14 | n = 5000
15 |
16 | zaxis = Vector.Zaxis()
17 |
18 | points = [Point(0, 0, 0), Point(3, 6, 0), Point(6, -6, 0), Point(9, 0, 0)]
19 | curve = Bezier(points)
20 |
21 | up = []
22 | down = []
23 | for i in linspace(0, 1, n):
24 | point = curve.point_at(i)
25 | tangent = curve.tangent_at(i)
26 | normal = zaxis.cross(tangent)
27 | up.append(point + normal * 0.1)
28 | down.append(point - normal * 0.1)
29 |
30 | polygons = []
31 | for (d, c), (a, b) in zip(pairwise(up), pairwise(down)):
32 | polygons.append(Polygon([a, b, c, d]))
33 |
34 | cmap = ColorMap.from_rgb()
35 |
36 | mesh = Mesh.from_polygons(polygons)
37 | facecolors = {i: cmap(i, minval=0, maxval=n - 1) for i in range(n)}
38 |
39 | viewer = Viewer(show_grid=False)
40 | viewer.scene.add(mesh, facecolor=facecolors, show_lines=False, show_points=False)
41 | viewer.show()
42 |
--------------------------------------------------------------------------------
/docs/userguide/samples/colors_maps_from-rgb_simple.py:
--------------------------------------------------------------------------------
1 | # type: ignore
2 |
3 | from compas_viewer import Viewer
4 |
5 | from compas.colors import ColorMap
6 | from compas.datastructures import Mesh
7 | from compas.geometry import Point
8 | from compas.geometry import Polygon
9 | from compas.itertools import linspace
10 | from compas.itertools import pairwise
11 |
12 | n = 256
13 | t = 0.3
14 |
15 | up = []
16 | down = []
17 | for i in linspace(0, 10, n):
18 | point = Point(i, 0, 0)
19 | up.append(point + [0, t, 0])
20 | down.append(point - [0, t, 0])
21 |
22 | polygons = []
23 | for (d, c), (a, b) in zip(pairwise(up), pairwise(down)):
24 | polygons.append(Polygon([a, b, c, d]))
25 |
26 | cmap = ColorMap.from_rgb()
27 |
28 | mesh = Mesh.from_polygons(polygons)
29 | facecolors = {i: cmap(i, minval=0, maxval=n - 1) for i in range(n)}
30 |
31 | viewer = Viewer(show_grid=False)
32 | viewer.scene.add(mesh, facecolor=facecolors, show_lines=False, show_points=False)
33 | viewer.show()
34 |
--------------------------------------------------------------------------------
/docs/userguide/samples/colors_maps_from-three-colors.py:
--------------------------------------------------------------------------------
1 | # type: ignore
2 |
3 | from compas_viewer import Viewer
4 |
5 | from compas.colors import Color
6 | from compas.colors import ColorMap
7 | from compas.datastructures import Mesh
8 | from compas.geometry import Point
9 | from compas.geometry import Polygon
10 | from compas.itertools import linspace
11 | from compas.itertools import pairwise
12 |
13 | n = 1000
14 | t = 0.3
15 |
16 | up = []
17 | down = []
18 | for i in linspace(0, 10, n):
19 | point = Point(i, 0, 0)
20 | up.append(point + [0, t, 0])
21 | down.append(point - [0, t, 0])
22 |
23 | polygons = []
24 | for (d, c), (a, b) in zip(pairwise(up), pairwise(down)):
25 | polygons.append(Polygon([a, b, c, d]))
26 |
27 | mesh = Mesh.from_polygons(polygons)
28 |
29 | viewer = Viewer(show_grid=False)
30 |
31 | cmap = ColorMap.from_three_colors(Color.red(), Color.green(), Color.blue())
32 | facecolors = {i: cmap(i, minval=0, maxval=n - 1) for i in range(n)}
33 |
34 | viewer.scene.add(mesh, facecolor=facecolors, show_lines=False, show_points=False)
35 |
36 | viewer.show()
37 |
--------------------------------------------------------------------------------
/docs/userguide/samples/colors_saturation.py:
--------------------------------------------------------------------------------
1 | # type: ignore
2 |
3 | from compas.geometry import Circle, Frame
4 | from compas.colors import Color
5 | from compas_viewer import Viewer
6 |
7 | viewer = Viewer(show_grid = False)
8 |
9 | colors = [
10 | Color.red(),
11 | Color.orange(),
12 | Color.yellow(),
13 | Color.lime(),
14 | Color.green(),
15 | Color.mint(),
16 | Color.cyan(),
17 | Color.azure(),
18 | Color.blue(),
19 | Color.violet(),
20 | Color.magenta(),
21 | Color.pink(),
22 | ]
23 |
24 | for up in range(11):
25 | for right, color in enumerate(colors):
26 | viewer.scene.add(Circle(0.4, Frame([right, up, 0])), linecolor=color.desaturated(up * 10), n=100)
27 |
28 | viewer.show()
29 |
--------------------------------------------------------------------------------
/docs/userguide/samples/obb.py:
--------------------------------------------------------------------------------
1 | from math import radians
2 |
3 | from compas_viewer import Viewer
4 |
5 | from compas.colors import Color
6 | from compas.geometry import Box
7 | from compas.geometry import Pointcloud
8 | from compas.geometry import Rotation
9 | from compas.geometry import oriented_bounding_box
10 |
11 | cloud = Pointcloud.from_bounds(10, 5, 3, 100)
12 |
13 | Rz = Rotation.from_axis_and_angle([0.0, 0.0, 1.0], radians(60))
14 | Ry = Rotation.from_axis_and_angle([0.0, 1.0, 0.0], radians(20))
15 | Rx = Rotation.from_axis_and_angle([1.0, 0.0, 0.0], radians(10))
16 |
17 | cloud.transform(Rz * Ry * Rx)
18 |
19 | bbox = oriented_bounding_box(cloud)
20 | box = Box.from_bounding_box(bbox)
21 |
22 | viewer = Viewer()
23 | viewer.scene.add(cloud)
24 | viewer.scene.add(box, show_faces=False, linecolor=Color(1, 0, 0), linewidth=3)
25 | viewer.show()
26 |
--------------------------------------------------------------------------------
/docs/userguide/samples/point_in_box.py:
--------------------------------------------------------------------------------
1 | import math
2 | from compas.geometry import Box, Pointcloud
3 | from compas.colors import Color
4 | from compas.scene import Scene
5 |
6 | box = Box(2)
7 | pcl = Pointcloud.from_bounds(x=10, y=10, z=5, n=1000)
8 |
9 | box.rotate(math.radians(30))
10 | box.translate(pcl.centroid)
11 |
12 | scene = Scene()
13 | scene.clear()
14 |
15 | scene.add(box)
16 |
17 | for point in pcl:
18 | color = Color.blue()
19 | size = 10
20 | if box.contains_point(point):
21 | color = Color.red()
22 | size = 30
23 | scene.add(point, pointcolor=color, pointsize=size)
24 |
25 | scene.draw()
26 |
--------------------------------------------------------------------------------
/docs/userguide/samples/quadmesh_planarize.py:
--------------------------------------------------------------------------------
1 | # type: ignore
2 | from compas_viewer import Viewer
3 |
4 | import compas
5 | from compas.colors import Color
6 | from compas.colors import ColorMap
7 | from compas.datastructures import Mesh
8 | # ! mesh_flatness is not available in compas.geometry
9 | from compas.datastructures import mesh_flatness
10 | from compas.geometry import quadmesh_planarize
11 |
12 | mesh = Mesh.from_obj(compas.get("tubemesh.obj"))
13 |
14 | V, F = mesh.to_vertices_and_faces()
15 | V2 = quadmesh_planarize((V, F), 500, 0.005)
16 |
17 | mesh = Mesh.from_vertices_and_faces(V2, F)
18 | dev = mesh_flatness(mesh, maxdev=0.02)
19 |
20 | cmap = ColorMap.from_two_colors(Color.white(), Color.blue())
21 | facecolor = {}
22 | for face in mesh.faces():
23 | if dev[face] <= 1.0:
24 | facecolor[face] = cmap(dev[face])
25 | else:
26 | facecolor[face] = Color.red()
27 |
28 | viewer = Viewer()
29 |
30 | viewer.scene.add(mesh, facecolor=facecolor)
31 | viewer.show()
32 |
--------------------------------------------------------------------------------
/docs/userguide/whatsnext.rst:
--------------------------------------------------------------------------------
1 | ********************************************************************************
2 | What's Next
3 | ********************************************************************************
4 |
5 | .. rst-class:: lead
6 |
7 | If you have successfully installed COMPAS and managed to run the samples in :doc:`/userguide/firststeps`,
8 | you are ready for the next challenge. Where to go from here depends on what you want to do.
9 | In any case, enjoy!, And if you have any questions, please don't hesitate to ask on the forum: https://forum.compas-framework.org.
10 |
11 | .. grid:: 1 2 2 2
12 | :gutter: 4
13 |
14 | .. grid-item-card:: Geometry Tutorial
15 |
16 | If you're still just exploring,
17 | you may want to continue with the basic geometry tutorial.
18 | +++
19 | :doc:`/userguide/basics.geometry`
20 |
21 | .. grid-item-card:: Workflows
22 |
23 | If you have a specific AEC application in mind,
24 | perhaps the AEC workflows on the COMPAS website can help you get started.
25 | +++
26 | `Workflows `_
27 |
28 | .. grid-item-card:: Developer guide
29 |
30 | If you're a developer and want to develop your own tools, or you want to contribute to COMPAS,
31 | go tod the developer guide.
32 | +++
33 | :doc:`/devguide/index`
34 |
--------------------------------------------------------------------------------
/requirements-dev.txt:
--------------------------------------------------------------------------------
1 | attrs >=17.4
2 | black >=22.12.0
3 | bump-my-version
4 | compas_invocations2
5 | invoke >=0.14
6 | pytest-cov
7 | ruff
8 | sphinx_compas2_theme
9 | twine
10 | wheel
11 | pythonnet
12 |
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | # flake8: noqa
2 | jsonschema
3 | networkx >= 3.0
4 | numpy >= 1.15.4
5 | scipy >= 1.1
6 | watchdog; sys_platform != 'emscripten'
7 |
--------------------------------------------------------------------------------
/src/compas/colors/__init__.py:
--------------------------------------------------------------------------------
1 | """
2 | This package defines a color and color map class,
3 | that can be used to work wihth colors in a consistent way across color spaces.
4 | """
5 |
6 | from __future__ import absolute_import
7 | from __future__ import division
8 | from __future__ import print_function
9 |
10 | from .color import Color
11 | from .colormap import ColorMap
12 | from .colordict import ColorDict
13 |
14 | __all__ = ["Color", "ColorMap", "ColorDict"]
15 |
--------------------------------------------------------------------------------
/src/compas/colors/cmcrameri/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Colormaps in cmcrameri/cm/cmaps:
4 | Copyright (c) 2020 Fabio Crameri
5 |
6 | Python scripts and packaging:
7 | Copyright (c) 2020 Callum Rollo
8 |
9 | Permission is hereby granted, free of charge, to any person obtaining a copy
10 | of this software and associated documentation files (the "Software"), to deal
11 | in the Software without restriction, including without limitation the rights
12 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 | copies of the Software, and to permit persons to whom the Software is
14 | furnished to do so, subject to the following conditions:
15 |
16 | The above copyright notice and this permission notice shall be included in all
17 | copies or substantial portions of the Software.
18 |
19 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25 | SOFTWARE.
26 |
--------------------------------------------------------------------------------
/src/compas/data/__init__.py:
--------------------------------------------------------------------------------
1 | """
2 | This package defines the core infrastructure for data serialisation in the COMPAS framework.
3 | It provides a base class for data objects, a JSON encoder and decoder, serialisers and deserialisers, and schema validation.
4 | """
5 |
6 | from __future__ import absolute_import
7 |
8 | from .exceptions import DecoderError
9 | from .encoders import DataEncoder
10 | from .encoders import DataDecoder
11 | from .data import Data
12 | from .json import json_load, json_loads, json_loadz, json_dump, json_dumps, json_dumpz
13 | from .schema import dataclass_dataschema, dataclass_typeschema, dataclass_jsonschema
14 | from .schema import compas_dataclasses
15 |
16 | __all__ = [
17 | "Data",
18 | "DataEncoder",
19 | "DataDecoder",
20 | "DecoderError",
21 | "json_load",
22 | "json_loads",
23 | "json_loadz",
24 | "json_dump",
25 | "json_dumps",
26 | "json_dumpz",
27 | "dataclass_dataschema",
28 | "dataclass_typeschema",
29 | "dataclass_jsonschema",
30 | "compas_dataclasses",
31 | ]
32 |
--------------------------------------------------------------------------------
/src/compas/data/exceptions.py:
--------------------------------------------------------------------------------
1 | class DecoderError(Exception):
2 | """Exception that is raised when the decoder fails at reconstructing an object that has been identified as a COMPAS data object."""
3 |
--------------------------------------------------------------------------------
/src/compas/data/samples/cone.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/compas-dev/compas/96c2ea7a5d7f799b6c8846690a19c464a6dee41e/src/compas/data/samples/cone.stl
--------------------------------------------------------------------------------
/src/compas/data/samples/cube.off:
--------------------------------------------------------------------------------
1 | OFF
2 | 8 6 24
3 | 0 0 0
4 | 0 0 1
5 | 0 1 0
6 | 0 1 1
7 | 1 0 0
8 | 1 0 1
9 | 1 1 0
10 | 1 1 1
11 | 4 0 1 3 2
12 | 4 2 3 7 6
13 | 4 4 6 7 5
14 | 4 0 4 5 1
15 | 4 1 5 7 3
16 | 4 0 2 6 4
17 |
--------------------------------------------------------------------------------
/src/compas/data/samples/cube_binary.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/compas-dev/compas/96c2ea7a5d7f799b6c8846690a19c464a6dee41e/src/compas/data/samples/cube_binary.stl
--------------------------------------------------------------------------------
/src/compas/data/samples/cube_binary_2.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/compas-dev/compas/96c2ea7a5d7f799b6c8846690a19c464a6dee41e/src/compas/data/samples/cube_binary_2.stl
--------------------------------------------------------------------------------
/src/compas/data/samples/faces.obj:
--------------------------------------------------------------------------------
1 | # Rhino
2 |
3 | v 0 0 0
4 | v 2 0 0
5 | v 4 0 0
6 | v 6 0 0
7 | v 8 0 0
8 | v 10 0 0
9 | v 0 2 0
10 | v 2 2 0
11 | v 4 2 0
12 | v 6 2 0
13 | v 8 2 0
14 | v 10 2 0
15 | v 0 4 0
16 | v 2 4 0
17 | v 4 4 0
18 | v 6 4 0
19 | v 8 4 0
20 | v 10 4 0
21 | v 0 6 0
22 | v 2 6 0
23 | v 4 6 0
24 | v 6 6 0
25 | v 8 6 0
26 | v 10 6 0
27 | v 0 8 0
28 | v 2 8 0
29 | v 4 8 0
30 | v 6 8 0
31 | v 8 8 0
32 | v 10 8 0
33 | v 0 10 0
34 | v 2 10 0
35 | v 4 10 0
36 | v 6 10 0
37 | v 8 10 0
38 | v 10 10 0
39 | f 1 2 8 7
40 | f 2 3 9 8
41 | f 3 4 10 9
42 | f 4 5 11 10
43 | f 5 6 12 11
44 | f 7 8 14 13
45 | f 8 9 15 14
46 | f 9 10 16 15
47 | f 10 11 17 16
48 | f 11 12 18 17
49 | f 13 14 20 19
50 | f 14 15 21 20
51 | f 15 16 22 21
52 | f 16 17 23 22
53 | f 17 18 24 23
54 | f 19 20 26 25
55 | f 20 21 27 26
56 | f 21 22 28 27
57 | f 22 23 29 28
58 | f 23 24 30 29
59 | f 25 26 32 31
60 | f 26 27 33 32
61 | f 27 28 34 33
62 | f 28 29 35 34
63 | f 29 30 36 35
64 |
--------------------------------------------------------------------------------
/src/compas/data/samples/faces_reversed.obj:
--------------------------------------------------------------------------------
1 | # Rhino
2 |
3 | v 0 0 0
4 | v 2 0 0
5 | v 4 0 0
6 | v 6 0 0
7 | v 8 0 0
8 | v 10 0 0
9 | v 0 2 0
10 | v 2 2 0
11 | v 4 2 0
12 | v 6 2 0
13 | v 8 2 0
14 | v 10 2 0
15 | v 0 4 0
16 | v 2 4 0
17 | v 4 4 0
18 | v 6 4 0
19 | v 8 4 0
20 | v 10 4 0
21 | v 0 6 0
22 | v 2 6 0
23 | v 4 6 0
24 | v 6 6 0
25 | v 8 6 0
26 | v 10 6 0
27 | v 0 8 0
28 | v 2 8 0
29 | v 4 8 0
30 | v 6 8 0
31 | v 8 8 0
32 | v 10 8 0
33 | v 0 10 0
34 | v 2 10 0
35 | v 4 10 0
36 | v 6 10 0
37 | v 8 10 0
38 | v 10 10 0
39 | f 7 8 2 1
40 | f 2 3 9 8
41 | f 3 4 10 9
42 | f 4 5 11 10
43 | f 5 6 12 11
44 | f 7 8 14 13
45 | f 8 9 15 14
46 | f 9 10 16 15
47 | f 16 17 11 10
48 | f 11 12 18 17
49 | f 13 14 20 19
50 | f 14 15 21 20
51 | f 15 16 22 21
52 | f 16 17 23 22
53 | f 17 18 24 23
54 | f 19 20 26 25
55 | f 26 27 21 20
56 | f 21 22 28 27
57 | f 22 23 29 28
58 | f 23 24 30 29
59 | f 25 26 32 31
60 | f 26 27 33 32
61 | f 27 28 34 33
62 | f 28 29 35 34
63 | f 29 30 36 35
64 |
--------------------------------------------------------------------------------
/src/compas/data/samples/point.json:
--------------------------------------------------------------------------------
1 | {"dtype": "compas.geometry/Point", "value": [0.0, 0.0, 0.0]}
--------------------------------------------------------------------------------
/src/compas/datastructures/assembly/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/compas-dev/compas/96c2ea7a5d7f799b6c8846690a19c464a6dee41e/src/compas/datastructures/assembly/__init__.py
--------------------------------------------------------------------------------
/src/compas/datastructures/assembly/exceptions.py:
--------------------------------------------------------------------------------
1 | class AssemblyError(Exception):
2 | pass
3 |
4 |
5 | class FeatureError(Exception):
6 | pass
7 |
--------------------------------------------------------------------------------
/src/compas/datastructures/cell_network/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/compas-dev/compas/96c2ea7a5d7f799b6c8846690a19c464a6dee41e/src/compas/datastructures/cell_network/__init__.py
--------------------------------------------------------------------------------
/src/compas/datastructures/graph/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/compas-dev/compas/96c2ea7a5d7f799b6c8846690a19c464a6dee41e/src/compas/datastructures/graph/__init__.py
--------------------------------------------------------------------------------
/src/compas/datastructures/graph/operations/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/compas-dev/compas/96c2ea7a5d7f799b6c8846690a19c464a6dee41e/src/compas/datastructures/graph/operations/__init__.py
--------------------------------------------------------------------------------
/src/compas/datastructures/mesh/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/compas-dev/compas/96c2ea7a5d7f799b6c8846690a19c464a6dee41e/src/compas/datastructures/mesh/__init__.py
--------------------------------------------------------------------------------
/src/compas/datastructures/mesh/operations/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/compas-dev/compas/96c2ea7a5d7f799b6c8846690a19c464a6dee41e/src/compas/datastructures/mesh/operations/__init__.py
--------------------------------------------------------------------------------
/src/compas/datastructures/mesh/operations/extrude.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/compas-dev/compas/96c2ea7a5d7f799b6c8846690a19c464a6dee41e/src/compas/datastructures/mesh/operations/extrude.py
--------------------------------------------------------------------------------
/src/compas/datastructures/mesh/operations/substitute.py:
--------------------------------------------------------------------------------
1 | from __future__ import absolute_import
2 | from __future__ import division
3 | from __future__ import print_function
4 |
5 |
6 | def mesh_substitute_vertex_in_faces(mesh, old_vkey, new_vkey, fkeys=None):
7 | """Substitute in a mesh a vertex by another one.
8 | In all faces by default or in a given set of faces.
9 |
10 | Parameters
11 | ----------
12 | old_vkey : int
13 | The old vertex key.
14 | new_vkey : int
15 | The new vertex key.
16 | fkeys : list[int], optional
17 | List of face keys where to subsitute the old vertex by the new one.
18 | Default is to subsitute in all faces.
19 |
20 | Returns
21 | -------
22 | list[int]
23 | The list of modified faces.
24 |
25 | """
26 |
27 | # apply to all faces if there is none chosen
28 | if fkeys is None:
29 | fkeys = list(mesh.faces())
30 |
31 | # substitute vertices
32 | for fkey in fkeys:
33 | face_vertices = [new_vkey if key == old_vkey else key for key in mesh.face_vertices(fkey)]
34 | mesh.delete_face(fkey)
35 | mesh.add_face(face_vertices, fkey)
36 |
37 | return fkeys
38 |
--------------------------------------------------------------------------------
/src/compas/datastructures/tree/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/compas-dev/compas/96c2ea7a5d7f799b6c8846690a19c464a6dee41e/src/compas/datastructures/tree/__init__.py
--------------------------------------------------------------------------------
/src/compas/datastructures/volmesh/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/compas-dev/compas/96c2ea7a5d7f799b6c8846690a19c464a6dee41e/src/compas/datastructures/volmesh/__init__.py
--------------------------------------------------------------------------------
/src/compas/files/__init__.py:
--------------------------------------------------------------------------------
1 | """
2 | This package defines a number of file formats and provides functionality for reading and writing data in these formats.
3 | """
4 |
5 | from __future__ import absolute_import
6 |
7 | from .gltf.gltf import GLTF
8 | from .gltf.gltf_content import GLTFContent # noqa: F401
9 | from .gltf.gltf_exporter import GLTFExporter # noqa: F401
10 | from .gltf.gltf_mesh import GLTFMesh # noqa: F401
11 | from .gltf.gltf_parser import GLTFParser # noqa: F401
12 | from .gltf.gltf_reader import GLTFReader # noqa: F401
13 | from .obj import OBJ, OBJParser, OBJReader, OBJWriter # noqa: F401
14 | from .off import OFF, OFFReader, OFFWriter # noqa: F401
15 | from .ply import PLY, PLYParser, PLYReader, PLYWriter # noqa: F401
16 | from .stl import STL, STLParser, STLReader, STLWriter # noqa: F401
17 | from .xml import XML, XMLElement, XMLReader, XMLWriter, prettify_string # noqa: F401
18 |
19 | __all__ = [
20 | "GLTF",
21 | "OBJ",
22 | "OFF",
23 | "PLY",
24 | "STL",
25 | "XML",
26 | "prettify_string",
27 | ]
28 |
--------------------------------------------------------------------------------
/src/compas/files/_xml/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/compas-dev/compas/96c2ea7a5d7f799b6c8846690a19c464a6dee41e/src/compas/files/_xml/__init__.py
--------------------------------------------------------------------------------
/src/compas/files/_xml/xml_cpython.py:
--------------------------------------------------------------------------------
1 | from __future__ import absolute_import
2 | from __future__ import division
3 | from __future__ import print_function
4 |
5 | import xml.etree.ElementTree as ET
6 | from http.client import HTTPResponse
7 | from xml.dom import minidom
8 |
9 | from compas.files._xml.xml_shared import shared_xml_from_file
10 | from compas.files._xml.xml_shared import shared_xml_from_string
11 |
12 |
13 | def prettify_string(rough_string):
14 | """Return an XML string with added whitespace for legibility.
15 |
16 | Parameters
17 | ----------
18 | rough_string : str
19 | XML string
20 | """
21 | reparsed = minidom.parseString(rough_string)
22 | return reparsed.toprettyxml(indent=" ", encoding="utf-8")
23 |
24 |
25 | def xml_from_file(source, tree_parser=None):
26 | tree_parser = tree_parser or ET.XMLParser
27 | return shared_xml_from_file(source, tree_parser, HTTPResponse)
28 |
29 |
30 | def xml_from_string(text, tree_parser=None):
31 | tree_parser = tree_parser or ET.XMLParser
32 | return shared_xml_from_string(text, tree_parser)
33 |
--------------------------------------------------------------------------------
/src/compas/files/_xml/xml_shared.py:
--------------------------------------------------------------------------------
1 | from __future__ import absolute_import
2 | from __future__ import division
3 | from __future__ import print_function
4 |
5 | import xml.etree.ElementTree as ET
6 |
7 | from compas import _iotools
8 |
9 |
10 | def shared_xml_from_file(source, tree_parser, http_response_type):
11 | target = TreeBuilderWithNamespaces()
12 | with _iotools.open_file(source, "r") as f:
13 | tree = ET.parse(f, tree_parser(target=target))
14 | return tree.getroot()
15 |
16 |
17 | def shared_xml_from_string(text, tree_parser):
18 | target = TreeBuilderWithNamespaces()
19 | root = ET.fromstring(text, tree_parser(target=target))
20 | return root
21 |
22 |
23 | class TreeBuilderWithNamespaces(ET.TreeBuilder):
24 | def start(self, tag, attrs):
25 | if hasattr(self, "_current_namespaces") and len(self._current_namespaces):
26 | attrs.update(self._current_namespaces)
27 |
28 | element = super(TreeBuilderWithNamespaces, self).start(tag, attrs)
29 |
30 | # reset current namespaces
31 | self._current_namespaces = {}
32 |
33 | return element
34 |
35 | def start_ns(self, prefix, uri):
36 | if not hasattr(self, "_current_namespaces"):
37 | self._current_namespaces = {}
38 |
39 | ns_prefix = "xmlns:" + prefix if prefix else "xmlns"
40 | self._current_namespaces[ns_prefix] = uri
41 |
--------------------------------------------------------------------------------
/src/compas/files/gltf/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/compas-dev/compas/96c2ea7a5d7f799b6c8846690a19c464a6dee41e/src/compas/files/gltf/__init__.py
--------------------------------------------------------------------------------
/src/compas/geometry/_core/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/compas-dev/compas/96c2ea7a5d7f799b6c8846690a19c464a6dee41e/src/compas/geometry/_core/__init__.py
--------------------------------------------------------------------------------
/src/compas/geometry/brep/errors.py:
--------------------------------------------------------------------------------
1 | class BrepError(Exception):
2 | """Represents a generic error in the Brep context"""
3 |
4 | pass
5 |
6 |
7 | class BrepInvalidError(BrepError):
8 | """Raised when the process of re-constructing a Brep has resulted in an invalid Brep"""
9 |
10 | pass
11 |
12 |
13 | class BrepTrimmingError(BrepError):
14 | """Raised when a trimming operation has failed or had not result"""
15 |
16 | pass
17 |
18 |
19 | class BrepFilletError(BrepError):
20 | """Raised when a fillet operation has failed or had not result"""
21 |
22 | pass
23 |
--------------------------------------------------------------------------------
/src/compas/geometry/brep/vertex.py:
--------------------------------------------------------------------------------
1 | from compas.data import Data
2 |
3 |
4 | class BrepVertex(Data):
5 | """An interface for a Brep Vertex
6 |
7 | Attributes
8 | ----------
9 | point : :class:`compas.geometry.Point`, read_only
10 | Returns the geometry of this vertex as a 3D point
11 | native_vertex : Any
12 | The underlying vertex object. Type is backend-dependent.
13 |
14 | """
15 |
16 | # ==============================================================================
17 | # Properties
18 | # ==============================================================================
19 |
20 | @property
21 | def point(self):
22 | raise NotImplementedError
23 |
24 | @property
25 | def native_vertex(self):
26 | raise NotImplementedError
27 |
28 | # ==============================================================================
29 | # Constructors
30 | # ==============================================================================
31 |
32 | @classmethod
33 | def from_point(cls, point):
34 | """Creates a Brep vertex from a Point
35 |
36 | Parameters
37 | ----------
38 | point: :class:`compas.geometry.Point`
39 | The point to create a vertex from
40 |
41 | Returns
42 | -------
43 | :class:`compas.geometry.BrepVertex`
44 | The created vertex
45 | """
46 | raise NotImplementedError
47 |
--------------------------------------------------------------------------------
/src/compas/geometry/contours.py:
--------------------------------------------------------------------------------
1 | from compas.plugins import PluginNotInstalledError
2 | from compas.plugins import pluggable
3 |
4 |
5 | @pluggable(category="contours")
6 | def scalarfield_contours(xy, s, levels=50, density=100):
7 | r"""Compute the contour lines of a scalarfield.
8 |
9 | Parameters
10 | ----------
11 | xy : array-like
12 | The xy-coordinates at which the scalar field is defined.
13 | s : array-like
14 | The values of the scalar field.
15 | levels : int, optional
16 | The number of contour lines to compute.
17 | Default is ``50``.
18 |
19 | Returns
20 | -------
21 | tuple
22 | A tuple of a list of levels and a list of contour geometry.
23 |
24 | The list of levels contains the values of the scalarfield at each of
25 | the contours. The second item in the tuple is a list of contour lines.
26 | Each contour line is a list of paths, and each path is a list polygons.
27 |
28 | """
29 | raise PluginNotInstalledError()
30 |
31 |
32 | scalarfield_contours.__pluggable__ = True
33 |
--------------------------------------------------------------------------------
/src/compas/geometry/curves/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/compas-dev/compas/96c2ea7a5d7f799b6c8846690a19c464a6dee41e/src/compas/geometry/curves/__init__.py
--------------------------------------------------------------------------------
/src/compas/geometry/curves/conic.py:
--------------------------------------------------------------------------------
1 | from __future__ import absolute_import
2 | from __future__ import division
3 | from __future__ import print_function
4 |
5 | from .curve import Curve
6 |
7 |
8 | class Conic(Curve):
9 | """Base class for curves that are conic sections."""
10 |
--------------------------------------------------------------------------------
/src/compas/geometry/interpolation_barycentric.py:
--------------------------------------------------------------------------------
1 | from __future__ import absolute_import
2 | from __future__ import division
3 | from __future__ import print_function
4 |
5 | from compas.geometry import dot_vectors
6 | from compas.geometry import subtract_vectors
7 |
8 |
9 | def barycentric_coordinates(point, triangle):
10 | """Compute the barycentric coordinates of a point wrt to a triangle.
11 |
12 | Parameters
13 | ----------
14 | point: [float, float, float] | :class:`compas.geometry.Point`
15 | Point location.
16 | triangle: [point, point, point]
17 | A triangle defined by 3 points.
18 |
19 | Returns
20 | -------
21 | [float, float, float]
22 | The barycentric coordinates of the point.
23 |
24 | """
25 | a, b, c = triangle
26 | v0 = subtract_vectors(b, a)
27 | v1 = subtract_vectors(c, a)
28 | v2 = subtract_vectors(point, a)
29 | d00 = dot_vectors(v0, v0)
30 | d01 = dot_vectors(v0, v1)
31 | d11 = dot_vectors(v1, v1)
32 | d20 = dot_vectors(v2, v0)
33 | d21 = dot_vectors(v2, v1)
34 | D = d00 * d11 - d01 * d01
35 | v = (d11 * d20 - d01 * d21) / D
36 | w = (d00 * d21 - d01 * d20) / D
37 | u = 1.0 - v - w
38 | return [u, v, w]
39 |
--------------------------------------------------------------------------------
/src/compas/geometry/quadmesh_planarize.py:
--------------------------------------------------------------------------------
1 | from __future__ import absolute_import
2 | from __future__ import division
3 | from __future__ import print_function
4 |
5 | from compas.plugins import pluggable
6 |
7 |
8 | @pluggable(category="quadmesh")
9 | def quadmesh_planarize(M, kmax=500, maxdev=0.005):
10 | """Planarize the faces of a quad mesh.
11 |
12 | Parameters
13 | ----------
14 | M : [sequence[[float, float, float]], sequence[[int, int, int, int]]]
15 | A quad mesh represented by a list of vertices and a list of faces.
16 | kmax : int, optional
17 | The maximum number of iterations.
18 | maxdev : float, optional
19 | The maximum deviation from planar.
20 |
21 | Returns
22 | -------
23 | list
24 | The coordinates of the new vertices.
25 |
26 | """
27 | raise NotImplementedError
28 |
29 |
30 | quadmesh_planarize.__pluggable__ = True
31 |
--------------------------------------------------------------------------------
/src/compas/geometry/shapes/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/compas-dev/compas/96c2ea7a5d7f799b6c8846690a19c464a6dee41e/src/compas/geometry/shapes/__init__.py
--------------------------------------------------------------------------------
/src/compas/geometry/surfaces/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/compas-dev/compas/96c2ea7a5d7f799b6c8846690a19c464a6dee41e/src/compas/geometry/surfaces/__init__.py
--------------------------------------------------------------------------------
/src/compas/geometry/surfaces/extrusion.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/compas-dev/compas/96c2ea7a5d7f799b6c8846690a19c464a6dee41e/src/compas/geometry/surfaces/extrusion.py
--------------------------------------------------------------------------------
/src/compas/geometry/surfaces/revolution.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/compas-dev/compas/96c2ea7a5d7f799b6c8846690a19c464a6dee41e/src/compas/geometry/surfaces/revolution.py
--------------------------------------------------------------------------------
/src/compas/geometry/trimesh_descent_numpy.py:
--------------------------------------------------------------------------------
1 | from numpy import asarray
2 |
3 | from .trimesh_gradient_numpy import trimesh_gradient_numpy
4 |
5 |
6 | def trimesh_descent_numpy(M):
7 | """Compute the descent directions of a triangular mesh as the gradient of the vertex heights.
8 |
9 | Parameters
10 | ----------
11 | M : tuple[vertices, faces]
12 | The vertices and faces of the mesh.
13 |
14 | Returns
15 | -------
16 | list[list[float]]]
17 | The descent directions.
18 |
19 | """
20 | vertices, faces = M
21 | V = asarray(vertices)
22 | F = asarray(faces)
23 | G = trimesh_gradient_numpy((V, F))
24 | sfield = V[:, 2].reshape((-1, 1))
25 | vfield = -G.dot(sfield)
26 | return vfield.reshape((-1, 3), order="F")
27 |
--------------------------------------------------------------------------------
/src/compas/geometry/trimesh_geodistance.py:
--------------------------------------------------------------------------------
1 | from compas.plugins import pluggable
2 |
3 |
4 | @pluggable(category="trimesh")
5 | def trimesh_geodistance(M, source, method="exact"):
6 | """Compute the geodesic distance from every vertex of the mesh to a source vertex.
7 |
8 | Parameters
9 | ----------
10 | M : tuple[sequence[[float, float, float] | :class:`compas.geometry.Point`], sequence[[int, int, int]]]
11 | A mesh represented by a list of vertices and a list of faces.
12 | source : int
13 | The index of the vertex from where the geodesic distances should be calculated.
14 | method : Literal['exact', 'heat'], optional
15 | The method for calculating the distances.
16 |
17 | Returns
18 | -------
19 | list[float]
20 | A list of geodesic distances from the source vertex.
21 |
22 | Raises
23 | ------
24 | NotImplementedError
25 | If `method` is not one of ``{'exact', 'heat'}``.
26 |
27 | Examples
28 | --------
29 | >>>
30 |
31 | """
32 | raise NotImplementedError
33 |
34 |
35 | trimesh_geodistance.__pluggable__ = True
36 |
--------------------------------------------------------------------------------
/src/compas/geometry/trimesh_isolines.py:
--------------------------------------------------------------------------------
1 | from __future__ import absolute_import
2 | from __future__ import division
3 | from __future__ import print_function
4 |
5 | from compas.plugins import pluggable
6 |
7 |
8 | @pluggable(category="trimesh")
9 | def trimesh_isolines(M, S, N=50):
10 | """Compute isolines on a triangle mesh using a scalarfield of data points
11 | assigned to its vertices.
12 |
13 | Parameters
14 | ----------
15 | M : tuple[sequence[[float, float, float] | :class:`compas.geometry.Point`], sequence[[int, int, int]]]
16 | A mesh represented by a list of vertices and a list of faces.
17 | S : list[float]
18 | A list of scalars.
19 | N : int, optional
20 | The number of isolines.
21 |
22 | Returns
23 | -------
24 | list[[float, float, float]]
25 | The coordinates of the polyline points.
26 | list[[int, int]]
27 | The segments of the polylines defined as pairs of points.
28 |
29 | Notes
30 | -----
31 | To convert the vertices and edges to sets of isolines, use :func:`groupsort_isolines`
32 |
33 | Examples
34 | --------
35 | >>>
36 |
37 | """
38 | raise NotImplementedError
39 |
40 |
41 | trimesh_isolines.__pluggable__ = True
42 |
--------------------------------------------------------------------------------
/src/compas/geometry/trimesh_matrices.py:
--------------------------------------------------------------------------------
1 | from __future__ import absolute_import
2 | from __future__ import division
3 | from __future__ import print_function
4 |
5 | from compas.plugins import pluggable
6 |
7 |
8 | @pluggable(category="trimesh")
9 | def trimesh_massmatrix(M):
10 | """Compute massmatrix on a triangle mesh using a scalarfield of data points
11 | assigned to its vertices.
12 |
13 | Parameters
14 | ----------
15 | M : tuple[sequence[[float, float, float] | :class:`compas.geometry.Point`], sequence[[int, int, int]]]
16 | A mesh represented by a list of vertices and a list of faces.
17 |
18 | Returns
19 | -------
20 | list[float]
21 | The mass per vertex.
22 |
23 | Examples
24 | --------
25 | >>>
26 |
27 | """
28 | raise NotImplementedError
29 |
30 |
31 | trimesh_massmatrix.__pluggable__ = True
32 |
--------------------------------------------------------------------------------
/src/compas/geometry/trimesh_slicing.py:
--------------------------------------------------------------------------------
1 | from __future__ import absolute_import
2 | from __future__ import division
3 | from __future__ import print_function
4 |
5 | from compas.plugins import pluggable
6 |
7 |
8 | @pluggable(category="trimesh")
9 | def trimesh_slice(mesh, planes):
10 | """Slice a mesh by a list of planes.
11 |
12 | Parameters
13 | ----------
14 | mesh : tuple[sequence[[float, float, float] | :class:`compas.geometry.Point`], sequence[[int, int, int]]]
15 | A mesh represented by a list of vertices and a list of faces.
16 | planes : sequence[[point, vector] | :class:`compas.geometry.Plane`]
17 | The slicing planes.
18 |
19 | Returns
20 | -------
21 | list[list[float, float, float]]
22 | The points defining the slice polylines.
23 |
24 | """
25 | raise NotImplementedError
26 |
27 |
28 | trimesh_slice.__pluggable__ = True
29 |
--------------------------------------------------------------------------------
/src/compas/geometry/trimesh_smoothing_numpy.py:
--------------------------------------------------------------------------------
1 | from numpy import array
2 |
3 | from .trimesh_matrices_numpy import trimesh_cotangent_laplacian_matrix
4 |
5 |
6 | def trimesh_smooth_laplacian_cotangent(trimesh, fixed, kmax=10):
7 | """Smooth a triangle mesh using a laplacian matrix with cotangent weights.
8 |
9 | Parameters
10 | ----------
11 | trimesh : :class:`compas.datastructures.Mesh`
12 | A triangle mesh.
13 | fixed : list[int]
14 | A list of fixed vertices.
15 | kmax : int, optional
16 | The maximum number of smoothing rounds.
17 |
18 | Returns
19 | -------
20 | None
21 | The mesh is modified in place.
22 |
23 | """
24 | for k in range(kmax):
25 | V = array(trimesh.vertices_attributes("xyz"))
26 | L = trimesh_cotangent_laplacian_matrix(trimesh)
27 | d = L.dot(V)
28 | V = V + d
29 | for key, attr in trimesh.vertices(True):
30 | if key in fixed:
31 | continue
32 | attr["x"] = V[key][0]
33 | attr["y"] = V[key][1]
34 | attr["z"] = V[key][2]
35 |
--------------------------------------------------------------------------------
/src/compas/rpc/__init__.py:
--------------------------------------------------------------------------------
1 | """
2 | COMPAS runs in many different environments, but in some environments the availablity of libraries is limited.
3 | For example, when running COMPAS in an IronPython-based environment like Rhino/Grasshopper,
4 | plenty of CPython libraries such as `numpy` and `scipy` are not available.
5 | To workaround this limitation, COMPAS provides a mechanisms to access the functionality of a CPython environment
6 | seemlessly from any other Python environment through a "Remote Procedure Call" or RPC.
7 | Through RPC, COMPAS can be used as a server for remote clients, and as a client for remote servers.
8 | A typical use case is to run algorithms that require packages like ``numpy`` or ``scipy`` on a remote server,
9 | when working in Rhino. Or to use COMPAS in a browser application.
10 | """
11 |
12 | from __future__ import absolute_import
13 |
14 | from .errors import RPCClientError, RPCServerError
15 | from .proxy import Proxy
16 | from .server import Server
17 | from .dispatcher import Dispatcher
18 |
19 |
20 | __all__ = ["RPCClientError", "RPCServerError", "Proxy", "Server", "Dispatcher"]
21 |
--------------------------------------------------------------------------------
/src/compas/rpc/errors.py:
--------------------------------------------------------------------------------
1 | from __future__ import absolute_import
2 | from __future__ import division
3 | from __future__ import print_function
4 |
5 |
6 | class RPCServerError(Exception):
7 | """Exception for errors originating from the server."""
8 |
9 |
10 | class RPCClientError(Exception):
11 | """Exception for errors originating from the client."""
12 |
--------------------------------------------------------------------------------
/src/compas/rpc/services/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/compas-dev/compas/96c2ea7a5d7f799b6c8846690a19c464a6dee41e/src/compas/rpc/services/__init__.py
--------------------------------------------------------------------------------
/src/compas/scene/curveobject.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/compas-dev/compas/96c2ea7a5d7f799b6c8846690a19c464a6dee41e/src/compas/scene/curveobject.py
--------------------------------------------------------------------------------
/src/compas/scene/descriptors/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/compas-dev/compas/96c2ea7a5d7f799b6c8846690a19c464a6dee41e/src/compas/scene/descriptors/__init__.py
--------------------------------------------------------------------------------
/src/compas/scene/descriptors/attribute.py:
--------------------------------------------------------------------------------
1 | class Attribute(object):
2 | """Descriptor for text dictionaries."""
3 |
4 | def __init__(self, default=None, **kwargs):
5 | super(Attribute, self).__init__(**kwargs)
6 | self.default = default
7 |
8 | def __set_name__(self, owner, name):
9 | """Record the name of the attribute this descriptor is assigned to.
10 | The attribute name is then used to identify the corresponding private attribute.
11 |
12 | Parameters
13 | ----------
14 | owner : object
15 | The class owning the attribute.
16 | name : str
17 | The name of the attribute.
18 |
19 | Returns
20 | -------
21 | None
22 |
23 | Notes
24 | -----
25 | In Python 3.6+ this method is called automatically.
26 | For earlier versions it needs to be used with a custom metaclass (``DescriptorProtocol``).
27 |
28 | """
29 | self.name = name
30 | self.private_name = "_" + name
31 |
--------------------------------------------------------------------------------
/src/compas/scene/descriptors/protocol.py:
--------------------------------------------------------------------------------
1 | from __future__ import absolute_import
2 | from __future__ import division
3 | from __future__ import print_function
4 |
5 |
6 | class DescriptorProtocol(type):
7 | """Meta class to provide support for the descriptor protocol in Python versions lower than 3.6"""
8 |
9 | def __init__(cls, name, bases, attrs):
10 | for key, value in iter(attrs.items()):
11 | if hasattr(value, "__set_name__"):
12 | value.__set_name__(cls, key)
13 |
--------------------------------------------------------------------------------
/src/compas/scene/exceptions.py:
--------------------------------------------------------------------------------
1 | from __future__ import absolute_import
2 | from __future__ import division
3 | from __future__ import print_function
4 |
5 |
6 | class SceneObjectNotRegisteredError(Exception):
7 | """Exception that is raised when no scene object is registered for a given data type."""
8 |
--------------------------------------------------------------------------------
/src/compas/scene/frameobject.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/compas-dev/compas/96c2ea7a5d7f799b6c8846690a19c464a6dee41e/src/compas/scene/frameobject.py
--------------------------------------------------------------------------------
/src/compas/scene/planeobject.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/compas-dev/compas/96c2ea7a5d7f799b6c8846690a19c464a6dee41e/src/compas/scene/planeobject.py
--------------------------------------------------------------------------------
/src/compas/scene/shapeobject.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/compas-dev/compas/96c2ea7a5d7f799b6c8846690a19c464a6dee41e/src/compas/scene/shapeobject.py
--------------------------------------------------------------------------------
/src/compas/scene/surfaceobject.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/compas-dev/compas/96c2ea7a5d7f799b6c8846690a19c464a6dee41e/src/compas/scene/surfaceobject.py
--------------------------------------------------------------------------------
/src/compas/topology/__init__.py:
--------------------------------------------------------------------------------
1 | """
2 | Package containing topological algorithms for traversal, connectivity, combinatorics, etc.
3 | """
4 |
5 | from __future__ import absolute_import
6 |
7 | from .traversal import (
8 | depth_first_ordering,
9 | breadth_first_ordering,
10 | breadth_first_traverse,
11 | breadth_first_paths,
12 | shortest_path,
13 | astar_lightest_path,
14 | astar_shortest_path,
15 | dijkstra_distances,
16 | dijkstra_path,
17 | )
18 | from .combinatorics import vertex_coloring, connected_components
19 | from .orientation import face_adjacency, unify_cycles
20 | from .connectivity import (
21 | vertex_adjacency_from_edges,
22 | vertex_adjacency_from_faces,
23 | edges_from_faces,
24 | faces_from_edges,
25 | )
26 |
27 | __all__ = [
28 | "astar_lightest_path",
29 | "astar_shortest_path",
30 | "breadth_first_ordering",
31 | "breadth_first_traverse",
32 | "breadth_first_paths",
33 | "connected_components",
34 | "depth_first_ordering",
35 | "dijkstra_distances",
36 | "dijkstra_path",
37 | "edges_from_faces",
38 | "face_adjacency",
39 | "faces_from_edges",
40 | "shortest_path",
41 | "unify_cycles",
42 | "vertex_adjacency_from_edges",
43 | "vertex_adjacency_from_faces",
44 | "vertex_coloring",
45 | ]
46 |
--------------------------------------------------------------------------------
/src/compas/utilities/__init__.py:
--------------------------------------------------------------------------------
1 | from __future__ import absolute_import
2 |
3 | from .azync import await_callback
4 | from .datetime import now, timestamp
5 | from .decorators import (
6 | abstractclassmethod,
7 | abstractstaticmethod,
8 | memoize,
9 | print_profile,
10 | )
11 |
12 | from .remote import download_file_from_remote
13 | from .ssh import SSH
14 |
15 | __all__ = [
16 | "await_callback",
17 | "timestamp",
18 | "now",
19 | "abstractstaticmethod",
20 | "abstractclassmethod",
21 | "memoize",
22 | "print_profile",
23 | "download_file_from_remote",
24 | "SSH",
25 | ]
26 |
--------------------------------------------------------------------------------
/src/compas/utilities/datetime.py:
--------------------------------------------------------------------------------
1 | from __future__ import absolute_import
2 | from __future__ import division
3 | from __future__ import print_function
4 |
5 | import datetime
6 | import time
7 |
8 |
9 | def timestamp():
10 | """Generate a timestamp using the current date and time.
11 |
12 | Returns
13 | -------
14 | str
15 | The timestamp.
16 |
17 | Examples
18 | --------
19 | >>> type(timestamp()) == type("")
20 | True
21 |
22 | """
23 | return datetime.datetime.fromtimestamp(time.time()).strftime("%Y%m%d%H%M%S")
24 |
25 |
26 | def now():
27 | """Generate a timestamp using the current date and time.
28 |
29 | Returns
30 | -------
31 | str
32 | The timestamp.
33 |
34 | Examples
35 | --------
36 | >>> type(now()) == type("")
37 | True
38 |
39 | """
40 | return timestamp()
41 |
--------------------------------------------------------------------------------
/src/compas_blender/conversions/breps.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/compas-dev/compas/96c2ea7a5d7f799b6c8846690a19c464a6dee41e/src/compas_blender/conversions/breps.py
--------------------------------------------------------------------------------
/src/compas_blender/conversions/colors.py:
--------------------------------------------------------------------------------
1 | import bpy # type: ignore
2 |
3 | from compas.colors import Color
4 |
5 |
6 | def color_to_blender_material(color: Color) -> bpy.types.Material:
7 | """Convert a COMPAS color to a Blender material.
8 |
9 | Parameters
10 | ----------
11 | color : :class:`compas.colors.Color`
12 | A COMPAS color.
13 |
14 | Returns
15 | -------
16 | :blender:`bpy.types.Material`
17 | A Blender material.
18 |
19 | """
20 | name = "-".join(["{0:.3f}".format(i) for i in color.rgba])
21 | material = bpy.data.materials.get(name, bpy.data.materials.new(name))
22 | material.diffuse_color = color.rgba
23 | return material
24 |
--------------------------------------------------------------------------------
/src/compas_blender/conversions/transformations.py:
--------------------------------------------------------------------------------
1 | import mathutils # type: ignore
2 |
3 | from compas.geometry import Transformation
4 |
5 | # =============================================================================
6 | # To Blender
7 | # =============================================================================
8 |
9 |
10 | def transformation_to_blender(transformation):
11 | """Convert a COMPAS transformation to a Blender transformation.
12 |
13 | Parameters
14 | ----------
15 | transformation : :class:`compas.geometry.Transformation`
16 | A COMPAS transformation.
17 |
18 | Returns
19 | -------
20 | :class:`mathutils.Matrix`
21 | A Blender transformation.
22 |
23 | """
24 | return mathutils.Matrix(transformation.matrix)
25 |
26 |
27 | # =============================================================================
28 | # To COMPAS
29 | # =============================================================================
30 |
31 |
32 | def transformation_to_compas(matrix):
33 | """Convert a Blender transformation to a COMPAS transformation.
34 |
35 | Parameters
36 | ----------
37 | matrix : :class:`mathutils.Matrix`
38 | A Blender transformation.
39 |
40 | Returns
41 | -------
42 | :class:`compas.geometry.Transformation`
43 | A COMPAS transformation.
44 |
45 | """
46 | return Transformation.from_matrix(matrix)
47 |
--------------------------------------------------------------------------------
/src/compas_blender/data.py:
--------------------------------------------------------------------------------
1 | import bpy # type: ignore
2 |
3 |
4 | def delete_unused_data():
5 | """Delete all collections, mesh and curve objects, meshes, curves, materials.
6 |
7 | Returns
8 | -------
9 | None
10 |
11 | """
12 | for block in bpy.data.meshes:
13 | if block.users == 0:
14 | bpy.data.meshes.remove(block)
15 |
16 | for block in bpy.data.curves:
17 | if block.users == 0:
18 | bpy.data.curves.remove(block)
19 |
20 | for block in bpy.data.materials:
21 | if block.users == 0:
22 | bpy.data.materials.remove(block)
23 |
24 | for block in bpy.data.textures:
25 | if block.users == 0:
26 | bpy.data.textures.remove(block)
27 |
28 | for block in bpy.data.images:
29 | if block.users == 0:
30 | bpy.data.images.remove(block)
31 |
--------------------------------------------------------------------------------
/src/compas_blender/geometry/__init__.py:
--------------------------------------------------------------------------------
1 | """
2 | This package provides plugins for various geometry pluggables using Blender as the backend.
3 | """
4 |
5 | from .booleans import boolean_difference_mesh_mesh
6 | from .booleans import boolean_intersection_mesh_mesh
7 | from .booleans import boolean_union_mesh_mesh
8 |
9 |
10 | __all__ = [
11 | "boolean_difference_mesh_mesh",
12 | "boolean_intersection_mesh_mesh",
13 | "boolean_union_mesh_mesh",
14 | ]
15 |
--------------------------------------------------------------------------------
/src/compas_blender/print_python_path.py:
--------------------------------------------------------------------------------
1 | import compas_blender
2 |
3 | if __name__ == "__main__":
4 | import argparse
5 |
6 | parser = argparse.ArgumentParser()
7 |
8 | parser.add_argument(
9 | "-v",
10 | "--version",
11 | choices=compas_blender.SUPPORTED_VERSIONS,
12 | default=compas_blender.DEFAULT_VERSION,
13 | help="The version of Blender.",
14 | )
15 |
16 | args = parser.parse_args()
17 |
18 | print(compas_blender._get_default_blender_python_path(args.version))
19 |
--------------------------------------------------------------------------------
/src/compas_blender/scene/boxobject.py:
--------------------------------------------------------------------------------
1 | import bpy # type: ignore
2 |
3 | from compas.scene import GeometryObject
4 | from compas_blender import conversions
5 |
6 | from .sceneobject import BlenderSceneObject
7 |
8 |
9 | class BoxObject(BlenderSceneObject, GeometryObject):
10 | """Scene object for drawing box shapes in Blender."""
11 |
12 | def draw(self) -> list[bpy.types.Object]:
13 | """Draw the box associated with the scene object.
14 |
15 | Returns
16 | -------
17 | list[:blender:`bpy.types.Object`]
18 | The object(s) created in Blender to represent the box.
19 |
20 | """
21 | mesh = conversions.vertices_and_faces_to_blender_mesh(self.geometry.vertices, self.geometry.faces, name=self.geometry.name)
22 |
23 | obj = self.create_object(mesh, name=self.geometry.name)
24 | self.update_object(obj, color=self.color, collection=self.collection, show_wire=self.show_wire)
25 |
26 | self._guids = [obj]
27 | return self.guids
28 |
--------------------------------------------------------------------------------
/src/compas_blender/scene/circleobject.py:
--------------------------------------------------------------------------------
1 | from typing import Optional
2 |
3 | import bpy # type: ignore
4 |
5 | from compas.colors import Color
6 | from compas.scene import GeometryObject
7 |
8 | from .sceneobject import BlenderSceneObject
9 |
10 |
11 | class CircleObject(BlenderSceneObject, GeometryObject):
12 | """Scene object for drawing circles in Blender."""
13 |
14 | def draw(self, color: Optional[Color] = None, collection: Optional[str] = None) -> list[bpy.types.Object]:
15 | """Draw the circle.
16 |
17 | Parameters
18 | ----------
19 | color : tuple[int, int, int] | tuple[float, float, float] | :class:`compas.colors.Color`, optional
20 | The RGB color of the capsule.
21 | collection : str, optional
22 | The name of the Blender scene collection containing the created object(s).
23 |
24 | Returns
25 | -------
26 | list[:blender:`bpy.types.Object`]
27 | The object created in Blender.
28 |
29 | """
30 | color = Color.coerce(color) or self.color
31 |
32 | bpy.ops.curve.primitive_bezier_circle_add(radius=self.geometry.radius)
33 |
34 | obj = bpy.context.object
35 | self.objects.append(obj)
36 | self.update_object(obj, color=color, collection=collection)
37 |
38 | self._guids = [obj]
39 | return self.guids
40 |
--------------------------------------------------------------------------------
/src/compas_blender/scene/polylineobject.py:
--------------------------------------------------------------------------------
1 | from typing import Optional
2 |
3 | import bpy # type: ignore
4 |
5 | from compas.colors import Color
6 | from compas.scene import GeometryObject
7 | from compas_blender import conversions
8 |
9 | from .sceneobject import BlenderSceneObject
10 |
11 |
12 | class PolylineObject(BlenderSceneObject, GeometryObject):
13 | """Scene object for drawing polylines in Blender."""
14 |
15 | def draw(self, color: Optional[Color] = None, collection: Optional[str] = None) -> list[bpy.types.Object]:
16 | """Draw the line.
17 |
18 | Parameters
19 | ----------
20 | color : tuple[float, float, float] | tuple[int, int, int] | :class:`compas.colors.Color`, optional
21 | The RGB color of the polyline.
22 | collection : str, optional
23 | The name of the Blender scene collection containing the created object(s).
24 |
25 | Returns
26 | -------
27 | list[:blender:`bpy.types.Object`]
28 | The objects created in Blender.
29 |
30 | """
31 | name = self.geometry.name
32 | color = Color.coerce(color) or self.color
33 |
34 | curve = conversions.polyline_to_blender_curve(self.geometry, name=name)
35 |
36 | obj = self.create_object(curve, name=name)
37 | self.update_object(obj, color=color, collection=collection)
38 |
39 | self._guids = [obj]
40 | return self.guids
41 |
--------------------------------------------------------------------------------
/src/compas_blender/scene/surfaceobject.py:
--------------------------------------------------------------------------------
1 | from typing import Optional
2 |
3 | import bpy # type: ignore
4 |
5 | from compas.colors import Color
6 | from compas.scene import GeometryObject
7 | from compas_blender import conversions
8 |
9 | from .sceneobject import BlenderSceneObject
10 |
11 |
12 | class SurfaceObject(BlenderSceneObject, GeometryObject):
13 | """Scene object for drawing surfaces in Blender."""
14 |
15 | def draw(self, color: Optional[Color] = None, collection: Optional[str] = None) -> list[bpy.types.Object]:
16 | """Draw the surface.
17 |
18 | Parameters
19 | ----------
20 | color : tuple[float, float, float] | tuple[int, int, int] | :class:`compas.colors.Color`, optional
21 | The RGB color of the surface.
22 | collection : str, optional
23 | The name of the Blender scene collection containing the created object(s).
24 |
25 | Returns
26 | -------
27 | list[:blender:`bpy.types.Object`]
28 | The objects created in Blender.
29 |
30 | """
31 | name = self.geometry.name
32 | color = Color.coerce(color) or self.color
33 |
34 | surface = conversions.nurbssurface_to_blender_surface(self.geometry)
35 |
36 | obj = self.create_object(surface, name=name)
37 | self.update_object(obj, color=color, collection=collection)
38 |
39 | self._guids = [obj]
40 | return self.guids
41 |
--------------------------------------------------------------------------------
/src/compas_blender/utilities/__init__.py:
--------------------------------------------------------------------------------
1 | from warnings import warn
2 |
3 | from ..drawing import (
4 | draw_circles,
5 | draw_cylinders,
6 | draw_cubes,
7 | draw_faces,
8 | draw_lines,
9 | draw_mesh,
10 | draw_pipes,
11 | draw_planes,
12 | draw_pointcloud,
13 | draw_points,
14 | draw_polylines,
15 | draw_spheres,
16 | draw_texts,
17 | draw_curves,
18 | draw_surfaces,
19 | RGBColor,
20 | )
21 |
22 |
23 | __all__ = [
24 | "draw_circles",
25 | "draw_cylinders",
26 | "draw_cubes",
27 | "draw_faces",
28 | "draw_lines",
29 | "draw_mesh",
30 | "draw_pipes",
31 | "draw_planes",
32 | "draw_pointcloud",
33 | "draw_points",
34 | "draw_polylines",
35 | "draw_spheres",
36 | "draw_texts",
37 | "draw_curves",
38 | "draw_surfaces",
39 | "RGBColor",
40 | ]
41 |
42 | warn("compas_blender.utilities will be removed in version 2.3. Please use compas_blender.drawing instead.", DeprecationWarning, stacklevel=2)
43 |
--------------------------------------------------------------------------------
/src/compas_ghpython/components/Compas_FromJson/code.py:
--------------------------------------------------------------------------------
1 | """
2 | Deserializes JSON into COMPAS objects.
3 | """
4 |
5 | from ghpythonlib.componentbase import executingcomponent as component
6 |
7 | import compas
8 |
9 |
10 | class CompasInfo(component):
11 | def RunScript(self, json):
12 | if not json:
13 | return None
14 |
15 | try:
16 | return compas.json_load(json)
17 | except: # noqa: E722
18 | return compas.json_loads(json)
19 |
--------------------------------------------------------------------------------
/src/compas_ghpython/components/Compas_FromJson/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/compas-dev/compas/96c2ea7a5d7f799b6c8846690a19c464a6dee41e/src/compas_ghpython/components/Compas_FromJson/icon.png
--------------------------------------------------------------------------------
/src/compas_ghpython/components/Compas_FromJson/metadata.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "From JSON",
3 | "nickname": "From JSON",
4 | "category": "COMPAS",
5 | "subcategory": "Data",
6 | "description": "Deserializes JSON into COMPAS objects.",
7 | "exposure": 2,
8 |
9 | "ghpython": {
10 | "isAdvancedMode": true,
11 | "iconDisplay": 2,
12 | "inputParameters": [
13 | {
14 | "name": "json",
15 | "description": "JSON file path or JSON string.",
16 | "typeHintID": "str"
17 | }
18 | ],
19 | "outputParameters": [
20 | {
21 | "name": "result",
22 | "description": "Deserialized objects."
23 | }
24 | ]
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/src/compas_ghpython/components/Compas_Info/code.py:
--------------------------------------------------------------------------------
1 | """
2 | Displays information about the active COMPAS environment.
3 | """
4 |
5 | import compas_bootstrapper
6 | from ghpythonlib.componentbase import executingcomponent as component
7 |
8 | import compas
9 |
10 |
11 | class CompasInfo(component):
12 | def RunScript(self):
13 | self.Message = "COMPAS v{}".format(compas.__version__)
14 | info = "COMPAS Version: {}\nEnvironment: {}"
15 | return info.format(compas.__version__, compas_bootstrapper.ENVIRONMENT_NAME)
16 |
--------------------------------------------------------------------------------
/src/compas_ghpython/components/Compas_Info/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/compas-dev/compas/96c2ea7a5d7f799b6c8846690a19c464a6dee41e/src/compas_ghpython/components/Compas_Info/icon.png
--------------------------------------------------------------------------------
/src/compas_ghpython/components/Compas_Info/metadata.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Info",
3 | "nickname": "Info",
4 | "category": "COMPAS",
5 | "subcategory": "Info",
6 | "description": "Displays information about the active COMPAS environment.",
7 | "exposure": 2,
8 |
9 | "ghpython": {
10 | "isAdvancedMode": true,
11 | "iconDisplay": 2,
12 | "inputParameters": [
13 | ],
14 | "outputParameters": [
15 | {
16 | "name": "info",
17 | "description": "Environment info."
18 | }
19 | ]
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/compas_ghpython/components/Compas_RpcCall/code.py:
--------------------------------------------------------------------------------
1 | """
2 | Remote Procedure Call: to invoke Python functions outside of Rhino, in the context of the CPython interpreter.
3 | """
4 |
5 | from ghpythonlib.componentbase import executingcomponent as component
6 |
7 | from compas.rpc import Proxy
8 |
9 |
10 | class CompasRpcCall(component):
11 | def RunScript(self, module, function, parameters, path, restart):
12 | if not (module and function):
13 | return
14 |
15 | if restart:
16 | proxy = Proxy(max_conn_attempts=1)
17 | proxy.stop_server()
18 |
19 | proxy = Proxy(module, path=path)
20 | fn = getattr(proxy, function)
21 | parameters = parameters or []
22 |
23 | try:
24 | result = fn(*parameters)
25 | except Exception:
26 | self.Message = "Error! Check details in stacktrace"
27 | raise
28 |
29 | self.Message = ""
30 |
31 | return result
32 |
--------------------------------------------------------------------------------
/src/compas_ghpython/components/Compas_RpcCall/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/compas-dev/compas/96c2ea7a5d7f799b6c8846690a19c464a6dee41e/src/compas_ghpython/components/Compas_RpcCall/icon.png
--------------------------------------------------------------------------------
/src/compas_ghpython/components/Compas_ToJson/code.py:
--------------------------------------------------------------------------------
1 | """
2 | Serializes COMPAS objects to JSON.
3 | """
4 |
5 | from ghpythonlib.componentbase import executingcomponent as component
6 |
7 | import compas
8 |
9 |
10 | class CompasInfo(component):
11 | def RunScript(self, data, filepath, pretty):
12 | json = filepath
13 |
14 | if filepath:
15 | compas.json_dump(data, filepath, pretty)
16 | else:
17 | json = compas.json_dumps(data, pretty)
18 |
19 | return json
20 |
--------------------------------------------------------------------------------
/src/compas_ghpython/components/Compas_ToJson/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/compas-dev/compas/96c2ea7a5d7f799b6c8846690a19c464a6dee41e/src/compas_ghpython/components/Compas_ToJson/icon.png
--------------------------------------------------------------------------------
/src/compas_ghpython/components/Compas_ToJson/metadata.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "To JSON",
3 | "nickname": "To JSON",
4 | "category": "COMPAS",
5 | "subcategory": "Data",
6 | "description": "Serializes COMPAS objects to JSON.",
7 | "exposure": 2,
8 |
9 | "ghpython": {
10 | "isAdvancedMode": true,
11 | "iconDisplay": 2,
12 | "inputParameters": [
13 | {
14 | "name": "data",
15 | "description": "COMPAS data objects to serialize."
16 | },
17 | {
18 | "name": "filepath",
19 | "description": "File path where to store the JSON file. If empty, it will not store to disk but instead return the JSON string.",
20 | "typeHintID": "str"
21 | },
22 | {
23 | "name": "pretty",
24 | "description": "If True, JSON data will be formatted with indentation and key sorting.",
25 | "typeHintID": "bool"
26 | }
27 | ],
28 | "outputParameters": [
29 | {
30 | "name": "json",
31 | "description": "JSON file path or JSON string."
32 | }
33 | ]
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/src/compas_ghpython/components/Compas_ToRhinoGeometry/code.py:
--------------------------------------------------------------------------------
1 | """
2 | Draws COMPAS geometry in Grasshopper.
3 | """
4 |
5 | from ghpythonlib.componentbase import executingcomponent as component
6 |
7 | from compas.scene import SceneObject
8 |
9 |
10 | class CompasToRhinoGeometry(component):
11 | def RunScript(self, cg):
12 | if not cg:
13 | return None
14 |
15 | return SceneObject(item=cg).draw()
16 |
--------------------------------------------------------------------------------
/src/compas_ghpython/components/Compas_ToRhinoGeometry/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/compas-dev/compas/96c2ea7a5d7f799b6c8846690a19c464a6dee41e/src/compas_ghpython/components/Compas_ToRhinoGeometry/icon.png
--------------------------------------------------------------------------------
/src/compas_ghpython/components/Compas_ToRhinoGeometry/metadata.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Draw",
3 | "nickname": "Draw",
4 | "category": "COMPAS",
5 | "subcategory": "Display",
6 | "description": "Draws COMPAS geometry",
7 | "exposure": 2,
8 |
9 | "ghpython": {
10 | "isAdvancedMode": true,
11 | "iconDisplay": 2,
12 | "inputParameters": [
13 | {
14 | "name": "cg",
15 | "description": "The COMPAS geometry or datastructure to be drawn."
16 | }
17 | ],
18 | "outputParameters": [
19 | {
20 | "name": "rg",
21 | "description": "The Rhino geometry object."
22 | }
23 | ]
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/compas_ghpython/components_cpython/Compas_FromJson/code.py:
--------------------------------------------------------------------------------
1 | # r: compas>=2.8.1
2 | """
3 | Deserializes JSON into COMPAS objects.
4 | """
5 |
6 | import Grasshopper
7 |
8 | import compas
9 |
10 |
11 | class CompasLoadFromJson(Grasshopper.Kernel.GH_ScriptInstance):
12 | def RunScript(self, json: str):
13 | if not json:
14 | return None
15 |
16 | try:
17 | return compas.json_load(json)
18 | except Exception:
19 | ghenv.Component.AddRuntimeMessage(Grasshopper.Kernel.GH_RuntimeMessageLevel.Warning, f"Failed to load JSON from path: {json}, Trying as string.") # noqa: F821
20 | return compas.json_loads(json)
21 |
--------------------------------------------------------------------------------
/src/compas_ghpython/components_cpython/Compas_FromJson/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/compas-dev/compas/96c2ea7a5d7f799b6c8846690a19c464a6dee41e/src/compas_ghpython/components_cpython/Compas_FromJson/icon.png
--------------------------------------------------------------------------------
/src/compas_ghpython/components_cpython/Compas_FromJson/metadata.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "From JSON",
3 | "nickname": "From JSON",
4 | "category": "COMPAS",
5 | "subcategory": "Data",
6 | "description": "Deserializes JSON into COMPAS objects.",
7 | "exposure": 2,
8 |
9 | "ghpython": {
10 | "isAdvancedMode": true,
11 | "iconDisplay": 2,
12 | "inputParameters": [
13 | {
14 | "name": "json",
15 | "description": "JSON file path or JSON string.",
16 | "typeHintID": "str"
17 | }
18 | ],
19 | "outputParameters": [
20 | {
21 | "name": "result",
22 | "description": "Deserialized objects."
23 | }
24 | ]
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/src/compas_ghpython/components_cpython/Compas_Info/code.py:
--------------------------------------------------------------------------------
1 | # r: compas>=2.8.1
2 | """
3 | Displays information about the active COMPAS environment.
4 | """
5 |
6 | import os
7 |
8 | import Grasshopper
9 |
10 | import compas
11 |
12 |
13 | class CompasInfo(Grasshopper.Kernel.GH_ScriptInstance):
14 | def RunScript(self):
15 | try:
16 | import compas_bootstrapper
17 |
18 | environment_name = compas_bootstrapper.ENVIRONMENT_NAME
19 | except ImportError:
20 | environment_name = os.path.dirname(compas.__file__)
21 | environment_name = os.path.abspath(os.path.join(environment_name, ".."))
22 |
23 | ghenv.Component.Message = "COMPAS v{}".format(compas.__version__) # noqa: F821
24 | info = "COMPAS Version: {}\nEnvironment: {}"
25 | return info.format(compas.__version__, environment_name)
26 |
--------------------------------------------------------------------------------
/src/compas_ghpython/components_cpython/Compas_Info/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/compas-dev/compas/96c2ea7a5d7f799b6c8846690a19c464a6dee41e/src/compas_ghpython/components_cpython/Compas_Info/icon.png
--------------------------------------------------------------------------------
/src/compas_ghpython/components_cpython/Compas_Info/metadata.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Info",
3 | "nickname": "Info",
4 | "category": "COMPAS",
5 | "subcategory": "Info",
6 | "description": "Displays information about the active COMPAS environment.",
7 | "exposure": 2,
8 |
9 | "ghpython": {
10 | "isAdvancedMode": true,
11 | "iconDisplay": 2,
12 | "inputParameters": [
13 | ],
14 | "outputParameters": [
15 | {
16 | "name": "info",
17 | "description": "Environment info."
18 | }
19 | ]
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/compas_ghpython/components_cpython/Compas_RpcCall/code.py:
--------------------------------------------------------------------------------
1 | # r: compas>=2.8.1
2 | """
3 | Remote Procedure Call: to invoke Python functions outside of Rhino, in the context of the CPython interpreter.
4 | """
5 |
6 | import Grasshopper
7 | import System
8 |
9 | from compas.rpc import Proxy
10 |
11 |
12 | class CompasRemoteProcedureCall(Grasshopper.Kernel.GH_ScriptInstance):
13 | def RunScript(self, module: str, function: str, parameters: System.Collections.Generic.List[object], path: str, restart: bool):
14 | if not (module and function):
15 | return
16 |
17 | if restart:
18 | proxy = Proxy(max_conn_attempts=1)
19 | proxy.stop_server()
20 |
21 | proxy = Proxy(module, path=path)
22 | fn = getattr(proxy, function)
23 | parameters = parameters or []
24 |
25 | result = fn(*parameters)
26 |
27 | return result
28 |
--------------------------------------------------------------------------------
/src/compas_ghpython/components_cpython/Compas_RpcCall/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/compas-dev/compas/96c2ea7a5d7f799b6c8846690a19c464a6dee41e/src/compas_ghpython/components_cpython/Compas_RpcCall/icon.png
--------------------------------------------------------------------------------
/src/compas_ghpython/components_cpython/Compas_ToJson/code.py:
--------------------------------------------------------------------------------
1 | # r: compas>=2.8.1
2 | """
3 | Serializes COMPAS objects to JSON.
4 | """
5 |
6 | from typing import Any
7 |
8 | import Grasshopper
9 |
10 | import compas
11 |
12 |
13 | class CompasDumpToJson(Grasshopper.Kernel.GH_ScriptInstance):
14 | def RunScript(self, data: Any, filepath: str, pretty: bool):
15 | json = filepath
16 |
17 | if filepath:
18 | compas.json_dump(data, filepath, pretty)
19 | else:
20 | json = compas.json_dumps(data, pretty)
21 |
22 | return json
23 |
--------------------------------------------------------------------------------
/src/compas_ghpython/components_cpython/Compas_ToJson/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/compas-dev/compas/96c2ea7a5d7f799b6c8846690a19c464a6dee41e/src/compas_ghpython/components_cpython/Compas_ToJson/icon.png
--------------------------------------------------------------------------------
/src/compas_ghpython/components_cpython/Compas_ToJson/metadata.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "To JSON",
3 | "nickname": "To JSON",
4 | "category": "COMPAS",
5 | "subcategory": "Data",
6 | "description": "Serializes COMPAS objects to JSON.",
7 | "exposure": 2,
8 |
9 | "ghpython": {
10 | "isAdvancedMode": true,
11 | "iconDisplay": 2,
12 | "inputParameters": [
13 | {
14 | "name": "data",
15 | "description": "COMPAS data objects to serialize."
16 | },
17 | {
18 | "name": "filepath",
19 | "description": "File path where to store the JSON file. If empty, it will not store to disk but instead return the JSON string.",
20 | "typeHintID": "str"
21 | },
22 | {
23 | "name": "pretty",
24 | "description": "If True, JSON data will be formatted with indentation and key sorting.",
25 | "typeHintID": "bool"
26 | }
27 | ],
28 | "outputParameters": [
29 | {
30 | "name": "json",
31 | "description": "JSON file path or JSON string."
32 | }
33 | ]
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/src/compas_ghpython/components_cpython/Compas_ToRhinoGeometry/code.py:
--------------------------------------------------------------------------------
1 | # r: compas>=2.8.1
2 | """
3 | Draws COMPAS geometry in Grasshopper.
4 | """
5 |
6 | from typing import Any
7 |
8 | import Grasshopper
9 |
10 | from compas.scene import SceneObject
11 |
12 |
13 | class CompasToRhinoGeometry(Grasshopper.Kernel.GH_ScriptInstance):
14 | def RunScript(self, cg: Any):
15 | if not cg:
16 | return None
17 |
18 | return SceneObject(item=cg).draw()
19 |
--------------------------------------------------------------------------------
/src/compas_ghpython/components_cpython/Compas_ToRhinoGeometry/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/compas-dev/compas/96c2ea7a5d7f799b6c8846690a19c464a6dee41e/src/compas_ghpython/components_cpython/Compas_ToRhinoGeometry/icon.png
--------------------------------------------------------------------------------
/src/compas_ghpython/components_cpython/Compas_ToRhinoGeometry/metadata.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Draw",
3 | "nickname": "Draw",
4 | "category": "COMPAS",
5 | "subcategory": "Display",
6 | "description": "Draws COMPAS geometry",
7 | "exposure": 2,
8 |
9 | "ghpython": {
10 | "isAdvancedMode": true,
11 | "iconDisplay": 2,
12 | "inputParameters": [
13 | {
14 | "name": "cg",
15 | "description": "The COMPAS geometry or datastructure to be drawn."
16 | }
17 | ],
18 | "outputParameters": [
19 | {
20 | "name": "rg",
21 | "description": "The Rhino geometry object."
22 | }
23 | ]
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/compas_ghpython/install.py:
--------------------------------------------------------------------------------
1 | from __future__ import absolute_import
2 | from __future__ import division
3 | from __future__ import print_function
4 |
5 | import os
6 |
7 | import compas.plugins
8 | from compas_ghpython.components import install_userobjects
9 |
10 |
11 | @compas.plugins.plugin(category="install")
12 | def installable_rhino_packages():
13 | return ["compas_ghpython"]
14 |
15 |
16 | @compas.plugins.plugin(category="install")
17 | def after_rhino_install(installed_packages):
18 | if "compas_ghpython" not in installed_packages:
19 | return []
20 |
21 | installed_objects = install_userobjects(os.path.join(os.path.dirname(__file__), "components", "ghuser"))
22 |
23 | return [
24 | (
25 | "compas_ghpython",
26 | "Installed {} GH User Objects".format(len(installed_objects)),
27 | True,
28 | )
29 | ]
30 |
--------------------------------------------------------------------------------
/src/compas_ghpython/scene/boxobject.py:
--------------------------------------------------------------------------------
1 | from __future__ import absolute_import
2 | from __future__ import division
3 | from __future__ import print_function
4 |
5 | from compas.scene import GeometryObject
6 | from compas_rhino import conversions
7 |
8 | from .sceneobject import GHSceneObject
9 |
10 |
11 | class BoxObject(GHSceneObject, GeometryObject):
12 | """Scene object for drawing box shapes."""
13 |
14 | def draw(self):
15 | """Draw the box associated with the scene object.
16 |
17 | Returns
18 | -------
19 | list[:rhino:`Rhino.Geometry.Box`]
20 | List of created Rhino box.
21 |
22 | """
23 | box = conversions.box_to_rhino(self.geometry)
24 | transformation = conversions.transformation_to_rhino(self.worldtransformation)
25 | box.Transform(transformation)
26 |
27 | self._guids = [box]
28 | return self.guids
29 |
--------------------------------------------------------------------------------
/src/compas_ghpython/scene/brepobject.py:
--------------------------------------------------------------------------------
1 | from __future__ import absolute_import
2 | from __future__ import division
3 | from __future__ import print_function
4 |
5 | from compas.scene import GeometryObject
6 | from compas_rhino import conversions
7 |
8 | from .sceneobject import GHSceneObject
9 |
10 |
11 | class BrepObject(GHSceneObject, GeometryObject):
12 | """A Scene object for drawing a brep in Grasshopper."""
13 |
14 | def draw(self):
15 | """Draw the brep as a Grasshopper geometry.
16 |
17 | Returns
18 | -------
19 | list[:rhino:`Rhino.Geometry.Brep`]
20 | List of created Rhino breps.
21 |
22 | """
23 | brep = conversions.brep_to_rhino(self.geometry)
24 | transformation = conversions.transformation_to_rhino(self.worldtransformation)
25 | brep.Transform(transformation)
26 |
27 | self._guids = [brep]
28 | return self.guids
29 |
--------------------------------------------------------------------------------
/src/compas_ghpython/scene/capsuleobject.py:
--------------------------------------------------------------------------------
1 | from __future__ import absolute_import
2 | from __future__ import division
3 | from __future__ import print_function
4 |
5 | from compas.scene import GeometryObject
6 | from compas_rhino import conversions
7 |
8 | from .sceneobject import GHSceneObject
9 |
10 |
11 | class CapsuleObject(GHSceneObject, GeometryObject):
12 | """Scene object for drawing capsule shapes."""
13 |
14 | def draw(self):
15 | """Draw the capsule associated with the scene object.
16 |
17 | Returns
18 | -------
19 | list[:rhino:`Rhino.Geometry.Brep`]
20 | List of created Rhino breps.
21 |
22 | """
23 | breps = conversions.capsule_to_rhino_brep(self.geometry)
24 | transformation = conversions.transformation_to_rhino(self.transformation)
25 | for geometry in breps:
26 | geometry.Transform(transformation)
27 |
28 | self._guids = breps
29 | return self.guids
30 |
--------------------------------------------------------------------------------
/src/compas_ghpython/scene/circleobject.py:
--------------------------------------------------------------------------------
1 | from __future__ import absolute_import
2 | from __future__ import division
3 | from __future__ import print_function
4 |
5 | from compas.scene import GeometryObject
6 | from compas_rhino import conversions
7 |
8 | from .sceneobject import GHSceneObject
9 |
10 |
11 | class CircleObject(GHSceneObject, GeometryObject):
12 | """Scene object for drawing circles."""
13 |
14 | def draw(self):
15 | """Draw the circle.
16 |
17 | Returns
18 | -------
19 | list[:rhino:`Rhino.Geometry.Circle`]
20 | List of created Rhino circles.
21 |
22 | """
23 | circle = conversions.circle_to_rhino(self.geometry)
24 | transformation = conversions.transformation_to_rhino(self.worldtransformation)
25 | circle.Transform(transformation)
26 |
27 | self._guids = [circle]
28 | return self.guids
29 |
--------------------------------------------------------------------------------
/src/compas_ghpython/scene/coneobject.py:
--------------------------------------------------------------------------------
1 | from __future__ import absolute_import
2 | from __future__ import division
3 | from __future__ import print_function
4 |
5 | from compas.scene import GeometryObject
6 | from compas_rhino import conversions
7 |
8 | from .sceneobject import GHSceneObject
9 |
10 |
11 | class ConeObject(GHSceneObject, GeometryObject):
12 | """Scene object for drawing cone shapes."""
13 |
14 | def draw(self):
15 | """Draw the cone associated with the scene object.
16 |
17 | Returns
18 | -------
19 | list[:rhino:`Rhino.Geometry.Brep`]
20 | List of created Rhino breps.
21 |
22 | """
23 | brep = conversions.cone_to_rhino_brep(self.geometry)
24 | transformation = conversions.transformation_to_rhino(self.worldtransformation)
25 | brep.Transform(transformation)
26 |
27 | self._guids = [brep]
28 | return self.guids
29 |
--------------------------------------------------------------------------------
/src/compas_ghpython/scene/curveobject.py:
--------------------------------------------------------------------------------
1 | from __future__ import absolute_import
2 | from __future__ import division
3 | from __future__ import print_function
4 |
5 | from compas.scene import GeometryObject
6 | from compas_rhino import conversions
7 |
8 | from .sceneobject import GHSceneObject
9 |
10 |
11 | class CurveObject(GHSceneObject, GeometryObject):
12 | """Scene object for drawing curves."""
13 |
14 | def draw(self):
15 | """Draw the curve.
16 |
17 | Returns
18 | -------
19 | list[:rhino:`Rhino.Geometry.Curve`]
20 |
21 | """
22 | geometry = conversions.curve_to_rhino(self.geometry)
23 | transformation = conversions.transformation_to_rhino(self.worldtransformation)
24 | geometry.Transform(transformation)
25 |
26 | self._guids = [geometry]
27 | return self.guids
28 |
--------------------------------------------------------------------------------
/src/compas_ghpython/scene/cylinderobject.py:
--------------------------------------------------------------------------------
1 | from __future__ import absolute_import
2 | from __future__ import division
3 | from __future__ import print_function
4 |
5 | from compas.scene import GeometryObject
6 | from compas_rhino import conversions
7 |
8 | from .sceneobject import GHSceneObject
9 |
10 |
11 | class CylinderObject(GHSceneObject, GeometryObject):
12 | """Scene object for drawing cylinder shapes."""
13 |
14 | def draw(self):
15 | """Draw the cylinder associated with the scene object.
16 |
17 | Returns
18 | -------
19 | list[:rhino:`Rhino.Geometry.Brep`]
20 | List of created Rhino breps.
21 |
22 | """
23 | geometry = conversions.cylinder_to_rhino_brep(self.geometry)
24 | geometry.Transform(conversions.transformation_to_rhino(self.worldtransformation))
25 |
26 | self._guids = [geometry]
27 | return self.guids
28 |
--------------------------------------------------------------------------------
/src/compas_ghpython/scene/ellipseobject.py:
--------------------------------------------------------------------------------
1 | from __future__ import absolute_import
2 | from __future__ import division
3 | from __future__ import print_function
4 |
5 | from compas.scene import GeometryObject
6 | from compas_rhino import conversions
7 |
8 | from .sceneobject import GHSceneObject
9 |
10 |
11 | class EllipseObject(GHSceneObject, GeometryObject):
12 | """Scene object for drawing ellipses."""
13 |
14 | def draw(self):
15 | """Draw the ellipse.
16 |
17 | Returns
18 | -------
19 | list[:rhino:`Rhino.Geometry.Ellipse`]
20 | List of created Rhino ellipse.
21 |
22 | """
23 | ellipse = conversions.ellipse_to_rhino(self.geometry)
24 | ellipse = ellipse.ToNurbsCurve()
25 | ellipse.Transform(conversions.transformation_to_rhino(self.worldtransformation))
26 |
27 | self._guids = [ellipse]
28 | return self.guids
29 |
--------------------------------------------------------------------------------
/src/compas_ghpython/scene/lineobject.py:
--------------------------------------------------------------------------------
1 | from __future__ import absolute_import
2 | from __future__ import division
3 | from __future__ import print_function
4 |
5 | from compas.scene import GeometryObject
6 | from compas_rhino import conversions
7 |
8 | from .sceneobject import GHSceneObject
9 |
10 |
11 | class LineObject(GHSceneObject, GeometryObject):
12 | """Scene object for drawing lines."""
13 |
14 | def draw(self):
15 | """Draw the line.
16 |
17 | Returns
18 | -------
19 | list[:rhino:`Rhino.Geometry.Line`]
20 | List of created Rhino lines.
21 |
22 | """
23 | geometry = conversions.line_to_rhino(self.geometry)
24 | geometry.Transform(conversions.transformation_to_rhino(self.worldtransformation))
25 |
26 | self._guids = [geometry]
27 | return self.guids
28 |
--------------------------------------------------------------------------------
/src/compas_ghpython/scene/pointobject.py:
--------------------------------------------------------------------------------
1 | from __future__ import absolute_import
2 | from __future__ import division
3 | from __future__ import print_function
4 |
5 | from compas.scene import GeometryObject
6 | from compas_rhino import conversions
7 |
8 | from .sceneobject import GHSceneObject
9 |
10 |
11 | class PointObject(GHSceneObject, GeometryObject):
12 | """Scene object for drawing points."""
13 |
14 | def draw(self):
15 | """Draw the point.
16 |
17 | Returns
18 | -------
19 | list[:rhino:`Rhino.Geometry.Point3d`]
20 | List of created Rhino points.
21 | """
22 | geometry = conversions.point_to_rhino(self.geometry)
23 | geometry.Transform(conversions.transformation_to_rhino(self.worldtransformation))
24 |
25 | self._guids = [geometry]
26 | return self.guids
27 |
--------------------------------------------------------------------------------
/src/compas_ghpython/scene/polygonobject.py:
--------------------------------------------------------------------------------
1 | from __future__ import absolute_import
2 | from __future__ import division
3 | from __future__ import print_function
4 |
5 | from compas.scene import GeometryObject
6 | from compas_rhino import conversions
7 |
8 | from .sceneobject import GHSceneObject
9 |
10 |
11 | class PolygonObject(GHSceneObject, GeometryObject):
12 | """Scene object for drawing polygons."""
13 |
14 | def draw(self):
15 | """Draw the polygon.
16 |
17 | Returns
18 | -------
19 | list[:rhino:`Rhino.Geometry.Mesh`]
20 |
21 | """
22 | color = self.surfacecolor
23 | vertices = self.geometry.vertices
24 | faces = self.geometry.faces
25 |
26 | geometry = conversions.vertices_and_faces_to_rhino(vertices, faces, color=color)
27 | geometry.Transform(conversions.transformation_to_rhino(self.worldtransformation))
28 |
29 | self._guids = [geometry]
30 | return self.guids
31 |
--------------------------------------------------------------------------------
/src/compas_ghpython/scene/polyhedronobject.py:
--------------------------------------------------------------------------------
1 | from __future__ import absolute_import
2 | from __future__ import division
3 | from __future__ import print_function
4 |
5 | from compas.scene import GeometryObject
6 | from compas_rhino import conversions
7 |
8 | from .sceneobject import GHSceneObject
9 |
10 |
11 | class PolyhedronObject(GHSceneObject, GeometryObject):
12 | """Scene object for drawing polyhedron shapes."""
13 |
14 | def draw(self):
15 | """Draw the polyhedron associated with the scene object.
16 |
17 | Parameters
18 | ----------
19 | color : tuple[int, int, int] | tuple[float, float, float] | :class:`compas.colors.Color`, optional
20 | The RGB color of the line.
21 |
22 | Returns
23 | -------
24 | list[:rhino:`Rhino.Geometry.Mesh`]
25 | List of created Rhino mesh.
26 |
27 | """
28 | color = self.surfacecolor
29 | vertices, faces = self.geometry.to_vertices_and_faces()
30 |
31 | geometry = conversions.vertices_and_faces_to_rhino(vertices, faces, color=color)
32 | geometry.Transform(conversions.transformation_to_rhino(self.worldtransformation))
33 |
34 | self._guids = [geometry]
35 | return self.guids
36 |
--------------------------------------------------------------------------------
/src/compas_ghpython/scene/polylineobject.py:
--------------------------------------------------------------------------------
1 | from __future__ import absolute_import
2 | from __future__ import division
3 | from __future__ import print_function
4 |
5 | from compas.scene import GeometryObject
6 | from compas_rhino import conversions
7 |
8 | from .sceneobject import GHSceneObject
9 |
10 |
11 | class PolylineObject(GHSceneObject, GeometryObject):
12 | """Scene object for drawing polylines."""
13 |
14 | def draw(self):
15 | """Draw the polyline.
16 |
17 | Returns
18 | -------
19 | list[:rhino:`Rhino.Geometry.PolylineCurve`]
20 | List of created Rhino polyline.
21 |
22 | """
23 | geometry = conversions.polyline_to_rhino_curve(self.geometry)
24 | geometry.Transform(conversions.transformation_to_rhino(self.worldtransformation))
25 |
26 | self._guids = [geometry]
27 | return self.guids
28 |
--------------------------------------------------------------------------------
/src/compas_ghpython/scene/sceneobject.py:
--------------------------------------------------------------------------------
1 | from __future__ import absolute_import
2 | from __future__ import division
3 | from __future__ import print_function
4 |
5 | from compas.scene import SceneObject
6 |
7 |
8 | class GHSceneObject(SceneObject):
9 | """Base class for all GH scene objects."""
10 |
--------------------------------------------------------------------------------
/src/compas_ghpython/scene/sphereobject.py:
--------------------------------------------------------------------------------
1 | from __future__ import absolute_import
2 | from __future__ import division
3 | from __future__ import print_function
4 |
5 | from compas.scene import GeometryObject
6 | from compas_rhino import conversions
7 |
8 | from .sceneobject import GHSceneObject
9 |
10 |
11 | class SphereObject(GHSceneObject, GeometryObject):
12 | """Scene object for drawing sphere shapes."""
13 |
14 | def draw(self):
15 | """Draw the sphere associated with the scene object.
16 |
17 | Returns
18 | -------
19 | list[:rhino:`Rhino.Geometry.Sphere`]
20 | List of created Rhino spheres.
21 |
22 | """
23 | geometry = conversions.sphere_to_rhino(self.geometry)
24 | geometry.Transform(conversions.transformation_to_rhino(self.worldtransformation))
25 |
26 | self._guids = [geometry]
27 | return self.guids
28 |
--------------------------------------------------------------------------------
/src/compas_ghpython/scene/surfaceobject.py:
--------------------------------------------------------------------------------
1 | from __future__ import absolute_import
2 | from __future__ import division
3 | from __future__ import print_function
4 |
5 | from compas.scene import GeometryObject
6 | from compas_rhino import conversions
7 |
8 | from .sceneobject import GHSceneObject
9 |
10 |
11 | class SurfaceObject(GHSceneObject, GeometryObject):
12 | """Scene object for drawing surfaces."""
13 |
14 | def draw(self):
15 | """Draw the surface.
16 |
17 | Returns
18 | -------
19 | list[:rhino:`Rhino.Geometry.Surface`]
20 | The created Rhino surfaces.
21 |
22 | """
23 | geometry = conversions.surface_to_rhino(self.geometry)
24 | geometry.Transform(conversions.transformation_to_rhino(self.worldtransformation))
25 |
26 | self._guids = [geometry]
27 | return self.guids
28 |
--------------------------------------------------------------------------------
/src/compas_ghpython/scene/torusobject.py:
--------------------------------------------------------------------------------
1 | from __future__ import absolute_import
2 | from __future__ import division
3 | from __future__ import print_function
4 |
5 | from compas.scene import GeometryObject
6 | from compas_rhino import conversions
7 |
8 | from .sceneobject import GHSceneObject
9 |
10 |
11 | class TorusObject(GHSceneObject, GeometryObject):
12 | """Scene object for drawing torus shapes."""
13 |
14 | def draw(self):
15 | """Draw the torus associated with the scene object.
16 |
17 | Returns
18 | -------
19 | list[:rhino:`Rhino.Geometry.Brep`]
20 | List of created Rhino torus.
21 |
22 | """
23 | brep = conversions.torus_to_rhino_brep(self.geometry)
24 | brep.Transform(conversions.transformation_to_rhino(self.worldtransformation))
25 |
26 | self._guids = [brep]
27 | return self.guids
28 |
--------------------------------------------------------------------------------
/src/compas_ghpython/scene/vectorobject.py:
--------------------------------------------------------------------------------
1 | from __future__ import absolute_import
2 | from __future__ import division
3 | from __future__ import print_function
4 |
5 | from compas.geometry import Point
6 | from compas.scene import GeometryObject
7 | from compas_rhino import conversions
8 |
9 | from .sceneobject import GHSceneObject
10 |
11 |
12 | class VectorObject(GHSceneObject, GeometryObject):
13 | """Scene object for drawing vectors."""
14 |
15 | def draw(self, point=None):
16 | """Draw the vector.
17 |
18 | Parameters
19 | ----------
20 | point : [float, float, float] | :class:`compas.geometry.Point`, optional
21 | Point of application of the vector.
22 | Default is ``Point(0, 0, 0)``.
23 |
24 | Returns
25 | -------
26 | list[:rhino:`Rhino.Geometry.Line`]
27 | List of created Rhino lines.
28 |
29 | """
30 | point = point or [0, 0, 0]
31 | start = Point(*point)
32 | end = start + self.geometry
33 |
34 | geometry = conversions.line_to_rhino([start, end])
35 | transformation = conversions.transformation_to_rhino(self.worldtransformation)
36 | geometry.Transform(transformation)
37 |
38 | self._guids = [geometry]
39 | return self.guids
40 |
--------------------------------------------------------------------------------
/src/compas_ghpython/timer.py:
--------------------------------------------------------------------------------
1 | from __future__ import absolute_import
2 | from __future__ import division
3 | from __future__ import print_function
4 |
5 | import Grasshopper # type: ignore
6 |
7 |
8 | def update_component(ghenv, delay):
9 | """Schedule an update of the Grasshopper component.
10 |
11 | After the specified delay, the GH component will be automatically updated.
12 |
13 | Parameters
14 | ----------
15 | ghenv : :class:`GhPython.Component.PythonEnvironment`
16 | The current GHPython environment.
17 | delay : :obj:`int`
18 | Time in milliseconds until the update is performed.
19 |
20 | Raises
21 | ------
22 | ValueError
23 | If the delay is less than zero.
24 |
25 | """
26 | if delay <= 0:
27 | raise ValueError("Delay must be greater than zero")
28 |
29 | ghcomp = ghenv.Component
30 | ghdoc = ghcomp.OnPingDocument()
31 |
32 | def callback(ghdoc):
33 | if ghdoc.SolutionState != Grasshopper.Kernel.GH_ProcessStep.Process:
34 | ghcomp.ExpireSolution(False)
35 |
36 | ghdoc.ScheduleSolution(delay, Grasshopper.Kernel.GH_Document.GH_ScheduleDelegate(callback))
37 |
--------------------------------------------------------------------------------
/src/compas_ghpython/uninstall.py:
--------------------------------------------------------------------------------
1 | from __future__ import absolute_import
2 | from __future__ import division
3 | from __future__ import print_function
4 |
5 | import glob
6 | import os
7 |
8 | import compas
9 | import compas.plugins
10 | from compas_ghpython.components import uninstall_userobjects
11 |
12 |
13 | @compas.plugins.plugin(category="install")
14 | def after_rhino_uninstall(uninstalled_packages):
15 | if "compas_ghpython" not in uninstalled_packages:
16 | return []
17 |
18 | srcdir = os.path.join(os.path.dirname(__file__), "components", "ghuser")
19 | userobjects = [os.path.basename(ghuser) for ghuser in glob.glob(os.path.join(srcdir, "*.ghuser"))]
20 | uninstalled_objects = uninstall_userobjects(userobjects)
21 |
22 | uninstall_errors = [uo[0] for uo in uninstalled_objects if not uo[1]]
23 | error_msg = "" if not uninstall_errors else "and {} failed to uninstall".format(len(uninstall_errors))
24 |
25 | return [
26 | (
27 | "compas_ghpython",
28 | "Uninstalled {} GH User Objects {}".format(len(uninstalled_objects), error_msg),
29 | True,
30 | )
31 | ]
32 |
--------------------------------------------------------------------------------
/src/compas_ghpython/yak_template/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/compas-dev/compas/96c2ea7a5d7f799b6c8846690a19c464a6dee41e/src/compas_ghpython/yak_template/icon.png
--------------------------------------------------------------------------------
/src/compas_ghpython/yak_template/manifest.yml:
--------------------------------------------------------------------------------
1 | name: bluejay
2 | version: {{ version }}
3 | authors:
4 | - tom van mele et. al.
5 | description: The **COMPAS** framework is an open-source, Python-based framework for computational research and collaboration in architecture, engineering, digital fabrication and construction.
6 | url: "https://github.com/compas-dev/compas"
7 | keywords: ["COMPAS", "compas", "framework", "architecture", "engineering", "digital", "fabrication", "construction"]
8 |
9 |
--------------------------------------------------------------------------------
/src/compas_rhino/conduits/__init__.py:
--------------------------------------------------------------------------------
1 | from __future__ import absolute_import
2 |
3 | from .base import BaseConduit
4 |
5 | from .faces import FacesConduit
6 | from .labels import LabelsConduit
7 | from .lines import LinesConduit
8 | from .points import PointsConduit
9 |
10 | __all__ = [
11 | "BaseConduit",
12 | "FacesConduit",
13 | "LabelsConduit",
14 | "LinesConduit",
15 | "PointsConduit",
16 | ]
17 |
--------------------------------------------------------------------------------
/src/compas_rhino/conversions/exceptions.py:
--------------------------------------------------------------------------------
1 | from __future__ import absolute_import
2 | from __future__ import division
3 | from __future__ import print_function
4 |
5 |
6 | class ConversionError(Exception):
7 | """Raised when a conversion is not possible."""
8 |
--------------------------------------------------------------------------------
/src/compas_rhino/conversions/transformations.py:
--------------------------------------------------------------------------------
1 | from __future__ import absolute_import
2 | from __future__ import division
3 | from __future__ import print_function
4 |
5 | import Rhino # type: ignore
6 |
7 |
8 | def transformation_to_rhino(transformation):
9 | """Creates a Rhino transformation from a COMPAS transformation.
10 |
11 | Parameters
12 | ----------
13 | transformation : :class:`compas.geometry.Transformation`
14 | COMPAS transformation.
15 |
16 | Returns
17 | -------
18 | :rhino:`Rhino.Geometry.Transform`
19 |
20 | """
21 | transform = Rhino.Geometry.Transform(1.0)
22 | for i in range(0, 4):
23 | for j in range(0, 4):
24 | transform[i, j] = transformation[i, j]
25 | return transform
26 |
27 |
28 | def transformation_matrix_to_rhino(matrix):
29 | """Creates a Rhino transformation from a 4x4 transformation matrix.
30 |
31 | Parameters
32 | ----------
33 | matrix : list[list[float]]
34 | The 4x4 transformation matrix in row-major order.
35 |
36 | Returns
37 | -------
38 | :rhino:`Rhino.Geometry.Transform`
39 |
40 | """
41 | transform = Rhino.Geometry.Transform(1.0)
42 | for i in range(0, 4):
43 | for j in range(0, 4):
44 | transform[i, j] = matrix[i][j]
45 | return transform
46 |
--------------------------------------------------------------------------------
/src/compas_rhino/geometry/__init__.py:
--------------------------------------------------------------------------------
1 | """
2 | This package provides plugins for various geometry pluggables using Rhino as the backend.
3 | """
4 |
5 | from __future__ import absolute_import
6 |
7 | from .curves.nurbs import RhinoNurbsCurve
8 | from .surfaces.nurbs import RhinoNurbsSurface
9 |
10 | from .brep.brep import RhinoBrep
11 | from .brep.loop import RhinoBrepLoop
12 | from .brep.vertex import RhinoBrepVertex
13 | from .brep.face import RhinoBrepFace
14 | from .brep.edge import RhinoBrepEdge
15 | from .brep.trim import RhinoBrepTrim
16 |
17 | from .booleans import boolean_difference_mesh_mesh
18 | from .booleans import boolean_union_mesh_mesh
19 | from .booleans import boolean_intersection_mesh_mesh
20 |
21 | from .trimesh_curvature import trimesh_gaussian_curvature
22 | from .trimesh_curvature import trimesh_mean_curvature
23 | from .trimesh_curvature import trimesh_principal_curvature
24 |
25 | from .trimesh_slicing import trimesh_slice
26 |
27 |
28 | __all__ = [
29 | "boolean_difference_mesh_mesh",
30 | "boolean_intersection_mesh_mesh",
31 | "boolean_union_mesh_mesh",
32 | "trimesh_gaussian_curvature",
33 | "trimesh_mean_curvature",
34 | "trimesh_principal_curvature",
35 | "trimesh_slice",
36 | "RhinoNurbsCurve",
37 | "RhinoNurbsSurface",
38 | "RhinoBrep",
39 | "RhinoBrepVertex",
40 | "RhinoBrepEdge",
41 | "RhinoBrepFace",
42 | "RhinoBrepLoop",
43 | "RhinoBrepTrim",
44 | ]
45 |
--------------------------------------------------------------------------------
/src/compas_rhino/geometry/curves/__init__.py:
--------------------------------------------------------------------------------
1 | from .nurbs import RhinoCurve
2 | from .nurbs import RhinoNurbsCurve
3 |
4 | from compas.plugins import plugin
5 |
6 |
7 | @plugin(category="factories", requires=["Rhino"])
8 | def curve_from_native(cls, *args, **kwargs):
9 | return RhinoCurve.from_native(*args, **kwargs)
10 |
11 |
12 | @plugin(category="factories", requires=["Rhino"])
13 | def nurbscurve_from_interpolation(cls, *args, **kwargs):
14 | return RhinoNurbsCurve.from_interpolation(*args, **kwargs)
15 |
16 |
17 | @plugin(category="factories", requires=["Rhino"])
18 | def nurbscurve_from_native(cls, *args, **kwargs):
19 | return RhinoNurbsCurve.from_native(*args, **kwargs)
20 |
21 |
22 | @plugin(category="factories", requires=["Rhino"])
23 | def nurbscurve_from_parameters(cls, *args, **kwargs):
24 | return RhinoNurbsCurve.from_parameters(*args, **kwargs)
25 |
26 |
27 | @plugin(category="factories", requires=["Rhino"])
28 | def nurbscurve_from_points(cls, *args, **kwargs):
29 | return RhinoNurbsCurve.from_points(*args, **kwargs)
30 |
31 |
32 | # @plugin(category="factories", requires=["Rhino"])
33 | # def nurbscurve_from_step(cls, *args, **kwargs):
34 | # return RhinoNurbsCurve.from_step(*args, **kwargs)
35 |
--------------------------------------------------------------------------------
/src/compas_rhino/install_with_pip.py:
--------------------------------------------------------------------------------
1 | import subprocess
2 |
3 | import compas_rhino
4 |
5 |
6 | def install(args):
7 | subprocess.check_call([compas_rhino._get_default_rhino_cpython_path("8.0"), "-m", "pip", "install"] + args)
8 |
9 |
10 | if __name__ == "__main__":
11 | import argparse
12 |
13 | parser = argparse.ArgumentParser()
14 |
15 | parser.add_argument("pipargs", help="Arguments to be passed on to pip as a string")
16 |
17 | args = parser.parse_args()
18 | pipargs = args.pipargs.split()
19 |
20 | install(pipargs)
21 |
--------------------------------------------------------------------------------
/src/compas_rhino/print_python_path.py:
--------------------------------------------------------------------------------
1 | import compas_rhino
2 |
3 | if __name__ == "__main__":
4 | import argparse
5 |
6 | parser = argparse.ArgumentParser()
7 |
8 | parser.add_argument(
9 | "-v",
10 | "--version",
11 | choices=compas_rhino.SUPPORTED_VERSIONS,
12 | default=compas_rhino.DEFAULT_VERSION,
13 | help="The version of Rhino.",
14 | )
15 |
16 | args = parser.parse_args()
17 |
18 | print(compas_rhino._get_default_rhino_cpython_path(version=args.version))
19 |
--------------------------------------------------------------------------------
/src/compas_rhino/scene/boxobject.py:
--------------------------------------------------------------------------------
1 | from __future__ import absolute_import
2 | from __future__ import division
3 | from __future__ import print_function
4 |
5 | import scriptcontext as sc # type: ignore
6 |
7 | from compas.scene import GeometryObject
8 | from compas_rhino.conversions import box_to_rhino
9 | from compas_rhino.conversions import transformation_to_rhino
10 |
11 | from .sceneobject import RhinoSceneObject
12 |
13 |
14 | class RhinoBoxObject(RhinoSceneObject, GeometryObject):
15 | """Scene object for drawing box shapes."""
16 |
17 | def draw(self):
18 | """Draw the box associated with the scene object.
19 |
20 | Returns
21 | -------
22 | list[System.Guid]
23 | List of GUIDs of the objects created in Rhino.
24 |
25 | """
26 | attr = self.compile_attributes()
27 | geometry = box_to_rhino(self.geometry)
28 | geometry.Transform(transformation_to_rhino(self.worldtransformation))
29 |
30 | self._guids = [sc.doc.Objects.AddBox(geometry, attr)]
31 | return self.guids
32 |
--------------------------------------------------------------------------------
/src/compas_rhino/scene/brepobject.py:
--------------------------------------------------------------------------------
1 | from __future__ import absolute_import
2 | from __future__ import division
3 | from __future__ import print_function
4 |
5 | import scriptcontext as sc # type: ignore
6 |
7 | from compas.scene import GeometryObject
8 | from compas_rhino.conversions import brep_to_rhino
9 | from compas_rhino.conversions import transformation_to_rhino
10 |
11 | from .sceneobject import RhinoSceneObject
12 |
13 |
14 | class RhinoBrepObject(RhinoSceneObject, GeometryObject):
15 | """A scene object for drawing a RhinoBrep."""
16 |
17 | def draw(self):
18 | """Bakes the Brep into the current document
19 |
20 | Returns
21 | -------
22 | list[System.Guid]
23 | List of GUIDs of the objects created in Rhino.
24 |
25 | """
26 | attr = self.compile_attributes()
27 | geometry = brep_to_rhino(self.geometry)
28 | geometry.Transform(transformation_to_rhino(self.worldtransformation))
29 |
30 | self._guids = [sc.doc.Objects.AddBrep(geometry, attr)]
31 | return self.guids
32 |
--------------------------------------------------------------------------------
/src/compas_rhino/scene/capsuleobject.py:
--------------------------------------------------------------------------------
1 | from __future__ import absolute_import
2 | from __future__ import division
3 | from __future__ import print_function
4 |
5 | import scriptcontext as sc # type: ignore
6 |
7 | from compas.scene import GeometryObject
8 | from compas_rhino.conversions import capsule_to_rhino_brep
9 | from compas_rhino.conversions import transformation_to_rhino
10 |
11 | from .sceneobject import RhinoSceneObject
12 |
13 |
14 | class RhinoCapsuleObject(RhinoSceneObject, GeometryObject):
15 | """Scene object for drawing capsule shapes."""
16 |
17 | def draw(self):
18 | """Draw the capsule associated with the scene object.
19 |
20 | Returns
21 | -------
22 | list[System.Guid]
23 | The GUIDs of the objects created in Rhino.
24 |
25 | """
26 | attr = self.compile_attributes()
27 | breps = capsule_to_rhino_brep(self.geometry)
28 | transformation = transformation_to_rhino(self.worldtransformation)
29 | for geometry in breps:
30 | geometry.Transform(transformation)
31 |
32 | self._guids = [sc.doc.Objects.AddBrep(brep, attr) for brep in breps]
33 | return self.guids
34 |
--------------------------------------------------------------------------------
/src/compas_rhino/scene/circleobject.py:
--------------------------------------------------------------------------------
1 | from __future__ import absolute_import
2 | from __future__ import division
3 | from __future__ import print_function
4 |
5 | import scriptcontext as sc # type: ignore
6 |
7 | from compas.scene import GeometryObject
8 | from compas_rhino.conversions import circle_to_rhino
9 | from compas_rhino.conversions import transformation_to_rhino
10 |
11 | from .sceneobject import RhinoSceneObject
12 |
13 |
14 | class RhinoCircleObject(RhinoSceneObject, GeometryObject):
15 | """Scene object for drawing circles."""
16 |
17 | def draw(self):
18 | """Draw the circle.
19 |
20 | Returns
21 | -------
22 | list[System.Guid]
23 | List of GUIDs of the objects created in Rhino.
24 |
25 | """
26 | attr = self.compile_attributes()
27 | geometry = circle_to_rhino(self.geometry)
28 | geometry.Transform(transformation_to_rhino(self.worldtransformation))
29 |
30 | self._guids = [sc.doc.Objects.AddCircle(geometry, attr)]
31 | return self.guids
32 |
--------------------------------------------------------------------------------
/src/compas_rhino/scene/coneobject.py:
--------------------------------------------------------------------------------
1 | from __future__ import absolute_import
2 | from __future__ import division
3 | from __future__ import print_function
4 |
5 | import scriptcontext as sc # type: ignore
6 |
7 | from compas.scene import GeometryObject
8 | from compas_rhino.conversions import cone_to_rhino_brep
9 | from compas_rhino.conversions import transformation_to_rhino
10 |
11 | from .sceneobject import RhinoSceneObject
12 |
13 |
14 | class RhinoConeObject(RhinoSceneObject, GeometryObject):
15 | """Scene object for drawing cone shapes."""
16 |
17 | def draw(self):
18 | """Draw the cone associated with the scene object.
19 |
20 | Returns
21 | -------
22 | System.Guid
23 | The GUID of the object created in Rhino.
24 |
25 | """
26 | attr = self.compile_attributes()
27 | geometry = cone_to_rhino_brep(self.geometry)
28 | geometry.Transform(transformation_to_rhino(self.worldtransformation))
29 |
30 | self._guids = [sc.doc.Objects.AddBrep(geometry, attr)]
31 | return self.guids
32 |
--------------------------------------------------------------------------------
/src/compas_rhino/scene/curveobject.py:
--------------------------------------------------------------------------------
1 | from __future__ import absolute_import
2 | from __future__ import division
3 | from __future__ import print_function
4 |
5 | import scriptcontext as sc # type: ignore
6 |
7 | from compas.scene import GeometryObject
8 | from compas_rhino.conversions import curve_to_rhino
9 | from compas_rhino.conversions import transformation_to_rhino
10 |
11 | from .sceneobject import RhinoSceneObject
12 |
13 |
14 | class RhinoCurveObject(RhinoSceneObject, GeometryObject):
15 | """Scene object for drawing curves."""
16 |
17 | def draw(self):
18 | """Draw the curve.
19 |
20 | Returns
21 | -------
22 | list[System.Guid]
23 | List of GUIDs of the objects created in Rhino.
24 |
25 | """
26 | attr = self.compile_attributes()
27 | geometry = curve_to_rhino(self.geometry)
28 | geometry.Transform(transformation_to_rhino(self.worldtransformation))
29 |
30 | self._guids = [sc.doc.Objects.AddCurve(geometry, attr)]
31 | return self.guids
32 |
--------------------------------------------------------------------------------
/src/compas_rhino/scene/cylinderobject.py:
--------------------------------------------------------------------------------
1 | from __future__ import absolute_import
2 | from __future__ import division
3 | from __future__ import print_function
4 |
5 | import scriptcontext as sc # type: ignore
6 |
7 | from compas.scene import GeometryObject
8 | from compas_rhino.conversions import cylinder_to_rhino_brep
9 | from compas_rhino.conversions import transformation_to_rhino
10 |
11 | from .sceneobject import RhinoSceneObject
12 |
13 |
14 | class RhinoCylinderObject(RhinoSceneObject, GeometryObject):
15 | """Scene object for drawing cylinder shapes."""
16 |
17 | def draw(self):
18 | """Draw the cylinder associated with the scene object.
19 |
20 | Returns
21 | -------
22 | list[System.Guid]
23 | The GUIDs of the objects created in Rhino.
24 |
25 | """
26 | attr = self.compile_attributes()
27 | geometry = cylinder_to_rhino_brep(self.geometry)
28 | geometry.Transform(transformation_to_rhino(self.worldtransformation))
29 |
30 | self._guids = [sc.doc.Objects.AddBrep(geometry, attr)]
31 | return self.guids
32 |
--------------------------------------------------------------------------------
/src/compas_rhino/scene/ellipseobject.py:
--------------------------------------------------------------------------------
1 | from __future__ import absolute_import
2 | from __future__ import division
3 | from __future__ import print_function
4 |
5 | import scriptcontext as sc # type: ignore
6 |
7 | from compas.scene import GeometryObject
8 | from compas_rhino.conversions import ellipse_to_rhino
9 | from compas_rhino.conversions import transformation_to_rhino
10 |
11 | from .sceneobject import RhinoSceneObject
12 |
13 |
14 | class RhinoEllipseObject(RhinoSceneObject, GeometryObject):
15 | """Scene object for drawing ellipses."""
16 |
17 | def draw(self):
18 | """Draw the ellipse.
19 |
20 | Returns
21 | -------
22 | list[System.Guid]
23 | The GUIDs of the objects created in Rhino.
24 |
25 | """
26 | attr = self.compile_attributes()
27 | ellipse = ellipse_to_rhino(self.geometry)
28 | ellipse = ellipse.ToNurbsCurve()
29 | ellipse.Transform(transformation_to_rhino(self.worldtransformation))
30 |
31 | self._guids = [sc.doc.Objects.AddCurve(ellipse, attr)]
32 | return self.guids
33 |
--------------------------------------------------------------------------------
/src/compas_rhino/scene/helpers.py:
--------------------------------------------------------------------------------
1 | from __future__ import absolute_import
2 | from __future__ import division
3 | from __future__ import print_function
4 |
5 | import rhinoscriptsyntax as rs # type: ignore
6 | import scriptcontext as sc # type: ignore
7 |
8 | from compas_rhino.layers import create_layers_from_path
9 |
10 | try:
11 | find_layer_by_fullpath = sc.doc.Layers.FindByFullPath
12 | except SystemError:
13 | find_layer_by_fullpath = None
14 |
15 |
16 | def ensure_layer(layerpath):
17 | if not rs.IsLayer(layerpath):
18 | create_layers_from_path(layerpath)
19 | if find_layer_by_fullpath:
20 | index = find_layer_by_fullpath(layerpath, True)
21 | else:
22 | index = 0
23 | return index
24 |
25 |
26 | def ngon(v):
27 | if v < 3:
28 | return
29 | if v == 3:
30 | return [0, 1, 2]
31 | if v == 4:
32 | return [0, 1, 2, 3]
33 | return list(range(v))
34 |
--------------------------------------------------------------------------------
/src/compas_rhino/scene/lineobject.py:
--------------------------------------------------------------------------------
1 | from __future__ import absolute_import
2 | from __future__ import division
3 | from __future__ import print_function
4 |
5 | import scriptcontext as sc # type: ignore
6 |
7 | from compas.scene import GeometryObject
8 | from compas_rhino.conversions import line_to_rhino
9 | from compas_rhino.conversions import transformation_to_rhino
10 |
11 | from .sceneobject import RhinoSceneObject
12 |
13 |
14 | class RhinoLineObject(RhinoSceneObject, GeometryObject):
15 | """Scene object for drawing lines."""
16 |
17 | def draw(self):
18 | """Draw the line.
19 |
20 | Returns
21 | -------
22 | System.Guid
23 | The GUID of the created Rhino object.
24 |
25 | """
26 | attr = self.compile_attributes()
27 | geometry = line_to_rhino(self.geometry)
28 | geometry.Transform(transformation_to_rhino(self.worldtransformation))
29 |
30 | self._guids = [sc.doc.Objects.AddLine(geometry, attr)]
31 | return self.guids
32 |
--------------------------------------------------------------------------------
/src/compas_rhino/scene/pointobject.py:
--------------------------------------------------------------------------------
1 | from __future__ import absolute_import
2 | from __future__ import division
3 | from __future__ import print_function
4 |
5 | import scriptcontext as sc # type: ignore
6 |
7 | from compas.scene import GeometryObject
8 | from compas_rhino.conversions import point_to_rhino
9 | from compas_rhino.conversions import transformation_to_rhino
10 |
11 | from .sceneobject import RhinoSceneObject
12 |
13 |
14 | class RhinoPointObject(RhinoSceneObject, GeometryObject):
15 | """Scene object for drawing points."""
16 |
17 | def draw(self):
18 | """Draw the point.
19 |
20 | Returns
21 | -------
22 | list[System.Guid]
23 | List of GUIDs of the objects created in Rhino.
24 |
25 | """
26 | attr = self.compile_attributes()
27 | geometry = point_to_rhino(self.geometry)
28 | geometry.Transform(transformation_to_rhino(self.worldtransformation))
29 |
30 | self._guids = [sc.doc.Objects.AddPoint(geometry, attr)]
31 | return self.guids
32 |
--------------------------------------------------------------------------------
/src/compas_rhino/scene/polygonobject.py:
--------------------------------------------------------------------------------
1 | from __future__ import absolute_import
2 | from __future__ import division
3 | from __future__ import print_function
4 |
5 | import scriptcontext as sc # type: ignore
6 |
7 | from compas.scene import GeometryObject
8 | from compas_rhino.conversions import transformation_to_rhino
9 | from compas_rhino.conversions import vertices_and_faces_to_rhino
10 |
11 | from .sceneobject import RhinoSceneObject
12 |
13 |
14 | class RhinoPolygonObject(RhinoSceneObject, GeometryObject):
15 | """Scene object for drawing polygons."""
16 |
17 | def draw(self):
18 | """Draw the polygon.
19 |
20 | Returns
21 | -------
22 | list[System.Guid]
23 | List of GUIDs of the objects created in Rhino.
24 |
25 | """
26 | attr = self.compile_attributes()
27 | vertices = self.geometry.points
28 | faces = self.geometry.faces
29 | mesh = vertices_and_faces_to_rhino(vertices, faces)
30 | mesh.Transform(transformation_to_rhino(self.worldtransformation))
31 |
32 | self._guids = [sc.doc.Objects.AddMesh(mesh, attr)]
33 | return self.guids
34 |
--------------------------------------------------------------------------------
/src/compas_rhino/scene/polyhedronobject.py:
--------------------------------------------------------------------------------
1 | from __future__ import absolute_import
2 | from __future__ import division
3 | from __future__ import print_function
4 |
5 | import scriptcontext as sc # type: ignore
6 |
7 | from compas.scene import GeometryObject
8 | from compas_rhino.conversions import transformation_to_rhino
9 | from compas_rhino.conversions import vertices_and_faces_to_rhino
10 |
11 | from .sceneobject import RhinoSceneObject
12 |
13 |
14 | class RhinoPolyhedronObject(RhinoSceneObject, GeometryObject):
15 | """Scene object for drawing polyhedron shapes."""
16 |
17 | def draw(self):
18 | """Draw the polyhedron associated with the scene object.
19 |
20 | Returns
21 | -------
22 | list[System.Guid]
23 | The GUIDs of the objects created in Rhino.
24 |
25 | """
26 | attr = self.compile_attributes()
27 | vertices = [list(vertex) for vertex in self.geometry.vertices]
28 | faces = self.geometry.faces
29 | geometry = vertices_and_faces_to_rhino(vertices, faces)
30 | geometry.Transform(transformation_to_rhino(self.worldtransformation))
31 |
32 | self._guids = [sc.doc.Objects.AddMesh(geometry, attr)]
33 | return self.guids
34 |
--------------------------------------------------------------------------------
/src/compas_rhino/scene/polylineobject.py:
--------------------------------------------------------------------------------
1 | from __future__ import absolute_import
2 | from __future__ import division
3 | from __future__ import print_function
4 |
5 | import scriptcontext as sc # type: ignore
6 |
7 | from compas.scene import GeometryObject
8 | from compas_rhino.conversions import polyline_to_rhino
9 | from compas_rhino.conversions import transformation_to_rhino
10 |
11 | from .sceneobject import RhinoSceneObject
12 |
13 |
14 | class RhinoPolylineObject(RhinoSceneObject, GeometryObject):
15 | """Scene object for drawing polylines."""
16 |
17 | def draw(self):
18 | """Draw the polyline.
19 |
20 | Returns
21 | -------
22 | list[System.Guid]
23 | List of GUIDs of the objects created in Rhino.
24 |
25 | """
26 | attr = self.compile_attributes()
27 | geometry = polyline_to_rhino(self.geometry)
28 | geometry.Transform(transformation_to_rhino(self.worldtransformation))
29 |
30 | self._guids = [sc.doc.Objects.AddPolyline(geometry, attr)]
31 | return self.guids
32 |
--------------------------------------------------------------------------------
/src/compas_rhino/scene/sphereobject.py:
--------------------------------------------------------------------------------
1 | from __future__ import absolute_import
2 | from __future__ import division
3 | from __future__ import print_function
4 |
5 | import scriptcontext as sc # type: ignore
6 |
7 | from compas.scene import GeometryObject
8 | from compas_rhino.conversions import sphere_to_rhino
9 | from compas_rhino.conversions import transformation_to_rhino
10 |
11 | from .sceneobject import RhinoSceneObject
12 |
13 |
14 | class RhinoSphereObject(RhinoSceneObject, GeometryObject):
15 | """Scene object for drawing sphere shapes."""
16 |
17 | def draw(self):
18 | """Draw the sphere associated with the scene object.
19 |
20 | Returns
21 | -------
22 | list[System.Guid]
23 | The GUIDs of the objects created in Rhino.
24 |
25 | """
26 | attr = self.compile_attributes()
27 | geometry = sphere_to_rhino(self.geometry)
28 | geometry.Transform(transformation_to_rhino(self.worldtransformation))
29 |
30 | self._guids = [sc.doc.Objects.AddSphere(geometry, attr)]
31 | return self.guids
32 |
--------------------------------------------------------------------------------
/src/compas_rhino/scene/surfaceobject.py:
--------------------------------------------------------------------------------
1 | from __future__ import absolute_import
2 | from __future__ import division
3 | from __future__ import print_function
4 |
5 | import scriptcontext as sc # type: ignore
6 |
7 | from compas.scene import GeometryObject
8 | from compas_rhino.conversions import surface_to_rhino
9 | from compas_rhino.conversions import transformation_to_rhino
10 |
11 | from .sceneobject import RhinoSceneObject
12 |
13 |
14 | class RhinoSurfaceObject(RhinoSceneObject, GeometryObject):
15 | """Scene object for drawing surfaces."""
16 |
17 | def draw(self):
18 | """Draw the surface.
19 |
20 | Returns
21 | -------
22 | list[System.Guid]
23 | The GUIDs of the objects created in Rhino.
24 |
25 | """
26 | attr = self.compile_attributes()
27 | surface = surface_to_rhino(self.geometry)
28 | surface.Transform(transformation_to_rhino(self.worldtransformation))
29 | self._guids = [sc.doc.Objects.AddSurface(surface, attr)]
30 | return self.guids
31 |
--------------------------------------------------------------------------------
/src/compas_rhino/scene/torusobject.py:
--------------------------------------------------------------------------------
1 | from __future__ import absolute_import
2 | from __future__ import division
3 | from __future__ import print_function
4 |
5 | import scriptcontext as sc # type: ignore
6 |
7 | from compas.scene import GeometryObject
8 | from compas_rhino.conversions import torus_to_rhino_brep
9 | from compas_rhino.conversions import transformation_to_rhino
10 |
11 | from .sceneobject import RhinoSceneObject
12 |
13 |
14 | class RhinoTorusObject(RhinoSceneObject, GeometryObject):
15 | """Scene object for drawing torus shapes."""
16 |
17 | def draw(self):
18 | """Draw the torus associated with the scene object.
19 |
20 | Returns
21 | -------
22 | list[System.Guid]
23 | The GUIDs of the objects created in Rhino.
24 |
25 | """
26 | attr = self.compile_attributes()
27 | brep = torus_to_rhino_brep(self.geometry)
28 | brep.Transform(transformation_to_rhino(self.worldtransformation))
29 |
30 | self._guids = [sc.doc.Objects.AddBrep(brep, attr)]
31 | return self.guids
32 |
--------------------------------------------------------------------------------
/src/compas_rhino/scene/vectorobject.py:
--------------------------------------------------------------------------------
1 | from __future__ import absolute_import
2 | from __future__ import division
3 | from __future__ import print_function
4 |
5 | import scriptcontext as sc # type: ignore
6 |
7 | from compas.geometry import Point
8 | from compas.scene import GeometryObject
9 | from compas_rhino.conversions import point_to_rhino
10 | from compas_rhino.conversions import transformation_to_rhino
11 |
12 | from .sceneobject import RhinoSceneObject
13 |
14 |
15 | class RhinoVectorObject(RhinoSceneObject, GeometryObject):
16 | """Scene object for drawing vectors."""
17 |
18 | def draw(self):
19 | """Draw the vector.
20 |
21 | Returns
22 | -------
23 | list[System.Guid]
24 | List of GUIDs of the objects created in Rhino.
25 |
26 | """
27 | attr = self.compile_attributes(arrow="end")
28 | start = Point(0, 0, 0)
29 | end = start + self.geometry
30 | start_geometry = point_to_rhino(start)
31 | end_geometry = point_to_rhino(end)
32 | transformation = transformation_to_rhino(self.worldtransformation)
33 | start_geometry.Transform(transformation)
34 | end_geometry.Transform(transformation)
35 |
36 | self._guids = [sc.doc.Objects.AddLine(start_geometry, end_geometry, attr)]
37 | return self.guids
38 |
--------------------------------------------------------------------------------
/src/compas_rhino/utilities/__init__.py:
--------------------------------------------------------------------------------
1 | from __future__ import absolute_import
2 | from warnings import warn
3 |
4 | from ..drawing import (
5 | draw_labels,
6 | draw_points,
7 | draw_lines,
8 | draw_geodesics,
9 | draw_polylines,
10 | draw_breps,
11 | draw_faces,
12 | draw_cylinders,
13 | draw_pipes,
14 | draw_spheres,
15 | draw_mesh,
16 | draw_circles,
17 | draw_curves,
18 | draw_surfaces,
19 | draw_brep,
20 | )
21 |
22 | __all__ = [
23 | "draw_labels",
24 | "draw_points",
25 | "draw_lines",
26 | "draw_geodesics",
27 | "draw_polylines",
28 | "draw_breps",
29 | "draw_faces",
30 | "draw_cylinders",
31 | "draw_pipes",
32 | "draw_spheres",
33 | "draw_mesh",
34 | "draw_circles",
35 | "draw_curves",
36 | "draw_surfaces",
37 | "draw_brep",
38 | ]
39 |
40 | warn("compas_rhino.utilities will be removed in version 2.3. Please use compas_rhino.drawing instead.", DeprecationWarning, stacklevel=2)
41 |
--------------------------------------------------------------------------------
/tasks.py:
--------------------------------------------------------------------------------
1 | from __future__ import print_function
2 |
3 | import os
4 |
5 | from compas_invocations2 import build
6 | from compas_invocations2 import docs
7 | from compas_invocations2 import style
8 | from compas_invocations2 import tests
9 | from compas_invocations2 import grasshopper
10 | from invoke import Collection
11 |
12 | ns = Collection(
13 | docs.help,
14 | style.check,
15 | style.lint,
16 | style.format,
17 | docs.docs,
18 | docs.linkcheck,
19 | tests.test,
20 | tests.testdocs,
21 | tests.testcodeblocks,
22 | build.prepare_changelog,
23 | build.clean,
24 | build.release,
25 | build.build_ghuser_components,
26 | build.build_cpython_ghuser_components,
27 | grasshopper.yakerize,
28 | grasshopper.publish_yak,
29 | )
30 | ns.configure(
31 | {
32 | "base_folder": os.path.dirname(__file__),
33 | "ghuser": {
34 | "source_dir": "src/compas_ghpython/components",
35 | "target_dir": "src/compas_ghpython/components/ghuser",
36 | "prefix": "COMPAS: ",
37 | },
38 | "ghuser_cpython": {
39 | "source_dir": "src/compas_ghpython/components_cpython",
40 | "target_dir": "src/compas_ghpython/components_cpython/ghuser",
41 | "prefix": "COMPAS: ",
42 | },
43 | }
44 | )
45 |
--------------------------------------------------------------------------------
/tests/compas/colors/test_colordict.py:
--------------------------------------------------------------------------------
1 | import compas
2 |
3 | from compas.colors import Color
4 | from compas.colors import ColorDict
5 |
6 |
7 | def test_colordict():
8 | cd = ColorDict(Color.red())
9 | assert cd.default == Color.red()
10 |
11 | cd = ColorDict((255, 0, 0))
12 | assert cd.default == Color.red()
13 |
14 | cd = ColorDict((1.0, 0.0, 0.0))
15 | assert cd.default == Color.red()
16 |
17 |
18 | def test_colordict_keys():
19 | cd = ColorDict(Color.red())
20 | cd[1] = Color.blue()
21 | cd[(1, 0)] = Color.green()
22 |
23 | assert cd[1] == Color.blue()
24 | assert cd["1"] == Color.blue()
25 |
26 | assert cd[(1, 0)] == Color.green()
27 | assert cd["0,1"] == Color.green()
28 |
29 | assert cd["1,0"] == Color.red()
30 |
31 |
32 | def test_colordict_json():
33 | cd1 = ColorDict(Color.red())
34 | cd1[1] = Color.blue()
35 | cd1[(1, 0)] = Color.green()
36 |
37 | cd2 = compas.json_loads(compas.json_dumps(cd1))
38 |
39 | assert cd2[1] == Color.blue()
40 | assert cd2["1"] == Color.blue()
41 |
42 | assert cd2[(1, 0)] == Color.green()
43 | assert cd2["0,1"] == Color.green()
44 |
45 | assert cd2["1,0"] == Color.red()
46 |
--------------------------------------------------------------------------------
/tests/compas/data/test_data.py:
--------------------------------------------------------------------------------
1 | from compas.data import Data
2 |
3 |
4 | def test_string_casting():
5 | class TestClass(Data):
6 | def __init__(self, i):
7 | self.i = i
8 |
9 | def __str__(self):
10 | return "TestClass {}".format(self.i)
11 |
12 | test = TestClass(42)
13 | assert str(test) == "TestClass 42"
14 |
--------------------------------------------------------------------------------
/tests/compas/data/test_json_dotnet.py:
--------------------------------------------------------------------------------
1 | import compas
2 |
3 | try:
4 | import System # type: ignore
5 |
6 | def test_decimal():
7 | before = System.Decimal(100.0)
8 |
9 | after = compas.json_loads(compas.json_dumps(before))
10 | assert after == 100.0
11 |
12 | except ImportError:
13 | pass
14 |
--------------------------------------------------------------------------------
/tests/compas/data/test_json_numpy.py:
--------------------------------------------------------------------------------
1 | import compas
2 |
3 | try:
4 | import numpy as np
5 |
6 | def test_json_numpy():
7 | before = [
8 | np.array([1, 2, 3]),
9 | np.array([1.0, 2.0, 3.0]),
10 | np.float64(1.0),
11 | np.int32(1),
12 | ]
13 | after = compas.json_loads(compas.json_dumps(before))
14 | assert after == [[1, 2, 3], [1.0, 2.0, 3.0], 1.0, 1]
15 |
16 | except ImportError:
17 | pass
18 |
19 |
20 | try:
21 | import numpy as np
22 |
23 | try:
24 | np_float = np.float_
25 | except AttributeError:
26 | np_float = np.float64
27 |
28 | def test_json_numpy_float():
29 | before = [
30 | np.array([1, 2, 3], dtype=np_float),
31 | np.array([1.0, 2.0, 3.0]),
32 | np_float(1.0),
33 | ]
34 | after = compas.json_loads(compas.json_dumps(before))
35 | assert after == [[1, 2, 3], [1.0, 2.0, 3.0], 1.0]
36 |
37 | except ImportError:
38 | pass
39 |
--------------------------------------------------------------------------------
/tests/compas/data/test_pickle.py:
--------------------------------------------------------------------------------
1 | import pickle
2 | from compas.geometry import Frame
3 |
4 |
5 | def test_pickling():
6 | f1 = Frame.worldXY()
7 | s = pickle.dumps(f1, protocol=pickle.HIGHEST_PROTOCOL)
8 | f2 = pickle.loads(s)
9 | assert all(a == b for a, b in zip(f1.point, f2.point))
10 | assert all(a == b for a, b in zip(f1.xaxis, f2.xaxis))
11 | assert all(a == b for a, b in zip(f1.yaxis, f2.yaxis))
12 | assert all(a == b for a, b in zip(f1.zaxis, f2.zaxis))
13 | assert f1.guid == f2.guid
14 |
--------------------------------------------------------------------------------
/tests/compas/datastructures/fixtures/non-planar.obj:
--------------------------------------------------------------------------------
1 | v 0.0 0.0 0.0
2 | v 1.0 0.0 0.0
3 | v 1.0 1.0 0.0
4 | v 0.0 1.0 0.0
5 | v 0.5 0.5 1.0
6 | l 1 2
7 | l 2 3
8 | l 3 4
9 | l 4 1
10 | l 1 3
11 | l 2 4
12 | l 1 5
13 | l 2 5
14 | l 3 5
15 | l 4 5
16 |
--------------------------------------------------------------------------------
/tests/compas/datastructures/fixtures/planar.obj:
--------------------------------------------------------------------------------
1 | v 0.0 0.0 0.0
2 | v 1.0 0.0 0.0
3 | v 1.0 1.0 0.0
4 | v 0.0 1.0 0.0
5 | l 1 2
6 | l 2 3
7 | l 3 4
8 | l 4 1
9 | l 1 3
10 | l 2 4
11 |
--------------------------------------------------------------------------------
/tests/compas/datastructures/test_hashtree.py:
--------------------------------------------------------------------------------
1 | from compas.datastructures import HashTree
2 | from compas.datastructures import Mesh
3 |
4 |
5 | def test_hashtree_from_dict():
6 | tree1 = HashTree.from_dict({"a": {"b": 1, "c": 3}, "d": [1, 2, 3], "e": 2})
7 | tree2 = HashTree.from_dict({"a": {"b": 1, "c": 2}, "d": [1, 2, 3], "f": 2})
8 | diff = tree2.diff(tree1)
9 |
10 | assert diff["added"] == [{"path": ".f", "value": 2}]
11 | assert diff["removed"] == [{"path": ".e", "value": 2}]
12 | assert diff["modified"] == [{"path": ".a.c", "old": 3, "new": 2}]
13 |
14 |
15 | def test_hashtree_from_mesh():
16 | mesh = Mesh.from_polyhedron(4)
17 | tree1 = HashTree.from_object(mesh)
18 | mesh.vertex_attribute(0, "x", 1.0)
19 | mesh.delete_face(3)
20 | tree2 = HashTree.from_object(mesh)
21 | diff = tree2.diff(tree1)
22 |
23 | assert diff["added"] == []
24 | assert diff["removed"] == [{"path": ".face.3", "value": [1, 3, 2]}, {"path": ".facedata.3", "value": None}]
25 | assert diff["modified"] == [{"path": ".vertex.0.x", "old": -0.8164965809277261, "new": 1.0}]
26 |
--------------------------------------------------------------------------------
/tests/compas/files/fixtures/gltf/AnimatedMorphCube.glb:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/compas-dev/compas/96c2ea7a5d7f799b6c8846690a19c464a6dee41e/tests/compas/files/fixtures/gltf/AnimatedMorphCube.glb
--------------------------------------------------------------------------------
/tests/compas/files/fixtures/gltf/BoxInterleaved.glb:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/compas-dev/compas/96c2ea7a5d7f799b6c8846690a19c464a6dee41e/tests/compas/files/fixtures/gltf/BoxInterleaved.glb
--------------------------------------------------------------------------------
/tests/compas/files/fixtures/gltf/BoxTextured.glb:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/compas-dev/compas/96c2ea7a5d7f799b6c8846690a19c464a6dee41e/tests/compas/files/fixtures/gltf/BoxTextured.glb
--------------------------------------------------------------------------------
/tests/compas/files/fixtures/gltf/SpecGlossVsMetalRough.glb:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/compas-dev/compas/96c2ea7a5d7f799b6c8846690a19c464a6dee41e/tests/compas/files/fixtures/gltf/SpecGlossVsMetalRough.glb
--------------------------------------------------------------------------------
/tests/compas/files/fixtures/gltf/SpecularTest.glb:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/compas-dev/compas/96c2ea7a5d7f799b6c8846690a19c464a6dee41e/tests/compas/files/fixtures/gltf/SpecularTest.glb
--------------------------------------------------------------------------------
/tests/compas/files/fixtures/gltf/TriangleWithoutIndices.gltf:
--------------------------------------------------------------------------------
1 | {
2 | "scene" : 0,
3 | "scenes" : [
4 | {
5 | "nodes" : [ 0 ]
6 | }
7 | ],
8 |
9 | "nodes" : [
10 | {
11 | "mesh" : 0
12 | }
13 | ],
14 |
15 | "meshes" : [
16 | {
17 | "primitives" : [ {
18 | "attributes" : {
19 | "POSITION" : 0
20 | }
21 | } ]
22 | }
23 | ],
24 |
25 | "buffers" : [
26 | {
27 | "uri" : "data:application/octet-stream;base64,AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAA",
28 | "byteLength" : 36
29 | }
30 | ],
31 | "bufferViews" : [
32 | {
33 | "buffer" : 0,
34 | "byteOffset" : 0,
35 | "byteLength" : 36,
36 | "target" : 34962
37 | }
38 | ],
39 | "accessors" : [
40 | {
41 | "bufferView" : 0,
42 | "byteOffset" : 0,
43 | "componentType" : 5126,
44 | "count" : 3,
45 | "type" : "VEC3",
46 | "max" : [ 1.0, 1.0, 0.0 ],
47 | "min" : [ 0.0, 0.0, 0.0 ]
48 | }
49 | ],
50 |
51 | "asset" : {
52 | "version" : "2.0"
53 | }
54 | }
--------------------------------------------------------------------------------
/tests/compas/files/fixtures/gltf/triangle.bin:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/compas-dev/compas/96c2ea7a5d7f799b6c8846690a19c464a6dee41e/tests/compas/files/fixtures/gltf/triangle.bin
--------------------------------------------------------------------------------
/tests/compas/files/fixtures/stl/binary-1.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/compas-dev/compas/96c2ea7a5d7f799b6c8846690a19c464a6dee41e/tests/compas/files/fixtures/stl/binary-1.stl
--------------------------------------------------------------------------------
/tests/compas/files/fixtures/stl/binary-2.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/compas-dev/compas/96c2ea7a5d7f799b6c8846690a19c464a6dee41e/tests/compas/files/fixtures/stl/binary-2.stl
--------------------------------------------------------------------------------
/tests/compas/files/fixtures/triangle_binary.ply:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/compas-dev/compas/96c2ea7a5d7f799b6c8846690a19c464a6dee41e/tests/compas/files/fixtures/triangle_binary.ply
--------------------------------------------------------------------------------
/tests/compas/files/fixtures/xml/basic.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Convert number to string
5 | Examp1.EXE
6 | 1
7 |
8 |
9 |
10 | Find succeeding characters
11 | Examp2.EXE
12 | abc
13 |
14 |
15 |
16 | Convert multiple numbers to strings
17 | Examp2.EXE /Verbose
18 | 123
19 |
20 |
21 |
22 | Find correlated key
23 | Examp3.EXE
24 | a1
25 |
26 |
27 |
28 | Count characters
29 | FinalExamp.EXE
30 | This is a test
31 |
32 |
33 |
34 | Another Test
35 | Examp2.EXE
36 | Test Input
37 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/tests/compas/files/fixtures/xml/default_nested_namespace.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/tests/compas/files/fixtures/xml/namespaces.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | -
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/tests/compas/fixtures/iotools/image.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/compas-dev/compas/96c2ea7a5d7f799b6c8846690a19c464a6dee41e/tests/compas/fixtures/iotools/image.png
--------------------------------------------------------------------------------
/tests/compas/fixtures/iotools/text.txt:
--------------------------------------------------------------------------------
1 | Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec erat turpis, condimentum eu elementum ut, scelerisque a tellus. Sed ac
2 | maximus felis. Proin ac libero ultricies, hendrerit ipsum nec, rutrum sem. Nam eu erat laoreet ex cursus iaculis sed eu nibh. In vel
3 | lobortis ipsum. Nam augue ligula, sollicitudin in imperdiet vel, sollicitudin in dui. Ut elementum rhoncus diam, vitae luctus metus
4 | sollicitudin ac. Vivamus diam lectus, scelerisque in dignissim vel, convallis non ligula. Suspendisse tellus nunc, egestas tempor laoreet
5 | tincidunt, tempor ut ante. Nulla interdum rutrum tellus ultricies lacinia. Etiam risus ligula, consequat vitae enim euismod, tincidunt
6 | congue eros. Integer ut quam accumsan, vestibulum lorem ac, aliquet lorem.
7 |
--------------------------------------------------------------------------------
/tests/compas/geometry/test_capsule.py:
--------------------------------------------------------------------------------
1 | import pytest
2 |
3 | from compas.geometry import Capsule
4 |
5 |
6 | @pytest.fixture
7 | def capsule():
8 | return Capsule(123.0, 13.0)
9 |
10 |
11 | def test_capsule_discretization(capsule):
12 | # just checking these don't break. Could not quickly find a formula that worked to test the actual values
13 | # as function of the resolution
14 | assert capsule.edges
15 | assert capsule.faces
16 | assert capsule.vertices
17 |
--------------------------------------------------------------------------------
/tests/compas/geometry/test_cone.py:
--------------------------------------------------------------------------------
1 | import pytest
2 |
3 | from compas.geometry import Cone
4 |
5 |
6 | @pytest.fixture
7 | def cone():
8 | return Cone(432.0, 123.0)
9 |
10 |
11 | def test_cone_discretization(cone):
12 | # just checking these don't break. Could not quickly find a formula that worked to test the actual values
13 | # as function of the resolution
14 | assert cone.edges
15 | assert cone.faces
16 | assert cone.vertices
17 |
--------------------------------------------------------------------------------
/tests/compas/geometry/test_core_distance.py:
--------------------------------------------------------------------------------
1 | import pytest
2 |
3 | from compas.geometry import Point
4 | from compas.geometry import Line
5 | from compas.geometry import closest_point_on_segment_xy
6 |
7 |
8 | @pytest.mark.parametrize("point,point_on_line", [[[0, 0, -10], [1, 1, 0]], [[5, 4, 80], [4.5, 4.5, 0]]])
9 | def test_closest_point_segment_xy(point, point_on_line):
10 | line = Line([1, 1, -15], [10, 10, 20])
11 | ponl = closest_point_on_segment_xy(Point(*point), line)
12 | assert ponl == Point(*point_on_line)
13 |
--------------------------------------------------------------------------------
/tests/compas/geometry/test_core_predicates_3.py:
--------------------------------------------------------------------------------
1 | from compas.geometry import is_coplanar
2 | import pytest
3 |
4 |
5 | def test_is_coplanar():
6 | # 4 points that are colinear:
7 | points = [[0, 0, 0], [0, 1, 0], [0, 2, 0], [0, 4, 0]]
8 |
9 | try:
10 | is_coplanar(points)
11 | except IndexError:
12 | pytest.fail("is_coplanar raised an IndexError")
13 |
--------------------------------------------------------------------------------
/tests/compas/geometry/test_core_queries.py:
--------------------------------------------------------------------------------
1 | from compas.geometry import Line
2 | from compas.geometry import Point
3 | from compas.geometry import is_colinear_line_line
4 |
5 |
6 | def test_is_colinear_line_line():
7 | assert is_colinear_line_line(Line(Point(0, 0, 0), Point(1, 1, 1)), Line(Point(3, 3, 3), Point(2, 2, 2))) is True
8 | assert is_colinear_line_line(Line(Point(0, 0, 0), Point(1, 1, 1)), Line(Point(4, 1, 0), Point(5, 2, 1))) is False
9 |
--------------------------------------------------------------------------------
/tests/compas/geometry/test_core_tangent.py:
--------------------------------------------------------------------------------
1 | from compas.tolerance import TOL
2 | from compas.geometry import tangent_points_to_circle_xy
3 |
4 |
5 | def test_tangent_points_to_circle_xy():
6 | circle = ((0.0, 0.0, 0.0), (0.0, 0.0, 1.0)), 1.0
7 | point = (2.0, 4.0, 0.0)
8 | t1, t2 = tangent_points_to_circle_xy(circle, point)
9 | assert TOL.is_allclose(t1, (-0.772, 0.636, 0.000), atol=1e-3)
10 | assert TOL.is_allclose(t2, (0.972, -0.236, 0.000), atol=1e-3)
11 |
--------------------------------------------------------------------------------
/tests/compas/geometry/test_core_transformations_numpy.py:
--------------------------------------------------------------------------------
1 | # numpy helper will be created separated first
2 |
--------------------------------------------------------------------------------
/tests/compas/geometry/test_cylinder.py:
--------------------------------------------------------------------------------
1 | import pytest
2 | from compas.geometry import Cylinder
3 |
4 |
5 | @pytest.fixture
6 | def cylinder():
7 | return Cylinder(radius=0.3, height=1.6)
8 |
9 |
10 | def test_cylinder_discretization(cylinder):
11 | # just checking these don't break. Could not quickly find a formula that worked to test the actual values
12 | # as function of the resolution
13 | assert cylinder.edges
14 | assert cylinder.faces
15 | assert cylinder.vertices
16 |
--------------------------------------------------------------------------------
/tests/compas/geometry/test_intersections.py:
--------------------------------------------------------------------------------
1 | from compas.tolerance import TOL
2 | from compas.geometry import intersection_sphere_line
3 | from compas.geometry import intersection_plane_circle
4 | from compas.geometry import intersection_circle_circle_xy
5 |
6 |
7 | def test_intersection_sphere_line():
8 | sphere = (3.0, 7.0, 4.0), 10.0
9 | line = (1.0, 0, 0.5), (2.0, 1.0, 0.5)
10 | ipt1, ipt2 = intersection_sphere_line(sphere, line)
11 | assert TOL.is_allclose(ipt1, (11.634, 10.634, 0.500), atol=1e-3)
12 | assert TOL.is_allclose(ipt2, (-0.634, -1.634, 0.500), atol=1e-3)
13 |
14 |
15 | def test_intersection_plane_circle():
16 | plane = (0, 0, 0), (0, 0, 1)
17 | circle = ((3.0, 7.0, 4.0), (0, 1, 0)), 10.0
18 | ipt1, ipt2 = intersection_plane_circle(plane, circle)
19 | assert TOL.is_allclose(ipt1, (-6.165, 7.000, 0.000), atol=1e-3)
20 | assert TOL.is_allclose(ipt2, (12.165, 7.000, 0.000), atol=1e-3)
21 |
22 |
23 | def test_intersection_circle_circle_xy():
24 | circle1 = ((0.0, 0.0, 0.0), (0, 0, 1)), 10.0
25 | circle2 = ((3.0, 7.0, 0.0), (0, 0, 1)), 10.0
26 | ipt1, ipt2 = intersection_circle_circle_xy(circle1, circle2)
27 | assert TOL.is_allclose(ipt1, (9.999, -0.142, 0.000), atol=1e-3)
28 | assert TOL.is_allclose(ipt2, (-6.999, 7.142, 0.000), atol=1e-3)
29 |
--------------------------------------------------------------------------------
/tests/compas/geometry/test_polyhedron.py:
--------------------------------------------------------------------------------
1 | from compas.geometry import Polyhedron
2 | from compas.itertools import pairwise
3 |
4 |
5 | def test_polyhedron():
6 | vertices = [[0, 0, 0], [1, 0, 0], [1, 1, 0], [0, 1, 0]]
7 | faces = [[0, 1, 2, 3]]
8 | name = "Test Polyhedron"
9 | polyhedron = Polyhedron(vertices, faces, name)
10 |
11 | assert polyhedron.vertices == vertices
12 | assert polyhedron.faces == faces
13 | assert polyhedron.name == name
14 | assert all(u < len(polyhedron.vertices) and v < len(polyhedron.vertices) for u, v in polyhedron.edges)
15 | assert all(v < len(polyhedron.vertices) for face in polyhedron.faces for v in face)
16 | assert polyhedron.points == vertices
17 | assert polyhedron.lines == [(a, b) for a, b in pairwise(vertices[-1:] + vertices)]
18 | assert polyhedron.points[0] == vertices[0]
19 | assert polyhedron.points[-1] != polyhedron.points[0]
20 |
--------------------------------------------------------------------------------
/tests/compas/geometry/test_shpere.py:
--------------------------------------------------------------------------------
1 | import pytest
2 |
3 | from compas.geometry import Frame
4 | from compas.geometry import Sphere
5 |
6 |
7 | @pytest.fixture
8 | def sphere():
9 | return Sphere(450.0, Frame.worldXY())
10 |
11 |
12 | def test_sphere_discretization(sphere):
13 | expected_face_count = sphere.resolution_v * sphere.resolution_u
14 | expected_vertex_count = (sphere.resolution_v - 1) * sphere.resolution_u + 2
15 | expected_edge_count = expected_face_count * 2 - sphere.resolution_u
16 |
17 | assert len(sphere.edges) == expected_edge_count
18 | assert len(sphere.faces) == expected_face_count
19 | assert len(sphere.vertices) == expected_vertex_count
20 |
--------------------------------------------------------------------------------
/tests/compas/geometry/test_transformations/test_reflection.py:
--------------------------------------------------------------------------------
1 | from compas.geometry import Frame
2 | from compas.geometry import Reflection
3 | from compas.geometry import Transformation
4 |
5 |
6 | def test_reflection():
7 | point = [1, 1, 1]
8 | normal = [0, 0, 1]
9 | plane = point, normal
10 | R1 = Reflection.from_plane(plane)
11 | R2 = Transformation([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, -1, 2], [0, 0, 0, 1]])
12 | assert R1 == R2
13 |
14 |
15 | def test_reflection_from_frame():
16 | point = [1, 1, 1]
17 | x = [1, 0, 0]
18 | y = [0, 1, 0]
19 |
20 | f = Frame(point, x, y)
21 | R1 = Reflection.from_frame(f)
22 | R2 = Transformation([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, -1, 2], [0, 0, 0, 1]])
23 | assert R1 == R2
24 |
--------------------------------------------------------------------------------
/tests/compas/geometry/test_transformations/test_scale.py:
--------------------------------------------------------------------------------
1 | from compas.geometry import Scale
2 | from compas.geometry import Frame
3 |
4 |
5 | def test_scale():
6 | S = Scale.from_factors([1, 2, 3])
7 | assert S.matrix == [
8 | [1.0, 0.0, 0.0, 0.0],
9 | [0.0, 2.0, 0.0, 0.0],
10 | [0.0, 0.0, 3.0, 0.0],
11 | [0.0, 0.0, 0.0, 1.0],
12 | ]
13 |
14 | S = Scale.from_factors([2.0] * 3, Frame((2, 5, 0), (1, 0, 0), (0, 1, 0)))
15 | assert S.matrix == [
16 | [2.0, 0.0, 0.0, -2.0],
17 | [0.0, 2.0, 0.0, -5.0],
18 | [0.0, 0.0, 2.0, 0.0],
19 | [0.0, 0.0, 0.0, 1.0],
20 | ]
21 |
--------------------------------------------------------------------------------
/tests/compas/geometry/test_transformations/test_shear.py:
--------------------------------------------------------------------------------
1 | from compas.geometry import Shear
2 | from compas.tolerance import TOL
3 |
4 |
5 | def test_shear():
6 | angle = 1
7 | direction = [1, 0, 0]
8 | point = [1, 1, 1]
9 | normal = [0, 0, 1]
10 | S = Shear.from_angle_direction_plane(angle, direction, (point, normal))
11 | s = [
12 | [1.0, 0.0, 1.557407724654902, -1.557407724654902],
13 | [0.0, 1.0, 0.0, -0.0],
14 | [0.0, 0.0, 1.0, -0.0],
15 | [0.0, 0.0, 0.0, 1.0],
16 | ]
17 | assert TOL.is_allclose(S.matrix, s)
18 |
19 |
20 | def test_from_entries():
21 | shear1 = [-0.41, -0.14, -0.35]
22 | S = Shear.from_entries(shear1)
23 | s = [
24 | [1.0, -0.41, -0.14, 0.0],
25 | [0.0, 1.0, -0.35, 0.0],
26 | [0.0, 0.0, 1.0, 0.0],
27 | [0.0, 0.0, 0.0, 1.0],
28 | ]
29 | assert TOL.is_allclose(S.matrix, s)
30 |
--------------------------------------------------------------------------------
/tests/compas/geometry/test_transformations/test_translation.py:
--------------------------------------------------------------------------------
1 | from compas.geometry import Translation
2 |
3 |
4 | def test_translation():
5 | T = Translation.from_vector([1, 2, 3])
6 | assert T.matrix == [
7 | [1.0, 0.0, 0.0, 1.0],
8 | [0.0, 1.0, 0.0, 2.0],
9 | [0.0, 0.0, 1.0, 3.0],
10 | [0.0, 0.0, 0.0, 1.0],
11 | ]
12 |
--------------------------------------------------------------------------------
/tests/compas/rpc/test_rpc.py:
--------------------------------------------------------------------------------
1 | # import os
2 |
3 | from compas.tolerance import TOL
4 | from compas.rpc import Proxy
5 |
6 |
7 | def test_basic_rpc_call():
8 | with Proxy("numpy", python="python") as proxy:
9 | assert proxy.arange(20) == list(range(20))
10 |
11 |
12 | def test_switch_package():
13 | with Proxy("numpy", python="python") as proxy:
14 | A = proxy.array([[1, 2], [3, 4]])
15 |
16 | proxy.package = "scipy.linalg"
17 | r = proxy.inv(A)
18 |
19 | assert TOL.is_allclose(r, [[-2, 1], [1.5, -0.5]])
20 |
--------------------------------------------------------------------------------
/tests/compas/test_tolerance.py:
--------------------------------------------------------------------------------
1 | from compas.tolerance import TOL
2 | from compas.tolerance import Tolerance
3 | from compas.geometry import Point
4 |
5 |
6 | def test_tolerance_default_tolerance():
7 | assert TOL.precision == Tolerance.PRECISION
8 | assert TOL.precision == 3
9 |
10 |
11 | def test_tolerance_format_number():
12 | assert TOL.format_number(0, precision=3) == "0.000"
13 | assert TOL.format_number(0.5, precision=3) == "0.500"
14 | assert TOL.format_number(float(0), precision=3) == "0.000"
15 |
16 |
17 | def test_tolerance_format_number_with_default_precision():
18 | assert TOL.format_number(0) == "0.000"
19 | assert TOL.format_number(0.5) == "0.500"
20 | assert TOL.format_number(float(0)) == "0.000"
21 |
22 |
23 | def test_tolerance_format_point():
24 | point = Point(0, 0, 0)
25 | assert str(point) == "Point(x=0.000, y=0.000, z=0.000)"
26 |
--------------------------------------------------------------------------------
/tests/compas/utilities/test_decorators.py:
--------------------------------------------------------------------------------
1 | from compas.utilities import memoize
2 |
3 |
4 | def test_memoize():
5 | ctx = dict(calls=0)
6 |
7 | @memoize
8 | def func(arg):
9 | ctx["calls"] += 1
10 |
11 | func(444)
12 | func(444)
13 | func(444)
14 | assert ctx["calls"] == 1
15 |
16 | func(555)
17 | assert ctx["calls"] == 2
18 |
--------------------------------------------------------------------------------
/tests/ipy_test_runner.py:
--------------------------------------------------------------------------------
1 | from __future__ import print_function
2 |
3 | import os
4 |
5 | import pytest
6 |
7 | HERE = os.path.dirname(__file__)
8 |
9 | if __name__ == "__main__":
10 | # Fake Rhino modules
11 | pytest.load_fake_module("Rhino")
12 | pytest.load_fake_module("Rhino.Geometry", fake_types=["RTree", "Sphere", "Point3d"])
13 |
14 | pytest.run(HERE)
15 |
--------------------------------------------------------------------------------