├── .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 | One 8 | 9 | 10 | Find succeeding characters 11 | Examp2.EXE 12 | abc 13 | def 14 | 15 | 16 | Convert multiple numbers to strings 17 | Examp2.EXE /Verbose 18 | 123 19 | One Two Three 20 | 21 | 22 | Find correlated key 23 | Examp3.EXE 24 | a1 25 | b1 26 | 27 | 28 | Count characters 29 | FinalExamp.EXE 30 | This is a test 31 | 14 32 | 33 | 34 | Another Test 35 | Examp2.EXE 36 | Test Input 37 | 10 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 | --------------------------------------------------------------------------------