diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 5781a2449bb4..d9a8a9dd8cba 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -15,7 +15,23 @@ jobs: if: github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v') || (github.event_name == 'pull_request_review' && github.event.review.state == 'approved') runs-on: ubuntu-latest steps: - - uses: compas-dev/compas-actions.docs@v3 + - uses: actions/checkout@v4 + + - name: Set up Python + uses: actions/setup-python@v5 with: - github_token: ${{ secrets.GITHUB_TOKEN }} - doc_url: https://compas.dev/compas + python-version: '3.11' + + - name: Install dependencies + run: | + pip install -e . + pip install mkdocs mkdocs-material "mkdocstrings[python]" + + - name: Build docs + run: mkdocs build --strict + + - name: Deploy to GitHub Pages + if: github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v') + run: mkdocs gh-deploy --force + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 000000000000..23017598d145 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,17 @@ +repos + - repo: https://github.com/PyCQA/flake8 + rev: 6.0.0 + hooks: + - id: flake8 + + - repo: https://github.com/PyCQA/isort + rev: 5.12.0 + hooks: + - id: isort + + - repo: https://github.com/ambv/black + rev: 23.3.0 + hooks: + - id: black + language_version: python3.8 + diff --git a/CHANGELOG.md b/CHANGELOG.md index 99790add62cc..8e52be958046 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,10 +9,19 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added +- MkDocs + Material theme based docs + ### Changed +- update CI workflow for mkdocs gh-deploy +- update invoke tasks for mkdocs commands + ### Removed +- replace Sphinx with MkDocs + Material theme +- use mkdocstrings for API docs from NumPy docstrings +- convert 73 RST files to Markdown +- remove RST directives from Python docstrings ## [2.15.0] 2025-11-12 diff --git a/docs/_static/PLACEHOLDER b/docs/_static/PLACEHOLDER deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/docs/api/compas.colors.html_colors.rst b/docs/api/compas.colors.html_colors.rst deleted file mode 100644 index 8174a60638f3..000000000000 --- a/docs/api/compas.colors.html_colors.rst +++ /dev/null @@ -1,6 +0,0 @@ -******************************************************************************** -HTML Colors -******************************************************************************** - -.. literalinclude:: ../../src/compas/colors/html_colors.py - :language: python diff --git a/docs/api/compas.colors.md b/docs/api/compas.colors.md new file mode 100644 index 000000000000..7dbf80b06147 --- /dev/null +++ b/docs/api/compas.colors.md @@ -0,0 +1,7 @@ +# compas.colors + +Color handling for COMPAS. + +::: compas.colors + options: + show_submodules: true diff --git a/docs/api/compas.colors.rst b/docs/api/compas.colors.rst deleted file mode 100644 index 64a6b15a874e..000000000000 --- a/docs/api/compas.colors.rst +++ /dev/null @@ -1,24 +0,0 @@ - -******************************************************************************** -compas.colors -******************************************************************************** - -.. currentmodule:: compas.colors - -.. rst-class:: lead - - -This package defines a color and color map class, -that can be used to work wihth colors in a consistent way across color spaces. - - -Classes -======= - -.. autosummary:: - :toctree: generated/ - :nosignatures: - - Color - ColorDict - ColorMap diff --git a/docs/api/compas.data.md b/docs/api/compas.data.md new file mode 100644 index 000000000000..b79689692d0c --- /dev/null +++ b/docs/api/compas.data.md @@ -0,0 +1,7 @@ +# compas.data + +Data serialization and persistence for COMPAS. + +::: compas.data + options: + show_submodules: true diff --git a/docs/api/compas.data.rst b/docs/api/compas.data.rst deleted file mode 100644 index bf70094578ae..000000000000 --- a/docs/api/compas.data.rst +++ /dev/null @@ -1,44 +0,0 @@ - -******************************************************************************** -compas.data -******************************************************************************** - -.. currentmodule:: compas.data - -.. rst-class:: lead - - -This package defines the core infrastructure for data serialisation in the COMPAS framework. -It provides a base class for data objects, a JSON encoder and decoder, serialisers and deserialisers, and schema validation. - - -Classes -======= - -.. autosummary:: - :toctree: generated/ - :nosignatures: - - Data - DataDecoder - DataEncoder - DecoderError - - -Functions -========= - -.. autosummary:: - :toctree: generated/ - :nosignatures: - - compas_dataclasses - dataclass_dataschema - dataclass_jsonschema - dataclass_typeschema - json_dump - json_dumps - json_dumpz - json_load - json_loads - json_loadz diff --git a/docs/api/compas.datastructures.Assembly.rst b/docs/api/compas.datastructures.Assembly.rst deleted file mode 100644 index 2269eff923ad..000000000000 --- a/docs/api/compas.datastructures.Assembly.rst +++ /dev/null @@ -1,109 +0,0 @@ -****************************************************************************** -Assembly -****************************************************************************** - -.. currentmodule:: compas.datastructures - -.. autoclass:: Assembly - -Methods -======= - -Constructors ------------- - -.. autosummary:: - :toctree: generated/ - :nosignatures: - - ~Assembly.from_json - - -Conversions ------------ - -.. autosummary:: - :toctree: generated/ - :nosignatures: - - ~Assembly.to_json - - -Builders and Modifiers ----------------------- - -.. autosummary:: - :toctree: generated/ - :nosignatures: - - -Accessors ---------- - -.. autosummary:: - :toctree: generated/ - :nosignatures: - - -Attributes ----------- - -.. autosummary:: - :toctree: generated/ - :nosignatures: - -Topology --------- - -.. autosummary:: - :toctree: generated/ - :nosignatures: - - -Geometry --------- - -.. autosummary:: - :toctree: generated/ - :nosignatures: - - -Paths ------ - -.. autosummary:: - :toctree: generated/ - :nosignatures: - - -Matrices --------- - -.. autosummary:: - :toctree: generated/ - :nosignatures: - - -Mappings --------- - -.. autosummary:: - :toctree: generated/ - :nosignatures: - - -Utilities ---------- - -.. autosummary:: - :toctree: generated/ - :nosignatures: - - -Other ------ - -.. autosummary:: - :toctree: generated/ - :nosignatures: - diff --git a/docs/api/compas.datastructures.CellNetwork.rst b/docs/api/compas.datastructures.CellNetwork.rst deleted file mode 100644 index eeca9e596737..000000000000 --- a/docs/api/compas.datastructures.CellNetwork.rst +++ /dev/null @@ -1,345 +0,0 @@ -****************************************************************************** -CellNetwork -****************************************************************************** - -.. currentmodule:: compas.datastructures - -.. autoclass:: CellNetwork - -Methods -======= - -Constructors ------------- - -.. autosummary:: - :toctree: generated/ - :nosignatures: - - ~CellNetwork.from_json - - -Conversions ------------ - -.. autosummary:: - :toctree: generated/ - :nosignatures: - - ~CellNetwork.cell_to_mesh - ~CellNetwork.cell_to_vertices_and_faces - ~CellNetwork.edges_to_graph - ~CellNetwork.faces_to_mesh - ~CellNetwork.to_json - - -Builders and Modifiers ----------------------- - -.. autosummary:: - :toctree: generated/ - :nosignatures: - - ~CellNetwork.add_cell - ~CellNetwork.add_edge - ~CellNetwork.add_face - ~CellNetwork.add_vertex - - -General -------- - -.. autosummary:: - :toctree: generated/ - :nosignatures: - - ~CellNetwork.aabb - ~CellNetwork.centroid - ~CellNetwork.is_valid - ~CellNetwork.number_of_cells - ~CellNetwork.number_of_edges - ~CellNetwork.number_of_faces - ~CellNetwork.number_of_vertices - - -Vertex Accessors ----------------- - -.. autosummary:: - :toctree: generated/ - :nosignatures: - - ~CellNetwork.vertex_sample - ~CellNetwork.vertices - ~CellNetwork.vertices_where - ~CellNetwork.vertices_where_predicate - - -Vertex Attributes ------------------ - -.. autosummary:: - :toctree: generated/ - :nosignatures: - - ~CellNetwork.vertex_attribute - ~CellNetwork.vertex_attributes - ~CellNetwork.vertices_attribute - ~CellNetwork.vertices_attributes - ~CellNetwork.update_default_vertex_attributes - ~CellNetwork.unset_vertex_attribute - - -Vertex Topology ---------------- - -.. autosummary:: - :toctree: generated/ - :nosignatures: - - ~CellNetwork.has_vertex - ~CellNetwork.vertex_cells - ~CellNetwork.vertex_degree - ~CellNetwork.vertex_faces - ~CellNetwork.vertex_max_degree - ~CellNetwork.vertex_min_degree - ~CellNetwork.vertex_neighbors - ~CellNetwork.vertex_neighborhood - - -Vertex Geometry ---------------- - -.. autosummary:: - :toctree: generated/ - :nosignatures: - - ~CellNetwork.vertex_coordinates - ~CellNetwork.vertex_point - ~CellNetwork.vertices_coordinates - ~CellNetwork.vertices_points - - -Edge Accessors --------------- - -.. autosummary:: - :toctree: generated/ - :nosignatures: - - ~CellNetwork.edge_sample - ~CellNetwork.edges - ~CellNetwork.edges_where - ~CellNetwork.edges_where_predicate - - -Edge Attributes ---------------- - -.. autosummary:: - :toctree: generated/ - :nosignatures: - - ~CellNetwork.edge_attribute - ~CellNetwork.edge_attributes - ~CellNetwork.edges_attribute - ~CellNetwork.edges_attributes - ~CellNetwork.update_default_edge_attributes - ~CellNetwork.unset_edge_attribute - - -Edge Topology -------------- - -.. autosummary:: - :toctree: generated/ - :nosignatures: - - ~CellNetwork.edge_cells - ~CellNetwork.edge_faces - ~CellNetwork.has_edge - - -Edge Geometry -------------- - -.. autosummary:: - :toctree: generated/ - :nosignatures: - - ~CellNetwork.edge_direction - ~CellNetwork.edge_end - ~CellNetwork.edge_length - ~CellNetwork.edge_line - ~CellNetwork.edge_vector - ~CellNetwork.edge_start - - -Face Accessors --------------- - -.. autosummary:: - :toctree: generated/ - :nosignatures: - - ~CellNetwork.face_sample - ~CellNetwork.faces - ~CellNetwork.faces_on_boundaries - ~CellNetwork.faces_where - ~CellNetwork.faces_where_predicate - - -Face Attributes ---------------- - -.. autosummary:: - :toctree: generated/ - :nosignatures: - - ~CellNetwork.face_attribute - ~CellNetwork.face_attributes - ~CellNetwork.faces_attribute - ~CellNetwork.faces_attributes - ~CellNetwork.update_default_face_attributes - ~CellNetwork.unset_face_attribute - - -Face Topology -------------- - -.. autosummary:: - :toctree: generated/ - :nosignatures: - - ~CellNetwork.face_cells - ~CellNetwork.face_edges - ~CellNetwork.face_vertices - ~CellNetwork.faces_on_boundaries - ~CellNetwork.is_face_on_boundary - ~CellNetwork.isolated_faces - - -Face Geometry -------------- - -.. autosummary:: - :toctree: generated/ - :nosignatures: - - ~CellNetwork.face_area - ~CellNetwork.face_center - ~CellNetwork.face_centroid - ~CellNetwork.face_coordinates - ~CellNetwork.face_normal - ~CellNetwork.face_points - ~CellNetwork.face_polygon - - -Cell Accessors --------------- - -.. autosummary:: - :toctree: generated/ - :nosignatures: - - ~CellNetwork.cell_sample - ~CellNetwork.cells - ~CellNetwork.cells_on_boundaries - ~CellNetwork.cells_where - ~CellNetwork.cells_where_predicate - - -Cell Attributes ---------------- - -.. autosummary:: - :toctree: generated/ - :nosignatures: - - ~CellNetwork.cell_attribute - ~CellNetwork.cell_attributes - ~CellNetwork.cells_attribute - ~CellNetwork.cells_attributes - ~CellNetwork.update_default_cell_attributes - ~CellNetwork.unset_cell_attribute - - -Cell Topology -------------- - -.. autosummary:: - :toctree: generated/ - :nosignatures: - - ~CellNetwork.cell_edges - ~CellNetwork.cell_face_halfedges - ~CellNetwork.cell_face_neighbors - ~CellNetwork.cell_face_vertices - ~CellNetwork.cell_faces - ~CellNetwork.cell_halfedge_face - ~CellNetwork.cell_halfedges - ~CellNetwork.cell_vertex_faces - ~CellNetwork.cell_vertex_neighbors - ~CellNetwork.cell_vertices - ~CellNetwork.cells_on_boundaries - ~CellNetwork.is_cell_on_boundary - - -Cell Geometry -------------- - -.. autosummary:: - :toctree: generated/ - :nosignatures: - - ~CellNetwork.cell_center - ~CellNetwork.cell_centroid - ~CellNetwork.cell_points - ~CellNetwork.cell_polyhedron - - -Paths ------ - -.. autosummary:: - :toctree: generated/ - :nosignatures: - - -Matrices --------- - -.. autosummary:: - :toctree: generated/ - :nosignatures: - - -Mappings --------- - -.. autosummary:: - :toctree: generated/ - :nosignatures: - - ~CellNetwork.index_vertex - ~CellNetwork.vertex_index - - -Utilities ---------- - -.. autosummary:: - :toctree: generated/ - :nosignatures: - - ~CellNetwork.clear - ~CellNetwork.copy - - -Other ------ - -.. autosummary:: - :toctree: generated/ - :nosignatures: - diff --git a/docs/api/compas.datastructures.Graph.rst b/docs/api/compas.datastructures.Graph.rst deleted file mode 100644 index 0c41402455c4..000000000000 --- a/docs/api/compas.datastructures.Graph.rst +++ /dev/null @@ -1,199 +0,0 @@ -****************************************************************************** -Graph -****************************************************************************** - -.. currentmodule:: compas.datastructures - -.. autoclass:: Graph - -Methods -======= - -Constructors ------------- - -.. autosummary:: - :toctree: generated/ - :nosignatures: - - ~Graph.from_edges - ~Graph.from_json - ~Graph.from_lines - ~Graph.from_networkx - ~Graph.from_nodes_and_edges - ~Graph.from_obj - ~Graph.from_pointcloud - -Conversions ------------ - -.. autosummary:: - :toctree: generated/ - :nosignatures: - - ~Graph.to_json - ~Graph.to_lines - ~Graph.to_networkx - ~Graph.to_obj - ~Graph.to_points - -Builders and Modifiers ----------------------- - -.. autosummary:: - :toctree: generated/ - :nosignatures: - - ~Graph.add_edge - ~Graph.add_node - ~Graph.delete_edge - ~Graph.delete_node - ~Graph.join_edges - ~Graph.split_edge - -Accessors ---------- - -.. autosummary:: - :toctree: generated/ - :nosignatures: - - ~Graph.edge_sample - ~Graph.edges - ~Graph.edges_where - ~Graph.edges_where_predicate - ~Graph.node_sample - ~Graph.nodes - ~Graph.nodes_where - ~Graph.nodes_where_predicate - -Attributes ----------- - -.. autosummary:: - :toctree: generated/ - :nosignatures: - - ~Graph.edge_attribute - ~Graph.edge_attributes - ~Graph.edges_attribute - ~Graph.edges_attributes - ~Graph.node_attribute - ~Graph.node_attributes - ~Graph.nodes_attribute - ~Graph.nodes_attributes - ~Graph.update_default_edge_attributes - ~Graph.update_default_node_attributes - ~Graph.unset_edge_attribute - ~Graph.unset_node_attribute - -Topology --------- - -.. autosummary:: - :toctree: generated/ - :nosignatures: - - ~Graph.complement - ~Graph.connected_nodes - ~Graph.connected_edges - ~Graph.degree - ~Graph.degree_out - ~Graph.degree_in - ~Graph.exploded - ~Graph.has_edge - ~Graph.has_node - ~Graph.is_leaf - ~Graph.is_node_connected - ~Graph.neighborhood - ~Graph.neighbors - ~Graph.neighbors_in - ~Graph.neighbors_out - ~Graph.node_edges - ~Graph.number_of_edges - ~Graph.number_of_nodes - -Geometry --------- - -.. autosummary:: - :toctree: generated/ - :nosignatures: - - ~Graph.edge_coordinates - ~Graph.edge_direction - ~Graph.edge_end - ~Graph.edge_length - ~Graph.edge_line - ~Graph.edge_midpoint - ~Graph.edge_point - ~Graph.edge_start - ~Graph.edge_vector - ~Graph.node_coordinates - ~Graph.node_point - ~Graph.node_laplacian - ~Graph.node_neighborhood_centroid - ~Graph.transform - ~Graph.transformed - -Paths ------ - -.. autosummary:: - :toctree: generated/ - :nosignatures: - - ~Graph.shortest_path - -Planarity ---------- - -.. autosummary:: - :toctree: generated/ - :nosignatures: - - ~Graph.count_crossings - ~Graph.embed_in_plane - ~Graph.find_crossings - ~Graph.find_cycles - ~Graph.is_crossed - ~Graph.is_planar - ~Graph.is_planar_embedding - ~Graph.is_xy - -Matrices --------- - -.. autosummary:: - :toctree: generated/ - :nosignatures: - - ~Graph.adjacency_matrix - ~Graph.connectivity_matrix - ~Graph.degree_matrix - ~Graph.laplacian_matrix - -Mappings --------- - -.. autosummary:: - :toctree: generated/ - :nosignatures: - - ~Graph.gkey_node - ~Graph.node_gkey - ~Graph.node_index - ~Graph.edge_index - ~Graph.index_node - ~Graph.index_edge - -Utilities ---------- - -.. autosummary:: - :toctree: generated/ - :nosignatures: - - ~Graph.summary - ~Graph.copy - ~Graph.clear diff --git a/docs/api/compas.datastructures.Mesh.rst b/docs/api/compas.datastructures.Mesh.rst deleted file mode 100644 index de3996c991bb..000000000000 --- a/docs/api/compas.datastructures.Mesh.rst +++ /dev/null @@ -1,293 +0,0 @@ -****************************************************************************** -Mesh -****************************************************************************** - -.. currentmodule:: compas.datastructures - -.. autoclass:: Mesh - -Methods -======= - -Constructors ------------- - -.. autosummary:: - :toctree: generated/ - :nosignatures: - - ~Mesh.from_json - ~Mesh.from_lines - ~Mesh.from_meshgrid - ~Mesh.from_obj - ~Mesh.from_off - ~Mesh.from_ply - ~Mesh.from_points - ~Mesh.from_polygons - ~Mesh.from_polyhedron - ~Mesh.from_polylines - ~Mesh.from_shape - ~Mesh.from_stl - ~Mesh.from_vertices_and_faces - -Conversions ------------ - -.. autosummary:: - :toctree: generated/ - :nosignatures: - - ~Mesh.to_json - ~Mesh.to_lines - ~Mesh.to_obj - ~Mesh.to_off - ~Mesh.to_ply - ~Mesh.to_points - ~Mesh.to_polygons - ~Mesh.to_polylines - ~Mesh.to_stl - ~Mesh.to_vertices_and_faces - -Builders and Modifiers ----------------------- - -.. autosummary:: - :toctree: generated/ - :nosignatures: - - ~Mesh.add_face - ~Mesh.add_vertex - ~Mesh.collapse_edge - ~Mesh.delete_face - ~Mesh.delete_vertex - ~Mesh.flip_cycles - ~Mesh.insert_vertex - ~Mesh.join - ~Mesh.merge_faces - ~Mesh.quads_to_triangles - ~Mesh.remove_duplicate_vertices - ~Mesh.remove_unused_vertices - ~Mesh.split_edge - ~Mesh.split_face - ~Mesh.unify_cycles - ~Mesh.unweld_edges - ~Mesh.unweld_vertices - ~Mesh.weld - -Accessors ---------- - -.. autosummary:: - :toctree: generated/ - :nosignatures: - - ~Mesh.edge_sample - ~Mesh.edges - ~Mesh.edges_on_boundaries - ~Mesh.edges_on_boundary - ~Mesh.edges_where - ~Mesh.edges_where_predicate - ~Mesh.face_sample - ~Mesh.faces - ~Mesh.faces_on_boundaries - ~Mesh.faces_on_boundary - ~Mesh.faces_where - ~Mesh.faces_where_predicate - ~Mesh.vertex_sample - ~Mesh.vertices - ~Mesh.vertices_on_boundaries - ~Mesh.vertices_on_boundary - ~Mesh.vertices_where - ~Mesh.vertices_where_predicate - -Attributes ----------- - -.. autosummary:: - :toctree: generated/ - :nosignatures: - - ~Mesh.edge_attribute - ~Mesh.edge_attributes - ~Mesh.edges_attribute - ~Mesh.edges_attributes - ~Mesh.face_attribute - ~Mesh.face_attributes - ~Mesh.faces_attribute - ~Mesh.faces_attributes - ~Mesh.vertex_attribute - ~Mesh.vertex_attributes - ~Mesh.vertices_attribute - ~Mesh.vertices_attributes - ~Mesh.update_default_edge_attributes - ~Mesh.update_default_face_attributes - ~Mesh.update_default_vertex_attributes - ~Mesh.unset_edge_attribute - ~Mesh.unset_face_attribute - ~Mesh.unset_vertex_attribute - -Topology --------- - -.. autosummary:: - :toctree: generated/ - :nosignatures: - - ~Mesh.connected_vertices - ~Mesh.connected_faces - ~Mesh.edge_faces - ~Mesh.edge_loop - ~Mesh.edge_strip - ~Mesh.euler - ~Mesh.face_adjacency_halfedge - ~Mesh.face_adjacency_vertices - ~Mesh.face_corners - ~Mesh.face_degree - ~Mesh.face_halfedges - ~Mesh.face_max_degree - ~Mesh.face_min_degree - ~Mesh.face_neighbors - ~Mesh.face_neighborhood - ~Mesh.face_vertex_ancestor - ~Mesh.face_vertex_descendant - ~Mesh.face_vertices - ~Mesh.halfedge_after - ~Mesh.halfedge_before - ~Mesh.halfedge_face - ~Mesh.halfedge_loop - ~Mesh.halfedge_loop_vertices - ~Mesh.halfedge_strip - ~Mesh.halfedge_strip_faces - ~Mesh.has_edge - ~Mesh.has_face - ~Mesh.has_halfedge - ~Mesh.has_vertex - ~Mesh.is_closed - ~Mesh.is_connected - ~Mesh.is_edge_on_boundary - ~Mesh.is_empty - ~Mesh.is_face_on_boundary - ~Mesh.is_manifold - ~Mesh.is_orientable - ~Mesh.is_quadmesh - ~Mesh.is_regular - ~Mesh.is_trimesh - ~Mesh.is_valid - ~Mesh.is_vertex_connected - ~Mesh.is_vertex_on_boundary - ~Mesh.number_of_edges - ~Mesh.number_of_faces - ~Mesh.number_of_vertices - ~Mesh.vertex_degree - ~Mesh.vertex_edges - ~Mesh.vertex_faces - ~Mesh.vertex_max_degree - ~Mesh.vertex_min_degree - ~Mesh.vertex_neighbors - ~Mesh.vertex_neighborhood - -Geometry --------- - -.. autosummary:: - :toctree: generated/ - :nosignatures: - - ~Mesh.aabb - ~Mesh.area - ~Mesh.centroid - ~Mesh.edge_coordinates - ~Mesh.edge_direction - ~Mesh.edge_end - ~Mesh.edge_length - ~Mesh.edge_line - ~Mesh.edge_midpoint - ~Mesh.edge_point - ~Mesh.edge_start - ~Mesh.edge_vector - ~Mesh.face_area - ~Mesh.face_aspect_ratio - ~Mesh.face_center - ~Mesh.face_centroid - ~Mesh.face_circle - ~Mesh.face_coordinates - ~Mesh.face_curvature - ~Mesh.face_flatness - ~Mesh.face_frame - ~Mesh.face_normal - ~Mesh.face_plane - ~Mesh.face_points - ~Mesh.face_polygon - ~Mesh.face_skewness - ~Mesh.normal - ~Mesh.obb - ~Mesh.vertex_area - ~Mesh.vertex_coordinates - ~Mesh.vertex_curvature - ~Mesh.vertex_point - ~Mesh.vertex_laplacian - ~Mesh.vertex_neighborhood_centroid - ~Mesh.vertex_normal - ~Mesh.vertices_points - ~Mesh.set_vertex_point - ~Mesh.smooth_area - ~Mesh.smooth_centroid - ~Mesh.transform - ~Mesh.transformed - -Paths ------ - -.. autosummary:: - :toctree: generated/ - :nosignatures: - - -Matrices --------- - -.. autosummary:: - :toctree: generated/ - :nosignatures: - - ~Mesh.adjacency_matrix - ~Mesh.connectivity_matrix - ~Mesh.degree_matrix - ~Mesh.face_matrix - ~Mesh.laplacian_matrix - -Mappings --------- - -.. autosummary:: - :toctree: generated/ - :nosignatures: - - ~Mesh.gkey_vertex - ~Mesh.vertex_gkey - ~Mesh.vertex_index - ~Mesh.index_vertex - -Utilities ---------- - -.. autosummary:: - :toctree: generated/ - :nosignatures: - - ~Mesh.summary - ~Mesh.copy - ~Mesh.clear - -Other ------ - -.. autosummary:: - :toctree: generated/ - :nosignatures: - - ~Mesh.dual - ~Mesh.exploded - ~Mesh.offset - ~Mesh.subdivided - ~Mesh.thickened diff --git a/docs/api/compas.datastructures.Tree.rst b/docs/api/compas.datastructures.Tree.rst deleted file mode 100644 index 9d6b3f0875d9..000000000000 --- a/docs/api/compas.datastructures.Tree.rst +++ /dev/null @@ -1,109 +0,0 @@ -****************************************************************************** -Tree -****************************************************************************** - -.. currentmodule:: compas.datastructures - -.. autoclass:: Tree - -Methods -======= - -Constructors ------------- - -.. autosummary:: - :toctree: generated/ - :nosignatures: - - ~Tree.from_json - - -Conversions ------------ - -.. autosummary:: - :toctree: generated/ - :nosignatures: - - ~Tree.to_json - - -Builders and Modifiers ----------------------- - -.. autosummary:: - :toctree: generated/ - :nosignatures: - - -Accessors ---------- - -.. autosummary:: - :toctree: generated/ - :nosignatures: - - -Attributes ----------- - -.. autosummary:: - :toctree: generated/ - :nosignatures: - -Topology --------- - -.. autosummary:: - :toctree: generated/ - :nosignatures: - - -Geometry --------- - -.. autosummary:: - :toctree: generated/ - :nosignatures: - - -Paths ------ - -.. autosummary:: - :toctree: generated/ - :nosignatures: - - -Matrices --------- - -.. autosummary:: - :toctree: generated/ - :nosignatures: - - -Mappings --------- - -.. autosummary:: - :toctree: generated/ - :nosignatures: - - -Utilities ---------- - -.. autosummary:: - :toctree: generated/ - :nosignatures: - - -Other ------ - -.. autosummary:: - :toctree: generated/ - :nosignatures: - diff --git a/docs/api/compas.datastructures.VolMesh.rst b/docs/api/compas.datastructures.VolMesh.rst deleted file mode 100644 index 640af292ab00..000000000000 --- a/docs/api/compas.datastructures.VolMesh.rst +++ /dev/null @@ -1,240 +0,0 @@ -****************************************************************************** -VolMesh -****************************************************************************** - -.. currentmodule:: compas.datastructures - -.. autoclass:: VolMesh - -Methods -======= - -Constructors ------------- - -.. autosummary:: - :toctree: generated/ - :nosignatures: - - ~VolMesh.from_json - ~VolMesh.from_obj - ~VolMesh.from_vertices_and_cells - - -Conversions ------------ - -.. autosummary:: - :toctree: generated/ - :nosignatures: - - ~VolMesh.cell_to_mesh - ~VolMesh.cell_to_vertices_and_faces - ~VolMesh.to_json - ~VolMesh.to_obj - ~VolMesh.to_vertices_and_cells - - -Builders and Modifiers ----------------------- - -.. autosummary:: - :toctree: generated/ - :nosignatures: - - ~VolMesh.add_cell - ~VolMesh.add_halfface - ~VolMesh.add_vertex - ~VolMesh.delete_cell - ~VolMesh.delete_vertex - ~VolMesh.remove_unused_vertices - - -Accessors ---------- - -.. autosummary:: - :toctree: generated/ - :nosignatures: - - ~VolMesh.cell_sample - ~VolMesh.cells - ~VolMesh.cells_on_boundaries - ~VolMesh.cells_where - ~VolMesh.cells_where_predicate - ~VolMesh.edge_sample - ~VolMesh.edges - ~VolMesh.edges_where - ~VolMesh.edges_where_predicate - ~VolMesh.face_sample - ~VolMesh.faces - ~VolMesh.faces_where - ~VolMesh.faces_where_predicate - ~VolMesh.halffaces - ~VolMesh.halffaces_on_boundaries - ~VolMesh.vertex_sample - ~VolMesh.vertices - ~VolMesh.vertices_on_boundaries - ~VolMesh.vertices_where - ~VolMesh.vertices_where_predicate - - -Attributes ----------- - -.. autosummary:: - :toctree: generated/ - :nosignatures: - - ~VolMesh.cell_attribute - ~VolMesh.cell_attributes - ~VolMesh.cells_attribute - ~VolMesh.cells_attributes - ~VolMesh.edge_attribute - ~VolMesh.edge_attributes - ~VolMesh.edges_attribute - ~VolMesh.edges_attributes - ~VolMesh.face_attribute - ~VolMesh.face_attributes - ~VolMesh.faces_attribute - ~VolMesh.faces_attributes - ~VolMesh.vertex_attribute - ~VolMesh.vertex_attributes - ~VolMesh.vertices_attribute - ~VolMesh.vertices_attributes - ~VolMesh.update_default_cell_attributes - ~VolMesh.update_default_edge_attributes - ~VolMesh.update_default_face_attributes - ~VolMesh.update_default_vertex_attributes - ~VolMesh.unset_cell_attribute - ~VolMesh.unset_edge_attribute - ~VolMesh.unset_face_attribute - ~VolMesh.unset_vertex_attribute - - -Topology --------- - -.. autosummary:: - :toctree: generated/ - :nosignatures: - - ~VolMesh.cell_edges - ~VolMesh.cell_face_neighbors - ~VolMesh.cell_faces - ~VolMesh.cell_halfedge_face - ~VolMesh.cell_halfedge_opposite_face - ~VolMesh.cell_halfedges - ~VolMesh.cell_neighbors - ~VolMesh.cell_vertex_faces - ~VolMesh.cell_vertex_neighbors - ~VolMesh.cell_vertices - ~VolMesh.edge_cells - ~VolMesh.edge_halffaces - ~VolMesh.halfface_cell - ~VolMesh.halfface_adjacent_halfface - ~VolMesh.halfface_halfedges - ~VolMesh.halfface_manifold_neighbors - ~VolMesh.halfface_manifold_neighborhood - ~VolMesh.halfface_opposite_cell - ~VolMesh.halfface_opposite_halfface - ~VolMesh.halfface_vertex_ancestor - ~VolMesh.halfface_vertex_descendent - ~VolMesh.halfface_vertices - ~VolMesh.has_edge - ~VolMesh.has_halfface - ~VolMesh.has_vertex - ~VolMesh.is_cell_on_boundary - ~VolMesh.is_edge_on_boundary - ~VolMesh.is_halfface_on_boundary - ~VolMesh.is_valid - ~VolMesh.is_vertex_on_boundary - ~VolMesh.number_of_cells - ~VolMesh.number_of_edges - ~VolMesh.number_of_faces - ~VolMesh.number_of_vertices - ~VolMesh.vertex_cells - ~VolMesh.vertex_degree - ~VolMesh.vertex_halffaces - ~VolMesh.vertex_max_degree - ~VolMesh.vertex_min_degree - ~VolMesh.vertex_neighbors - ~VolMesh.vertex_neighborhood - - -Geometry --------- - -.. autosummary:: - :toctree: generated/ - :nosignatures: - - ~VolMesh.cell_center - ~VolMesh.cell_centroid - ~VolMesh.cell_points - ~VolMesh.cell_polyhedron - ~VolMesh.cell_vertex_normal - ~VolMesh.edge_direction - ~VolMesh.edge_end - ~VolMesh.edge_length - ~VolMesh.edge_line - ~VolMesh.edge_vector - ~VolMesh.edge_start - ~VolMesh.face_area - ~VolMesh.face_center - ~VolMesh.face_centroid - ~VolMesh.face_coordinates - ~VolMesh.face_normal - ~VolMesh.face_points - ~VolMesh.face_polygon - ~VolMesh.vertex_coordinates - ~VolMesh.vertex_point - - -Paths ------ - -.. autosummary:: - :toctree: generated/ - :nosignatures: - - -Matrices --------- - -.. autosummary:: - :toctree: generated/ - :nosignatures: - - -Mappings --------- - -.. autosummary:: - :toctree: generated/ - :nosignatures: - - ~VolMesh.gkey_vertex - ~VolMesh.index_vertex - ~VolMesh.vertex_gkey - ~VolMesh.vertex_index - - -Utilities ---------- - -.. autosummary:: - :toctree: generated/ - :nosignatures: - - ~VolMesh.clear - ~VolMesh.copy - - -Other ------ - -.. autosummary:: - :toctree: generated/ - :nosignatures: - diff --git a/docs/api/compas.datastructures.md b/docs/api/compas.datastructures.md new file mode 100644 index 000000000000..ede85e26bf79 --- /dev/null +++ b/docs/api/compas.datastructures.md @@ -0,0 +1,8 @@ +# compas.datastructures + +Core data structures of the COMPAS framework. +The data structures provide a structured way of storing and accessing data on individual components of both topological and geometrical objects. + +::: compas.datastructures + options: + show_submodules: true diff --git a/docs/api/compas.datastructures.rst b/docs/api/compas.datastructures.rst deleted file mode 100644 index 8bcc9502e59d..000000000000 --- a/docs/api/compas.datastructures.rst +++ /dev/null @@ -1,37 +0,0 @@ - -******************************************************************************** -compas.datastructures -******************************************************************************** - -.. currentmodule:: compas.datastructures - -.. rst-class:: lead - - -This package defines the core data structures of the COMPAS framework. -The data structures provide a structured way of storing and accessing data on individual components of both topological and geometrical objects. - -Classes -======= - -.. toctree:: - :maxdepth: 1 - :titlesonly: - - compas.datastructures.Graph - compas.datastructures.Mesh - compas.datastructures.VolMesh - compas.datastructures.CellNetwork - compas.datastructures.Tree - compas.datastructures.Assembly - - -Exceptions -========== - -.. autosummary:: - :toctree: generated/ - :nosignatures: - - AssemblyError - FeatureError diff --git a/docs/api/compas.files.md b/docs/api/compas.files.md new file mode 100644 index 000000000000..8b1d022e71dc --- /dev/null +++ b/docs/api/compas.files.md @@ -0,0 +1,7 @@ +# compas.files + +File I/O for COMPAS. + +::: compas.files + options: + show_submodules: true diff --git a/docs/api/compas.files.rst b/docs/api/compas.files.rst deleted file mode 100644 index cc1df2a29702..000000000000 --- a/docs/api/compas.files.rst +++ /dev/null @@ -1,36 +0,0 @@ - -******************************************************************************** -compas.files -******************************************************************************** - -.. currentmodule:: compas.files - -.. rst-class:: lead - - -This package defines a number of file formats and provides functionality for reading and writing data in these formats. - - -Classes -======= - -.. autosummary:: - :toctree: generated/ - :nosignatures: - - GLTF - OBJ - OFF - PLY - STL - XML - - -Functions -========= - -.. autosummary:: - :toctree: generated/ - :nosignatures: - - prettify_string diff --git a/docs/api/compas.geometry.md b/docs/api/compas.geometry.md new file mode 100644 index 000000000000..c341c9c3e0fd --- /dev/null +++ b/docs/api/compas.geometry.md @@ -0,0 +1,9 @@ +# compas.geometry + +This package defines all functionality for working with geometry in COMPAS. +It provides classes representing geometric primitives, transformations, (NURBS) curves and surfaces, +shapes, general polygons and polyhedrons, boundary representations (B-reps), and a number of geometry processing algorithms. + +::: compas.geometry + options: + show_submodules: true diff --git a/docs/api/compas.geometry.rst b/docs/api/compas.geometry.rst deleted file mode 100644 index 0c894fd5dc01..000000000000 --- a/docs/api/compas.geometry.rst +++ /dev/null @@ -1,399 +0,0 @@ - -******************************************************************************** -compas.geometry -******************************************************************************** - -.. currentmodule:: compas.geometry - -.. rst-class:: lead - - -This package defines all functionality for working with geometry in COMPAS. -It provides classes representing geometric primitives, transformations, (NURBS) curves and surfaces, -shapes, general polygons and polyhedrons, boundary representations (B-reps), and a number of geometry processing algorithms. - - -Classes -======= - - - -.. autosummary:: - :toctree: generated/ - :nosignatures: - - Arc - Bezier - Box - Brep - BrepEdge - BrepError - BrepFace - BrepFilletError - BrepInvalidError - BrepLoop - BrepOrientation - BrepTrim - BrepTrimIsoStatus - BrepTrimmingError - BrepType - BrepVertex - Capsule - Circle - Cone - ConicalSurface - Curve - CurveType - Cylinder - CylindricalSurface - Ellipse - Frame - Geometry - Hyperbola - KDTree - Line - NurbsCurve - NurbsSurface - Parabola - PlanarSurface - Plane - Point - Pointcloud - Polygon - Polyhedron - Polyline - Projection - Quaternion - Reflection - Rotation - Scale - Shape - Shear - Sphere - SphericalSurface - Surface - SurfaceType - ToroidalSurface - Torus - Transformation - Translation - Vector - - -Functions -========= - - - -.. autosummary:: - :toctree: generated/ - :nosignatures: - - add_vectors - add_vectors_xy - angle_planes - angle_points - angle_points_xy - angle_vectors - angle_vectors_signed - angle_vectors_xy - angles_points - angles_points_xy - angles_vectors - angles_vectors_xy - area_polygon - area_polygon_xy - area_triangle - area_triangle_xy - argmax - argmin - axis_and_angle_from_matrix - axis_angle_from_quaternion - axis_angle_vector_from_matrix - barycentric_coordinates - basis_vectors_from_matrix - bestfit_plane - bounding_box - bounding_box_xy - centroid_points - centroid_points_weighted - centroid_points_xy - centroid_polygon - centroid_polygon_edges - centroid_polygon_edges_xy - centroid_polygon_vertices - centroid_polygon_vertices_xy - centroid_polygon_xy - centroid_polyhedron - closest_line_to_point - closest_point_in_cloud - closest_point_in_cloud_xy - closest_point_on_line - closest_point_on_line_xy - closest_point_on_plane - closest_point_on_polygon_xy - closest_point_on_polyline - closest_point_on_polyline_xy - closest_point_on_segment - closest_point_on_segment_xy - compose_matrix - compute_basisfuncs - compute_basisfuncsderivs - construct_knotvector - convex_hull - convex_hull_xy - cross_vectors - cross_vectors_xy - decompose_matrix - dehomogenize_vectors - discrete_coons_patch - distance_line_line - distance_point_line - distance_point_line_sqrd - distance_point_line_sqrd_xy - distance_point_line_xy - distance_point_plane - distance_point_plane_signed - distance_point_point - distance_point_point_sqrd - distance_point_point_sqrd_xy - distance_point_point_xy - divide_vectors - divide_vectors_xy - dot_vectors - dot_vectors_xy - earclip_polygon - euler_angles_from_matrix - euler_angles_from_quaternion - find_span - homogenize_vectors - identity_matrix - intersection_circle_circle_xy - intersection_ellipse_line_xy - intersection_line_box_xy - intersection_line_line - intersection_line_line_xy - intersection_line_plane - intersection_line_segment - intersection_line_segment_xy - intersection_line_triangle - intersection_plane_circle - intersection_plane_plane - intersection_plane_plane_plane - intersection_polyline_box_xy - intersection_polyline_plane - intersection_segment_plane - intersection_segment_polyline - intersection_segment_polyline_xy - intersection_segment_segment - intersection_segment_segment_xy - intersection_sphere_line - intersection_sphere_sphere - is_ccw_xy - is_colinear - is_colinear_line_line - is_colinear_xy - is_coplanar - is_matrix_square - is_parallel_line_line - is_parallel_vector_vector - is_point_behind_plane - is_point_in_circle - is_point_in_circle_xy - is_point_in_convex_polygon_xy - is_point_in_polygon_xy - is_point_in_polyhedron - is_point_in_triangle - is_point_in_triangle_xy - is_point_infrontof_plane - is_point_on_line - is_point_on_line_xy - is_point_on_plane - is_point_on_polyline - is_point_on_polyline_xy - is_point_on_segment - is_point_on_segment_xy - is_polygon_convex - is_polygon_convex_xy - is_polygon_in_polygon_xy - knots_and_mults_to_knotvector - knotvector_to_knots_and_mults - length_vector - length_vector_sqrd - length_vector_sqrd_xy - length_vector_xy - local_axes - local_to_world_coordinates - matrix_determinant - matrix_from_axis_and_angle - matrix_from_axis_angle_vector - matrix_from_basis_vectors - matrix_from_change_of_basis - matrix_from_euler_angles - matrix_from_frame - matrix_from_frame_to_frame - matrix_from_orthogonal_projection - matrix_from_parallel_projection - matrix_from_perspective_entries - matrix_from_perspective_projection - matrix_from_quaternion - matrix_from_scale_factors - matrix_from_shear - matrix_from_shear_entries - matrix_from_translation - matrix_inverse - matrix_minor - midpoint_line - midpoint_line_xy - midpoint_point_point - midpoint_point_point_xy - mirror_point_plane - mirror_points_line - mirror_points_line_xy - mirror_points_plane - mirror_points_point - mirror_points_point_xy - mirror_vector_vector - multiply_matrices - multiply_matrix_vector - multiply_vectors - multiply_vectors_xy - norm_vector - norm_vectors - normal_polygon - normal_triangle - normal_triangle_xy - normalize_vector - normalize_vector_xy - normalize_vectors - normalize_vectors_xy - offset_line - offset_polygon - offset_polyline - orient_points - orthonormalize_axes - orthonormalize_vectors - power_vector - power_vectors - project_point_line - project_point_line_xy - project_point_plane - project_points_line - project_points_line_xy - project_points_plane - quaternion_canonize - quaternion_conjugate - quaternion_from_axis_angle - quaternion_from_euler_angles - quaternion_from_matrix - quaternion_is_unit - quaternion_multiply - quaternion_norm - quaternion_unitize - reflect_line_plane - reflect_line_triangle - rotate_points - rotate_points_xy - scale_points - scale_points_xy - scale_vector - scale_vector_xy - scale_vectors - scale_vectors_xy - sort_points - sort_points_xy - square_vector - square_vectors - subtract_vectors - subtract_vectors_xy - sum_vectors - tangent_points_to_circle_xy - transform_frames - transform_points - transform_vectors - translate_points - translate_points_xy - translation_from_matrix - transpose_matrix - tween_points - tween_points_distance - vector_average - vector_component - vector_component_xy - vector_standard_deviation - vector_variance - volume_polyhedron - world_to_local_coordinates - - -Functions using Numpy -===================== - -In environments where numpy is not available, these functions can still be accessed through RPC. - -.. autosummary:: - :toctree: generated/ - :nosignatures: - - bestfit_circle_numpy - bestfit_frame_numpy - bestfit_line_numpy - bestfit_plane_numpy - bestfit_sphere_numpy - closest_points_in_cloud_numpy - convex_hull_numpy - convex_hull_xy_numpy - dehomogenize_and_unflatten_frames_numpy - dehomogenize_numpy - homogenize_and_flatten_frames_numpy - homogenize_numpy - icp_numpy - local_to_world_coordinates_numpy - oriented_bounding_box_numpy - oriented_bounding_box_xy_numpy - pca_numpy - transform_points_numpy - transform_vectors_numpy - trimesh_descent_numpy - trimesh_gradient_numpy - world_to_local_coordinates_numpy - - -Pluggables -========== - -Pluggables are functions that don't have an actual implementation, but receive an implementation from a plugin. - -.. autosummary:: - :toctree: generated/ - :nosignatures: - - boolean_difference_mesh_mesh - boolean_difference_polygon_polygon - boolean_intersection_mesh_mesh - boolean_intersection_polygon_polygon - boolean_symmetric_difference_polygon_polygon - boolean_union_mesh_mesh - boolean_union_polygon_polygon - conforming_delaunay_triangulation - constrained_delaunay_triangulation - delaunay_triangulation - intersection_mesh_mesh - intersection_ray_mesh - oriented_bounding_box - quadmesh_planarize - trimesh_gaussian_curvature - trimesh_geodistance - trimesh_harmonic - trimesh_isolines - trimesh_lscm - trimesh_massmatrix - trimesh_mean_curvature - trimesh_principal_curvature - trimesh_remesh - trimesh_remesh_along_isoline - trimesh_remesh_constrained - trimesh_slice - - - diff --git a/docs/api/compas.itertools.md b/docs/api/compas.itertools.md new file mode 100644 index 000000000000..151f8fc7ed44 --- /dev/null +++ b/docs/api/compas.itertools.md @@ -0,0 +1,7 @@ +# compas.itertools + +Iteration utilities for COMPAS. + +::: compas.itertools + options: + show_submodules: true diff --git a/docs/api/compas.itertools.rst b/docs/api/compas.itertools.rst deleted file mode 100644 index fe28978e66e5..000000000000 --- a/docs/api/compas.itertools.rst +++ /dev/null @@ -1,27 +0,0 @@ -******************************************************************************** -compas.itertools -******************************************************************************** - -.. currentmodule:: compas.itertools - -.. rst-class:: lead - -This package defines useful functions for working with iterable objects. - - -Functions -========= - -.. autosummary:: - :toctree: generated/ - :nosignatures: - - normalize_values - remap_values - meshgrid - linspace - flatten - reshape - pairwise - window - iterable_like diff --git a/docs/api/compas.plugins.md b/docs/api/compas.plugins.md new file mode 100644 index 000000000000..e9448af2e9c0 --- /dev/null +++ b/docs/api/compas.plugins.md @@ -0,0 +1,7 @@ +# compas.plugins + +Plugin system for COMPAS. + +::: compas.plugins + options: + show_submodules: true diff --git a/docs/api/compas.plugins.rst b/docs/api/compas.plugins.rst deleted file mode 100644 index 98200a9d3b74..000000000000 --- a/docs/api/compas.plugins.rst +++ /dev/null @@ -1,38 +0,0 @@ - -******************************************************************************** -compas.plugins -******************************************************************************** - -.. currentmodule:: compas.plugins - -.. rst-class:: lead - - -COMPAS has an extensible architecture based on plugins that allows to -customize and extend the functionality of the core framework. - - -Classes -======= - -.. autosummary:: - :toctree: generated/ - :nosignatures: - - IncompletePluginImplError - PluginDefaultNotAvailableError - PluginManager - PluginNotInstalledError - PluginValidator - - -Functions -========= - -.. autosummary:: - :toctree: generated/ - :nosignatures: - - pluggable - plugin - plugin_manager diff --git a/docs/api/compas.rpc.md b/docs/api/compas.rpc.md new file mode 100644 index 000000000000..1a4d64f48b17 --- /dev/null +++ b/docs/api/compas.rpc.md @@ -0,0 +1,7 @@ +# compas.rpc + +Remote Procedure Calls for COMPAS. + +::: compas.rpc + options: + show_submodules: true diff --git a/docs/api/compas.rpc.rst b/docs/api/compas.rpc.rst deleted file mode 100644 index f2c777476434..000000000000 --- a/docs/api/compas.rpc.rst +++ /dev/null @@ -1,31 +0,0 @@ - -******************************************************************************** -compas.rpc -******************************************************************************** - -.. currentmodule:: compas.rpc - -.. rst-class:: lead - - -COMPAS runs in many different environments, but in some environments the availablity of libraries is limited. -For example, when running COMPAS in an IronPython-based environment like Rhino/Grasshopper, -plenty of CPython libraries such as `numpy` and `scipy` are not available. -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. -Through RPC, COMPAS can be used as a server for remote clients, and as a client for remote servers. -A typical use case is to run algorithms that require packages like ``numpy`` or ``scipy`` on a remote server, when working in Rhino. -Or to use COMPAS in a browser application. - - -Classes -======= - -.. autosummary:: - :toctree: generated/ - :nosignatures: - - Dispatcher - Proxy - RPCClientError - RPCServerError - Server diff --git a/docs/api/compas.scene.md b/docs/api/compas.scene.md new file mode 100644 index 000000000000..b602e59a5770 --- /dev/null +++ b/docs/api/compas.scene.md @@ -0,0 +1,7 @@ +# compas.scene + +Visualization scenes for COMPAS. + +::: compas.scene + options: + show_submodules: true diff --git a/docs/api/compas.scene.rst b/docs/api/compas.scene.rst deleted file mode 100644 index 4a9a252bf868..000000000000 --- a/docs/api/compas.scene.rst +++ /dev/null @@ -1,56 +0,0 @@ - -******************************************************************************** -compas.scene -******************************************************************************** - -.. currentmodule:: compas.scene - -.. rst-class:: lead - - -This package defines sceneobjects for visualising COMPAS items (geometry & datastructures). -Every item type is paired with a corresponding scene object type that is capable of visualizing the data of the object. -The scene objects are implemented as pluggables, and automatically switch between plugins depending on the contexct in which they are used. - - -Classes -======= - -.. autosummary:: - :toctree: generated/ - :nosignatures: - - GeometryObject - MeshObject - GraphObject - NoSceneObjectContextError - Scene - SceneObject - SceneObjectNotRegisteredError - VolMeshObject - - -Functions -========= - -.. autosummary:: - :toctree: generated/ - :nosignatures: - - get_sceneobject_cls - register - - -Pluggables -========== - -Pluggables are functions that don't have an actual implementation, but receive an implementation from a plugin. - -.. autosummary:: - :toctree: generated/ - :nosignatures: - - clear - before_draw - after_draw - register_scene_objects diff --git a/docs/api/compas.tolerance.md b/docs/api/compas.tolerance.md new file mode 100644 index 000000000000..1f2f792cebf4 --- /dev/null +++ b/docs/api/compas.tolerance.md @@ -0,0 +1,7 @@ +# compas.tolerance + +Tolerance settings for COMPAS. + +::: compas.tolerance + options: + show_submodules: true diff --git a/docs/api/compas.tolerance.rst b/docs/api/compas.tolerance.rst deleted file mode 100644 index 71f2e5338275..000000000000 --- a/docs/api/compas.tolerance.rst +++ /dev/null @@ -1,38 +0,0 @@ - -******************************************************************************** -compas.tolerance -******************************************************************************** - -.. currentmodule:: compas.tolerance - -.. rst-class:: lead - - -The tolerance module provides functionality to deal with tolerances consistently across all other COMPAS packages. - - -Classes -======= - - - -.. autosummary:: - :toctree: generated/ - :nosignatures: - - Tolerance - - -Functions -========= - - - -.. autosummary:: - :toctree: generated/ - :nosignatures: - - TOL - - - diff --git a/docs/api/compas_blender.conversions.md b/docs/api/compas_blender.conversions.md new file mode 100644 index 000000000000..132fbdcb8ec5 --- /dev/null +++ b/docs/api/compas_blender.conversions.md @@ -0,0 +1,7 @@ +# compas_blender.conversions + +Conversions between COMPAS and Blender objects. + +::: compas_blender.conversions + options: + show_submodules: true diff --git a/docs/api/compas_blender.conversions.rst b/docs/api/compas_blender.conversions.rst deleted file mode 100644 index 1cc41157f1cc..000000000000 --- a/docs/api/compas_blender.conversions.rst +++ /dev/null @@ -1,41 +0,0 @@ - -******************************************************************************** -compas_blender.conversions -******************************************************************************** - -.. currentmodule:: compas_blender.conversions - -.. rst-class:: lead - - -This package provides functions to convert between COMPAS data/objects and Blender data/objects. - - -Functions -========= - -.. autosummary:: - :toctree: generated/ - :nosignatures: - - bmesh_to_compas - circle_to_blender_curve - color_to_blender_material - cylinder_to_blender_mesh - line_to_blender_curve - mesh_to_blender - mesh_to_compas - meshobj_to_compas - monkey_to_compas - nurbscurve_to_blender_curve - nurbssurface_to_blender_surface - pointcloud_to_blender - polygon_to_blender_mesh - polyline_to_blender_curve - sphere_to_blender_mesh - transformation_to_blender - transformation_to_compas - vertices_and_faces_to_blender_mesh - - - diff --git a/docs/api/compas_blender.geometry.md b/docs/api/compas_blender.geometry.md new file mode 100644 index 000000000000..3125747bf6a1 --- /dev/null +++ b/docs/api/compas_blender.geometry.md @@ -0,0 +1,7 @@ +# compas_blender.geometry + +Geometry classes for Blender. + +::: compas_blender.geometry + options: + show_submodules: true diff --git a/docs/api/compas_blender.geometry.rst b/docs/api/compas_blender.geometry.rst deleted file mode 100644 index 092cb82bb45c..000000000000 --- a/docs/api/compas_blender.geometry.rst +++ /dev/null @@ -1,28 +0,0 @@ - -******************************************************************************** -compas_blender.geometry -******************************************************************************** - -.. currentmodule:: compas_blender.geometry - -.. rst-class:: lead - - -This package provides plugins for various geometry pluggables using Blender as the backend. - - -Plugins -======= - -Plugins provide implementations for pluggables. You can use the plugin directly, or through the pluggable. - -.. autosummary:: - :toctree: generated/ - :nosignatures: - - boolean_difference_mesh_mesh - boolean_intersection_mesh_mesh - boolean_union_mesh_mesh - - - diff --git a/docs/api/compas_blender.scene.md b/docs/api/compas_blender.scene.md new file mode 100644 index 000000000000..8ecd862800da --- /dev/null +++ b/docs/api/compas_blender.scene.md @@ -0,0 +1,7 @@ +# compas_blender.scene + +Scene objects for Blender. + +::: compas_blender.scene + options: + show_submodules: true diff --git a/docs/api/compas_blender.scene.rst b/docs/api/compas_blender.scene.rst deleted file mode 100644 index 6f10b8f9283a..000000000000 --- a/docs/api/compas_blender.scene.rst +++ /dev/null @@ -1,45 +0,0 @@ - -******************************************************************************** -compas_blender.scene -******************************************************************************** - -.. currentmodule:: compas_blender.scene - -.. rst-class:: lead - - -This package provides scene object plugins for visualising COMPAS objects in Blender. -When working in Blender, :class:`compas.scene.SceneObject` will automatically use the corresponding Blender scene object for each COMPAS object type. - - -Classes -======= - -.. autosummary:: - :toctree: generated/ - :nosignatures: - - BlenderSceneObject - BoxObject - CapsuleObject - CircleObject - ConeObject - CurveObject - CylinderObject - FrameObject - LineObject - MeshObject - GraphObject - PointObject - PointcloudObject - PolygonObject - PolyhedronObject - PolylineObject - SphereObject - SurfaceObject - TorusObject - VectorObject - VolMeshObject - - - diff --git a/docs/api/compas_ghpython.components.md b/docs/api/compas_ghpython.components.md new file mode 100644 index 000000000000..ca77404d7ff8 --- /dev/null +++ b/docs/api/compas_ghpython.components.md @@ -0,0 +1,7 @@ +# compas_ghpython.components + +Grasshopper components for COMPAS. + +::: compas_ghpython.components + options: + show_submodules: true diff --git a/docs/api/compas_ghpython.components.rst b/docs/api/compas_ghpython.components.rst deleted file mode 100644 index 23c45915f1d4..000000000000 --- a/docs/api/compas_ghpython.components.rst +++ /dev/null @@ -1,21 +0,0 @@ - -******************************************************************************** -compas_ghpython.components -******************************************************************************** - -.. currentmodule:: compas_ghpython.components - -.. rst-class:: lead - -This package provides a small set of functions to easily install and uninstall user-defined GH Components. - - -Functions -========= - -.. autosummary:: - :toctree: generated/ - :nosignatures: - - install_userobjects - uninstall_userobjects diff --git a/docs/api/compas_ghpython.scene.md b/docs/api/compas_ghpython.scene.md new file mode 100644 index 000000000000..9e4e3b67e4b7 --- /dev/null +++ b/docs/api/compas_ghpython.scene.md @@ -0,0 +1,7 @@ +# compas_ghpython.scene + +Scene objects for Grasshopper. + +::: compas_ghpython.scene + options: + show_submodules: true diff --git a/docs/api/compas_ghpython.scene.rst b/docs/api/compas_ghpython.scene.rst deleted file mode 100644 index 87f7258b9257..000000000000 --- a/docs/api/compas_ghpython.scene.rst +++ /dev/null @@ -1,45 +0,0 @@ - -******************************************************************************** -compas_ghpython.scene -******************************************************************************** - -.. currentmodule:: compas_ghpython.scene - -.. rst-class:: lead - - -This package provides scene object plugins for visualising COMPAS objects in Grasshopper. -When working in GH Python components, :class:`compas.scene.SceneObject` will automatically use the corresponding GHPython scene object for each COMPAS object type. - - -Classes -======= - -.. autosummary:: - :toctree: generated/ - :nosignatures: - - BoxObject - CapsuleObject - CircleObject - ConeObject - CurveObject - CylinderObject - EllipseObject - FrameObject - GHSceneObject - LineObject - MeshObject - GraphObject - PointObject - PolygonObject - PolyhedronObject - PolylineObject - SphereObject - SurfaceObject - TorusObject - VectorObject - VolMeshObject - - - diff --git a/docs/api/compas_rhino.conversions.md b/docs/api/compas_rhino.conversions.md new file mode 100644 index 000000000000..2ea94341373d --- /dev/null +++ b/docs/api/compas_rhino.conversions.md @@ -0,0 +1,7 @@ +# compas_rhino.conversions + +Conversions between COMPAS and Rhino objects. + +::: compas_rhino.conversions + options: + show_submodules: true diff --git a/docs/api/compas_rhino.conversions.rst b/docs/api/compas_rhino.conversions.rst deleted file mode 100644 index 1011a291aa4a..000000000000 --- a/docs/api/compas_rhino.conversions.rst +++ /dev/null @@ -1,96 +0,0 @@ - -******************************************************************************** -compas_rhino.conversions -******************************************************************************** - -.. currentmodule:: compas_rhino.conversions - -.. rst-class:: lead - - -This package provides functions to convert between COMPAS data/objects and Rhino data/objects. - - -Classes -======= - -.. autosummary:: - :toctree: generated/ - :nosignatures: - - ConversionError - - -Functions -========= - -.. autosummary:: - :toctree: generated/ - :nosignatures: - - arc_to_compas - arc_to_rhino - box_to_compas - box_to_rhino - brep_to_compas_box - brep_to_compas_cone - brep_to_compas_cylinder - brep_to_compas_sphere - brep_to_rhino - capsule_to_rhino_brep - circle_to_compas - circle_to_rhino - circle_to_rhino_curve - cone_to_compas - cone_to_rhino - cone_to_rhino_brep - curve_to_compas_circle - curve_to_compas_ellipse - curve_to_compas_line - curve_to_compas_polyline - curve_to_rhino - cylinder_to_compas - cylinder_to_rhino - cylinder_to_rhino_brep - data_to_rhino_surface - ellipse_to_compas - ellipse_to_rhino - ellipse_to_rhino_curve - extrusion_to_compas_box - extrusion_to_compas_cylinder - extrusion_to_compas_torus - frame_to_rhino - frame_to_rhino_plane - line_to_compas - line_to_rhino - line_to_rhino_curve - mesh_to_compas - mesh_to_rhino - plane_to_compas - plane_to_compas_frame - plane_to_rhino - point_to_compas - point_to_rhino - polygon_to_compas - polygon_to_rhino - polyhedron_to_rhino - polyline_to_compas - polyline_to_rhino - polyline_to_rhino_curve - sphere_to_compas - sphere_to_rhino - surface_to_compas - surface_to_compas_data - surface_to_compas_mesh - surface_to_compas_quadmesh - surface_to_rhino - torus_to_rhino - torus_to_rhino_brep - transformation_matrix_to_rhino - transformation_to_rhino - vector_to_compas - vector_to_rhino - vertices_and_faces_to_rhino - - - diff --git a/docs/api/compas_rhino.geometry.md b/docs/api/compas_rhino.geometry.md new file mode 100644 index 000000000000..1996da1e16ce --- /dev/null +++ b/docs/api/compas_rhino.geometry.md @@ -0,0 +1,7 @@ +# compas_rhino.geometry + +Geometry classes for Rhino. + +::: compas_rhino.geometry + options: + show_submodules: true diff --git a/docs/api/compas_rhino.geometry.rst b/docs/api/compas_rhino.geometry.rst deleted file mode 100644 index cc3f16233f9f..000000000000 --- a/docs/api/compas_rhino.geometry.rst +++ /dev/null @@ -1,49 +0,0 @@ - -******************************************************************************** -compas_rhino.geometry -******************************************************************************** - -.. currentmodule:: compas_rhino.geometry - -.. rst-class:: lead - - -This package provides plugins for various geometry pluggables using Rhino as the backend. - - -Classes -======= - -.. autosummary:: - :toctree: generated/ - :nosignatures: - - RhinoBrep - RhinoBrepEdge - RhinoBrepFace - RhinoBrepLoop - RhinoBrepTrim - RhinoBrepVertex - RhinoNurbsCurve - RhinoNurbsSurface - - -Plugins -======= - -Plugins provide implementations for pluggables. You can use the plugin directly, or through the pluggable. - -.. autosummary:: - :toctree: generated/ - :nosignatures: - - boolean_difference_mesh_mesh - boolean_intersection_mesh_mesh - boolean_union_mesh_mesh - trimesh_gaussian_curvature - trimesh_mean_curvature - trimesh_principal_curvature - trimesh_slice - - - diff --git a/docs/api/compas_rhino.scene.md b/docs/api/compas_rhino.scene.md new file mode 100644 index 000000000000..7636e5278ccb --- /dev/null +++ b/docs/api/compas_rhino.scene.md @@ -0,0 +1,7 @@ +# compas_rhino.scene + +Scene objects for Rhino. + +::: compas_rhino.scene + options: + show_submodules: true diff --git a/docs/api/compas_rhino.scene.rst b/docs/api/compas_rhino.scene.rst deleted file mode 100644 index dbf8519241de..000000000000 --- a/docs/api/compas_rhino.scene.rst +++ /dev/null @@ -1,47 +0,0 @@ - -******************************************************************************** -compas_rhino.scene -******************************************************************************** - -.. currentmodule:: compas_rhino.scene - -.. rst-class:: lead - - -This package provides scene object plugins for visualising COMPAS objects in Rhino. -When working in Rhino, :class:`compas.scene.SceneObject` will automatically use the corresponding Rhino scene object for each COMPAS object type. - - -Classes -======= - -.. autosummary:: - :toctree: generated/ - :nosignatures: - - RhinoBoxObject - RhinoBrepObject - RhinoCapsuleObject - RhinoCircleObject - RhinoConeObject - RhinoCurveObject - RhinoCylinderObject - RhinoEllipseObject - RhinoFrameObject - RhinoLineObject - RhinoMeshObject - RhinoGraphObject - RhinoPlaneObject - RhinoPointObject - RhinoPolygonObject - RhinoPolyhedronObject - RhinoPolylineObject - RhinoSceneObject - RhinoSphereObject - RhinoSurfaceObject - RhinoTorusObject - RhinoVectorObject - RhinoVolMeshObject - - - diff --git a/docs/api/index.md b/docs/api/index.md new file mode 100644 index 000000000000..b0ed3e912061 --- /dev/null +++ b/docs/api/index.md @@ -0,0 +1,45 @@ +# API Reference + +## compas + +This package is the core package of the COMPAS framework. +It defines all functionality for geometry processing, +data structures, topology, numerical methods, robotics, the plugin mechanism, remote procedure calls... +and can be used independently of CAD systems in any environment that supports Python programming. + +- [compas.colors](compas.colors.md) - Color handling +- [compas.data](compas.data.md) - Data serialization +- [compas.datastructures](compas.datastructures.md) - Core data structures +- [compas.files](compas.files.md) - File I/O +- [compas.geometry](compas.geometry.md) - Geometry processing +- [compas.itertools](compas.itertools.md) - Iteration utilities +- [compas.plugins](compas.plugins.md) - Plugin system +- [compas.rpc](compas.rpc.md) - Remote procedure calls +- [compas.scene](compas.scene.md) - Visualization scenes +- [compas.tolerance](compas.tolerance.md) - Tolerance settings + +## compas_blender + +This package provides functionality for reading and writing Blender geometry, for visualising +COMPAS geometry and data structures in Blender, and for basic user interaction. + +- [compas_blender.conversions](compas_blender.conversions.md) +- [compas_blender.geometry](compas_blender.geometry.md) +- [compas_blender.scene](compas_blender.scene.md) + +## compas_ghpython + +This package provides functionality for reading and writing Rhino geometry, and for visualising +COMPAS geometry and data structures in Rhino, through GHPython. + +- [compas_ghpython.components](compas_ghpython.components.md) +- [compas_ghpython.scene](compas_ghpython.scene.md) + +## compas_rhino + +This package provides functionality for reading and writing Rhino geometry, for visualising +COMPAS geometry and data structures in Rhino, and for basic user interaction. + +- [compas_rhino.conversions](compas_rhino.conversions.md) +- [compas_rhino.geometry](compas_rhino.geometry.md) +- [compas_rhino.scene](compas_rhino.scene.md) diff --git a/docs/api/index.rst b/docs/api/index.rst deleted file mode 100644 index ea028c7fa64c..000000000000 --- a/docs/api/index.rst +++ /dev/null @@ -1,75 +0,0 @@ - -******************************************************************************** -API Reference -******************************************************************************** - -compas ------- - -This package is the core package of the COMPAS framework. -It defines all functionality for geometry processing, -data structures, topology, numerical methods, robotics, the plugin mechanism, remote procedure calls ... -and can be used independently of CAD systems in any environment that supports Python programming. - -.. toctree:: - :maxdepth: 1 - :titlesonly: - :caption: compas - - compas.colors - compas.data - compas.datastructures - compas.files - compas.geometry - compas.itertools - compas.plugins - compas.rpc - compas.scene - compas.tolerance - - -compas_blender --------------- - -This package provides functionality for reading and writing Blender geometry, for visualising -COMPAS geometry and data structures in Blender, and for basic user inter interaction. - -.. toctree:: - :maxdepth: 1 - :titlesonly: - :caption: compas_blender - - compas_blender.conversions - compas_blender.geometry - compas_blender.scene - - -compas_ghpython ---------------- - -This package provides functionality for reading and writing Rhino geometry, and for visualising -COMPAS geometry and data structures in Rhino, through GHPython. - -.. toctree:: - :maxdepth: 1 - :titlesonly: - :caption: compas_ghpython - - compas_ghpython.components - compas_ghpython.scene - - -compas_rhino ------------- - -This package provides functionality for reading and writing Rhino geometry, for visualising -COMPAS geometry and data structures in Rhino, and for basic user inter interaction. - -.. toctree:: - :maxdepth: 1 - :titlesonly: - :caption: compas_rhino - - compas_rhino.conversions - compas_rhino.geometry - compas_rhino.scene diff --git a/docs/conf.py b/docs/conf.py deleted file mode 100644 index 224f7bb03a2c..000000000000 --- a/docs/conf.py +++ /dev/null @@ -1,161 +0,0 @@ -# flake8: noqa -# -*- coding: utf-8 -*- - -from sphinx.writers import html, html5 -import sphinx_compas2_theme - -# -- General configuration ------------------------------------------------ - -project = "COMPAS" -copyright = "COMPAS Association" -author = "Tom Van Mele" -organization = "compas-dev" -package = "compas" - -master_doc = "index" -source_suffix = {".rst": "restructuredtext", ".md": "markdown"} -templates_path = sphinx_compas2_theme.get_autosummary_templates_path() -exclude_patterns = sphinx_compas2_theme.default_exclude_patterns -add_module_names = True -language = "en" - -latest_version = sphinx_compas2_theme.get_latest_version() - -if latest_version == "Unreleased": - release = "Unreleased" - version = "latest" -else: - release = latest_version - version = ".".join(release.split(".")[0:2]) # type: ignore - -# -- Extension configuration ------------------------------------------------ - -extensions = sphinx_compas2_theme.default_extensions - -# numpydoc options - -numpydoc_show_class_members = False -numpydoc_class_members_toctree = False -numpydoc_attributes_as_param_list = True -numpydoc_show_inherited_class_members = False - -# bibtex options - -# autodoc options - -autodoc_type_aliases = {} -autodoc_typehints_description_target = "documented" -autodoc_mock_imports = sphinx_compas2_theme.default_mock_imports -autodoc_default_options = { - "undoc-members": True, - "show-inheritance": True, -} -autodoc_member_order = "groupwise" -autodoc_typehints = "description" -autodoc_class_signature = "separated" - -autoclass_content = "class" - - -def setup(app): - app.connect("autodoc-skip-member", sphinx_compas2_theme.skip) - - -# autosummary options - -autosummary_generate = True -autosummary_mock_imports = sphinx_compas2_theme.default_mock_imports - -# graph options - -# plot options - -# intersphinx options - -intersphinx_mapping = { - "python": ("https://docs.python.org/", None), - "compas": ("https://compas.dev/compas/latest/", None), -} - -# linkcode - -linkcode_resolve = sphinx_compas2_theme.get_linkcode_resolve(organization, package) - -# extlinks - -extlinks = { - "rhino": ("https://developer.rhino3d.com/api/RhinoCommon/html/T_%s.htm", "%s"), - "blender": ("https://docs.blender.org/api/2.93/%s.html", "%s"), -} - -# from pytorch - -sphinx_compas2_theme.replace(html.HTMLTranslator) -sphinx_compas2_theme.replace(html5.HTML5Translator) - -# -- Options for HTML output ---------------------------------------------- - -html_theme = "multisection" -html_title = project -html_sidebars = {"index": []} - -favicons = [ - { - "rel": "icon", - "href": "compas.ico", - } -] - -html_theme_options = { - "external_links": [ - {"name": "COMPAS Framework", "url": "https://compas.dev"}, - ], - "icon_links": [ - { - "name": "GitHub", - "url": f"https://github.com/{organization}/{package}", - "icon": "fa-brands fa-github", - "type": "fontawesome", - }, - { - "name": "Discourse", - "url": "http://forum.compas-framework.org/", - "icon": "fa-brands fa-discourse", - "type": "fontawesome", - }, - { - "name": "PyPI", - "url": f"https://pypi.org/project/{package}/", - "icon": "fa-brands fa-python", - "type": "fontawesome", - }, - ], - "switcher": { - "json_url": f"https://raw.githubusercontent.com/{organization}/{package}/gh-pages/versions.json", - "version_match": version, - }, - "logo": { - "image_light": "_static/compas_icon_white.png", - "image_dark": "_static/compas_icon_white.png", - "text": "COMPAS docs", - }, - "navigation_depth": 2, -} - -html_context = { - "github_url": "https://github.com", - "github_user": organization, - "github_repo": package, - "github_version": "main", - "doc_path": "docs", -} - -html_static_path = sphinx_compas2_theme.get_html_static_path() + ["_static"] -html_css_files = [] -html_extra_path = [] -html_last_updated_fmt = "" -html_copy_source = False -html_show_sourcelink = True -html_permalinks = False -html_permalinks_icon = "" -html_compact_lists = True diff --git a/docs/devguide/code.md b/docs/devguide/code.md new file mode 100644 index 000000000000..9c331d63833c --- /dev/null +++ b/docs/devguide/code.md @@ -0,0 +1,171 @@ +# Code Contributions + +!!! note + + For the proper way of contributing code to COMPAS, please follow the [Development Workflow](workflow.md). + +To keep code clean, consistent and readable we try to follow the following guidelines when developing COMPAS. +Generally, we try to follow the [PEP8](https://peps.python.org/pep-0008/) style guide for Python code. + +## Naming conventions + +!!! note + + When naming **variables**, **functions**, **classes** and **modules** it is important to take the time and choose meaningful names. + Names should be short but descriptive and ideally unambiguous in the field they are intended to be used. + +**Classes** should be named using the `CamelCase` convention + +```python +class MyClass(object): + ... +``` + +**Functions**, **methods**, **arguments** and **local/member variables** should be named using the `snake_case` convention + +```python +def my_function(): + ... + +def add(self, x, y): + result = x + y + return result +``` + +**Functions**, **methods** and **member variables** which are intended for internal use only should be prefixed with an `_` (underscore) + +```python +class Rectangle(object): + + def __init__(self, width, length): + self._width = width + self._length = length + self._area = None + self._init_class() + + def _init_class(): + self._area = self._width * self._length + + @staticmethod + def _some_helper_function(): + ... +``` + +**Class attributes** should be named using all caps and underscores + +```python +class MyClass(object): + MY_CONSTANT = 42 + + def __init__(self): + self.my_attribute = 0 + + def my_method(self): + return self.my_attribute + self.MY_CONSTANT +``` + +## Line length + +**COMPAS uses a line length of 180 characters**. While longer than the 80 characters recommended by `PEP8`, it is in our opinion a more reasonable limit for modern displays. + +**Indentations are 4 spaces**. Tab to spaces setting can be set in `.editorconfig` which is respected by most editors. For more information see [EditorConfig](https://editorconfig.org/). + +## Imports + +Imports are grouped in the following order with a blank line between each group: + +1. Python standard library imports +2. Third party imports +3. Local application imports + +Single-item imports are preferred over multi-item imports + +```python +# use: +from compas.geometry import Frame +from compas.geometry import Point + +# instead of: +from compas.geometry import Frame, Point +``` + +Star (`*`) imports should be avoided. + +## Second-level imports + +To keep the API clean and consistent, any new public functions or classes should be importable from a second-level package. +This is achieved by importing the function or class in the `__init__.py` file of the package. + +For example: + +``` +compas +├── __init__.py +└── my_package + ├── __init__.py + └── new_module.py +``` + +```python +# new_module.py +class NewClass(object): + ... +``` + +```python +# compas.my_package.__init__.py +from .new_module import NewClass + +__all__ = ['NewClass'] +``` + +The result should be: + +```python +>>> from compas.my_package import NewClass +``` + +## Comments + +The code should be self-explanatory and comments should be used sparingly. However, if a portion of the code is best understood in a certain context, a comment could be added. + +```python +def my_function(): + # while seems unlikely, 42 is the answer to everything + return some_piece_of_code() + 42 +``` + +## Docstrings + +Docstrings in the COMPAS ecosystem follow the [NumPy style docstrings](https://numpydoc.readthedocs.io/en/latest/format.html). +These docstrings are later used to generate the API documentation. + +Therefore, it is important that functions and methods have at least the following docstrings: + +```python +def my_function(point, line): + """This is a one-line description of the function. + + This is a longer description of the function. + It can span multiple lines. + + Parameters + ---------- + point : :class:`~compas.geometry.Point` + Point to check. + line : :class:`~compas.geometry.Line` + Line to analyze. + + Returns + ------- + :class:`~compas.geometry.Plane` + The resulting plane of the operation. + + """ + ... +``` + +## Python 2.7 compatibility + +**To keep COMPAS usable in Rhino, we make sure to maintain Python 2.7 compatibility** in parts of the package which are used in Rhino. +Packages that are not intended to be used in Rhino can utilise Python 3 features. diff --git a/docs/devguide/code.rst b/docs/devguide/code.rst deleted file mode 100644 index 8e182d8ca292..000000000000 --- a/docs/devguide/code.rst +++ /dev/null @@ -1,180 +0,0 @@ -.. _code-contributions: - -Code Contributions -=================== - -.. note:: - For the proper way of contributing code to COMPAS, please follow the :ref:`development-workflow`. - -To keep code clean, consistent and readable we try to follow the following guidelines when developing COMPAS. -Generally, we try to follow the `PEP8 `_ style guide for Python code. - -Naming conventions ------------------- - -.. note:: - - When naming **variables**, **functions**, **classes** and **modules** it is important to take the time and choose meaningful names. - Names should be short but descriptive and ideally unambiguous in the field they are intended to be used. - -**Classes** should be named using the ``CamelCase`` convention - -.. code-block:: python - - class MyClass(object): - ... - -**Functions**, **methods**, **arguments** and **local/member variables** should be named using the ``snake_case`` convention - -.. code-block:: python - - def my_function(): - ... - - def add(self, x, y): - result = x + y - return result - -**Functions**, **methods** and **member variables** which are intended for internal use only should be prefixed with an ``_`` (underscore) - -.. code-block:: python - - class Rectangle(object): - - def __init__(self, width, lentgh): - self._width = width - self._length = length - self._area = None - self._init_class() - - def _init_class(): - self._area = self._width * self._length - - @staticmethod - def _some_helper_function(): - ... - - -**Class attributes** should be named using all caps and underscores - -.. code-block:: python - - class MyClass(object): - MY_CONSTANT = 42 - - def __init__(self): - self.my_attribute = 0 - - def my_method(self): - return self.my_attribute + self.MY_CONSTANT - -Line length ------------ - -**COMPAS uses a line length of 180 characters**. While longer than the 80 characters recommended by ``PEP8``, it is in our opinion a more reasonable limit for modern displays. - -**Indentations are 4 spaces**. Tab to spaces setting can be set in ``.editorconfig`` which is respected by most editors. For more information see `EditorConfig `_. - -Imports -------- - -Imports are grouped in the following order with a blank line between each group: - -1. Python standard library imports -2. Third party imports -3. Local application imports - -Single-item imports are preferred over multi-item imports - -.. code-block:: python - - # use: - from compas.geometry import Frame - from compas.geometry import Point - - # instead of: - from compas.geometry import Frame, Point - -Star (``*``) imports should be avoided. - -Second-level imports --------------------- -To keep the API clean and consistent, any new public functions or classes should be importable from a second-level package. -This is achieved by importing the function or class in the ``__init__.py`` file of the package. - -For example: - -.. code-block:: bash - - compas - ├── __init__.py - └── my_package - ├── __init__.py - └── new_module.py - -.. code-block:: python - - # new_module.py - class NewClass(object): - ... - -.. code-block:: python - - # compas.my_package.__init__.py - from .new_module import NewClass - - __all__ = ['NewClass'] - -The result should be: - -.. code-block:: python - - >>> from compas.my_package import NewClass - -Comments --------- - -The code should be self-explanatory and comments should be used sparingly. However, if a portion of the code is best understood in a certain context, a comment could be added. - -.. code-block:: python - - def my_function(): - # while seems unlikely, 42 is the answer to everything - return some_piece_of_code() + 42 - -Docstrings ----------- - -Docstings in the COMPAS ecosystem follow the `NumPy style docstrings `_. -These docstrings are later used by `Sphinx `_ to generate the API documentation. - -Therefore, it is important that functions and methods have at least the following docstrings: - -.. code-block:: python - - def my_function(point, line): - """This is a one-line description of the function. - - This is a longer description of the function. - It can span multiple lines. - - Parameters - ---------- - point : :class:`~compas.geometry.Point` - Point to check. - line : :class:`~compas.geometry.Line` - Line to analyze. - - Returns - ------- - :class:`~compas.geometry.Plane` - The resulting plane of the operation. - - """ - ... - -Python 2.7 compatibility ------------------------- - -**To keep COMPAS usable in Rhino, we make sure to maintain Python 2.7 compatibility** in parts of the package which are used in Rhino. -Packages that are not intended to be used in Rhino can utilise Python 3 features. diff --git a/docs/devguide/documentation.md b/docs/devguide/documentation.md new file mode 100644 index 000000000000..bda60ec03fc1 --- /dev/null +++ b/docs/devguide/documentation.md @@ -0,0 +1,51 @@ +# Documentation + +This section covers how to write and build documentation for COMPAS. + +## Building the docs + +To build the documentation locally: + +```bash +mkdocs serve +``` + +This will start a local server and you can view the documentation at `http://localhost:8000`. + +To build the documentation for deployment: + +```bash +mkdocs build +``` + +## Writing documentation + +Documentation is written in Markdown and stored in the `docs/` directory. + +### API documentation + +API documentation is automatically generated from docstrings using mkdocstrings. + +To reference a class or function in the documentation: + +```markdown +See [`Point`][compas.geometry.Point] for more information. +``` + +### Admonitions + +Use admonitions to highlight important information: + +```markdown +!!! note + + This is a note. + +!!! warning + + This is a warning. + +!!! tip + + This is a tip. +``` diff --git a/docs/devguide/documentation.rst b/docs/devguide/documentation.rst deleted file mode 100644 index 09f7ec41593c..000000000000 --- a/docs/devguide/documentation.rst +++ /dev/null @@ -1,2 +0,0 @@ -Contributing to the Documentation -================================= diff --git a/docs/devguide/dtypes.md b/docs/devguide/dtypes.md new file mode 100644 index 000000000000..6fdf3dbe9c97 --- /dev/null +++ b/docs/devguide/dtypes.md @@ -0,0 +1,5 @@ +# Data Types + +This section covers working with data types in COMPAS. + +For more information, see the API reference for [`compas.data`][compas.data]. diff --git a/docs/devguide/dtypes.rst b/docs/devguide/dtypes.rst deleted file mode 100644 index 07aa041a850b..000000000000 --- a/docs/devguide/dtypes.rst +++ /dev/null @@ -1,184 +0,0 @@ -Implementing a New Data Type -============================ - -COMPAS data types are classes that are based on :class:`compas.data.Data`. - -Data types can be serialized to JSON with - -* :func:`compas.json_dump` -* :func:`compas.json_dumps` -* :func:`compas.json_dumpz` - -and deserialized with the corresponding "load" functions - -* :func:`compas.json_load` -* :func:`compas.json_loads` -* :func:`compas.json_loadz` - -All geometry objects and data structures, -and also, for example, the visualization scene, -are serializable data types. - - -Creating a new data type -======================== - -In most cases, it is sufficient to implement the ``__data__`` property when creating your custom `Data` class. - -.. code-block:: python - - class SomeThing(Data): - - def __init__(self, a, b) - super().__init__() - # note that if the code needs to be compatible with IronPython - # you should write the following: - # super(SomeThing, self).__init__() - self.a = a - self.b = b - - @property - def __data__(self): - return { - "a": self.a, - "b": self.b, - } - - ->>> custom = SomeThing(a=1, b=2) ->>> compas.json_dump(custom, "custom.json") ->>> result = compas.json_load("custom.json") ->>> isinstance(result, SomeThing) -True ->>> result.a -1 ->>> result.b -2 - -If the attributes stored in the data dictionary defined by the ``__data__`` property -are different from the initialization parameters of the class, -you must also customize the ``__from_data__`` class method to compensate for the difference. - -.. code-block:: python - - class SomeThing(Data): - - def __init__(self) - super().__init__() - # note that if the code needs to be compatible with IronPython - # you should write the following: - # super(SomeThing, self).__init__() - self.items = [] - - @property - def __data__(self): - return { - "items": self.items, - } - - @classmethod - def __from_data__(cls, data): - custom = cls() - for item in data['items']: - custom.add(item) - return custom - - def add(self, item): - self.items.append(item) - - ->>> custom = SomeThing() ->>> custom.add(1) ->>> custom.add(2) ->>> compas.json_dump(custom, "custom.json") ->>> result = compas.json_load("custom.json") ->>> isinstance(result, SomeThing) -True ->>> result.items -[1, 2] - - -Attribute types -=============== - -Any attribute that is an instance of a Python base type or a serializable COMPAS data object -can be included in the data dict created by the ``__data__`` property without further processing. -The serialization process will recursively serialize all these attributes. - -.. code-block:: python - - class SomeThing(Data): - - def __init__(self, point, frame, mesh): - super().__init__() - # note that if the code needs to be compatible with IronPython - # you should write the following: - # super(SomeThing, self).__init__() - self.point = point - self.frame = frame - self.mesh = mesh - - @property - def __data__(self): - return { - "point": self.point, - "frame": self.frame, - "mesh": self.mesh, - } - - ->>> import compas ->>> from compas.geometry import Point, Frame ->>> from compas.datastructures import Mesh ->>> point = Point(1, 2, 3) ->>> frame = Frame() ->>> mesh = Mesh.from_meshgrid(10, 10) ->>> custom = SomeThing(point, frame, mesh) ->>> compas.json_dump(custom, "custom.json") ->>> result = compas.json_load("custom.json") ->>> isinstance(result.point, Point) -True ->>> isinstance(result.frame, Frame) -True ->>> isinstance(result.mesh, Mesh) -True ->>> result.point == point -True ->>> result.point is point -False - - -Note that the the automatic serialization process will incur overhead information -that increases the size of the resulting JSON file. -The performance impact may be significant when many of these instances are serialized. - -To avoid this, anticipated conversions can be included explicitly in `__data__` and `__from_data__`. - -.. code-block:: python - - class SomeThing(Data): - - def __init__(self, point, frame, mesh): - super().__init__() - # note that if the code needs to be compatible with IronPython - # you should write the following: - # super(SomeThing, self).__init__() - self.point = point - self.frame = frame - self.mesh = mesh - - @property - def __data__(self): - return { - "point": self.point.__data__, - "frame": self.frame.__data__, - "mesh": self.mesh.__data__, - } - - @classmethod - def __from_data__(cls, data): - return cls( - Point.__from_data__(data['point']), - Frame.__from_data__(data['frame']), - Mesh.__from_data__(data['mesh']), - ) diff --git a/docs/devguide/extensions.md b/docs/devguide/extensions.md new file mode 100644 index 000000000000..4a546e360908 --- /dev/null +++ b/docs/devguide/extensions.md @@ -0,0 +1,3 @@ +# Extensions + +This section covers how to create COMPAS extensions. diff --git a/docs/devguide/extensions.rst b/docs/devguide/extensions.rst deleted file mode 100644 index fec52cfa5ab4..000000000000 --- a/docs/devguide/extensions.rst +++ /dev/null @@ -1,2 +0,0 @@ -Developing an Extension -======================= diff --git a/docs/devguide/ghcomponent.md b/docs/devguide/ghcomponent.md new file mode 100644 index 000000000000..2e384ec7ff95 --- /dev/null +++ b/docs/devguide/ghcomponent.md @@ -0,0 +1,5 @@ +# Grasshopper Components + +This section covers how to create Grasshopper components for COMPAS. + +For more information, see the API reference for [`compas_ghpython.components`][compas_ghpython.components]. diff --git a/docs/devguide/ghcomponent.rst b/docs/devguide/ghcomponent.rst deleted file mode 100644 index 78327b7a75a7..000000000000 --- a/docs/devguide/ghcomponent.rst +++ /dev/null @@ -1,182 +0,0 @@ -.. _developing-components: - -Developing a GH Component -========================== - -The COMPAS ecosystem offers excellent integration with Grasshopper. Thanks to the `GHPython Componentizer `_ -it is possible to write Grasshopper components in Python, in a git friendly way, including the components' code in the same repository as the rest of your project. - -.. note:: - - To develop GH components using the GHPython Componentizer, you would need a development setup of COMPAS. See :ref:`dev_setup` for more information. - -GHPython Componentizer ----------------------- - -To use the Componentizer, it is recommended that your project's repository be made from the `cookiecutter template for COMPAS packages `_. -This takes care of a lot of the boilerplate code, and makes compiling and installing the components so much easier. - -The ``ghuser`` section in the ``tasks.py`` file of your project tell the Componentizer where to find the source code of your components, and where to put the generated components. - -By default, the components' code is expected in ``src/{your_package_name}/components`` folder of your project. - -.. code-block:: python - - ns.configure( - { - "ghuser": { - "source_dir": "src/compas_bananas/components", - "target_dir": "src/compas_bananas/components/ghuser", - "prefix": "(COMPAS_BANANAS)", - }, - } - ) - -Creating a component --------------------- - -Inside the ``source_dir`` folder, each component shall have its own folder with the following three files: - -1. ``code.py`` - this is where our component's code goes -2. ``metadata.json`` - this is where we let the Componentizer know about different settings of our component -3. ``icon.png`` - this icon will appear in GH. It must be exactly 24x24 pixels. - -.. note:: - - By convension, we name the component folders with a two letter prefix, followed by an underscore, followed by the name of the component. For example, ``Cb_ExampleComponent``. - -.. code-block:: bash - - src/compas_bananas/components/Cb_ExampleComponent - ├── code.py - ├── icon.png - └── metadata.json - -Metadata --------- - -A typical ``metadata.json`` file has the following structure: - -.. code-block:: json - - { - "name": "Example Component", - "nickname": "Example", - "category": "COMPAS Bananas", - "subcategory": "Example", - "description": "This is an example component.", - "exposure": 4, - "ghpython": { - "isAdvancedMode": true, - "iconDisplay": 0, - "inputParameters": [ - { - "name": "Arg1", - "description": "First example argument.", - "typeHintID": "none", - "scriptParamAccess": 1 - }, - { - "name": "Arg2", - "description": "Second example argument.", - "typeHintID": "bool", - "scriptParamAccess": 0 - } - ], - "outputParameters": [ - { - "name": "Output1", - "description": "First output." - }, - { - "name": "Output2", - "description": "Second output." - } - ] - } - } - -For more information about the required fields and their possible values please visit `GHPython Componentizer `_. - -Code ----- - -The GHPython Componentizer only supports GHPython components in advanced mode. -This means each component must inherit from the ``ghpythonlib.component`` class and implement the ``RunScript()`` method. - -A typical ``code`` file might look like this: - -.. code-block:: python - - from ghpythonlib.componentbase import executingcomponent as component - - class ExampleComponent(component): - - def RunScript(self, Input1, Input2): - # do the work here - Output1 = None - Output2 = None - return Output1, Output2 - -Please not that the inputs to the ``RunScript()`` method must match the ones defined in the ``metadata.json`` file by name and number. -The outputs must also match the ones defined in the ``metadata.json`` file by name and number. - -Icon ----- - -Finally, the component's folder must include an icon used to represent the component in GH. -The icon must be a 24x24 pixel PNG file named ``icon.png``. - -Compiling the components ------------------------- - -.. note:: - - IronPython 2.7 must be installed on your system in order to run the Componentizer. - You can download it from `here `_ - -In order to run the Componentizer make sure your dev virtual environment is activated and run - -.. code-block:: bash - - invoke build-ghuser-components - -If everything went well, you should see at least the following output: - -.. code-block:: bash - - Processing component bundles: - [x] Cb_ExampleComponent => C:\Users\path_to_repo\src\project_slug\ghpython\components\ghuser\Cb_ExampleComponent.ghuser - -If any error occurs, the Componentizer will let you know what went wrong. - -Installing the components to Rhino ----------------------------------- - -Once the components are compiled, and are in the ``target_dir`` folder, you can install them to Rhino by running - -.. code-block:: bash - - python -m compas_rhino.install -v 7.0 - -.. code-block:: bash - - You should then see - - Installing COMPAS packages to Rhino 7.0 scripts folder: - C:\Users\username\AppData\Roaming\McNeel\Rhinoceros\7.0\scripts - - compas OK - compas_ghpython OK - compas_rhino OK - compas_bananas OK - - Running post-installation steps... - - compas_bananas OK: Installed 1 GH User Objects - - -You component should now appear in Grasshopper - -.. image:: ../_images/ghpython_custom.jpg - :align: center diff --git a/docs/devguide/index.md b/docs/devguide/index.md new file mode 100644 index 000000000000..b8c42ebf3078 --- /dev/null +++ b/docs/devguide/index.md @@ -0,0 +1,17 @@ +# Developer Guide + +This guide is intended for developers who want to contribute to the code and/or documentation of COMPAS. + +## Development Basics + +- [Setup](setup.md) - Set up your development environment +- [Workflow](workflow.md) - Development workflow and contributing +- [Code Style](code.md) - Code style guidelines +- [Documentation](documentation.md) - Writing documentation + +## Advanced Topics + +- [Extensions](extensions.md) - Creating COMPAS extensions +- [Plugins](plugins.md) - Creating COMPAS plugins +- [GH Components](ghcomponent.md) - Creating Grasshopper components +- [Data Types](dtypes.md) - Working with data types diff --git a/docs/devguide/index.rst b/docs/devguide/index.rst deleted file mode 100644 index d7a92a2fe1b9..000000000000 --- a/docs/devguide/index.rst +++ /dev/null @@ -1,24 +0,0 @@ -Developer Guide -=============== - -This guide is intended for developers who want to contribute to the code and/or documentation of COMPAS. - -.. toctree:: - :maxdepth: 1 - :titlesonly: - :caption: Development Basics - - setup - workflow - code - documentation - -.. toctree:: - :maxdepth: 1 - :titlesonly: - :caption: Advanced Topics - - extensions - plugins - ghcomponent - dtypes diff --git a/docs/devguide/plugins.md b/docs/devguide/plugins.md new file mode 100644 index 000000000000..466781b60c5f --- /dev/null +++ b/docs/devguide/plugins.md @@ -0,0 +1,5 @@ +# Plugins + +This section covers how to create COMPAS plugins. + +For more information, see the API reference for [`compas.plugins`][compas.plugins]. diff --git a/docs/devguide/plugins.rst b/docs/devguide/plugins.rst deleted file mode 100644 index 3e04b0bf00c4..000000000000 --- a/docs/devguide/plugins.rst +++ /dev/null @@ -1,2 +0,0 @@ -Developing a Plugin For a Pluggable -=================================== diff --git a/docs/devguide/setup.md b/docs/devguide/setup.md new file mode 100644 index 000000000000..a0a576b4c3ed --- /dev/null +++ b/docs/devguide/setup.md @@ -0,0 +1,43 @@ +# Development Setup + +!!! note + + This section is for you if you are intending to develop for COMPAS. If you + just want to use it, please check out the [Installation](../userguide/installation.md) guide. + +## Tools + +To get started you would need to install the following tools: + +- Text/code editor +- Git +- Python (virtual environment) + +## Text/code editor + +While any text editor can be used for developing COMPAS, we recommend using [Visual Studio Code](https://code.visualstudio.com/). +It is free to use, open source and has a lot of useful features for developing python code. + +## Git + +For version control we use [git](https://git-scm.com/). Our remote repository is hosted on [GitHub](https://github.com/compas-dev/compas/). + +While git offers an extensive command line interface, there are plenty of GUI based clients out there including: + +- [GitHub Desktop](https://desktop.github.com/) +- [SourceTree](https://www.sourcetreeapp.com/) + +VS Code also has a built-in git client. + +![VS Code Git](../images/vscode_git.JPG) + +## Python virtual environments + +During development there might be a need to install different versions of different dependencies, some of them might conflict with ones used for other projects. +Moreover, using early development code can often lead to a corrupt python environment which can be hard to fix. For these reasons it is highly recommended to use virtual environments for development. + +For developing COMPAS we recommend using [conda](https://conda.io/docs/). + +## Installing COMPAS for development + +See the [Development Workflow](workflow.md) for more details on how to install COMPAS for development and how to contribute to the project. diff --git a/docs/devguide/setup.rst b/docs/devguide/setup.rst deleted file mode 100644 index da13e2d9b8a2..000000000000 --- a/docs/devguide/setup.rst +++ /dev/null @@ -1,48 +0,0 @@ -.. _dev_setup: - -Development Setup -================= - -.. note:: - This section is for you if you are intending to develop for COMPAS. If you - just want to use it, please check out the user :ref:`user_guide_install` guide. - -Tools ------ -To get started you would need to install the following tools: - -* Text/code editor -* Git -* Python (virtual environment) - -Text/code editor ----------------- -While any text editor can be used for developing COMPAS, we recommend using `Visual Studio Code `_. -It is free to use, open source and has a lot of useful features for developing python code. - -Git ---- -For version control we use `git `_. Our remote repository is hosted on `GitHub `_ - -While git offers an extensive command line interface, there are plentty of GUI based clients out there including: - -* `GitHub Desktop `_ -* `SourceTree `_ - -VS Code also has a built-in git client - -.. image:: ../_images/vscode_git.JPG - :align: center - -Python virtual environments ---------------------------- - -During development there might be a need to install different versions of different dependencies, some of them might conflict with ones used for other projects. -Moreover, using early development code can often lead to a corrupt python environment which can be hard to fix. For these reasons it is highly recommended to use virtual environments for development. - -For developing COMPAS we recommend using `conda `_. - -Installing COMPAS for development ---------------------------------- - -See the :ref:`development-workflow` for more details on how to install COMPAS for development and how to contribute to the project. diff --git a/docs/devguide/workflow.md b/docs/devguide/workflow.md new file mode 100644 index 000000000000..1a66a311dc8f --- /dev/null +++ b/docs/devguide/workflow.md @@ -0,0 +1,111 @@ +# Development Workflow + +## Setup + +To set up a developer environment: + +1. Fork [the repository](https://github.com/compas-dev/compas) and clone the fork. See [Fork a repo](https://help.github.com/articles/fork-a-repo/) for more information. + +2. Create a virtual environment using your tool of choice (e.g. `virtualenv`, `conda`, etc). + + ```bash + conda create -n compas-dev python=3.9 --yes + conda activate compas-dev + ``` + +3. Install development dependencies: + + ```bash + cd path/to/compas + pip install -e ".[dev]" + ``` + +4. Make sure all tests pass and the code is free of lint: + + ```bash + invoke lint + invoke test + ``` + +## Making changes + +1. Create a branch for your contributions. + + Prefix your branch name with the type of contribution you are making (e.g. `feature-`, `bugfix-`, `doc-`, etc), followed by a short title of the proposed changes. + + ```bash + git branch feature-new-method + git checkout feature-new-method + ``` + +2. Making and pushing changes. + + Go ahead and make a few changes to the project using your favorite text editor. When you're ready to submit your changes, stage and commit your changes. Please use clear commit messages detailing the changes made. + + ```bash + git add . + git commit -m "add functionality X to compas" + git push origin feature-new-method + ``` + + You can continue to make more changes, and take more commit snapshots. + +3. Keeping your branch up to date. + + If you are working on a branch for a longer period of time, it is a good idea to keep your branch up to date with the main branch. This way, you can avoid merge conflicts when you submit your changes through a pull request. + + ```bash + git checkout main + git pull origin main + git checkout feature-new-method + git merge main + ``` + + If there are any conflicts, you will have to resolve them manually. Once you are done, you can push your changes to your fork. + + ```bash + git push origin feature-new-method + ``` + +## Submitting a PR + +!!! note + + The smaller the PR, the easier it is to review and merge. If you are working on a larger feature, consider splitting it up into multiple PRs. This will make it easier for us to review your changes and provide feedback. Alternatively, you can open a draft PR to get feedback on your work in progress. + +Once you are done making changes, you have to submit your contribution through a pull request (PR). +The procedure for submitting a PR is the following. + +1. Please merge the `main` branch into your feature branch and resolve any conflicts (see above). + +2. Make sure all tests still pass, the code is free of lint, and the docstrings compile correctly: + + ```bash + invoke lint + invoke test + invoke docs + ``` + +3. Add yourself to `AUTHORS.md`. + +4. Summarize the changes you made in `CHANGELOG.md` in the `Unreleased` section under the most fitting heading (e.g. `Added`, `Changed`, `Removed`). + +5. Commit your changes and push your branch to GitHub. + + ```bash + git add . + git commit -m "add functionality X to compas" + git push origin feature-new-method + ``` + +6. Create a [pull request](https://help.github.com/articles/about-pull-requests/). + + - Give your PR a title and describe your change in a few sentences. + - If your PR fixes an issue, add `Fixes #123` to the description, where `123` is the issue number. + - If your PR adds a new feature, add `New feature` to the description. + - If your PR fixes a bug, add `Bug fix` to the description. + - If your PR changes the API, add `Breaking change` to the description. + +7. Wait for the tests to pass and for the code to be reviewed. + + We review pull requests as soon as we can, typically within a week. If you get no review comments within two weeks, feel free to ask for feedback by adding a comment on your PR (this will notify maintainers). Thank you! diff --git a/docs/devguide/workflow.rst b/docs/devguide/workflow.rst deleted file mode 100644 index dc35ad28b811..000000000000 --- a/docs/devguide/workflow.rst +++ /dev/null @@ -1,121 +0,0 @@ -.. _development-workflow: - -Development Workflow -==================== - -Setup ------ - -To set up a developer environment - -1. Fork `the repository `_ and clone the fork. See `Fork a repo `_ for more information. - -2. Create a virtual environment using your tool of choice (e.g. `virtualenv`, `conda`, etc). - - .. code-block:: bash - - conda create -n compas-dev python=3.9 --yes - conda activate compas-dev - -3. Install development dependencies: - - .. code-block:: bash - - cd path/to/compas - pip install -e ".[dev]" - -4. Make sure all tests pass and the code is free of lint: - - .. code-block:: bash - - invoke lint - invoke test - - -Making changes --------------- - -1. Create a branch for your contributions. - - Prefix your branch name with the type of contribution you are making (e.g. ``feature-``, ``bugfix-``, ``doc-``, etc), followed by a short title of the proposed changes. - - .. code-block:: - - git branch feature-new-method - git checkout feature-new-method - - -2. Making and pushing changes. - - Go ahead and make a few changes to the project using your favorite text editor. When you're ready to submit your changes, stage and commit your changes. Please use clear commit messages detailing the changes made. - - .. code-block:: bash - - git add . - git commit -m "add functionality X to compas" - git push origin feature-new-method - - You can continue to make more changes, and take more commit snapshots. - -3. Keeping your branch up to date. - - If you are working on a branch for a longer period of time, it is a good idea to keep your branch up to date with the main branch. This way, you can avoid merge conflicts when you submit your changes through a pull request. - - .. code-block:: bash - - git checkout main - git pull origin main - git checkout feature-new-method - git merge main - - If there are any conflicts, you will have to resolve them manually. Once you are done, you can push your changes to your fork. - - .. code-block:: bash - - git push origin feature-new-method - - -Submitting a PR ---------------- - -.. note:: - - The smaller the PR, the easier it is to review and merge. If you are working on a larger feature, consider splitting it up into multiple PRs. This will make it easier for us to review your changes and provide feedback. Alternatively, you can open a draft PR to get feedback on your work in progress. - -Once you are done making changes, you have to submit your contribution through a pull request (PR). -The procedure for submitting a PR is the following. - - -1. Please merge the `main` branch into your feature branch and resolve any conflicts (see above). - -2. Make sure all tests still pass, the code is free of lint, and the docstrings compile correctly: - - .. code-block:: bash - - invoke lint - invoke test - invoke docs - -3. Add yourself to ``AUTHORS.md``. - -4. Summarize the changes you made in ``CHANGELOG.md`` in the `Unreleased` section under the most fitting heading (e.g. `Added`, `Changed`, `Removed`). - -5. Commit your changes and push your branch to GitHub. - - .. code-block:: bash - - git add . - git commit -m "add functionality X to compas" - git push origin feature-new-method - -5. Create a `pull request `_. - - * Give your PR a title and describe your change in a few sentences. - * If your PR fixes an issue, add ``Fixes #123`` to the description, where ``123`` is the issue number. - * If your PR adds a new feature, add ``New feature`` to the description. - * If your PR fixes a bug, add ``Bug fix`` to the description. - * If your PR changes the API, add ``Breaking change`` to the description. - -6. Wait for the tests to pass and for the code to be reviewed. - - We review pull requests as soon as we can, typically within a week. If you get no review comments within two weeks, feel free to ask for feedback by adding a comment on your PR (this will notify maintainers). Thank you! diff --git a/docs/_images/COMPAS.png b/docs/images/COMPAS.png similarity index 100% rename from docs/_images/COMPAS.png rename to docs/images/COMPAS.png diff --git a/docs/_images/extensions/compas-robots.png b/docs/images/extensions/compas-robots.png similarity index 100% rename from docs/_images/extensions/compas-robots.png rename to docs/images/extensions/compas-robots.png diff --git a/docs/_images/extensions/compas_3gs.jpg b/docs/images/extensions/compas_3gs.jpg similarity index 100% rename from docs/_images/extensions/compas_3gs.jpg rename to docs/images/extensions/compas_3gs.jpg diff --git a/docs/_images/extensions/compas_ags.png b/docs/images/extensions/compas_ags.png similarity index 100% rename from docs/_images/extensions/compas_ags.png rename to docs/images/extensions/compas_ags.png diff --git a/docs/_images/extensions/compas_assembly.png b/docs/images/extensions/compas_assembly.png similarity index 100% rename from docs/_images/extensions/compas_assembly.png rename to docs/images/extensions/compas_assembly.png diff --git a/docs/_images/extensions/compas_cem.png b/docs/images/extensions/compas_cem.png similarity index 100% rename from docs/_images/extensions/compas_cem.png rename to docs/images/extensions/compas_cem.png diff --git a/docs/_images/extensions/compas_cgal.png b/docs/images/extensions/compas_cgal.png similarity index 100% rename from docs/_images/extensions/compas_cgal.png rename to docs/images/extensions/compas_cgal.png diff --git a/docs/_images/extensions/compas_cloud.png b/docs/images/extensions/compas_cloud.png similarity index 100% rename from docs/_images/extensions/compas_cloud.png rename to docs/images/extensions/compas_cloud.png diff --git a/docs/_images/extensions/compas_cra.png b/docs/images/extensions/compas_cra.png similarity index 100% rename from docs/_images/extensions/compas_cra.png rename to docs/images/extensions/compas_cra.png diff --git a/docs/_images/extensions/compas_fab.png b/docs/images/extensions/compas_fab.png similarity index 100% rename from docs/_images/extensions/compas_fab.png rename to docs/images/extensions/compas_fab.png diff --git a/docs/_images/extensions/compas_fea.png b/docs/images/extensions/compas_fea.png similarity index 100% rename from docs/_images/extensions/compas_fea.png rename to docs/images/extensions/compas_fea.png diff --git a/docs/_images/extensions/compas_fem.png b/docs/images/extensions/compas_fem.png similarity index 100% rename from docs/_images/extensions/compas_fem.png rename to docs/images/extensions/compas_fem.png diff --git a/docs/_images/extensions/compas_gmsh.png b/docs/images/extensions/compas_gmsh.png similarity index 100% rename from docs/_images/extensions/compas_gmsh.png rename to docs/images/extensions/compas_gmsh.png diff --git a/docs/_images/extensions/compas_libigl.png b/docs/images/extensions/compas_libigl.png similarity index 100% rename from docs/_images/extensions/compas_libigl.png rename to docs/images/extensions/compas_libigl.png diff --git a/docs/_images/extensions/compas_occ.png b/docs/images/extensions/compas_occ.png similarity index 100% rename from docs/_images/extensions/compas_occ.png rename to docs/images/extensions/compas_occ.png diff --git a/docs/_images/extensions/compas_pattern1.png b/docs/images/extensions/compas_pattern1.png similarity index 100% rename from docs/_images/extensions/compas_pattern1.png rename to docs/images/extensions/compas_pattern1.png diff --git a/docs/_images/extensions/compas_pattern2.png b/docs/images/extensions/compas_pattern2.png similarity index 100% rename from docs/_images/extensions/compas_pattern2.png rename to docs/images/extensions/compas_pattern2.png diff --git a/docs/_images/extensions/compas_rbe.jpg b/docs/images/extensions/compas_rbe.jpg similarity index 100% rename from docs/_images/extensions/compas_rbe.jpg rename to docs/images/extensions/compas_rbe.jpg diff --git a/docs/_images/extensions/compas_rrc.png b/docs/images/extensions/compas_rrc.png similarity index 100% rename from docs/_images/extensions/compas_rrc.png rename to docs/images/extensions/compas_rrc.png diff --git a/docs/_images/extensions/compas_skeleton.png b/docs/images/extensions/compas_skeleton.png similarity index 100% rename from docs/_images/extensions/compas_skeleton.png rename to docs/images/extensions/compas_skeleton.png diff --git a/docs/_images/extensions/compas_slicer.jpg b/docs/images/extensions/compas_slicer.jpg similarity index 100% rename from docs/_images/extensions/compas_slicer.jpg rename to docs/images/extensions/compas_slicer.jpg diff --git a/docs/_images/extensions/compas_tia.png b/docs/images/extensions/compas_tia.png similarity index 100% rename from docs/_images/extensions/compas_tia.png rename to docs/images/extensions/compas_tia.png diff --git a/docs/_images/extensions/compas_tna.jpg b/docs/images/extensions/compas_tna.jpg similarity index 100% rename from docs/_images/extensions/compas_tna.jpg rename to docs/images/extensions/compas_tna.jpg diff --git a/docs/_images/extensions/compas_triangle.png b/docs/images/extensions/compas_triangle.png similarity index 100% rename from docs/_images/extensions/compas_triangle.png rename to docs/images/extensions/compas_triangle.png diff --git a/docs/_images/extensions/compas_vol.png b/docs/images/extensions/compas_vol.png similarity index 100% rename from docs/_images/extensions/compas_vol.png rename to docs/images/extensions/compas_vol.png diff --git a/docs/_images/ghpython_custom.jpg b/docs/images/ghpython_custom.jpg similarity index 100% rename from docs/_images/ghpython_custom.jpg rename to docs/images/ghpython_custom.jpg diff --git a/docs/_images/installation.gif b/docs/images/installation.gif similarity index 100% rename from docs/_images/installation.gif rename to docs/images/installation.gif diff --git a/docs/_images/rhino_scripteditor.png b/docs/images/rhino_scripteditor.png similarity index 100% rename from docs/_images/rhino_scripteditor.png rename to docs/images/rhino_scripteditor.png diff --git a/docs/_images/tutorial/plotters_dynamic.gif b/docs/images/tutorial/plotters_dynamic.gif similarity index 100% rename from docs/_images/tutorial/plotters_dynamic.gif rename to docs/images/tutorial/plotters_dynamic.gif diff --git a/docs/_images/tutorial/plotters_example.png b/docs/images/tutorial/plotters_example.png similarity index 100% rename from docs/_images/tutorial/plotters_example.png rename to docs/images/tutorial/plotters_example.png diff --git a/docs/_images/tutorial/plotters_line-options.png b/docs/images/tutorial/plotters_line-options.png similarity index 100% rename from docs/_images/tutorial/plotters_line-options.png rename to docs/images/tutorial/plotters_line-options.png diff --git a/docs/_images/tutorial/plotters_point-options.png b/docs/images/tutorial/plotters_point-options.png similarity index 100% rename from docs/_images/tutorial/plotters_point-options.png rename to docs/images/tutorial/plotters_point-options.png diff --git a/docs/_images/tutorial/plotters_polygon-options.png b/docs/images/tutorial/plotters_polygon-options.png similarity index 100% rename from docs/_images/tutorial/plotters_polygon-options.png rename to docs/images/tutorial/plotters_polygon-options.png diff --git a/docs/_images/tutorial/plotters_vector-options.png b/docs/images/tutorial/plotters_vector-options.png similarity index 100% rename from docs/_images/tutorial/plotters_vector-options.png rename to docs/images/tutorial/plotters_vector-options.png diff --git a/docs/_images/userguide/basics.colors_color-circle.png b/docs/images/userguide/basics.colors_color-circle.png similarity index 100% rename from docs/_images/userguide/basics.colors_color-circle.png rename to docs/images/userguide/basics.colors_color-circle.png diff --git a/docs/_images/userguide/basics.colors_lightness.png b/docs/images/userguide/basics.colors_lightness.png similarity index 100% rename from docs/_images/userguide/basics.colors_lightness.png rename to docs/images/userguide/basics.colors_lightness.png diff --git a/docs/_images/userguide/basics.colors_maps.png b/docs/images/userguide/basics.colors_maps.png similarity index 100% rename from docs/_images/userguide/basics.colors_maps.png rename to docs/images/userguide/basics.colors_maps.png diff --git a/docs/_images/userguide/basics.colors_maps_from-one-color.png b/docs/images/userguide/basics.colors_maps_from-one-color.png similarity index 100% rename from docs/_images/userguide/basics.colors_maps_from-one-color.png rename to docs/images/userguide/basics.colors_maps_from-one-color.png diff --git a/docs/_images/userguide/basics.colors_maps_from-rgb.png b/docs/images/userguide/basics.colors_maps_from-rgb.png similarity index 100% rename from docs/_images/userguide/basics.colors_maps_from-rgb.png rename to docs/images/userguide/basics.colors_maps_from-rgb.png diff --git a/docs/_images/userguide/basics.colors_maps_from-three-colors.png b/docs/images/userguide/basics.colors_maps_from-three-colors.png similarity index 100% rename from docs/_images/userguide/basics.colors_maps_from-three-colors.png rename to docs/images/userguide/basics.colors_maps_from-three-colors.png diff --git a/docs/_images/userguide/basics.colors_maps_from-two-colors.png b/docs/images/userguide/basics.colors_maps_from-two-colors.png similarity index 100% rename from docs/_images/userguide/basics.colors_maps_from-two-colors.png rename to docs/images/userguide/basics.colors_maps_from-two-colors.png diff --git a/docs/_images/userguide/basics.colors_saturation.png b/docs/images/userguide/basics.colors_saturation.png similarity index 100% rename from docs/_images/userguide/basics.colors_saturation.png rename to docs/images/userguide/basics.colors_saturation.png diff --git a/docs/_images/userguide/basics.datastructures.cellnetworks.example_color.png b/docs/images/userguide/basics.datastructures.cellnetworks.example_color.png similarity index 100% rename from docs/_images/userguide/basics.datastructures.cellnetworks.example_color.png rename to docs/images/userguide/basics.datastructures.cellnetworks.example_color.png diff --git a/docs/_images/userguide/basics.datastructures.cellnetworks.example_grey.png b/docs/images/userguide/basics.datastructures.cellnetworks.example_grey.png similarity index 100% rename from docs/_images/userguide/basics.datastructures.cellnetworks.example_grey.png rename to docs/images/userguide/basics.datastructures.cellnetworks.example_grey.png diff --git a/docs/_images/userguide/basics.datastructures.cellnetworks.example_hull.png b/docs/images/userguide/basics.datastructures.cellnetworks.example_hull.png similarity index 100% rename from docs/_images/userguide/basics.datastructures.cellnetworks.example_hull.png rename to docs/images/userguide/basics.datastructures.cellnetworks.example_hull.png diff --git a/docs/_images/userguide/basics.datastructures.meshes.cycles.png b/docs/images/userguide/basics.datastructures.meshes.cycles.png similarity index 100% rename from docs/_images/userguide/basics.datastructures.meshes.cycles.png rename to docs/images/userguide/basics.datastructures.meshes.cycles.png diff --git a/docs/_images/userguide/basics.datastructures.meshes.edge-loop.png b/docs/images/userguide/basics.datastructures.meshes.edge-loop.png similarity index 100% rename from docs/_images/userguide/basics.datastructures.meshes.edge-loop.png rename to docs/images/userguide/basics.datastructures.meshes.edge-loop.png diff --git a/docs/_images/userguide/basics.datastructures.meshes.edge-strip.png b/docs/images/userguide/basics.datastructures.meshes.edge-strip.png similarity index 100% rename from docs/_images/userguide/basics.datastructures.meshes.edge-strip.png rename to docs/images/userguide/basics.datastructures.meshes.edge-strip.png diff --git a/docs/_images/userguide/basics.datastructures.meshes.face-neighbours.png b/docs/images/userguide/basics.datastructures.meshes.face-neighbours.png similarity index 100% rename from docs/_images/userguide/basics.datastructures.meshes.face-neighbours.png rename to docs/images/userguide/basics.datastructures.meshes.face-neighbours.png diff --git a/docs/_images/userguide/basics.datastructures.meshes.meshgrid-column0.png b/docs/images/userguide/basics.datastructures.meshes.meshgrid-column0.png similarity index 100% rename from docs/_images/userguide/basics.datastructures.meshes.meshgrid-column0.png rename to docs/images/userguide/basics.datastructures.meshes.meshgrid-column0.png diff --git a/docs/_images/userguide/basics.datastructures.meshes.meshgrid-column3.png b/docs/images/userguide/basics.datastructures.meshes.meshgrid-column3.png similarity index 100% rename from docs/_images/userguide/basics.datastructures.meshes.meshgrid-column3.png rename to docs/images/userguide/basics.datastructures.meshes.meshgrid-column3.png diff --git a/docs/_images/userguide/basics.datastructures.meshes.tubemesh.png b/docs/images/userguide/basics.datastructures.meshes.tubemesh.png similarity index 100% rename from docs/_images/userguide/basics.datastructures.meshes.tubemesh.png rename to docs/images/userguide/basics.datastructures.meshes.tubemesh.png diff --git a/docs/_images/userguide/basics.datastructures.meshes.vertex-faces.png b/docs/images/userguide/basics.datastructures.meshes.vertex-faces.png similarity index 100% rename from docs/_images/userguide/basics.datastructures.meshes.vertex-faces.png rename to docs/images/userguide/basics.datastructures.meshes.vertex-faces.png diff --git a/docs/_images/userguide/basics.datastructures.meshes.vertex-neighbours.png b/docs/images/userguide/basics.datastructures.meshes.vertex-neighbours.png similarity index 100% rename from docs/_images/userguide/basics.datastructures.meshes.vertex-neighbours.png rename to docs/images/userguide/basics.datastructures.meshes.vertex-neighbours.png diff --git a/docs/_images/userguide/cad.blender.visualisation.png b/docs/images/userguide/cad.blender.visualisation.png similarity index 100% rename from docs/_images/userguide/cad.blender.visualisation.png rename to docs/images/userguide/cad.blender.visualisation.png diff --git a/docs/_images/userguide/cad.grasshopper.gh_verify.jpg b/docs/images/userguide/cad.grasshopper.gh_verify.jpg similarity index 100% rename from docs/_images/userguide/cad.grasshopper.gh_verify.jpg rename to docs/images/userguide/cad.grasshopper.gh_verify.jpg diff --git a/docs/_images/userguide/cad.grasshopper.ghpython_component.jpg b/docs/images/userguide/cad.grasshopper.ghpython_component.jpg similarity index 100% rename from docs/_images/userguide/cad.grasshopper.ghpython_component.jpg rename to docs/images/userguide/cad.grasshopper.ghpython_component.jpg diff --git a/docs/_images/vscode_git.JPG b/docs/images/vscode_git.JPG similarity index 100% rename from docs/_images/vscode_git.JPG rename to docs/images/vscode_git.JPG diff --git a/docs/index.md b/docs/index.md new file mode 100644 index 000000000000..1ff14ca6f2e6 --- /dev/null +++ b/docs/index.md @@ -0,0 +1,30 @@ +# COMPAS Documentation + +This is the documentation of the core infrastructure of COMPAS, +an open source framework for computational research and collaboration +in Architecture, Engineering, Fabrication, and Construction. + +!!! note + + This is the documentation of the core Python package of COMPAS. + If you are looking for the COMPAS Framework website, + please go to [compas.dev](https://compas.dev). + +## User Guide + +If you want to use COMPAS for your research or in one of your projects, +this is the place to start. + +[Get Started](userguide/index.md){ .md-button .md-button--primary } + +## Development + +If you want to contribute to COMPAS, this is the place to start. + +[Developer Guide](devguide/index.md){ .md-button } + +## API Reference + +The reference documentation of the core package and the CAD packages. + +[API Reference](api/index.md){ .md-button } diff --git a/docs/index.rst b/docs/index.rst deleted file mode 100644 index 6fc87ba38982..000000000000 --- a/docs/index.rst +++ /dev/null @@ -1,61 +0,0 @@ -:html_theme.sidebar_secondary.remove: true - -******************************************************************************** -COMPAS Documentation -******************************************************************************** - -.. rst-class:: lead - -This is the documentation of the core infratructure of COMPAS, -an open source framework for computational research and collaboration -in Architecture, Engineering, Fabrication, and Construction. - -.. note:: - - This is the documentation of the core Python package of COMPAS. - If you are looking for the COMPAS Framework website, - please go to https://compas.dev. - - -User Guide -========== - -If you want to use COMPAS for your research or in one of your projects, -this is the place to start. - -.. toctree:: - :maxdepth: 2 - :titlesonly: - - userguide/index - - -Development -=========== - -If you want to contribute to COMPAS, this is the place to start. - -.. toctree:: - :maxdepth: 2 - :titlesonly: - - devguide/index - - -API Reference -============= - -The reference documentation of the core package and the CAD packages. - -.. toctree:: - :maxdepth: 2 - - api/index - - -Indices and tables -================== - -* :ref:`genindex` -* :ref:`modindex` -* :ref:`search` diff --git a/docs/javascripts/mathjax.js b/docs/javascripts/mathjax.js new file mode 100644 index 000000000000..06dbf38bfd36 --- /dev/null +++ b/docs/javascripts/mathjax.js @@ -0,0 +1,16 @@ +window.MathJax = { + tex: { + inlineMath: [["\\(", "\\)"]], + displayMath: [["\\[", "\\]"]], + processEscapes: true, + processEnvironments: true + }, + options: { + ignoreHtmlClass: ".*|", + processHtmlClass: "arithmatex" + } +}; + +document$.subscribe(() => { + MathJax.typesetPromise() +}) diff --git a/docs/sort__all__.py b/docs/sort__all__.py deleted file mode 100644 index 182eee9ae3dc..000000000000 --- a/docs/sort__all__.py +++ /dev/null @@ -1,40 +0,0 @@ -import compas -from compas_blender import conversions as module - -functions = [] -classes = [] -errors = [] -numpy = [] - -__newall__ = { - "classes": [], - "errors": [], - "functions": [], - "numpy": [], - "pluggables": [], - "plugins": [], -} - -for name in module.__all__: - obj = getattr(module, name) - - if name.endswith("_numpy"): - numpy.append(name) - continue - - if isinstance(obj, type): - classes.append(name) - else: - functions.append(name) - -for name in sorted(classes): - __newall__["classes"].append(name) - -for name in sorted(functions): - __newall__["functions"].append(name) - -for name in sorted(numpy): - __newall__["numpy"].append(name) - - -compas.json_dump(__newall__, f"docs/{module.__name__}__all__.json", pretty=True) diff --git a/docs/stylesheets/extra.css b/docs/stylesheets/extra.css new file mode 100644 index 000000000000..557d48468991 --- /dev/null +++ b/docs/stylesheets/extra.css @@ -0,0 +1,28 @@ +/* Custom COMPAS styling */ + +/* Lead text styling */ +.lead { + font-size: 1.2em; + font-weight: 300; + color: var(--md-default-fg-color--light); +} + +/* Better code block styling */ +.highlight code { + font-size: 0.85em; +} + +/* API documentation styling */ +.doc-heading { + font-weight: 600; +} + +/* Better table styling */ +.md-typeset table:not([class]) { + font-size: 0.85em; +} + +/* Admonition tweaks */ +.md-typeset .admonition { + font-size: 0.9em; +} diff --git a/docs/userguide/advanced.hashtree.md b/docs/userguide/advanced.hashtree.md new file mode 100644 index 000000000000..38d2fe478d84 --- /dev/null +++ b/docs/userguide/advanced.hashtree.md @@ -0,0 +1,5 @@ +# Hash Trees + +This section covers hash trees in COMPAS. + +For more information, see the API reference for [`compas.data`][compas.data]. diff --git a/docs/userguide/advanced.hashtree.rst b/docs/userguide/advanced.hashtree.rst deleted file mode 100644 index 8e6863fac596..000000000000 --- a/docs/userguide/advanced.hashtree.rst +++ /dev/null @@ -1,80 +0,0 @@ -******************************************************************************** -Hash Tree -******************************************************************************** - -Hash tree (or Merkle tree) is a tree data structure in which every leaf node is labelled with the hash of a data block and every non-leaf node is labelled with the cryptographic hash of the labels of its child nodes. -Hash trees are useful because they allow efficient and secure verification of the contents of large data structures. It is widly used in modern distributed version control systems like Git as well as peer-to-peer systems like Blockchain. -COMPAS provides a simple implementation of a hash tree that can be used for detecting and locating changes in a complex data structure. In context of AEC, this feature can also be useful for many real-world applications, -such as detecting changes in a complicated Building Information Model, tracking minor deformation in structural assessments, or even detecting robot joint movements in a digital fabracation process, and many more. - -Hash Tree From Dict -=================== - -A COMPAS hash tree can be created from any raw python dictionary using the `HashTree.from_dict` method. - ->>> from compas.datastructures import HashTree ->>> data = {'a': 1, 'b': 2, 'c': {'d': 3, 'e': 4}} ->>> tree = HashTree.from_dict(data) - -The structure of the hash tree and crypo hash on each node can be visualised using the `print` function. - ->>> print(tree) - -└── ROOT @ b2e1c - ├── .a:1 @ 4d9a8 - ├── .b:2 @ 82b86 - └── .c @ 664a3 - ├── .d:3 @ 76d82 - └── .e:4 @ ebe84 - -Once the original data is modified, a new hash tree can be created from the modified data and the changes can be detected by comparing the two hash trees. - ->>> data['c']['d'] = 5 ->>> del data["b"] ->>> data["f"] = True ->>> new_tree = HashTree.from_dict(data) ->>> print(new_tree) - -└── ROOT @ a8c1b - ├── .a:1 @ 4d9a8 - ├── .c @ e1701 - │ ├── .d:5 @ 98b1e - │ └── .e:4 @ ebe84 - └── .f:True @ 753e5 - ->>> new_tree.diff(tree) -{'added': [{'path': '.f', 'value': True}], 'removed': [{'path': '.b', 'value': 2}], 'modified': [{'path': '.c.d', 'old': 3, 'new': 5}]} - -Hash Tree From COMPAS Data -========================== - -A COMPAS hash tree can also be created from any classes that inherit from the base `Data` class in COMPAS, such as `Mesh`, `Graph`, `Shape`, `Geometry`, etc. -This is done by hashing the serilised data of the object. - ->>> from compas.datastructures import Mesh ->>> mesh = Mesh.from_polyhedron(6) ->>> tree = HashTree.from_object(mesh) ->>> print(tree) - -└── ROOT @ 44cc1 - ├── .attributes @ 3370c - ├── .default_vertex_attributes @ 84700 - │ ├── .x:0.0 @ 5bc2d - │ ├── .y:0.0 @ 1704b - │ └── .z:0.0 @ 6199e - ├── .default_edge_attributes @ 5e834 - ├── .default_face_attributes @ 5a8d9 - ├── .vertex @ ff6d0 - │ ├── .0 @ 84ec1 - │ │ ├── .x:-1.1547005383792517 @ 874f4 - │ │ ├── .y:-1.1547005383792517 @ d2b16 - │ │ └── .z:-1.1547005383792517 @ bd9f0 - │ ├── .1 @ 316d3 -... - ->>> mesh.vertex_attribute(0, "x", 1.0) ->>> mesh.delete_face(3) ->>> new_tree = HashTree.from_object(mesh) ->>> new_tree.diff(tree) -{'added': [], 'removed': [{'path': '.face.3', 'value': [4, 2, 3, 5]}, {'path': '.facedata.3', 'value': None}], 'modified': [{'path': '.vertex.0.x', 'old': -1.1547005383792517, 'new': 1.0}]} - diff --git a/docs/userguide/advanced.pluggables.md b/docs/userguide/advanced.pluggables.md new file mode 100644 index 000000000000..8e9e8ad1d922 --- /dev/null +++ b/docs/userguide/advanced.pluggables.md @@ -0,0 +1,5 @@ +# Pluggables + +This section covers the pluggable system in COMPAS. + +For more information, see the API reference for [`compas.plugins`][compas.plugins]. diff --git a/docs/userguide/advanced.pluggables.rst b/docs/userguide/advanced.pluggables.rst deleted file mode 100644 index 3d717837865b..000000000000 --- a/docs/userguide/advanced.pluggables.rst +++ /dev/null @@ -1,4 +0,0 @@ -******************************************************************************** -Pluggables and Plugins -******************************************************************************** - diff --git a/docs/userguide/advanced.rpc.md b/docs/userguide/advanced.rpc.md new file mode 100644 index 000000000000..5ab394c35dd6 --- /dev/null +++ b/docs/userguide/advanced.rpc.md @@ -0,0 +1,5 @@ +# RPC + +This section covers Remote Procedure Calls in COMPAS. + +For more information, see the API reference for [`compas.rpc`][compas.rpc]. diff --git a/docs/userguide/advanced.rpc.rst b/docs/userguide/advanced.rpc.rst deleted file mode 100644 index d2add101424c..000000000000 --- a/docs/userguide/advanced.rpc.rst +++ /dev/null @@ -1,202 +0,0 @@ -******************************************************************************** -Remote Procedure Calls (RPC) -******************************************************************************** - -.. rst-class:: lead - -Remote Procedure Calls (``RPC``) is a mechanism to transparently execute code in -a remote process or computer. This is especially useful in scenarios where COMPAS -runs inside an IronPython host (eg. Rhino) and needs to execute code that only -runs on CPython (eg. code that requires ``numpy``). - - -Basic Usage -=========== - -The basic usage of RPC is simple. -For example, consider a CPython script using the Force Density method. - ->>> from compas.geometry import icp_numpy ->>> source = ... ->>> target = ... ->>> points, transformation = icp_numpy(source, target) - -This script does not work in Rhino or GH because ``numpy`` and ``scipy`` are not available. -Therefore, instead of importing and calling the function directly, -we call it through a proxy object. - ->>> from compas.rpc import Proxy ->>> geometry = Proxy('compas.geometry') ->>> source = ... ->>> target = ... ->>> points, transformation = geometry.icp_numpy(source, target) - -To use functions from more than one package in the same script, simply change the -package attribute of the proxy object, which determines where the proxy will look -for the requested function. - ->>> from compas.rpc import Proxy ->>> proxy = Proxy() - ->>> proxy.package = 'compas.numerical' ->>> proxy.pca_numpy(...) - ->>> proxy.package = 'compas.geometry' ->>> proxy.bestfit_plane_numpy(...) - -The use of :mod:`compas.rpc` is not restricted to COMPAS packages only. - ->>> from compas.rpc import Proxy ->>> linalg = Proxy('scipy.linalg') ->>> x = linalg.solve(A, b) - - -Configuration Options -===================== - -The :class:`compas.rpc.Proxy` object has several configuration options. -We will discuss only a few of those here. -For a complete overview, please refer to the API docs (:mod:`compas.rpc`). - -``python`` ----------- - -The :class:`compas.rpc.Proxy` object will automatically try to reconnect to an -active instance of the command server, or start a new one if no active server can be found. - -By default, a newly started server will run an instance of the default Python interpreter of the active environment. -For example, when running RPC from an Anaconda Prompt, or from a ``conda``-enabled Terminal it will use the interpreter of the active ``conda`` environment. - -When running RPC from Rhino, it will (try to) use the Python interpreter specified in `compas_bootstrapper`. - -In some cases, this might not be what you want, or might not result in the expected behaviour. -To use a specific Python iterpreter instead, you can specify the path to an executable through the ``python`` parameter. - ->>> from compas.rpc import Proxy ->>> proxy = Proxy(python=r"C:\\Users\\\\anaconda3\\envs\\research\\python.exe") - - -``path`` --------- - -Sometimes you will want the server to run custom functions that are not on the ``PYTHONPATH`` of the Python interpreter on the server. -To allow the server to find such functions, you can specify an additional search path. - -For example, if you have a Python script on your desktop that defines a wrapper for the k-means clustering algorithm of ``scikit-learn``, -you can tell the command server where to find it using the ``path`` parameter. - -.. code-block:: python - - # C:\Users\\Desktop\clustering.py - - from sklearn.cluster import KMeans - from numpy import array - - - def cluster(points, n_clusters): - kmeans = KMeans(n_clusters=n_clusters, n_init=2000, max_iter=1000).fit(array(cloud, dtype=float)) - clusters = {} - for label, point in zip(kmeans.labels_, cloud): - if label not in clusters: - clusters[label] = [] - clusters[label].append(point) - return clusters - - ->>> from compas.geometry import Pointcloud ->>> from compas.rpc import Proxy ->>> cloud = Pointcloud.from_bounds(10, 5, 3, 100) ->>> proxy = Proxy(package='clustering', path=r'C:\\Users\\\\Desktop') ->>> clusters = proxy.cluster(cloud, 10) - - -Supported data types -==================== - -:mod:`compas.rpc` uses JSON serialization to transfer data between the "client" -(your script) and the server running the selected CPython environment. - -All COMPAS objects (primitives, shapes, data structures, etc.) support JSON -serialization through their ``to_json`` ``from_json`` methods. On a lower level, -these methods convert (complex) internal data to simple dictionaries, and -vice versa, with ``to_data`` and ``from_data``. - -In combination with custom JSON encoders and decoders this allows for COMPAS -objects to be serialized and de-serialized without loss of information on either -side of the RPC communication network. - -Therefore the data types supported by :mod:`compas.rpc` include all native Python -data types and COMPAS objects. ``numpy`` arrays are automatically converted to lists. - ->>> from compas.geometry import icp_numpy ->>> source = ... ->>> target = ... ->>> points, transformation = icp_numpy(source, target) ->>> type(points) - - ->>> from compas.rpc import Proxy ->>> proxy = Proxy('compas.geometry') ->>> source = ... ->>> target = ... ->>> points, transformation = proxy.icp_numpy(source, target) ->>> type(points) - - -Sparse matrices, for example from ``scipy.sparse``, are not (yet) supported. - - -Starting and Stopping -===================== - -Once a server is started it will keep running "as long as possible". -There are many reasons to stop and (re)start the server during its lifetime. -For example, to load functionality from a different conda environment, or to -load changes that were made to the packages in the environment after it was started. -This happens frequently while a package is still under active development. - -Stopping and starting the server is easy. - ->>> from compas.rpc import Proxy ->>> proxy = Proxy() ->>> proxy.restart_server() - -To restart the server after every call, you can use a context manager. -When used in this way, RPC behaves much like its predecessor ``XFunc``. - ->>> with Proxy('compas.numerical') as numerical: -... numerical.pca_numpy(...) -... - - -Starting an RPC server manually -=============================== - -``Proxy`` will try to start an RPC server automatically -if no server is already running, but very often it is recommended -to start it manually from the command-line. - -To start a new RPC server use the following command on the terminal -(default port is ``1753``): - -:: - - $ compas_rpc start [--port PORT] - -Conversely, to stop an existing RPC server: - -:: - - $ compas_rpc stop [--port PORT] - - -.. note:: - - If COMPAS is installed in a virtual environment, make sure it is activated - before trying to use this command-line utility. - -.. note:: - - Currently, the RPC server is launched on the ``localhost``. - However, it would also be possible to launch it on a remote computer on a - network, or on a server reachable over the internet. diff --git a/docs/userguide/advanced.serialisation.md b/docs/userguide/advanced.serialisation.md new file mode 100644 index 000000000000..b8b2fb34e3c2 --- /dev/null +++ b/docs/userguide/advanced.serialisation.md @@ -0,0 +1,5 @@ +# Serialisation + +This section covers data serialisation in COMPAS. + +For more information, see the API reference for [`compas.data`][compas.data]. diff --git a/docs/userguide/advanced.serialisation.rst b/docs/userguide/advanced.serialisation.rst deleted file mode 100644 index 1b814fe7b3f0..000000000000 --- a/docs/userguide/advanced.serialisation.rst +++ /dev/null @@ -1,232 +0,0 @@ -******************************************************************************** -Serialising Data -******************************************************************************** - -.. rst-class:: lead - -The data package provides a base class (:class:`compas.data.Data`) for all data objects in the COMPAS framework, -the mechanism for serialization of data to JSON format, -and the base infrastructure for validation of the data of COMPAS objects in both the original Python and serialized JSON formats. - ->>> from compas.data import Data ->>> from compas.geometry import Point, Box, Rotation ->>> from compas.datastructures import Mesh ->>> from compas.robots import RobotModel - ->>> issubclass(Point, Data) -True ->>> issubclass(Box, Data) -True ->>> issubclass(Rotation, Data) -True ->>> issubclass(Mesh, Data) -True ->>> issubclass(RobotModel, Data) -True - - -Interface -========= - -The base data class defines a common data interface for all objects. -Among other things, this interface provides a read-only GUID (:attr:`compas.data.Data.guid`), -a modifiable object name (:attr:`compas.data.Data.name`) that defaults to the class name, -a read-only data type (:attr:`compas.data.Data.dtype`), -and, most importantly, an attribute containing the underlying data of the object (:attr:`compas.data.Data.data`). - ->>> from compas.geometry import Point ->>> point = Point(0, 0, 0) ->>> point.guid -UUID('48613a5b-4c9b-4d7c-8c88-59c28297fd75') ->>> point.name -'Point' ->>> point.dtype -'compas.geometry/Point' ->>> point.data -[0.0, 0.0, 0.0] - - -JSON Serialization -================== - -All objects inheriting the data interface, can be serialized to a JSON string or file. - ->>> from compas.geometry import Point ->>> point = Point(0, 0, 0) ->>> point.to_jsonstring() -'[0.0, 0.0, 0.0]' ->>> point.to_json('point.json') - ->>> from compas.geometry import Frame ->>> frame = Frame.worldXY() ->>> frame.to_jsonstring() -'{"point": [0.0, 0.0, 0.0], "xaxis": [1.0, 0.0, 0.0], "yaxis": [0.0, 1.0, 0.0]}' ->>> frame.to_json('frame.json') - -Conversely, COMPAS data objects can be reconstructed from a compatible JSON string or file. - ->>> from compas.geometry import Frame, Box ->>> box = Box(Frame.worldXY(), 1, 1, 1) ->>> jsonstring = box.to_jsonstring() ->>> other = Box.from_jsonstring(jsonstring) ->>> box == other -True - ->>> from compas.datastructures import Mesh ->>> mesh = Mesh.from_obj('faces.obj') ->>> mesh.to_json('mesh.json') ->>> other = Mesh.from_json('mesh.json') - -The serialization mechanism applies recursively to nested structures of objects as well. - ->>> from compas.datastructures import Network, Mesh ->>> from compas.geometry import Point, Transformation, Box, Frame ->>> point = Point(0, 0, 0) ->>> xform = Transformation() ->>> mesh = Mesh.from_shape(Box(Frame.worldXY(), 1, 1, 1)) ->>> network = Network() ->>> a = network.add_node(point=point) ->>> b = network.add_node(transformation=xform) ->>> c = network.add_node(box=mesh) ->>> network.to_json('network.json') - ->>> other = Network.from_json('network.json') ->>> other.node_attribute(a, 'point') == network.node_attribute(a, 'point') -True ->>> other.node_attribute(b, 'transformation') == network.node_attribute(b, 'transformation') -True - - -Working Sessions -================ - -One of the most useful features of the serialization meshanisms provided by the data package is the ability to store and load entire COMPAS working sessions. - -.. code-block:: python - - # script A - - import compas - from compas.datastructures import Mesh - from compas.geometry import Pointcloud, Box - - box = Box.from_width_height_depth(1, 1, 1) - mesh = Mesh.from_poyhedron(12) - - boxes = [] - for point in Pointcloud.from_bounds(10, 10, 10, 100): - boxcopy = box.copy() - boxcopy.frame.point = point - - session = {'mesh': mesh, 'boxes': boxes} - compas.json_dump(session, 'session.json') - -.. code-block:: python - - # script B - - import compas - - session = compas.json_load('session.json') - mesh = session['mesh'] - boxes = session['boxes'] - -Note that if you are working in Python 3.6 or higher, you could add some type information to script B -such that your editor knows what kind of objects have been loaded, -which will help with IntelliSense and code completion. - -.. code-block:: python - - # script B - - from typing import List - import compas - from compas.datastructures import Mesh - from compas.geometry import Box - - session = compas.json_load('session.json') - mesh: Mesh = session['mesh'] - boxes: List[Box] = session['boxes'] - - -Inheritance -=========== - -When working with custom classes that inherit from COMPAS datastructures, COMPAS will encode the inheritance chain in the serialized data. This allows the object to be reconstructed using the closest available superclass if the custom class is not available in the environment where the data is loaded. -For example, a user can create a custom mesh class and serialize it to JSON: - -.. code-block:: python - - from compas.datastructures import Mesh - from compas import json_dump - - class CustomMesh(Mesh): - def __init__(self, *args, **kwargs): - super(CustomMesh, self).__init__(*args, **kwargs) - self.custom_mesh_attr = "custom_mesh" - - @property - def __data__(self): - data = super(CustomMesh, self).__data__ - data["custom_mesh_attr"] = self.custom_mesh_attr - return data - - @classmethod - def __from_data__(cls, data): - obj = super(CustomMesh, cls).__from_data__(data) - obj.custom_mesh_attr = data.get("custom_mesh_attr", "") - return obj - - # Create and serialize a custom mesh - custom_mesh = CustomMesh(name="test") - json_dump(custom_mesh, 'custom_mesh.json') - -If another user loads "custom_mesh.json" in an environment where the CustomMesh class is not available, COMPAS will reconstruct the object as an instance of its closest available superclass, which in this case is the regular Mesh class: - -.. code-block:: python - - from compas.datastructures import Mesh - from compas import json_load - - mesh = json_load('custom_mesh.json') - assert isinstance(mesh, Mesh) # This will be True - - - -Validation -========== - -A somewhat experimental feature of the data package is data validation. -The base data class defines two unimplemented attributes :attr:`compas.data.Data.JSONSCHEMA` and :attr:`compas.data.Data.DATASCHEMA`. -The former is meant to define the name of the json schema in the ``schema`` folder of :mod:`compas.data`, -and the latter a Python schema using :mod:`schema.Schema`. - -If a deriving class implements those attributes, data sources can be validated against the two schemas to verify compatibility -of the available data with the object type. - -:: - - >>> from compas.data import validate_data - >>> from compas.geometry import Frame - >>> data = {'point': [0.0, 0.0, 0.0], 'xaxis': [1.0, 0.0, 0.0], 'zaxis': [0.0, 0.0, 1.0]} - >>> validate_data(data, Frame) - Validation against the JSON schema of this object failed. - Traceback (most recent call last): - ... - - jsonschema.exceptions.ValidationError: 'yaxis' is a required property - - Failed validating 'required' in schema: - {'$compas': '1.7.1', - '$id': 'frame.json', - '$schema': 'http://json-schema.org/draft-07/schema#', - 'properties': {'point': {'$ref': 'compas.json#/definitions/point'}, - 'xaxis': {'$ref': 'compas.json#/definitions/vector'}, - 'yaxis': {'$ref': 'compas.json#/definitions/vector'}}, - 'required': ['point', 'xaxis', 'yaxis'], - 'type': 'object'} - - On instance: - {'point': [0.0, 0.0, 0.0], - 'xaxis': [1.0, 0.0, 0.0], - 'zaxis': [0.0, 0.0, 1.0]} diff --git a/docs/userguide/advanced.tolerance.md b/docs/userguide/advanced.tolerance.md new file mode 100644 index 000000000000..bb36979c703f --- /dev/null +++ b/docs/userguide/advanced.tolerance.md @@ -0,0 +1,5 @@ +# Tolerance + +This section covers tolerance settings in COMPAS. + +For more information, see the API reference for [`compas.tolerance`][compas.tolerance]. diff --git a/docs/userguide/advanced.tolerance.rst b/docs/userguide/advanced.tolerance.rst deleted file mode 100644 index b7cad2346c5e..000000000000 --- a/docs/userguide/advanced.tolerance.rst +++ /dev/null @@ -1,107 +0,0 @@ -******************************************************************************** -Dealing with Tolerances -******************************************************************************** - -.. rst-class:: lead - -:class:`compas.tolerance.Tolerance` provides a consistent way of dealing with -tolerances, precision, comparisons, approximations, number formatting, etc. in COMPAS and across COMPAS packages. - -Defaults -======== - -Different tolerance values are used for different checks and comparisons. -These are the default values: - ->>> from compas.tolerance import Tolerance ->>> tol = Tolerance() ->>> tol.absolute -1e-09 ->>> tol.relative -1e-06 ->>> tol.angular -1e-06 ->>> tol.approximation -1e-03 ->>> tol.precision -6 - - -Comparisons -=========== - -Comparisons of numbers involves two types of tolerances: absolute and relative. -The absolute tolerance is a fixed value. -The relative tolerance is relative to the magnitude of the numbers being compared. -When comparing two numbers the following formula is used: - -.. math:: - - |a - b| \leq relative \cdot |b| + absolute - -This means that the relative tolerance dominates the comparison for larger numbers, -while the absolute tolerance becaomes dominant when numbers are close to zero. - ->>> tol.is_close(1.1, 1) -False ->>> tol.is_close(100000.1, 1) -True ->>> tol.is_close(1 + 1e-5, 1) -False ->>> tol.is_close(1 + 1e-6, 1) -True ->>> tol.is_close(0 + 1e-6, 0) -False ->>> tol.is_close(0 + 1e-9, 0) -True - - -Zero, Positive, Negative -======================== - -Comparisons to zero, and checking if a number is positive or negative, are special cases, and only involve the absolute tolerance. - ->>> tol.is_zero(0) -True ->>> tol.is_zero(1e-9) -True ->>> tol.is_zero(1e-8) -False ->>> tol.is_zero(1e-8, tol=1e-8) -True ->>> tol.is_positive(1e-8) -True ->>> tol.is_positive(1e-9) -False ->>> tol.is_negative(-1e-8) -True ->>> tol.is_negative(-1e-9) -False - - -Number Formatting -================= - -By default, numbers are formatted (in strings) using the precision value. - ->>> tol.format_number(1.23456) -'1.235' - -To use a precision value based on the tolerance, use :meth:`compas.tolerance.Tolerance.precision_from_tolerance`. - ->>> tol.format_number(1.23456, precision=tol.precision_from_tolerance()) -'1.234560000' - -Positive precision values are interpreted as the number of digits after the decimal point. -Negative precision values are interpreted as the number of digits before the decimal point. -So higher values increase precision, and lower number decrease it. - ->>> tol.format_number(1.23456, precision=2) -'1.23' ->>> tol.format_number(1.23456, precision=6) -'1.234560' - ->>> tol.format_number(123456, precision=-2) -'123460' ->>> tol.format_number(123456, precision=-6) -'100000' diff --git a/docs/userguide/basics.colors.md b/docs/userguide/basics.colors.md new file mode 100644 index 000000000000..5a24c49132a6 --- /dev/null +++ b/docs/userguide/basics.colors.md @@ -0,0 +1,5 @@ +# Colors + +This section covers working with colors in COMPAS. + +For more information, see the API reference for [`compas.colors`][compas.colors]. diff --git a/docs/userguide/basics.colors.rst b/docs/userguide/basics.colors.rst deleted file mode 100644 index a25760535e83..000000000000 --- a/docs/userguide/basics.colors.rst +++ /dev/null @@ -1,225 +0,0 @@ -********************* -Colors and Color Maps -********************* - -.. rst-class:: lead - -In COMPAS colors are defined in RGB color space, with components in the range of 0-1. - -Basic Usage -=========== - - -Color Spaces -============ - - -Color Information -================= - - -The RGB Color Circle -==================== - -The color class (:class:`compas.colors.Color`) provides constructor methods -for the primary, secondary, and tertiary colors of the RGB color wheel or color circle. - -Primary Colors --------------- - ->>> Color.red() -Color(1.0, 0.0, 0.0, 1.0) ->>> Color.green() -Color(0.0, 1.0, 0.0, 1.0) ->>> Color.blue() -Color(0.0, 0.0, 1.0, 1.0) - -Secondary Colors ----------------- - ->>> Color.yellow() -Color(1.0, 1.0, 0.0, 1.0) ->>> Color.cyan() -Color(0.0, 1.0, 1.0, 1.0) ->>> Color.magenta() -Color(1.0, 0.0, 1.0, 1.0) - -Tertiary Colors ---------------- - ->>> Color.orange() -Color(1.0, 0.5, 0.0, 1.0) ->>> Color.lime() -Color(0.5, 1.0, 0.0, 1.0) ->>> Color.mint() -Color(0.0, 1.0, 0.5, 1.0) ->>> Color.azure() -Color(0.0, 0.5, 1.0, 1.0) ->>> Color.violet() -Color(0.5, 0.0, 1.0, 1.0) ->>> Color.pink() -Color(1.0, 0.0, 0.5, 1.0) - -.. figure:: /_images/userguide/basics.colors_color-circle.png - :figclass: figure - :class: figure-img img-fluid - - The RGB color circle. - - -Lighter and Darker Colors -========================= - -The color class (:class:`compas.colors.Color`) provides methods to generate lighter and darker variations of a given color. -The methods can be used to modify the colors in-place (:meth:`compas.colors.Color.lighten` and :meth:`compas.colors.Color.darken`), -or to generate new colors (:meth:`compas.colors.Color.lightened` and :meth:`compas.colors.Color.darkened`). - ->>> red = Color.red() ->>> red.lighten(50) -None ->>> red.darken(50) -None ->>> red -Color(1.0, 0.0, 0.0, 1.0) - ->>> red = Color.red() ->>> red.lightened(50) -Color(1.0, 0.5, 0.5, 1.0) ->>> red.darkened(50) -Color(0.5, 0.0, 0.0, 1.0) - -.. figure:: /_images/userguide/basics.colors_lightness.png - :figclass: figure - :class: figure-img img-fluid - - Lightness. - - -Saturation -========== - -Similar to generating lighter and darker colors, the color class provides methods for saturating or desaturating colors -(:meth:`compas.colors.Color.saturate` and :meth:`compas.colors.Color.desaturate`, and :meth:`compas.colors.Color.saturated` and :meth:`compas.colors.Color.desaturated`). - -.. figure:: /_images/userguide/basics.colors_saturation.png - :figclass: figure - :class: figure-img img-fluid - - Saturation. - - -Color Maps -========== - -Using :class:`compas.colors.ColorMap`, color maps can be constructed from various color inputs. - -* :meth:`compas.colors.ColorMap.from_rgb` -* :meth:`compas.colors.ColorMap.from_color` -* :meth:`compas.colors.ColorMap.from_two_colors` -* :meth:`compas.colors.ColorMap.from_three_colors` - -Maps based on named scientific color palettes designed by Fabio Crameri (https://www.fabiocrameri.ch/colourmaps/) -and some of the `matplotlib` color palettes are also available. - -* :meth:`compas.colors.ColorMap.from_palette` -* :meth:`compas.colors.ColorMap.from_mpl` - - -There is currently no predefined function for color map examples. -However, using the following template we can compare various examples. - ->>> from compas.geometry import Point, Polygon ->>> from compas.utilities import linspace, pairwise ->>> from compas.datastructures import Mesh ->>> from compas.colors import Color, ColorMap ->>> from compas_viewer import Viewer - ->>> n = 1000 ->>> t = 0.3 - ->>> up = [] ->>> down = [] ->>> for i in linspace(0, 10, n): -... point = Point(i, 0, 0) -... up.append(point + [0, t, 0]) -... down.append(point - [0, t, 0]) - ->>> polygons = [] ->>> for (d, c), (a, b) in zip(pairwise(up), pairwise(down)): -... polygons.append(Polygon([a, b, c, d])) - ->>> mesh = Mesh.from_polygons(polygons) - ->>> cmap = ... # define color map here ->>> facecolor = {i: cmap(i, minval=0, maxval=n - 1) for i in range(n)} - ->>> viewer = Viewer(show_grid = False) ->>> viewer.scene.add(mesh, facecolor=facecolor, show_lines=False) ->>> viewer.show() - - -From Palette ------------- - ->>> cmap = ColorMap.from_mpl('viridis') - -.. figure:: /_images/userguide/basics.colors_maps.png - :figclass: figure - :class: figure-img img-fluid - - `viridis` color map from matplotlib. - - -From RGB --------- - ->>> cmap = ColorMap.from_rgb() - -.. figure:: /_images/userguide/basics.colors_maps_from-rgb.png - :figclass: figure - :class: figure-img img-fluid - - Color map from RGB. - - -From One Color --------------- - ->>> cmap = ColorMap.from_color(Color.red()) ->>> cmap = ColorMap.from_color(Color.red(), rangetype='light') ->>> cmap = ColorMap.from_color(Color.red(), rangetype='dark') - -.. figure:: /_images/userguide/basics.colors_maps_from-one-color.png - :figclass: figure - :class: figure-img img-fluid - - Color maps constructed from a single color. - - -From Two Colors ---------------- - -:: - - >>> cmap = ColorMap.from_two_colors(Color.from_hex('#0092D2'), Color.pink()) - >>> cmap = ColorMap.from_two_colors(Color.from_hex('#0092D2'), Color.pink(), diverging=True) - -.. figure:: /_images/userguide/basics.colors_maps_from-two-colors.png - :figclass: figure - :class: figure-img img-fluid - - Color maps constructed from two colors. - - -From Three Colors ------------------ - -:: - - >>> cmap = ColorMap.from_three_colors(Color.red(), Color.green(), Color.blue()) - -.. figure:: /_images/userguide/basics.colors_maps_from-three-colors.png - :figclass: figure - :class: figure-img img-fluid - - Color maps constructed from three colors. diff --git a/docs/userguide/basics.datastructures.cellnetwork.md b/docs/userguide/basics.datastructures.cellnetwork.md new file mode 100644 index 000000000000..1d4814da37a6 --- /dev/null +++ b/docs/userguide/basics.datastructures.cellnetwork.md @@ -0,0 +1,5 @@ +# CellNetworks + +This section covers the CellNetwork data structure in COMPAS. + +For more information, see the API reference for [`compas.datastructures.CellNetwork`][compas.datastructures.CellNetwork]. diff --git a/docs/userguide/basics.datastructures.cellnetwork.rst b/docs/userguide/basics.datastructures.cellnetwork.rst deleted file mode 100644 index fa6928bfc39b..000000000000 --- a/docs/userguide/basics.datastructures.cellnetwork.rst +++ /dev/null @@ -1,137 +0,0 @@ -******************************************************************************** -Cell Networks -******************************************************************************** - -.. rst-class:: lead - -A :class:`compas.datastructures.CellNetwork` uses a halfface data structure to represent a collection of mixed topologic entities (cells, faces, edges and vertices) -and to facilitate the application of topological and geometrical operations on it. -In addition, it provides a number of methods for storing arbitrary data on vertices, edges, faces, cells, and the overall cell network itself. - -.. note:: - - Please refer to the API for a complete overview of all functionality: - - * :class:`compas.datastructures.CellNetwork` - * :class:`compas.datastructures.HalfFace` - - -CellNetwork Construction -======================== - -CellNetworks can be constructed in a number of ways: - -* from scratch, by adding vertices, faces and cells one by one, -* using a special constructor function, or -* from the data contained in a file. - -From Scratch ------------- - ->>> from compas.datastructures import CellNetwork ->>> cell_network = CellNetwork() ->>> vertices = [(0, 0, 0), (0, 1, 0), (1, 1, 0), (1, 0, 0), (0, 0, 1), (1, 0, 1), (1, 1, 1), (0, 1, 1)] ->>> faces = [[0, 1, 2, 3], [0, 3, 5, 4], [3, 2, 6, 5], [2, 1, 7, 6], [1, 0, 4, 7], [4, 5, 6, 7]] ->>> cells = [[0, 1, 2, 3, 4, 5]] ->>> vertices = [cell_network.add_vertex(x=x, y=y, z=z) for x, y, z in vertices] ->>> faces = [cell_network.add_face(fverts) for fverts in faces] ->>> cells = [cell_network.add_cell(fkeys) for fkeys in cells] ->>> print(cell_network) - - -Using Constructors ------------------- - ->>> from compas.datastructures import CellNetwork ->>> cell_network = CellNetwork.from_vertices_and_cells(...) - - -From Data in a File -------------------- - ->>> from compas.datastructures import CellNetwork ->>> cell_network = CellNetwork.from_obj(...) ->>> cell_network = CellNetwork.from_json(...) - - -Visualisation -============= - -Like all other COMPAS geometry objects and data structures, cell networks can be visualised by placing them in a scene. -For more information about visualisation with :class:`compas.scene.Scene`, see :doc:`/userguide/basics.visualisation`. - ->>> import compas ->>> from compas.datastructures import CellNetwork ->>> from compas.scene import Scene ->>> cell_network = CellNetwork.from_json(compas.get('cellnetwork_example.json')) ->>> scene = Scene() ->>> scene.add(mesh) ->>> scene.show() - -.. figure:: /_images/userguide/basics.datastructures.cellnetworks.example_grey.png - - -Vertices, Edges, Faces, Cells -============================= - -The cell network contains mixed topologic entities such as cells, faces, edges and vertices. - * Vertices are identified by a positive integer that is unique among the vertices of the current mesh. - * Edges are identified by a pair (tuple) of two vertex identifiers. - * Faces are identified by a positive integer that is unique among the faces of the current mesh. - * Cells are identified by a positive integer that is unique among the cells of the current mesh. - ->>> cell_network = CellNetwork.from_json(compas.get('cellnetwork_example.json')) ->>> cell_network.number_of_vertices() -44 ->>> cell_network.number_of_edges() -91 ->>> cell_network.number_of_faces() -43 ->>> cell_network.number_of_cells() -6 - -An edge can be assigned to any number of faces, or to none. If an edge is assigned to more than 2 faces, it is non-manifold. - ->>> cell_network.edge_faces((2, 6)) -[2, 3, 39] ->>> cell_network.edge_faces((1, 10)) -[8] ->>> cell_network.edge_faces((43, 34)) -[] ->>> cell_network.edges_without_face() -[(43, 34)] ->>> nme = cell_network.nonmanifold_edges() - -A face can be at maximum assigned to two cells, to one or None. A face is on the boundary if is is exactly assigned to one cell. - ->>> cell_network.face_cells(7) -[12, 8] ->>> cell_network.face_cells(9) -[8] ->>> cell_network.faces_without_cell() -[34, 35, 36, 37, 38, 39] ->>> boundary = cell_network.faces_on_boundaries() ->>> boundary -[1, 2, 3, 5, 9, 10, 11, 13, 16, 17, 18, 20, 21, 22, 23, 24, 25, 26, 27, 30, 31, 32, 40, 41, 42, 43, 44, 49] - -If all cells are connected, those faces form a closed cell as well: - ->>> cell_network.is_faces_closed(boundary) -True - -This shows only the faces on the boundary displayed. - -.. figure:: /_images/userguide/basics.datastructures.cellnetworks.example_hull.png - - -If we want to add a cell, we need to provide a list of face keys that form a closed volume. -If they don't, the cell will not be added. - -In the following image, the faces belonging to 2 cells are showin in yellow, the faces to one cell are shown in grey, and the faces belonging to no cell are shown in blue. -There is also one edge without face, shown with thicker linewidth. - -.. figure:: /_images/userguide/basics.datastructures.cellnetworks.example_color.png - - - - diff --git a/docs/userguide/basics.datastructures.cells.md b/docs/userguide/basics.datastructures.cells.md new file mode 100644 index 000000000000..35670395354b --- /dev/null +++ b/docs/userguide/basics.datastructures.cells.md @@ -0,0 +1,5 @@ +# Cells + +This section covers cell-based data structures in COMPAS. + +For more information, see the API reference for [`compas.datastructures.CellNetwork`][compas.datastructures.CellNetwork]. diff --git a/docs/userguide/basics.datastructures.cells.rst b/docs/userguide/basics.datastructures.cells.rst deleted file mode 100644 index 46c872b0672d..000000000000 --- a/docs/userguide/basics.datastructures.cells.rst +++ /dev/null @@ -1,3 +0,0 @@ -******************************************************************************** -Cellular Meshes -******************************************************************************** diff --git a/docs/userguide/basics.datastructures.graphs.md b/docs/userguide/basics.datastructures.graphs.md new file mode 100644 index 000000000000..fd89aba65c3b --- /dev/null +++ b/docs/userguide/basics.datastructures.graphs.md @@ -0,0 +1,5 @@ +# Graphs + +This section covers the Graph data structure in COMPAS. + +For more information, see the API reference for [`compas.datastructures.Graph`][compas.datastructures.Graph]. diff --git a/docs/userguide/basics.datastructures.graphs.rst b/docs/userguide/basics.datastructures.graphs.rst deleted file mode 100644 index 2db0da7b9191..000000000000 --- a/docs/userguide/basics.datastructures.graphs.rst +++ /dev/null @@ -1,3 +0,0 @@ -******************************************************************************** -Graphs -******************************************************************************** diff --git a/docs/userguide/basics.datastructures.md b/docs/userguide/basics.datastructures.md new file mode 100644 index 000000000000..b9b5e20761ff --- /dev/null +++ b/docs/userguide/basics.datastructures.md @@ -0,0 +1,11 @@ +# Data Structures + +This section covers the core data structures of COMPAS. + +## Topics + +- [Graphs](basics.datastructures.graphs.md) +- [Meshes](basics.datastructures.meshes.md) +- [Cells](basics.datastructures.cells.md) +- [CellNetworks](basics.datastructures.cellnetwork.md) +- [Trees](basics.datastructures.trees.md) diff --git a/docs/userguide/basics.datastructures.meshes.md b/docs/userguide/basics.datastructures.meshes.md new file mode 100644 index 000000000000..45f92faa4ea4 --- /dev/null +++ b/docs/userguide/basics.datastructures.meshes.md @@ -0,0 +1,5 @@ +# Meshes + +This section covers the Mesh data structure in COMPAS. + +For more information, see the API reference for [`compas.datastructures.Mesh`][compas.datastructures.Mesh]. diff --git a/docs/userguide/basics.datastructures.meshes.rst b/docs/userguide/basics.datastructures.meshes.rst deleted file mode 100644 index 096ab1ddf080..000000000000 --- a/docs/userguide/basics.datastructures.meshes.rst +++ /dev/null @@ -1,420 +0,0 @@ -******************************************************************************** -Meshes -******************************************************************************** - -.. rst-class:: lead - -A :class:`compas.datastructures.Mesh` uses a halfedge data structure to represent the topology and geometry of a polygonal mesh, -and to facilitate the application of topological and geometrical operations on it. -In addition, it provides a number of methods for storing arbitrary data on vertices, edges and faces, and the overall mesh itself. - -.. note:: - - Please refer to the API for a complete overview of all functionality: - - * :class:`compas.datastructures.Mesh` - - -Mesh Construction -================= - -Meshes can be constructed in a number of ways: - -* from scratch, by adding vertices and faces one by one, -* using a special constructor function, or -* from the data contained in a file. - -From Scratch ------------- - ->>> from compas.datastructures import Mesh ->>> mesh = Mesh() ->>> a = mesh.add_vertex(x=0, y=0, z=0) ->>> b = mesh.add_vertex(x=1, y=0, z=0) ->>> c = mesh.add_vertex(x=1, y=1, z=0) ->>> d = mesh.add_vertex(x=0, y=1, z=0) ->>> face = mesh.add_face([a, b, c, d]) ->>> mesh - - -Using Constructors ------------------- - ->>> from compas.datastructures import Mesh ->>> mesh = Mesh.from_lines(...) ->>> mesh = Mesh.from_meshgrid(...) ->>> mesh = Mesh.from_polygons(...) ->>> mesh = Mesh.from_polyhedron(...) ->>> mesh = Mesh.from_shape(...) ->>> mesh = Mesh.from_vertices_and_faces(...) - -From Data in a File -------------------- - ->>> from compas.datastructures import Mesh ->>> mesh = Mesh.from_obj('mesh.obj') ->>> mesh = Mesh.from_off('mesh.off') ->>> mesh = Mesh.from_ply('mesh.ply') ->>> mesh = Mesh.from_stl('mesh.stl') - - -Visualisation -============= - -Like all other COMPAS geometry objects and data structures, meshes can be visualised by placing them in a scene. -For more information about visualisation with :class:`compas.scene.Scene`, see :doc:`/userguide/basics.visualisation`. - ->>> from compas.datastructures import Mesh ->>> from compas.scene import Scene ->>> mesh = Mesh.from_obj(compas.get('tubemesh.obj')) ->>> scene = Scene() ->>> scene.add(mesh) ->>> scene.show() - -.. figure:: /_images/userguide/basics.datastructures.meshes.tubemesh.png - - -Vertices, Edges, Faces -====================== - -A mesh has vertices, edges, and faces. -Vertices are identified by a positive integer that is unique among the vertices of the current mesh. -Faces are identified by a positive integer that is unique among the faces of the current mesh. -Edges are identified by a pair (tuple) of two vertex identifiers. - ->>> mesh = Mesh.from_meshgrid(dx=10, dy=10, nx=10, ny=10) ->>> mesh.number_of_vertices() -121 ->>> mesh.number_of_edges() -200 ->>> mesh.number_of_faces() -81 - -Vertex, edge, and face accessors are generators: they are meant to be used in loops. - ->>> mesh.vertices() - ->>> mesh.edges() - ->>> mesh.faces() - - ->>> for vertex in mesh.vertices(): -... # do something with this vertex -... print(vertex) -... -0 -1 -2 -... - ->>> for edge in mesh.edges(): -... # do something with this edge -... print(edge) -... -(0, 1) -(1, 2) -(2, 3) -... - ->>> for face in mesh.faces(): -... # do something with this face -... print(face) -... -0 -1 -2 -... - -Lists of vertices, edges, and faces have to be constructed explicitly. - ->>> vertices = list(mesh.vertices()) ->>> vertices -[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, ..., 120] - ->>> edges = list(mesh.edges()) ->>> edges -[(0, 1), (1, 2), (2, 3), (3, 4), (4, 5), ..., (115, 120)] - ->>> faces = list(mesh.faces()) ->>> faces -[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, ..., 80] - - -Vertex, Edge, Face Attributes -============================= - -Arbitrary data can be assigned to vertices, edges, and faces, as vertex/edge/face attributes, and to the overall mesh itself. -To allow for serialisatin of the mesh and all the data associated with it, the data should be JSON serialisable. -See :ref:`Mesh Serialisation` for more information. - -The functionality is demonstrated here using vertex attributes. -The mechanism is exactly the same for edges and faces. - -It is good practice to declare default values for the added data attributes. - ->>> mesh = Mesh.from_meshgrid(dx=10, dy=10, nx=10, ny=10) ->>> mesh.update_default_vertex_attributes(a=None, b=0.0, c=False) - -Get the value of one attribute of one vertex. - ->>> mesh.vertex_attribute(0, 'a') -None - -Get the value of multiple attributes of one vertex. - ->>> mesh.vertex_attributes(0, ['a', 'b']) -(None, 0.0) - -Get the value of one attribute of all vertices. - ->>> mesh.vertices_attribute('a') -[None, None, None, ... None] - -Get the value of multiple attributes of all vertices. - ->>> mesh.vertices_attributes(['b', 'c']) -[(0.0, False), (0.0, False), (0.0, False), ..., (0.0, False)] - -Similarly, for a selection of vertices. - ->>> mesh.vertices_attribute('b', vertices=[0, 1, 2, 3]) -[0.0, 0.0, 0.0, 0.0] - ->>> mesh.vertices_attributes(['a', 'c'], vertices=[0, 1, 2, 3]) -[(None, False), (None, False), (None, False), (None, False)] - -Updating attributes is currently only possible one vertex at a time. - ->>> mesh.vertex_attribute(0, 'a', (1.0, 0.0, 0.0)) - ->>> for vertex in mesh.vertices(): -... if mesh.vertex_degree(vertex) == 2: -... mesh.vertex_attribute(vertex, 'a', (1.0, 0.0, 0.0)) -... - -Finally, note that the xyz coordinates of vertices can be accessed and modified using the same functions. - ->>> mesh.vertex_attributes(0, 'xyz') -(0.0, 0.0, 0.0) ->>> mesh.vertices_attribute('x') -[0.0, 1.0, 2.0, ..., 9.0] - - -Halfedge Data Structure -======================= - -The topology of a mesh is stored in a halfedge data structure. -In this data structure, vertices are connected to other vertices, and faces to other faces, via edges. -An edge has two connected vertices, and at most two connected faces. -Each edge is split into two halfedges, one for each of the connected faces. -If an edge has only one connected face, the edge is on the boundary. - -Note that in a mesh constructed using :meth:`compas.datastructures.Mesh.from_meshgrid`, the vertices are organised in a specific way. -We will use that structure to explain some of the topological concepts more easily. - ->>> mesh = Mesh.from_meshgrid(dx=9, nx=9) - ->>> for i in range(0, 10): ->>> print(mesh.is_vertex_on_boundary(i)) -... -True -True -True -True -True -True -True -True -True -True - -.. figure:: /_images/userguide/basics.datastructures.meshes.meshgrid-column0.png - - ->>> for i in range(30, 40): ->>> print(mesh.is_vertex_on_boundary(i)) -... -True -False -False -False -False -False -False -False -False -True - -.. figure:: /_images/userguide/basics.datastructures.meshes.meshgrid-column3.png - - -Halfedge Cycles ---------------- - -The vertices of a face of the mesh are ordered in a continuous cycle. -Every two consecutive vertices are connected by a halfedge of the face. -Like the vertices, the halfedges of a face form a continuous cycle. -In a valid halfedge mesh, all the cycle directions are consisten. -By cycling the faces, each edge is traversed exactly twice, -in opposite direction, except fo the edges on the boundary. - ->>> for face in mesh.faces(): -... for edge in mesh.face_halfedges(face): -... print(mesh.halfedge_face(edge) == face) -... -True -True -... -True - -.. figure:: /_images/userguide/basics.datastructures.meshes.cycles.png - -Using a combination of the halfedge functions, it is possible to traverse the mesh in a number of ways. - -* :meth:`compas.datastructures.Mesh.face_halfedges` -* :meth:`compas.datastructures.Mesh.halfedge_face` -* :meth:`compas.datastructures.Mesh.halfedge_before` -* :meth:`compas.datastructures.Mesh.halfedge_after` - - -Neighbours ----------- - ->>> for i, nbr in enumerate(mesh.vertex_neighbors(23, ordered=True)): -... print(i, nbr) -... -0 22 -1 13 -2 24 -3 33 - -.. figure:: /_images/userguide/basics.datastructures.meshes.vertex-neighbours.png - ->>> for i, face in enumerate(mesh.vertex_faces(23)): -... print(i, face) -... -0 20 -1 11 -2 12 -3 21 - -.. figure:: /_images/userguide/basics.datastructures.meshes.vertex-faces.png - ->>> for i, nbr in enumerate(mesh.face_neighbors(21)): -... print(i, nbr) -... -0 20 -1 22 -2 23 -3 24 - -.. figure:: /_images/userguide/basics.datastructures.meshes.face-neighbours.png - - -Loops and Strips ----------------- - ->>> for edge in mesh.halfedge_loop((32, 33)): -... print(edge) -... -(32, 33) -(33, 34) -(34, 35) -(35, 36) -(36, 37) -(37, 38) -(38, 39) - ->>> for edge in mesh.edge_loop((62, 63)): -... print(edge) -... -(60, 61) -(61, 62) -(62, 63) -(63, 64) -(64, 65) -(65, 66) -(66, 67) -(67, 68) -(68, 69) - -.. figure:: /_images/userguide/basics.datastructures.meshes.edge-loop.png - ->>> for edge in mesh.edge_strip((20, 30)): -... print(edge) -... -(20, 30) -(21, 31) -(22, 32) -(23, 33) -(24, 34) -(25, 35) -(26, 36) -(27, 37) -(28, 38) -(29, 39) - -.. figure:: /_images/userguide/basics.datastructures.meshes.edge-strip.png - -Mesh Geometry -============= - -* vertex_point -* vertex_area -* vertex_normal -* vertex_laplacian -* vertex_curvature - -* face_area -* face_normal -* face_flatness -* face_circle -* face_centroid -* face_polygon - -* edge_vector -* edge_line -* edge_midpoint -* edge_length -* edge_direction - - -Filtering -========= - -* vertices_where -* edges_where -* faces_where - - -Mesh Serialisation -================== - ->>> mesh.to_json('mesh.json') ->>> mesh = Mesh.from_json('mesh.json') ->>> mesh - - ->>> s = mesh.to_jsonstring() ->>> mesh = Mesh.from_jsonstring(s) ->>> mesh - - ->>> session = {'mesh': mesh, 'a': 1, 'b': 2} ->>> compas.json_dump(session, 'session.json') ->>> session = compas.json_load('session.json') ->>> mesh = session['mesh'] ->>> mesh - - - -A Simple Example -================ - -* mesh from obj -* mesh delete faces -* mesh remesh -* mesh dual -* mesh frame subdivision -* mesh to FE mesh diff --git a/docs/userguide/basics.datastructures.rst b/docs/userguide/basics.datastructures.rst deleted file mode 100644 index 718780e5fe1f..000000000000 --- a/docs/userguide/basics.datastructures.rst +++ /dev/null @@ -1,14 +0,0 @@ -******************************************************************************** -Datastructures -******************************************************************************** - -.. toctree:: - :maxdepth: 2 - :titlesonly: - :caption: Data Structures - - basics.datastructures.graphs - basics.datastructures.meshes - basics.datastructures.cells - basics.datastructures.cellnetwork - basics.datastructures.trees diff --git a/docs/userguide/basics.datastructures.trees.md b/docs/userguide/basics.datastructures.trees.md new file mode 100644 index 000000000000..dfa4f35e7aba --- /dev/null +++ b/docs/userguide/basics.datastructures.trees.md @@ -0,0 +1,5 @@ +# Trees + +This section covers the Tree data structure in COMPAS. + +For more information, see the API reference for [`compas.datastructures.Tree`][compas.datastructures.Tree]. diff --git a/docs/userguide/basics.datastructures.trees.rst b/docs/userguide/basics.datastructures.trees.rst deleted file mode 100644 index 23bda36d0cc5..000000000000 --- a/docs/userguide/basics.datastructures.trees.rst +++ /dev/null @@ -1,189 +0,0 @@ -******************************************************************************** -Trees -******************************************************************************** - -.. rst-class:: lead - -A :class:`compas.datastructures.Tree` is a data structure that can be used to -represent hierarchical relationships between data. It starts with a single root -node, and each node can have a number of children nodes. Each node can -store arbitrary attributes. - - -.. note:: - - Please refer to the API for a complete overview of all functionality: - - * :class:`compas.datastructures.Tree` - -Tree Construction -================= - -Trees can be constructed in a number of ways: -* by adding nodes to a tree instance, specifiying parent node, -* by adding nodes directly to another node instance that belongs to a tree, or -* directly loaded from a serilised json file. - -Adding To Tree --------------- - ->>> from compas.datastructures import Tree ->>> from compas.datastructures import TreeNode ->>> tree = Tree() ->>> root_node = TreeNode('root') ->>> tree.add(root_node) ->>> branch_node = TreeNode('branch') ->>> tree.add(branch_node, parent=root_node) ->>> leaf_node1 = TreeNode('leaf1') ->>> tree.add(leaf_node1, parent=branch_node) ->>> leaf_node2 = TreeNode('leaf2') ->>> tree.add(leaf_node2, parent=branch_node) ->>> tree.print_hierarchy() -└── - └── - ├── - └── - -Adding To Node --------------- - ->>> from compas.datastructures import Tree ->>> from compas.datastructures import TreeNode ->>> tree = Tree() ->>> root_node = TreeNode('root') ->>> tree.add(root_node) ->>> branch_node = TreeNode('branch') ->>> root_node.add(branch_node) ->>> leaf_node1 = TreeNode('leaf1') ->>> branch_node.add(leaf_node1) ->>> leaf_node2 = TreeNode('leaf2') ->>> branch_node.add(leaf_node2) -└── - └── - ├── - └── - -Loading From File ------------------ - ->>> from compas.data import json_load ->>> tree = json_load('tree.json') ->>> tree.print_hierarchy() -└── - └── - ├── - └── - -Remove Node ------------ - ->>> tree.remove(leaf_node2) # Or branch_node.remove(leaf_node2) ->>> tree.print_hierarchy() -└── - └── - └── - - -Tree Traversal -============== -The tree can be traversed in a number of ways, including depth-first and breadth-first. -For depth-first traversal, there are additional options for pre-order and post-order. - -Depth-First ------------ -The algorithm starts at the root node and explores as far as possible along each branch before backtracking. -The traversal can be done in pre-orderor post-order. In pre-order, the parent node is visited before its children. In post-order, -the parent node is visited after its children. - ->>> from compas.datastructures import Tree ->>> from compas.datastructures import TreeNode ->>> tree = Tree() ->>> root_node = TreeNode('root') ->>> tree.add(root_node) ->>> branch_node1 = TreeNode('branch1') ->>> root_node.add(branch_node1) ->>> leaf_node1 = TreeNode('leaf1') ->>> branch_node1.add(leaf_node1) ->>> leaf_node2 = TreeNode('leaf2') ->>> branch_node1.add(leaf_node2) ->>> branch_node2 = TreeNode('branch2') ->>> root_node.add(branch_node2) ->>> leaf_node3 = TreeNode('leaf3') ->>> branch_node2.add(leaf_node3) ->>> leaf_node4 = TreeNode('leaf4') ->>> branch_node2.add(leaf_node4) ->>> tree.print_hierarchy() -└── - ├── - │ ├── - │ └── - └── - ├── - └── - ->>> for node in tree.traverse(strategy='depthfirst', order='preorder'): -... print(node) - - - - - - - - ->>> for node in tree.traverse(strategy='depthfirst', order='postorder'): -... print(node) - - - - - - - - - -Breadth-First -------------- -The algorithm starts at the root node and explores the neighbour nodes first, before moving to the next level neighbours. - ->>> for node in tree.traverse(strategy='breadthfirst'): -... print(node) - - - - - - - - - -Node Attributes -=============== - ->>> nodes = tree.get_nodes_by_name('branch1') ->>> nodes -[] - ->>> node = tree.get_node_by_name('branch1') ->>> node - - ->>> node.is_root -False ->>> node.is_leaf -False ->>> node.is_branch -True - ->>> node.parent - ->>> node.children -[, ] - ->>> leaf1 = node.children[0] ->>> list(leaf1.ancestors) -[, ] ->>> root = leaf1.ancestors[-1] ->>> list(root.descendants) -[, , , , , ] - diff --git a/docs/userguide/basics.datastructures.volmeshes.md b/docs/userguide/basics.datastructures.volmeshes.md new file mode 100644 index 000000000000..f5120790daca --- /dev/null +++ b/docs/userguide/basics.datastructures.volmeshes.md @@ -0,0 +1,5 @@ +# VolMeshes + +This section covers the VolMesh data structure in COMPAS. + +For more information, see the API reference for [`compas.datastructures.VolMesh`][compas.datastructures.VolMesh]. diff --git a/docs/userguide/basics.datastructures.volmeshes.rst b/docs/userguide/basics.datastructures.volmeshes.rst deleted file mode 100644 index 5d25cdd02430..000000000000 --- a/docs/userguide/basics.datastructures.volmeshes.rst +++ /dev/null @@ -1,367 +0,0 @@ -******************************************************************************** -Vol(umetric) Meshes -******************************************************************************** - -.. currentmodule:: compas.datastructures - -.. rst-class:: lead - -A :class:`compas.datastructures.VolMesh` uses a "halfface" data structure to represent the topology and geometry of a cellular mesh, -and to facilitate the application of topological and geometrical operations on it. -In addition, it provides a number of methods for storing arbitrary data on vertices, edges, faces, and cell, and on the overall mesh itself. - -.. note:: - - Please refer to the API for a complete overview of all functionality: - - * :class:`compas.datastructures.VolMesh` - -General Properties -================== - -A `VolMesh` consists of vertices, edges, faces, and cells. -Currenly, a `VolMesh` can only be constructed by providing information about the vertices and cells. -This means that edges and faces are created implicitly, and can only exist as part of the topology of a cell. - -An edge connects exactly two vertices. -All edges of a valid `VolMesh` belong to at least one cell. - -A face consists of three or vertices, which are ordered such that they form a closed cycle. -The faces of a cell form a closed mesh. -The structure of this mesh is equivalent to the structure of a halfedge mesh (:class:`compas.datastructures.Mesh`). -The cycle directions of the faces are such that the resulting normals point towards the interior of the cell. - -Neighbouring cells share at least one face. -A face can be shared by at most two neighbouring cells. -The cycle directions of the faces through which two neighbouring cells are connected are exactly opposite. - -Naked faces are faces without an opposite face, or with an opposite face that doesn"t belong to a cell. -Cells with naked faces are considered to be on the boundary of the `VolMesh`. - -An empty `VolMesh` is valid. -A `VolMesh` with only vertices, but no cells is also valid. - -VolMesh Construction -==================== - -VolMeshes can be constructed in a number of ways: - -* from scratch, by adding vertices and cells one by one, -* from geometric input, -* using a special constructor function, or -* from the data contained in a file. - -.. note:: - - During construction, the validity of the input is not verified. - The `VolMesh` is created with the input that is provided. - Wrong input means wrong result. - -From Scratch ------------- - -The following snippet constructs a `VolMesh` with one cell in the form of a unit cube. -Note that the vertices of the faces are ordered such that the corresponding normal vectors point toward the interior of the cube. - ->>> from compas.datastructures import VolMesh ->>> volmesh = VolMesh() - ->>> a = volmesh.add_vertex(x=0, y=0, z=0) ->>> b = volmesh.add_vertex(x=1, y=0, z=0) ->>> c = volmesh.add_vertex(x=1, y=1, z=0) ->>> d = volmesh.add_vertex(x=0, y=1, z=0) ->>> e = volmesh.add_vertex(x=0, y=0, z=1) ->>> f = volmesh.add_vertex(x=1, y=0, z=1) ->>> g = volmesh.add_vertex(x=1, y=1, z=1) ->>> h = volmesh.add_vertex(x=0, y=1, z=1) - ->>> faces = [[a, b, c, d], [e, h, g, f], [a, e, f, b], [b, f, g, c], [c, g, h, d], [a, d, h, e]] ->>> cell = volmesh.add_cell(faces) - -Using Constructors ------------------- - -Constructing `VolMesh` objects "from scratch", as shown above, obviously quickly becomes rather tedious. -Therefore, the `VolMesh` class provides class methods that can be used to construct volumetric meshes -more easily from various types of common inputs. - -* :meth:`VolMesh.from_vertices_and_cells` -* :meth:`VolMesh.from_meshgrid` -* :meth:`VolMesh.from_meshes` -* :meth:`VolMesh.from_polyhedrons` - ->>> from compas.datastructures import VolMesh ->>> volmesh = VolMesh.from_obj("meshes.obj") - -From Data in a File -------------------- - -Currently only OBJ files containing closed meshes are supported. - -* :meth:`VolMesh.from_obj` - ->>> from compas.datastructures import VolMesh ->>> volmesh = VolMesh.from_obj("volmeshring.obj") - -Equivalently, the geometry of a `VolMesh` can also be written to an OBJ file. -However, note that all additional data attributes (see :ref:`Vertex, Edges, Face, Cell Attributes`) are lost during this process. -Only the geometry survives this conversion process. - ->>> volmesh.to_obj("volmeshring.obj") - -Visualisation -============= - -Like all other COMPAS geometry objects and data structures, volumetric meshes can be visualised by placing them in a scene. -For more information about visualisation with :class:`compas.scene.Scene`, see :doc:`/userguide/basics.visualisation`. -The snippet below uses `volmesh.obj`, which is available here: :download:`volmeshring.obj`. - ->>> from compas.datastructures import VolMesh ->>> from compas.scene import Scene ->>> mesh = Mesh.from_obj("volmeshring.obj") ->>> scene = Scene() ->>> scene.add(mesh) ->>> scene.show() - -.. figure:: /_images/userguide/basics.datastructures.volmeshes.volmeshring.png - -Vertices, Edges, Faces, Cells -============================= - -A `VolMesh` can only be constructed by providing information about the vertices and cells. -Edges are created implicitly, and can only exist as part of the topology of a cell. -Faces are not stored explicitly, but are generated automatically based on the corresponding (pairs of) halffaces. - -Vertices, faces, and cells are identified by unique, positive and increasing integers. -Edges are identified by pairs of vertex identifiers. - -In this section, we will use a `VolMesh` constructed from a mesh grid, -because its highly structured nature allows for easy and transparent counting and verification. - ->>> volmesh = VolMesh.from_meshgrid(dx=3, nx=3) - -.. figure:: /_images/userguide/basics.datastructures.volmeshes.volmeshgrid_3x3.png - ->>> volmesh.number_of_vertices() -64 ->>> volmesh.number_of_edges() -144 ->>> volmesh.number_of_faces() -108 ->>> volmesh.number_of_cells() -27 - -To iterate over vertices, edges, faces, and cells the `VolMesh` provides corresponding generators. - ->>> volmesh.vertices() - ->>> volmesh.edges() - ->>> volmesh.faces() - ->>> volmesh.cells() - - -These generators are meant to be used in loops. - ->>> for vertex in volmesh.vertices(): -... print(vertex) -... -0 -1 -2 -3 -4 -# etc. - ->>> for edge in volmesh.edges(): -... print(edge) -(0, 1) -(0, 4) -(0, 16) -(1, 2) -(1, 5) -# etc. - -The edges are not stored explicitly in the data structure, -but instead generated automatically from the adjacency information of the vertices. -They are generated following the order of the vertex identifiers to make sure the order of edges is deterministic. - ->>> for face in volmesh.faces(): -... print(face) -0 -1 -2 -3 -4 -# etc - ->>> for cell in volmesh.cells(): -... print(cell) -0 -1 -2 -3 -4 -# etc - -Lists of vertices, edges, faces, and cells have to be constructed explicitly. - ->>> vertices = list(volmesh.vertices()) ->>> vertices -[0, 1, 2, 3, 4, ..., 63] - ->>> edges = list(volmesh.edges()) ->>> edges -[(0, 1), (0, 4), (0, 16), (1, 2), (1, 5), ..., (62, 63)] - -# NOTE: this is not ideal. - ->>> faces = list(volmesh.faces()) ->>> faces -[???] - ->>> cells = list(volmesh.cells()) ->>> cells -[0, 1, 2, 3, 4, ..., 27] - -Vertex, Edge, Face, Cell Attributes -=================================== - -Arbitrary data can be assigned to vertices, edges, faces, and cells as vertex/edge/face/cell attributes, and to the overall `VolMesh` itself. -To allow for serialisatin of the `VolMesh` and all the data associated with it, the data should be JSON serialisable. -See :ref:`Data Serialisation` for more information. - -The functionality is demonstrated here using vertex attributes. -The mechanism is exactly the same for edges, faces, and cells. - -It is good practice to declare default values for the added data attributes. - ->>> volmesh = VolMesh.from_meshgrid(dx=3, nx=10) ->>> volmesh.update_default_vertex_attributes(a=None, b=0.0, c=False) - -Get the value of one attribute of one vertex. - ->>> volmesh.vertex_attribute(vertex=0, name="a") -None - -Get the value of multiple attributes of one vertex. - ->>> volmesh.vertex_attributes(vertex=0, names=["a", "b"]) -(None, 0.0) - -Get the value of one attribute of all vertices. - ->>> volmesh.vertices_attribute(name="a") -[None, None, None, ... None] - -Get the value of multiple attributes of all vertices. - ->>> volmesh.vertices_attributes(names=["b", "c"]) -[(0.0, False), (0.0, False), (0.0, False), ..., (0.0, False)] - -Similarly, for a selection of vertices. - ->>> volmesh.vertices_attribute(name="b", vertices=[0, 1, 2, 3]) -[0.0, 0.0, 0.0, 0.0] - ->>> volmesh.vertices_attributes(names=["a", "c"], vertices=[0, 1, 2, 3]) -[(None, False), (None, False), (None, False), (None, False)] - -Updating attributes is currently only possible one vertex at a time. - ->>> volmesh.vertex_attribute(vertex=0, name="a", value=(1.0, 0.0, 0.0)) - ->>> for vertex in volmesh.vertices(): -... if volmesh.vertex_degree(vertex) == 2: -... volmesh.vertex_attribute(vertex=vertex, name="a", value=(1.0, 0.0, 0.0)) -... - -Overall Topology -================ - -More info coming... - -* vertex_neighbors -* vertex_cells -* vertex_edges -* vertex_faces -* edge_cells -* edge_faces -* edge_halffaces -* cell_neighbors - -Topology of a Cell -================== - -Within the context of a cell, the topology of a `VolMesh` is the same as the topology of a regular `Mesh`. -Vertices are connected to other vertices, and faces to other faces, via edges. -An edge has two connected vertices, and at most two connected faces. -Each edge is split into two halfedges, one for each of the connected faces. - ->>> volmesh = VolMesh.from_meshgrid(dx=3, nx=3) ->>> cell = volmesh.cell_sample(size=1).next() ->>> - -* cell_vertices -* cell_edges -* cell_halfedges -* cell_halffaces -* cell_faces -* cell_vertex_halffaces -* cell_vertex_faces -* cell_vertex_neighbors -* cell_edge_halffaces -* cell_edge_faces - -.. edges and faces are implicit, and only used to store additional data -.. their identifiers are also implicit -.. halfedge_face -.. face_attributes -.. - -Geometry -======== - -* vertex_point -* edge_vector -* edge_line -* edge_start -* edge_end -* face_centroid -* face_area -* halfface_centroid -* halfface_polygon -* halfface_normal -* cell_volume -* cell_centroid -* cell_polyhedron - -Filtering -========= - -* vertices_where -* edges_where -* faces_where -* cells_where - -Data Serialisation -================== - ->>> volmesh.to_json("volmesh.json") ->>> volmesh = VolMesh.from_json("volmesh.json") - ->>> s = volmesh.to_jsonstring() ->>> volmesh = VolMesh.from_jsonstring(s) - ->>> session = {"volmesh": volmesh, "a": 1, "b": 2} ->>> compas.json_dump(session, "session.json") ->>> session = compas.json_load("session.json") ->>> volmesh = session["volmesh"] - -Examples -======== - -.. literalinclude:: basics.datastructures.volmeshes_example-1.py - :language: python - diff --git a/docs/userguide/basics.geometry.breps.md b/docs/userguide/basics.geometry.breps.md new file mode 100644 index 000000000000..51cb6a1e4fd5 --- /dev/null +++ b/docs/userguide/basics.geometry.breps.md @@ -0,0 +1,5 @@ +# Breps + +This section covers Boundary Representations (Breps) in COMPAS. + +For more information, see the API reference for [`compas.geometry.Brep`][compas.geometry.Brep]. diff --git a/docs/userguide/basics.geometry.breps.rst b/docs/userguide/basics.geometry.breps.rst deleted file mode 100644 index 70aa9ca85e56..000000000000 --- a/docs/userguide/basics.geometry.breps.rst +++ /dev/null @@ -1,134 +0,0 @@ -******************************************************************************** -Boundary Representations -******************************************************************************** - -.. rst-class:: lead - -Boundary representation (Brep) support is realized in COMPAS using its `plugin` system. -The expected interface for Brep related classes is defined in the :mod:`compas.geometry.brep` module -whereas the actual implementation is context dependent and implemented using plugins. - -.. currentmodule:: compas.geometry - -.. highlight:: python - -Brep Basics -=========== - -Brep is a data structure used to describe a shape by means of recording topological and geometrical information of the shape's boundaries. -Some topological properties are associated with an underlying geometry, while others are purely topological. - -A Brep is comprised of the following: - -.. rst-class:: table table-bordered - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Topology - - Geometry - - Description - * - Vertex - - 3D Point - - The most basic element of a Brep, geometrically described as a point in 3D space. - * - Edge - - 3D Curve - - An edge has a start vertex and an end vertex. The underlying 3D curve describes the geometry of the edge (Line, Circle etc.). Closed edges feature start_vertex == end_vertex. - * - Loop - - None - - A collection of trims which define the inner or outer boundary of a face. - * - Face - - Surface - - Defines the geometry of one of the shape's faces using a surface. Associated with at least one loop which describes the trimmed outer boundary of the surface. Inner loops are referred to as holes in the face. - * - Trim - - 2D Curve - - A 2D curve which trims a face. Trims are associated with a corresponding edge. - - -Getting Started with COMPAS Brep -================================ - -To create an empty `Brep` - -.. code-block:: - - >>> from compas.geometry import Brep - >>> brep = Brep() - - -Notice that the type of the actual instance created by `Brep()` will differ depending on the currently available backend. -For example, when in Rhino - -.. code-block:: - - >>> type(brep) - compas_rhino.geometry.RhinoBrep - -Every backend is expected to implement some alternative constructors - -.. code-block:: - - >>> from compas.geometry import Box - >>> from compas.geometry import Brep - >>> ... - >>> box = Box.from_width_height_depth(5., 5., 5.) - >>> brep_box = Brep.from_box(box) - - -`Brep` can also be instantiated from an instance of a backend native `Brep` - -.. code-block:: - - >>> import Rhino - >>> from compas.geometry import Brep - >>> ... - >>> Brep.from_native(Rhino.Geometry.Brep()) - -Brep operations -=============== - -Trimming a Brep in Grasshopper - -.. code-block:: - - from compas.geometry import Frame - from compas.geometry import Point - from compas.geometry import Brep - - box = Box.from_width_height_depth(5, 5, 10) - - brep = Brep.from_box(box) - cutting_plane = Frame(Point(0, 2.5, 0), [1, 0, 0], [0, 1, 1.5]) - - brep.trim(cutting_plane) - -|pic1| |pic2| - -.. |pic1| image:: files/box_w_plane.png - :width: 48% - -.. |pic2| image:: files/trimmed_box.png - :width: 48% - -Splitting a Brep in Grasshopper - -.. code-block:: - - from compas.geometry import Brep, Box, Frame, Translation - - brep = Brep.from_box(Box.from_width_height_depth(5,5,5)) - cutter = Brep.from_box(Box.from_width_height_depth(1, 6, 6)) - - a, b, c = brep.split(cutter) - - world_xy = Frame.worldXY() - translated_frame = Frame((0, 0, 1.), world_xy.xaxis, world_xy.yaxis) - t = Translation.from_frame_to_frame(world_xy, translated_frame) - a.transform(t) - b.transform(t) - - result = [x.native_brep for x in [a, b, c]] - -.. image:: files/3_way_split.png - :width: 50% diff --git a/docs/userguide/basics.geometry.curves_and_surfaces.md b/docs/userguide/basics.geometry.curves_and_surfaces.md new file mode 100644 index 000000000000..cd988e3b8edc --- /dev/null +++ b/docs/userguide/basics.geometry.curves_and_surfaces.md @@ -0,0 +1,10 @@ +# Curves and Surfaces + +This section covers curves and surfaces in COMPAS. + +For more information, see the API reference for: + +- [`compas.geometry.Curve`][compas.geometry.Curve] +- [`compas.geometry.NurbsCurve`][compas.geometry.NurbsCurve] +- [`compas.geometry.Surface`][compas.geometry.Surface] +- [`compas.geometry.NurbsSurface`][compas.geometry.NurbsSurface] diff --git a/docs/userguide/basics.geometry.curves_and_surfaces.rst b/docs/userguide/basics.geometry.curves_and_surfaces.rst deleted file mode 100644 index 423f9910b6a7..000000000000 --- a/docs/userguide/basics.geometry.curves_and_surfaces.rst +++ /dev/null @@ -1,3 +0,0 @@ -******************************************************************************** -Curves and Surfaces -******************************************************************************** diff --git a/docs/userguide/basics.geometry.distance_and_membership.md b/docs/userguide/basics.geometry.distance_and_membership.md new file mode 100644 index 000000000000..0a3f1e7d2961 --- /dev/null +++ b/docs/userguide/basics.geometry.distance_and_membership.md @@ -0,0 +1,5 @@ +# Distance and Membership + +This section covers distance calculations and membership tests in COMPAS. + +For more information, see the distance and membership functions in [`compas.geometry`][compas.geometry]. diff --git a/docs/userguide/basics.geometry.distance_and_membership.rst b/docs/userguide/basics.geometry.distance_and_membership.rst deleted file mode 100644 index 686733e52a17..000000000000 --- a/docs/userguide/basics.geometry.distance_and_membership.rst +++ /dev/null @@ -1,3 +0,0 @@ -****************************************************************************** -Distance and Membership -****************************************************************************** diff --git a/docs/userguide/basics.geometry.intersections.md b/docs/userguide/basics.geometry.intersections.md new file mode 100644 index 000000000000..b4fa2ab8cc9d --- /dev/null +++ b/docs/userguide/basics.geometry.intersections.md @@ -0,0 +1,5 @@ +# Intersections + +This section covers intersection calculations in COMPAS. + +For more information, see the intersection functions in [`compas.geometry`][compas.geometry]. diff --git a/docs/userguide/basics.geometry.intersections.rst b/docs/userguide/basics.geometry.intersections.rst deleted file mode 100644 index eefbc4695925..000000000000 --- a/docs/userguide/basics.geometry.intersections.rst +++ /dev/null @@ -1,3 +0,0 @@ -******************************************************************************** -Intersections -******************************************************************************** diff --git a/docs/userguide/basics.geometry.md b/docs/userguide/basics.geometry.md new file mode 100644 index 000000000000..d6a4ce578030 --- /dev/null +++ b/docs/userguide/basics.geometry.md @@ -0,0 +1,15 @@ +# Geometry + +This section covers the fundamentals of working with geometry in COMPAS. + +## Topics + +- [Points and Vectors](basics.geometry.points_and_vectors.md) +- [Planes and Frames](basics.geometry.planes_and_frames.md) +- [Polygons and Polyhedrons](basics.geometry.polygons_and_polyhedrons.md) +- [Curves and Surfaces](basics.geometry.curves_and_surfaces.md) +- [Solids](basics.geometry.solids.md) +- [Breps](basics.geometry.breps.md) +- [Transformations](basics.geometry.transformations.md) +- [Intersections](basics.geometry.intersections.md) +- [Distance and Membership](basics.geometry.distance_and_membership.md) diff --git a/docs/userguide/basics.geometry.planes_and_frames.rst b/docs/userguide/basics.geometry.planes_and_frames.md similarity index 83% rename from docs/userguide/basics.geometry.planes_and_frames.rst rename to docs/userguide/basics.geometry.planes_and_frames.md index bfa816b8a2bb..2cbf9ee0893b 100644 --- a/docs/userguide/basics.geometry.planes_and_frames.rst +++ b/docs/userguide/basics.geometry.planes_and_frames.md @@ -1,22 +1,20 @@ -****************************************************************************** -Planes and Frames -****************************************************************************** +# Planes and Frames -[...intro...] - -Planes -============================================================================== +## Planes A plane is defined by a point and a normal vector. +```python >>> from compas.geometry import Point, Vector >>> from compas.geometry import Plane >>> plane = Plane(Point(0, 0, 0), Vector(0, 0, 1)) >>> plane Plane(point=Point(x=0.0, y=0.0, z=0.0), normal=Vector(x=0.0, y=0.0, z=1.0)) +``` Pure Python inputs are automatically converted. +```python >>> plane = Plane([0, 0, 0], [0, 0, 1]) >>> plane Plane(point=Point(x=0.0, y=0.0, z=0.0), normal=Vector(x=0.0, y=0.0, z=1.0)) @@ -24,30 +22,38 @@ Plane(point=Point(x=0.0, y=0.0, z=0.0), normal=Vector(x=0.0, y=0.0, z=1.0)) Point(x=0.0, y=0.0, z=0.0) >>> plane.normal Vector(x=0.0, y=0.0, z=1.0) +``` The input vector is automatically normalized. +```python >>> plane = Plane([0, 0, 0], [0, 0, 10]) >>> plane.normal Vector(x=0.0, y=0.0, z=1.0) +``` Both point and normal can be modified. +```python >>> plane.point = [1, 2, 3] >>> plane.normal = [10, 0, 0] >>> plane.point Point(x=1.0, y=2.0, z=3.0) >>> plane.normal Vector(x=1.0, y=0.0, z=0.0) +``` The coefficients of the plane equation can be accessed as well. +```python >>> plane = Plane([0, 0, 10], [0, 0, 10]) >>> plane.abcd (0.0, 0.0, 1.0, -10.0) +``` -Special planes can be constructed using predefined contructor methods. +Special planes can be constructed using predefined constructor methods. +```python >>> xy = Plane.worldXY() >>> xy.normal Vector(x=0.0, y=0.0, z=1.0) @@ -57,41 +63,47 @@ Vector(x=1.0, y=0.0, z=0.0) >>> zx = Plane.worldZX() >>> zx.normal Vector(x=0.0, y=1.0, z=0.0) +``` -Planes can also be contructed from other inputs than point and normal. +Planes can also be constructed from other inputs than point and normal. +```python >>> plane = Plane.from_abcd(...) >>> plane = Plane.from_frame(...) >>> plane = Plane.from_point_and_two_vectors(...) >>> plane = Plane.from_three_points(...) +``` -For distance calculations and membership verifications involving planes, see :doc:`/userguide/basics.geometry.distance_and_membership`. -For intersections between planes and other objects, see :doc:`/userguide/basics.geometry.intersections`. - +For distance calculations and membership verifications involving planes, see [Distance and Membership](basics.geometry.distance_and_membership.md). +For intersections between planes and other objects, see [Intersections](basics.geometry.intersections.md). -Frames -============================================================================== +## Frames Frames are defined by a point and two vectors, and are used to represent local coordinate systems. +```python >>> from compas.geometry import Point, Vector >>> from compas.geometry import Frame >>> frame = Frame(Point(0, 0, 0), Vector(1, 0, 0), Vector(0, 1, 0)) >>> frame Frame(point=Point(x=0.0, y=0.0, z=0.0), xaxis=Vector(x=1.0, y=0.0, z=0.0), yaxis=Vector(x=0.0, y=1.0, z=0.0)) +``` As with planes, pure Python inputs are automatically converted. +```python >>> frame = Frame([0, 0, 0], [1, 0, 0], [0, 1, 0]) >>> frame Frame(point=Point(x=0.0, y=0.0, z=0.0), xaxis=Vector(x=1.0, y=0.0, z=0.0), yaxis=Vector(x=0.0, y=1.0, z=0.0)) +``` -The first input vector is the X-axis of the corrdinate system. +The first input vector is the X-axis of the coordinate system. The second input vector should be a vector in the XY-plane of the coordinate system. It is automatically converted to the Y-axis of the coordinate system. From the two input vectors, the Z-axis is computed. +```python >>> frame = Frame([0, 0, 0], [1, 0, 0], [0, 0, 1]) >>> frame.xaxis Vector(x=1.0, y=0.0, z=0.0) @@ -99,17 +111,21 @@ Vector(x=1.0, y=0.0, z=0.0) Vector(x=0.0, y=1.0, z=0.0) >>> frame.zaxis Vector(x=0.0, y=0.0, z=1.0) +``` The input vectors are automatically normalized. +```python >>> frame = Frame([0, 0, 0], [10, 0, 0], [0, 10, 0]) >>> frame.xaxis Vector(x=1.0, y=0.0, z=0.0) >>> frame.yaxis Vector(x=0.0, y=1.0, z=0.0) +``` Specific frames can be constructed using predefined constructor methods. +```python >>> frame = Frame.worldXY() >>> frame.xaxis Vector(x=1.0, y=0.0, z=0.0) @@ -133,9 +149,11 @@ Vector(x=0.0, y=0.0, z=1.0) Vector(x=1.0, y=0.0, z=0.0) >>> frame.zaxis Vector(x=0.0, y=1.0, z=0.0) +``` Frames can also be constructed from other inputs than point and two vectors. +```python >>> frame = Frame.from_axis_angle_vector(...) >>> frame = Frame.from_euler_angles(...) >>> frame = Frame.from_change_of_basis(...) @@ -146,18 +164,18 @@ Frames can also be constructed from other inputs than point and two vectors. >>> frame = Frame.from_quaternion(...) >>> frame = Frame.from_rotation(...) >>> frame = Frame.from_transformation(...) +``` Frames are closely related to transformations. -For more information on transformations and their relationship to frames, see :doc:`/userguide/basics.geometry.transformations`. - +For more information on transformations and their relationship to frames, see [Transformations](basics.geometry.transformations.md). -Plane/Frame Conversions -============================================================================== +## Plane/Frame Conversions A plane can be constructed from a frame. The plane will have the same origin as the frame, and its normal vector will be equal to the Z-axis of the frame. +```python >>> from compas.geometry import Frame >>> from compas.geometry import Plane >>> frame = Frame.worldXY() @@ -166,9 +184,11 @@ and its normal vector will be equal to the Z-axis of the frame. True >>> plane.normal == frame.zaxis True +``` Note that during the conversion, some information is lost. +```python >>> from compas.geometry import Frame >>> from compas.geometry import Plane >>> frame1 = Frame([0, 0, 0], [0, 1, 0], [-1, 0, 0]) @@ -182,3 +202,4 @@ True False >>> frame1.yaxis == frame2.yaxis False +``` diff --git a/docs/userguide/basics.geometry.points_and_vectors.rst b/docs/userguide/basics.geometry.points_and_vectors.md similarity index 76% rename from docs/userguide/basics.geometry.points_and_vectors.rst rename to docs/userguide/basics.geometry.points_and_vectors.md index 6d721ec14981..636d6b51aa5a 100644 --- a/docs/userguide/basics.geometry.points_and_vectors.rst +++ b/docs/userguide/basics.geometry.points_and_vectors.md @@ -1,22 +1,22 @@ -****************************************************************************** -Points and Vectors -****************************************************************************** +# Points and Vectors Points and vectors are represented by three floats, planes by a point and a vector, and frames by a point and two vectors. -Points -============================================================================== +## Points -A :class:`~compas.geometry.Point` represents a location in 3D space. +A [`Point`][compas.geometry.Point] represents a location in 3D space. +```python >>> from compas.geometry import Point >>> a = Point(1, 2, 3) >>> a Point(x=1.0, y=2.0, z=3.0) +``` The individual coordinates of a point can be accessed by their names, -or by the corresponding index of each name (``0 -> x, 1 -> y, 2 -> z``). +or by the corresponding index of each name (`0 -> x, 1 -> y, 2 -> z`). +```python >>> a.x 1.0 >>> a.y @@ -30,17 +30,21 @@ or by the corresponding index of each name (``0 -> x, 1 -> y, 2 -> z``). 2.0 >>> a[2] 3.0 +``` -When construction a point, the Z coordinate is optional and defaults to zero. +When constructing a point, the Z coordinate is optional and defaults to zero. +```python >>> b = Point(1, 2) >>> b Point(x=1.0, y=2.0, z=0.0) >>> b.z 0.0 +``` The coordinates of a point can be modified by assigning new values to the corresponding attributes. +```python >>> a = Point(0, 0, 0) >>> b = Point(0, 0, 0) >>> a.x = 1 @@ -49,74 +53,88 @@ Point(x=1.0, y=0.0, z=0.0) >>> b[1] = 1 >>> b Point(x=0.0, y=1.0, z=0.0) +``` Point objects have various methods for distance calculations, and for membership tests. -See :doc:`/userguide/basics.geometry.distance_and_membership` for more information. +See [Distance and Membership](basics.geometry.distance_and_membership.md) for more information. +## Vectors -Vectors -============================================================================== - -A :class:`~compas.geometry.Vector` represents a direction in 3D space +A [`Vector`][compas.geometry.Vector] represents a direction in 3D space and a distance or magnitude along that direction (the length of the vector). Vectors are always based at the origin of the coordinate system. A vector is the direction, and distance along that direction, from the origin of the coordinate system to a point in space. +```python >>> from compas.geometry import Vector >>> u = Vector(1.0, 0.0, 0.0) >>> u Vector(x=1.0, y=0.0, z=0.0) +``` Special vectors can be constructed using predefined constructor methods. +```python >>> Vector.Xaxis() Vector(x=1.0, y=0.0, z=0.0) >>> Vector.Yaxis() Vector(x=0.0, y=1.0, z=0.0) >>> Vector.Zaxis() Vector(x=0.0, y=0.0, z=1.0) +``` Working with vectors is very similar to working with points. Vector components can be accessed using the component attribute names, or using the corresponding indices. +```python >>> u.x == u[0] True >>> u.y = 1.0 >>> u[2] = 1.0 >>> u Vector(x=1.0, y=1.0, z=1.0) +``` All components are automatically converted to floats. The Z component is optional and defaults to zero. +```python >>> Vector(1, 0) Vector(x=1.0, y=0.0, z=0.0) +``` In addition to information about components or coordinates, vectors have a direction and magnitude. +```python >>> u.direction Vector(x=0.5773502691896258, y=0.5773502691896258, z=0.5773502691896258) >>> u.magnitude 1.7320508075688772 +``` -An alias for ``magnitude`` is ``length``. +An alias for `magnitude` is `length`. +```python >>> u.length 1.7320508075688772 +``` Vector objects support dot and cross product calculations. +```python >>> u = Vector(1, 0, 0) >>> v = Vector(0, 1, 0) >>> u.dot(v) 0.0 >>> u.cross(v) Vector(x=0.0, y=0.0, z=1.0) +``` Angles between two vectors can also be calculated. Note that the angles are always returned in radians. +```python >>> u = Vector(1, 0, 0) >>> v = Vector(0, 1, 0) >>> u.angle(v) @@ -125,24 +143,24 @@ Note that the angles are always returned in radians. (1.5707963267948966, 4.71238898038469) >>> u.angle_signed(v, normal=[0, 0, -1]) -1.5707963267948966 +``` +## Basic Arithmetic -Basic Arithmetic -============================================================================== - -:class:`~compas.geometry.Point` and :class:`~compas.geometry.Vector` objects support basic arithmetic +[`Point`][compas.geometry.Point] and [`Vector`][compas.geometry.Vector] objects support basic arithmetic through Python's built-in operators. +```python >>> a = Point(1, 0, 0) >>> b = Point(0, 1, 0) >>> a + b Point(x=1.0, y=1.0, z=0.0) >>> a - b -Vector(x=1.0, y=-1.0, z=0.0) # not sure that this is helpful +Vector(x=1.0, y=-1.0, z=0.0) >>> a * 2 Point(x=2.0, y=0.0, z=0.0) >>> a / 2 -Point(x=0.5, x=0.0, z=0.0) +Point(x=0.5, y=0.0, z=0.0) >>> u = Vector(1, 0, 0) >>> v = Vector(0, 1, 0) @@ -154,30 +172,36 @@ Vector(x=1.0, y=-1.0, z=0.0) Vector(x=2.0, y=0.0, z=0.0) >>> u / 2 Vector(x=0.5, y=0.0, z=0.0) +``` The second operand of addition and subtraction can also be a Python list or tuple. +```python >>> a + [0, 1, 0] Point(x=1.0, y=1.0, z=0.0) >>> u + [0, 1, 0] Vector(x=1.0, y=1.0, z=0.0) +``` A binary operator involving points and vectors returns a new object. Therefore the operators can be chained. +```python >>> a = Point(1, 0, 0) >>> b = Point(0, 1, 0) >>> c = Point(0, 0, 1) >>> a + b * 2 + c * 3 Point(x=1.0, y=2.0, z=3.0) +``` The in-place variants of binary operators modify the objects in place. Chaining is therefore not possible. +```python >>> u = Vector(1, 0, 0) >>> v = Vector(0, 1, 0) >>> u += v -None >>> u Vector(x=1.0, y=1.0, z=0.0) +``` diff --git a/docs/userguide/basics.geometry.polygons_and_polyhedrons.md b/docs/userguide/basics.geometry.polygons_and_polyhedrons.md new file mode 100644 index 000000000000..463b50c5ae52 --- /dev/null +++ b/docs/userguide/basics.geometry.polygons_and_polyhedrons.md @@ -0,0 +1,8 @@ +# Polygons and Polyhedrons + +This section covers polygons and polyhedrons in COMPAS. + +For more information, see the API reference for: + +- [`compas.geometry.Polygon`][compas.geometry.Polygon] +- [`compas.geometry.Polyhedron`][compas.geometry.Polyhedron] diff --git a/docs/userguide/basics.geometry.polygons_and_polyhedrons.rst b/docs/userguide/basics.geometry.polygons_and_polyhedrons.rst deleted file mode 100644 index effb2e45b4b2..000000000000 --- a/docs/userguide/basics.geometry.polygons_and_polyhedrons.rst +++ /dev/null @@ -1,3 +0,0 @@ -******************************************************************************** -Polygons and Polyhedrons -******************************************************************************** diff --git a/docs/userguide/basics.geometry.rst b/docs/userguide/basics.geometry.rst deleted file mode 100644 index 41058380679a..000000000000 --- a/docs/userguide/basics.geometry.rst +++ /dev/null @@ -1,15 +0,0 @@ -Geometry -======== - -.. toctree:: - :maxdepth: 2 - :titlesonly: - :caption: Geometry - - basics.geometry.points_and_vectors - basics.geometry.planes_and_frames - basics.geometry.polygons_and_polyhedrons - basics.geometry.curves_and_surfaces - basics.geometry.solids - basics.geometry.breps - basics.geometry.transformations diff --git a/docs/userguide/basics.geometry.solids.md b/docs/userguide/basics.geometry.solids.md new file mode 100644 index 000000000000..94c16c86cb93 --- /dev/null +++ b/docs/userguide/basics.geometry.solids.md @@ -0,0 +1,12 @@ +# Solids + +This section covers solid geometry in COMPAS. + +For more information, see the API reference for: + +- [`compas.geometry.Box`][compas.geometry.Box] +- [`compas.geometry.Sphere`][compas.geometry.Sphere] +- [`compas.geometry.Cylinder`][compas.geometry.Cylinder] +- [`compas.geometry.Cone`][compas.geometry.Cone] +- [`compas.geometry.Torus`][compas.geometry.Torus] +- [`compas.geometry.Capsule`][compas.geometry.Capsule] diff --git a/docs/userguide/basics.geometry.solids.rst b/docs/userguide/basics.geometry.solids.rst deleted file mode 100644 index a18c78527603..000000000000 --- a/docs/userguide/basics.geometry.solids.rst +++ /dev/null @@ -1,3 +0,0 @@ -******************************************************************************** -Shapes and Solids -******************************************************************************** diff --git a/docs/userguide/basics.geometry.transformations.md b/docs/userguide/basics.geometry.transformations.md new file mode 100644 index 000000000000..f88bce8dc9a9 --- /dev/null +++ b/docs/userguide/basics.geometry.transformations.md @@ -0,0 +1,5 @@ +# Transformations + +This section covers geometric transformations in COMPAS. + +For more information, see the API reference for [`compas.geometry.Transformation`][compas.geometry.Transformation]. diff --git a/docs/userguide/basics.geometry.transformations.rst b/docs/userguide/basics.geometry.transformations.rst deleted file mode 100644 index 22cf528c1172..000000000000 --- a/docs/userguide/basics.geometry.transformations.rst +++ /dev/null @@ -1,3 +0,0 @@ -******************************************************************************** -Transformations -******************************************************************************** diff --git a/docs/userguide/basics.visualisation.rst b/docs/userguide/basics.visualisation.md similarity index 63% rename from docs/userguide/basics.visualisation.rst rename to docs/userguide/basics.visualisation.md index 18fa32d3495f..5a39c2460dd5 100644 --- a/docs/userguide/basics.visualisation.rst +++ b/docs/userguide/basics.visualisation.md @@ -1,150 +1,152 @@ -******************************************************************************** -Visualisation -******************************************************************************** +# Visualisation COMPAS (data) objects can be visualised by placing them into a "scene". +```python >>> from compas.scene import Scene >>> from compas.geometry import Box >>> box = Box(1) >>> scene = Scene() >>> scene.add(box) >>> scene.draw() +``` -.. When a COMPAS object is added, the scene automatically creates a corresponding scene object for the current/active visualisation context. -.. Currently, four visualisation contexts are supported: COMPAS Viewer (default), Rhino, Grasshopper, and Blender. - -Scene Objects -============= +## Scene Objects When a COMPAS object is added to a scene, a scene object is created automatically, corresponding to the type of COMPAS object. +```python >>> sceneobj = scene.add(box) >>> sceneobj BoxObject +``` The scene object holds a reference to the COMPAS data object, and stores its visualisation settings and transformation matrix. Multiple scene objects can be created for the same COMPAS data object, each with different visualisation settings and transformations. +```python >>> sceneobj1 = scene.add(box) >>> sceneobj2 = scene.add(box) >>> sceneobj1 is sceneobj2 False >>> sceneobj1.data is sceneobj2.data True +``` -Visualiation Settings -===================== +## Visualisation Settings Scene objects have visualisation settings that can be changed by setting the corresponding attributes. All scene objects have a color attribute. +```python >>> sceneobj = scene.add(box) >>> sceneobj.color Color(0.0, 0.0, 0.0, alpha=1.0) +``` Color attributes can be set using a COMPAS Color object, or a tuple of RGB values, with the color components specified as floats in the range 0.0-1.0 or as integers in the range 0-255. -.. note:: +!!! note - For more information about working with colors in COMPAS, see :doc:`basics.colors`. + For more information about working with colors in COMPAS, see [Colors](basics.colors.md). +```python >>> sceneobj.color = (255, 0, 0) >>> sceneobj.color Color(1.0, 0.0, 0.0, alpha=1.0) +``` -Visualisation settings can be changed by modifying the corresponding attributes of the scene object, or by providing values or the attributes to the :meth:`Scene.add` method. +Visualisation settings can be changed by modifying the corresponding attributes of the scene object, or by providing values for the attributes to the `Scene.add` method. +```python >>> sceneobj = scene.add(box, color=(0, 255, 0)) >>> sceneobj.color Color(0.0, 1.0, 0.0, alpha=1.0) +``` Some objects have additional color attributes, for more precise control over the visualisation. For example, meshes can have different colors for the vertices, the edges, and the faces. And the colors of vertices, edges, and faces can be specified individually, per element. -See the section about mesh visualisation for more information. -Scene Hierarchy -=============== +## Scene Hierarchy Scene objects are organised in a hierarchy, with the scene as the root node. The hierarchy is represented by a COMPAS Tree data structure. All scene objects are nodes in the tree. The scene tree has an implicit root node, which is the scene itself. +```python >>> scene = Scene() >>> scene.root SceneObject +``` By default, every scene object is added as a direct child of the scene. +```python >>> sceneobj = scene.add(box) >>> sceneobj.parent SceneObject >>> scene.children() [BoxObject] +``` To use a different scene object as the parent, the parent attribute of the scene object can be set to the desired parent. +```python >>> from compas.geometry import Point >>> point = Point(1, 2, 3) >>> pointobj = scene.add(point) >>> boxobj = scene.add(box, parent=pointobj) >>> boxobj.parent PointObject +``` -Object Frame And Transformation -===================== +## Object Frame And Transformation -Every scene objects can have a reference "frame" that represents its local coordinate system relative to the frame of its hierarchical parent. +Every scene object can have a reference "frame" that represents its local coordinate system relative to the frame of its hierarchical parent. In addition, an object can also have a local "transformation" which orientates this object from its frame. -The final transformation of an object relative to the world coordinate system is the aggregated multiplication of all its hierarchical ancesters' frames, -together with its own local frame and transformation. This prorperty can be accessed through the read-only attribute "worldtransformation". +The final transformation of an object relative to the world coordinate system is the aggregated multiplication of all its hierarchical ancestors' frames, together with its own local frame and transformation. This property can be accessed through the read-only attribute `worldtransformation`. +```python >>> from compas.geometry import Translation >>> from compas.geometry import Box >>> from compas.geometry import Frame >>> sceneobj1 = scene.add(Box()) ->>> sceneobj1.frame = Frame(point = [1.0, 0.0, 0.0], xaxis=[1.0, 0.0, 0.0],yaxis=[0.0, 1.0, 0.0]) +>>> sceneobj1.frame = Frame(point=[1.0, 0.0, 0.0], xaxis=[1.0, 0.0, 0.0], yaxis=[0.0, 1.0, 0.0]) >>> sceneobj1.transformation = Translation.from_vector([10.0, 0.0, 0.0]) >>> sceneobj1.worldtransformation Transformation([[1.0, 0.0, 0.0, 11.0], [0.0, 1.0, 0.0, 0.0], [0.0, 0.0, 1.0, 0.0], [0.0, 0.0, 0.0, 1.0]], check=False) ->>> sceneobj1.worldtransformation == sceneobj1.frame.to_transfromation() * sceneobj1.transformation -True - -The worldtransformation of a nestd "sceneobj2" will be calculated as: Frame of "sceneobj1" * Frame of "sceneobj2" * Transformation of "sceneobj2" ->>> sceneobj2 = scene.add(Box(), parent=sceneobj1) ->>> sceneobj2.frame = Frame([1.0, 1.0, 0.0], xaxis=[1.0, 0.0, 0.0],yaxis=[0.0, 1.0, 0.0]) ->>> sceneobj2.transformation = Translation.from_vector([10.0, 10.0, 0.0]) ->>> sceneobj.worldtransformation -Transformation([[1.0, 0.0, 0.0, 12.0], [0.0, 1.0, 0.0, 11.0], [0.0, 0.0, 1.0, 0.0], [0.0, 0.0, 0.0, 1.0]], check=False) ->>> sceneobj2.worldtransformation == sceneobj1.frame.to_transfromation() * sceneobj2.frame.to_transfrom() * sceneobj2.transformation -True - +``` -Scene Context -============= +## Scene Context Depending on where the code is executed, the "scene" will detect the current visualisation context. -If the code is executed in the Rhino, the scene context will be automatically set as "Rhino". +If the code is executed in Rhino, the scene context will be automatically set as "Rhino". +```python >>> from compas.scene import Scene >>> from compas.geometry import Box >>> scene = Scene() >>> scene.context Rhino +``` For every context, the appropriate scene object implementations will be used automatically. +```python >>> box = Box.from_width_height_depth(1, 1, 1) >>> scene.add(box) +``` Users can also set the scene context manually: +```python >>> scene = Scene(context="MyContextName") >>> scene.context MyContextName +``` The currently supported contexts are: "Viewer", "Rhino", "Grasshopper", "Blender" and None. -For working with different contexts please refer to the next section "Tutorial: Working in CAD". \ No newline at end of file +For working with different contexts please refer to the [CAD sections](cad.rhino.md). diff --git a/docs/userguide/cad.blender.md b/docs/userguide/cad.blender.md new file mode 100644 index 000000000000..5f2f5cc983a3 --- /dev/null +++ b/docs/userguide/cad.blender.md @@ -0,0 +1,5 @@ +# Working in Blender + +This section covers working with COMPAS in Blender. + +For more information, see the API reference for [`compas_blender`][compas_blender]. diff --git a/docs/userguide/cad.blender.rst b/docs/userguide/cad.blender.rst deleted file mode 100644 index 1e0470f35454..000000000000 --- a/docs/userguide/cad.blender.rst +++ /dev/null @@ -1,155 +0,0 @@ -******************************************************************************** -Working in Blender -******************************************************************************** - -.. rst-class:: lead - -COMPAS packages can be installed in Blender and used in Blender scripts. -Blender is also a supported visualisation backend for COMPAS scenes, -and :mod:`compas_blender` provides functionality for converting COMPAS objects to Blender objects, and vice versa. - -.. note:: - - These instructions are for the current LTS versions of Blender (3.3, 3.6 and 4.2). - Other versions are currently not supported. - -.. warning:: - - The installation procedure is a work in progress. - It has currently only been tested on macOS, and may change in the future. - - -Installation -============ - -The installation of COMPAS in Blender can be done in two ways: - -* by installing COMPAS in Blender's Python environment using ``pip``, or -* by using the ``compas_blender.install`` command. - -Using ``pip`` (recommended) ---------------------------- - -Blender comes with its own Python installation. -This procedure simply uses that Python installation and associated ``pip`` to install COMPAS. -The location of the executable is different on different platforms. -The default locations are: - -* Windows: ``C:\Program Files\Blender Foundation\Blender 4.2\4.2\python\bin\python.exe`` -* macOS: ``/Applications/Blender.app/Contents/Resources/4.2/python/bin/python3.10`` -* Linux: ``/usr/share/blender/4.2/python/bin/python3.10`` (i think :) - -.. note:: - - If you already have an installation of COMPAS on your system, you can try finding the Blender Python executable by running the following in a terminal or command prompt: - - .. code-block:: python - - python -m compas_blender.print_python_path - -Update `pip` -~~~~~~~~~~~~ - -Before installing `compas` with `pip`, it is highly recommended that you update `pip` itself. - -.. code-block:: bash - - $ /Applications/Blender.app/Contents/Resources/4.2/python/bin/python3.10 -m pip install --upgrade pip - - -Install from PyPI -~~~~~~~~~~~~~~~~~ - -For example on Mac: - -.. code-block:: bash - - $ /Applications/Blender.app/Contents/Resources/4.2/python/bin/python3.10 -m pip install compas - - -Install from Source -~~~~~~~~~~~~~~~~~~~ - -.. code-block:: bash - - $ cd path/to/compas - $ /Applications/Blender.app/Contents/Resources/4.2/python/bin/python3.10 -m pip install -e . - - -Using ``compas_blender.install`` --------------------------------- - -.. warning:: - - This procedure will not install any of the dependencies required by COMPAS. - They have to already be present in the Blender Python environment. - -The ``compas_blender.install`` command installs COMPAS in Blender's Python ``site-packages`` folder -by creating symlinks to COMPAS packages installed in an existing (``conda``) environment. -Therefore, before running the command below, you should activate the environment in which you have installed COMPAS. - -.. code-block:: bash - - $ python -m compas_blender.install - -Optionally, you can specify the version of Blender using the ``-v`` flag. - -.. code-block:: bash - - $ python -m compas_blender.install -v 4.2 - -To remove all previously installed symlinks before installing new ones, use the ``--clean`` flag. - -.. code-block:: bash - - $ python -m compas_blender.install --clean - - -Verification -============ - -To test if the installation was successful, you can run the following on the Blender command line. - ->>> import compas ->>> print(compas.__version__) -'2.4.0' - - -Visualisation -============= - -Visualisation of COMPAS objects in Blender is handled using viualisation scenes. -For more information on visualisation scenes, see :doc:`/userguide/basics.visualisation`. - -.. figure:: /_images/userguide/cad.blender.visualisation.png - -.. code-block:: python - - import compas - from compas.datastructures import Mesh - from compas.scene import Scene - - mesh = Mesh.from_obj(compas.get('tubemesh.obj')) - - scene = Scene() - scene.clear() - scene.add(mesh) - scene.draw() - - -Conversions -=========== - -More info coming soon... - -.. code-block:: python - - import compas - from compas.datastructures import Mesh - from compas_blender import conversions - - mesh = Mesh.from_obj(compas.get('tubemesh.obj')) - - blender_mesh = conversions.mesh_to_blender(mesh) - - mesh = conversions.mesh_to_compas(blender_mesh) diff --git a/docs/userguide/cad.grasshopper.md b/docs/userguide/cad.grasshopper.md new file mode 100644 index 000000000000..99c4662de5fb --- /dev/null +++ b/docs/userguide/cad.grasshopper.md @@ -0,0 +1,5 @@ +# Working in Grasshopper + +This section covers working with COMPAS in Grasshopper. + +For more information, see the API reference for [`compas_ghpython`][compas_ghpython]. diff --git a/docs/userguide/cad.grasshopper.rst b/docs/userguide/cad.grasshopper.rst deleted file mode 100644 index 1009bae19e9d..000000000000 --- a/docs/userguide/cad.grasshopper.rst +++ /dev/null @@ -1,114 +0,0 @@ -******************************************************************************** -Working in Grasshopper -******************************************************************************** - -.. rst-class:: lead - -To get COMPAS working in Grasshopper, you first have to install COMPAS for Rhino (see :doc:`/userguide/cad.rhino`). -In Grasshopper, COMPAS is imported from within a GhPython component. Rhino for -Mac and Rhino 6+ all come with their own GhPython interpreter, but if you use -Rhino 5 on Windows, please download and install GhPython `here `_. - - -Verify setup -============ - -To verify that everything is working properly, simply create a GhPython -component on your Grasshopper canvas, paste the following script and hit `OK`. - -.. code-block:: python - - import compas - from compas.datastructures import Mesh - from compas.scene import Scene - - mesh = Mesh.from_obj(compas.get('faces.obj')) - - scene = Scene() - scene.add(mesh) - a = scene.draw() - - -.. figure:: /_images/userguide/cad.grasshopper.gh_verify.jpg - - -Grasshopper components for COMPAS -================================= - -When COMPAS for Rhino is installed, it also installs Grasshopper components for -COMPAS. For example, the current environment information can be retrieved with -the INFO component. - - -.. figure:: /_images/userguide/cad.grasshopper.ghpython_component.jpg - - -Reloading changed libraries -=========================== - -If you change a Python library during a running Rhino application, which is -imported in a GhPython component (e.g. via ``import compas_fab``), -it is necessary to reload the library so that the GhPython interpreter -recognizes the changes. To avoid restarting Rhino, you can use the method -``unload_modules`` of ``DevTools``. The following example reloads the library ``compas_fab``. - -.. code-block:: python - - from compas_rhino import DevTools - - DevTools.unload_modules('compas_fab') - -.. note:: - - Prefer using `unload_modules` as early as possible in your grasshopper - workflow. Re-loading modules later might result, for example, - in COMPAS not being able to find a `SceneObject` as well as other issues - related to a mid-workflow re-definition of Python types. - - -Python Scripting Outside Rhino/Grasshopper with Auto-Reloading -============================================================== - -Developing Python scripts outside of Rhino/Grasshopper allows you to take advantage of -modern code editors. However, this workflow requires two key steps: ensuring the Python -interpreter can access your script's location and enabling automatic reloading of the -script when changes are made in your external editor. -If the scripts or modules you are working on are located in the same folder as the Rhino/Grasshopper file you are editing, the ``DevTools`` class can be used to make them importable and reload them automatically when modified. - -This approach provides a seamless workflow for developing Python scripts in modern IDEs, -such as Visual Studio Code, while running and testing the code inside Rhino/Grasshopper -with minimal interruptions. - -Enabling Auto-Reloading ------------------------ - -To enable this feature, use the ``enable_reloader`` method of the ``DevTools`` class. -This makes all Python scripts in the same folder as the Grasshopper file importable -and ensures they automatically reload when changes are applied. - -.. code-block:: python - - from compas_rhino import DevTools - DevTools.enable_reloader() - -.. note:: - - Call this method early in your script to start the monitoring service immediately. - -Importing Local Modules ------------------------ - -Once auto-reloading is enabled, any script component that needs to use local modules can include the following at the top of the script: - -.. code-block:: python - - from compas_rhino import DevTools - DevTools.ensure_path() - -This ensures local modules are accessible. For instance, if a file named ``my_module.py`` is in -the same folder as your Grasshopper file, you can import it in a script component like this: - -.. code-block:: python - - import my_module - diff --git a/docs/userguide/cad.other.md b/docs/userguide/cad.other.md new file mode 100644 index 000000000000..1806014653d1 --- /dev/null +++ b/docs/userguide/cad.other.md @@ -0,0 +1,3 @@ +# Other CAD Environments + +This section covers working with COMPAS in other CAD environments. diff --git a/docs/userguide/cad.other.rst b/docs/userguide/cad.other.rst deleted file mode 100644 index 08c3d85baafc..000000000000 --- a/docs/userguide/cad.other.rst +++ /dev/null @@ -1,4 +0,0 @@ -******************************************************************************** -Working in Other CAD Software -******************************************************************************** - diff --git a/docs/userguide/cad.rhino.md b/docs/userguide/cad.rhino.md new file mode 100644 index 000000000000..f2586db82e85 --- /dev/null +++ b/docs/userguide/cad.rhino.md @@ -0,0 +1,198 @@ +# Working in Rhino + +The core library of COMPAS (`compas`), and the Rhino CAD package (`compas_rhino`) +are backwards compatible with Python 2.7 and written in pure Python, +such that they can be used in Rhino IronPython scripts (Rhino 7 and below), +as well as in the new Rhino CPython scripts (Rhino 8). + +## Installation + +!!! warning + + These instructions are for Rhino 6 and 7. + For Rhino 8, please refer to [Rhino 8](cad.rhino8.md). + +To use COMPAS in Rhino 6 or 7, you need to make Rhino aware of your COMPAS installation. +This can be done with a simple command on the command line. + +!!! note + + Assuming COMPAS is installed in a `conda` environment, make sure to activate the environment before running any of the commands below. + It is recommended to also close Rhino before running the commands. + If Rhino was still running, it will have to restarted before the changes take effect. + +```bash +python -m compas_rhino.install +``` + +This will install all Rhino-compatible packages of COMPAS that are present in the current Python environment into Rhino. +It will also automatically install all GH Components that are available for the installed packages. + +The default Rhino version is 8. +To install into Rhino 7, use the `-v` flag. + +```bash +python -m compas_rhino.install -v 7.0 +``` + +Note that if COMPAS is installed in a `conda` environment, you need to activate the environment before running the command. + +```bash +conda activate compas-dev +python -m compas_rhino.install +``` + +## Verification + +To test if the installation was successful, you can run the following script in Rhino. + +```python +import compas + +print(compas.__version__) +``` + +## Visualisation + +Visualisation of COMPAS objects in Rhino is handled using visualisation scenes. +For more information on visualisation scenes, see [Visualisation](basics.visualisation.md). + +```python +import compas +from compas.datastructures import Mesh +from compas.scene import Scene + +mesh = Mesh.from_obj(compas.get('tubemesh.obj')) + +scene = Scene() +scene.clear() +scene.add(mesh) +scene.draw() +``` + +## Conversions + +For conversion between Rhino objects and COMPAS objects, different scenarios exist. + +### Rhino Geometry to COMPAS + +Conversions of geometry is straightforward and explicit. + +```python +import Rhino.Geometry +import compas_rhino.conversions + +point = Rhino.Geometry.Point3d(...) +point = compas_rhino.conversions.point_to_compas(point) + +line = Rhino.Geometry.Line(...) +line = compas_rhino.conversions.line_to_compas(line) + +plane = Rhino.Geometry.Plane(...) +plane = compas_rhino.conversions.plane_to_compas(plane) + +box = Rhino.Geometry.Box(...) +box = compas_rhino.conversions.box_to_compas(box) + +mesh = Rhino.Geometry.Mesh(...) +mesh = compas_rhino.conversions.mesh_to_compas(mesh) + +curve = Rhino.Geometry.Curve(...) +curve = compas_rhino.conversions.curve_to_compas(curve) + +surface = Rhino.Geometry.Surface(...) +surface = compas_rhino.conversions.surface_to_compas(surface) + +brep = Rhino.Geometry.Brep(...) +brep = compas_rhino.conversions.brep_to_compas(brep) +``` + +Note that Rhino doesn't distinguish between a frame and a plane. +Therefore, to convert `Rhino.Geometry.Plane` to `compas.geometry.Frame`: + +```python +plane = Rhino.Geometry.Plane(...) +frame = compas_rhino.conversions.plane_to_compas_frame(plane) +``` + +### Rhino Object to COMPAS + +A Rhino Document contains Rhino Objects instead of Rhino Geometry. +The geometry of a Rhino Object is stored in the corresponding attribute (`obj.Geometry`). + +Converting point, curve, and mesh objects is straightforward. + +```python +import compas_rhino.objects +import compas_rhino.conversions + +guid = compas_rhino.objects.select_point() +point = compas_rhino.conversions.pointobject_to_compas(guid) + +guid = compas_rhino.objects.select_curve() +curve = compas_rhino.conversions.curveobject_to_compas(guid) + +guid = compas_rhino.objects.select_mesh() +mesh = compas_rhino.conversions.meshobject_to_compas(guid) +``` + +### COMPAS to Rhino Geometry + +```python +import compas.geometry +import compas_rhino.conversions + +point = compas.geometry.Point(...) +point = compas_rhino.conversions.point_to_rhino(point) + +line = compas.geometry.Line(...) +line = compas_rhino.conversions.line_to_rhino(line) + +plane = compas.geometry.Plane(...) +plane = compas_rhino.conversions.plane_to_rhino(plane) + +box = compas.geometry.Box(...) +box = compas_rhino.conversions.box_to_rhino(box) + +curve = compas.geometry.Curve(...) +curve = compas_rhino.conversions.curve_to_rhino(curve) + +surface = compas.geometry.Surface(...) +surface = compas_rhino.conversions.surface_to_rhino(surface) + +brep = compas.geometry.Brep(...) +brep = compas_rhino.conversions.brep_to_rhino(brep) +``` + +To convert a `compas.geometry.Frame`: + +```python +frame = compas.geometry.Frame(...) +plane = compas_rhino.conversions.frame_to_rhino_plane(frame) +``` + +### COMPAS to Rhino Object + +COMPAS objects are converted to Rhino Objects implicitly, by placing them into a visualisation scene. +However, you can create a Rhino Object in a Rhino Document explicitly from a COMPAS object. + +```python +import scriptcontext as sc +import compas.geometry +import compas_rhino.conversions + +point = compas.geometry.Point(...) +geometry = compas_rhino.conversions.point_to_rhino(point) + +guid = sc.doc.Objects.AddPoint(geometry) +``` + +## Data Exchange + +### JSON + +### rhino3dm + +## Remote Procedure Calls + +## Known Issues diff --git a/docs/userguide/cad.rhino.rst b/docs/userguide/cad.rhino.rst deleted file mode 100644 index 495e4f95575c..000000000000 --- a/docs/userguide/cad.rhino.rst +++ /dev/null @@ -1,275 +0,0 @@ -******************************************************************************** -Working in Rhino -******************************************************************************** - -.. rst-class:: lead - -The core library of COMPAS (:mod:`compas`), and the Rhino CAD package (:mod:`compas_rhino`) -are backwards compatible with Python 2.7 and written in pure Python, -such that they can be used in Rhino IronPython scripts (Rhino 7 and below), -as well as in the new Rhino CPython scripts (Rhino 8). - -Installation -============ - -.. warning:: - - These instructions are for Rhino 6 and 7. - For Rhino 8, please refer to :doc:`/userguide/cad.rhino8`. - -To use COMPAS in Rhino 6 or 7, you need to make Rhino aware of your COMPAS installation. -This can be done with a simple command on the command line. - -.. note:: - - Assuming COMPAS is installed in a ``conda`` environment, make sure to activate the environment before running any of the commands below. - It is recommended to also close Rhino before running the commands. - If Rhino was still running, it will have to restarted before the changes take effect. - -.. code-block:: bash - - python -m compas_rhino.install - -This will install all Rhino-compatible packages of COMPAS that are present in the current Python environment into Rhino. -It will also automatically install all GH Components that are available for the installed packages. -Once the command terminates, you should see a message like this: - -.. code-block:: bash - - ... - -The default Rhino version is 8. -To install into Rhino 7, use the ``-v`` flag. - -.. code-block:: bash - - python -m compas_rhino.install -v 7.0 - -Note that if COMPAS is installed in a ``conda`` environment, you need to activate it the environment before running the command. - -.. code-block:: bash - - conda activate compas-dev - python -m compas_rhino.install - - -Verification -============ - -To test if the installation was successful, you can run the following script in Rhino. - -.. code-block:: python - - import compas - - print(compas.__version__) - - -Visualisation -============= - -Visualisation of COMPAS objects in Rhino is handled using viualisation scenes. -For more information on visualisation scenes, see :doc:`/userguide/basics.visualisation`. - -.. code-block:: python - - import compas - from compas.datastructures import Mesh - from compas.scene import Scene - - mesh = Mesh.from_obj(compas.get('tubemesh.obj')) - - scene = Scene() - scene.clear() - scene.add(mesh) - scene.draw() - - -Conversions -=========== - -For conversion between Rhino objects and COMPAS objects, different scenarios exist. - -Rhino Geometry to COMPAS ------------------------- - -Conversions of geometry is straightforward and explicit. - -.. code-block:: python - - import Rhino.Geometry - import compas_rhino.conversions - - point = Rhino.Geometry.Point3d(...) - point = compas_rhino.conversions.point_to_compas(point) - - line = Rhino.Geometry.Line(...) - line = compas_rhino.conversions.line_to_compas(line) - - plane = Rhino.Geometry.Plane(...) - plane = compas_rhino.conversions.plane_to_compas(plane) - - box = Rhino.Geometry.Box(...) - box = compas_rhino.conversions.box_to_compas(box) - - mesh = Rhino.Geometry.Mesh(...) - mesh = compas_rhino.conversions.mesh_to_compas(mesh) - - curve = Rhino.Geometry.Curve(...) - curve = compas_rhino.conversions.curve_to_compas(curve) - - surface = Rhino.Geometry.Surface(...) - surface = compas_rhino.conversions.surface_to_compas(surface) - - brep = Rhino.Geometry.Brep(...) - brep = compas_rhino.conversions.brep_to_compas(brep) - - -Note that Rhino doen't distinguish between a frame and a plane. -Therefore, to convert `Rhino.Geometry.Plane` to :class:`compas.geometry.Frame`. - -.. code-block:: python - - plane = Rhino.Geometry.Plane(...) - frame = compas_rhino.conversions.plane_to_compas_frame(plane) - - -Rhino Object to COMPAS ----------------------- - -A Rhino Document contains Rhino Object instead of Rhino Geometry. -The geometry of a Rhino Object is stored in the corresponding attribute (`obj.Geometry`). - -Converting point, curve, and mesh objects is straightforward. - -.. code-block:: python - - import compas_rhino.objects - import compas_rhino.conversions - - guid = compas_rhino.objects.select_point() - point = compas_rhino.conversions.pointobject_to_compas(guid) - - guid = compas_rhino.objects.select_curve() - curve = compas_rhino.conversions.curveobject_to_compas(guid) - - guid = compas_rhino.objects.select_mesh() - mesh = compas_rhino.conversions.meshobject_to_compas(guid) - - -In the case of curve objects, note that the conversion function will return a NurbsCurve in almost all cases. -If the curve has a specific geometry, it can be converted explicitly using the corresponding geomtry conversion function. -For example, if the curve is a circle. - -.. code-block:: python - - import compas_rhino.objects - import compas_rhino.conversions - - guid = compas_rhino.objects.select_curve() - obj = compas_rhino.objects.find_object(guid) - - circle = compas_rhino.conversions.curve_to_compas_circle(obj.Geometry) - - -In the case of all other objects, conversions are a bit trickier. -This is because in a Rhino Document, almost all other geometries are represented by a BrepObject regardless of the actual geometry type. -For example, when you add a sphere to a model, the DocObject is a BrepObject, and the geometry of the object is a Brep. -Therefore, conversions of other objects have to be done more carefully. - -.. code-block:: python - - import compas_rhino.objects - import compas_rhino.conversions - - guid = compas_rhino.objects.select_object() - brep = compas_rhino.conversions.brepobject_to_compas(guid) - - -Also here, if the object is (supposed to be) a specific type of geometry, -conversion can be done more explicitly using the geometry conversion functions instead. -For example, if the geometry of the object is a Rhino Cylinder. - -.. code-block:: python - - import compas_rhino.objects - import compas_rhino.conversions - - guid = compas_rhino.objects.select_object() - obj = compas_rhino.objects.find_object(guid) - - cylinder = compas_rhino.conversions.brep_to_compas_cylinder(obj.Geometry) - - -COMPAS to Rhino Geometry ------------------------- - -.. code-block:: python - - import compas.geometry - import compas_rhino.conversions - - point = compas.geometry.Point(...) - point = compas_rhino.conversions.point_to_rhino(point) - - line = compas.geometry.Line(...) - line = compas_rhino.conversions.line_to_rhino(line) - - plane = compas.geometry.Plane(...) - plane = compas_rhino.conversions.plane_to_rhino(plane) - - box = compas.geometry.Box(...) - box = compas_rhino.conversions.box_to_rhino(box) - - curve = compas.geometry.Curve(...) - curve = compas_rhino.conversions.curve_to_rhino(curve) - - surface = compas.geometry.Surface(...) - surface = compas_rhino.conversions.surface_to_rhino(surface) - - brep = compas.geometry.Brep(...) - brep = compas_rhino.conversions.brep_to_rhino(brep) - - -To convert a :class:`compas.geometry.Frame`. - -.. code-block:: python - - frame = compas.geometry.Frame(...) - plane = compas_rhino.conversions.frame_to_rhino_plane(frame) - - -COMPAS to Rhino Object ----------------------- - -COMPAS objects are converted to Rhino Objects implicitly, by placing them into a visualisation scene. -However, you can create a Rhino Object in a Rhino Dcocument explicitly from a COMPAS object. - -.. code-block:: python - - import scriptcontext as sc - import compas.geometry - import compas_rhino_conversions - - point = compas.geometry.Point(...) - geometry = compas_rhino.conversions.point_to_rhino(point) - - guid = sc.doc.Objects.AddPoint(geometry) - - -Data Exchange -============= - -JSON ----- - -rhino3dm --------- - -Remote Procedure Calls -====================== - - -Known Issues -============ - diff --git a/docs/userguide/cad.rhino8.md b/docs/userguide/cad.rhino8.md new file mode 100644 index 000000000000..8bd549a77e86 --- /dev/null +++ b/docs/userguide/cad.rhino8.md @@ -0,0 +1,7 @@ +# Working in Rhino 8 + +This section covers working with COMPAS in Rhino 8. + +Rhino 8 includes a new CPython scripting environment that allows you to use COMPAS directly without installation. + +For more information, see the API reference for [`compas_rhino`][compas_rhino]. diff --git a/docs/userguide/cad.rhino8.rst b/docs/userguide/cad.rhino8.rst deleted file mode 100644 index 5807c0772495..000000000000 --- a/docs/userguide/cad.rhino8.rst +++ /dev/null @@ -1,127 +0,0 @@ -******************************************************************************** -Working in Rhino 8 (with CPython) -******************************************************************************** - -.. warning:: - - Support for the new Rhino 8 Script Editor is experimental. - - -Rhino 8 supports both CPython and IronPython. -The instructions on this page are for working with COMPAS in the new Script Editor using CPython. -More information about the Script Editor is available here: - -For working with COMPAS in Rhino 8 with IronPython, -or for information about working in earlier versions of Rhino, see :doc:`/userguide/cad.rhino`. - -.. note:: - - To launch Rhino 8 Script Editor, simply type `ScriptEditor` at the Rhino 8 command prompt. - -Installation -============ - -To use COMPAS packages in your Rhino 8 CPython scripts, -you can now simply add the packages as requirements in a comment. - -.. code-block:: python - - #! python3 - # r: compas - - import compas - from compas.datastructures import Mesh - - mesh = ... - -More information is available here: - -.. note:: - - This also works in the Python 3 Script node in Grasshopper. - -Alternative Method -================== - -The above method only works if the package you want to install is available on `PyPI `_. -If you want to install a package from local source, -you can use `pip` directly in combination with the Python executable that is included in Rhino. -The default location of the executable is different for Windows and Mac. - -* Windows: ``%USERPROFILE%\.rhinocode\py39-rh8\python.exe`` -* macOS: ``~/.rhinocode/py39-rh8/python3.9`` - -.. code-block:: bash - - $ cd path/to/compas - $ ~/.rhinocode/py39-rh8/python3.9 -m pip install . - -To create an editable install, you should update `pip` itself, first. - -.. code-block:: bash - - $ ~/.rhinocode/py39-rh8/python3.9 -m pip install --upgrade pip - -.. code-block:: bash - - $ cd path/to/compas - $ ~/.rhinocode/py39-rh8/python3.9 -m pip install -e . - - -Experimental Method -=================== - -COMPAS now makes the `install_in_rhino` command line utility available to simplify the installation of Python packages in Rhino 8 CPython. -This utility is available after installing the main `compas` package: - -Install any Python package from PyPI - -.. code-block:: bash - - install_in_rhino requests numpy - -Install from the current directory - -.. code-block:: bash - - install_in_rhino . - -Install from a local path - -.. code-block:: bash - - install_in_rhino path/to/package - -Install from a requirements file - -.. code-block:: bash - - install_in_rhino -r requirements.txt - -Install in a specific site environment. - -.. code-block:: bash - - install_in_rhino compas --env compas-dev - -Clear the site environment before installing - -.. code-block:: bash - - install_in_rhino compas --env compas-dev --clear - - -For more information, see :func:`compas_rhino.install_with_pip.install_in_rhino_with_pip`. - - -Verification -============ - -In Rhino 8, open the Python editor (just type ``ScriptEditor``), open an new ``Python 3`` edito tab, and type the following: - -.. code-block:: python - - import compas - print(compas.__version__) - -If everything is installed correctly, this should print the version number of the installed COMPAS package. diff --git a/docs/userguide/citing.md b/docs/userguide/citing.md new file mode 100644 index 000000000000..d25446054b46 --- /dev/null +++ b/docs/userguide/citing.md @@ -0,0 +1,12 @@ +# Citing COMPAS + +If you use COMPAS in your research, please cite it using the following reference: + +```bibtex +@software{compas, + author = {Van Mele, Tom and others}, + title = {COMPAS: A framework for computational research in architecture and structures}, + url = {https://compas.dev}, + year = {2017} +} +``` diff --git a/docs/userguide/citing.rst b/docs/userguide/citing.rst deleted file mode 100644 index 91cf4aa08d5e..000000000000 --- a/docs/userguide/citing.rst +++ /dev/null @@ -1,21 +0,0 @@ -******************************************************************************** -Citing -******************************************************************************** - -.. rst-class:: lead - - The core library of COMPAS is developed by a small team of nerds at ETH Zurich. - If you use COMPAS in your work, please acknowledge their many sleepless nights - and lack of social life :) - -:: - - @misc{compas-dev, - title = {{COMPAS}: A framework for computational research in architecture and structures.}, - author = {Tom Van Mele and many others}, - note = {http://compas.dev}, - year = {2017-2021}, - doi = {10.5281/zenodo.2594510}, - url = {https://doi.org/10.5281/zenodo.2594510}, - } - diff --git a/docs/userguide/firststeps.md b/docs/userguide/firststeps.md new file mode 100644 index 000000000000..613c996114d9 --- /dev/null +++ b/docs/userguide/firststeps.md @@ -0,0 +1,60 @@ +# First Steps + +Once COMPAS is installed, you can start using it in your Python scripts. +On this page are a few simple snippets to get you started. + +!!! note + + The visualisations shown on this page are generated with the COMPAS Viewer in VS Code. + See [Visualisation](basics.visualisation.md) for more information on how to set it up and use it. + + Alternatively, you can run the examples in Rhino or Blender. + See [Rhino](cad.rhino.md) and [Blender](cad.blender.md) for more information on how to get started with that. + +## A Simple Box + +```python +from compas.geometry import Box +from compas.scene import Scene + +box = Box(1, 1, 1) + +scene = Scene() +scene.add(box) +scene.draw() +``` + +## Points-in-box Test + +```python +from compas.geometry import Box, Pointcloud +from compas.colors import Color +from compas.scene import Scene + +box = Box(1, 1, 1) +pcl = Pointcloud.from_bounds(x=10, y=10, z=10, n=100) + +box.rotate([0, 0, 1], 45) +box.translate(pcl.centroid) + +scene = Scene() +scene.add(box) +for point in pcl: + color = Color.red() if box.contains(point) else Color.blue() + scene.add(point, color=color) +scene.draw() +``` + +## Creating a Mesh From an OBJ File + +```python +import compas +from compas.datastructures import Mesh +from compas.scene import Scene + +mesh = Mesh.from_obj(compas.get('tubemesh.obj')) + +scene = Scene() +scene.add(mesh) +scene.draw() +``` diff --git a/docs/userguide/firststeps.rst b/docs/userguide/firststeps.rst deleted file mode 100644 index 906022f8d474..000000000000 --- a/docs/userguide/firststeps.rst +++ /dev/null @@ -1,70 +0,0 @@ -******************************************************************************** -First Steps -******************************************************************************** - -.. rst-class:: lead - -Once COMPAS is installed, you can start using it in your Python scripts. -On this page are a few simple snippets to get you started. - -.. note:: - - The visualisations shown on this page are generated with the COMPAS Viewer in VS Code. - See :doc:`basics.visualisation` for more information on how to set it up and use it. - - Alternatively, you can run the examples in Rhino or Blender. - See :doc:`cad.rhino` and :doc:`cad.blender` for more information on how to get started with that. - - -A Simple Box -============ - -.. code-block:: python - - from compas.geometry import Box - from compas.scene import Scene - - box = Box(1, 1, 1) - - scene = Scene() - scene.add(box) - scene.draw() - - -Points-in-box Test -================== - -.. code-block:: python - - from compas.geometry import Box, Pointcloud - from compas.colors import Color - from compas.scene import Scene - - box = Box(1, 1, 1) - pcl = Pointcloud.from_bounds(x=10, y=10, z=10, n=100) - - box.rotate([0, 0, 1], 45) - box.translate(pcl.centroid) - - scene = Scene() - scene.add(box) - for point in pcl: - color = Color.red() if box.contains(point) else Color.blue() - scene.add(point, color=color) - scene.draw() - - -Creating a Mesh From an OBJ File -================================ - -.. code-block:: python - - import compas - from compas.datastructures import Mesh - from compas.scene import Scene - - mesh = Mesh.from_obj(compas.get('tubemesh.obj')) - - scene = Scene() - scene.add(mesh) - scene.draw() diff --git a/docs/userguide/index.md b/docs/userguide/index.md new file mode 100644 index 000000000000..d96e7bfa2dc2 --- /dev/null +++ b/docs/userguide/index.md @@ -0,0 +1,60 @@ +# User Guide + +Welcome to the COMPAS User Guide. This guide will help you get started with COMPAS and explore its features. + +## Getting Started + +- [Introduction](introduction.md) - Learn about COMPAS and its ecosystem +- [Installation](installation.md) - Install COMPAS on your system +- [First Steps](firststeps.md) - Run your first COMPAS scripts +- [What's Next](whatsnext.md) - Where to go from here + +## Basics: Geometry + +- [Overview](basics.geometry.md) +- [Points and Vectors](basics.geometry.points_and_vectors.md) +- [Planes and Frames](basics.geometry.planes_and_frames.md) +- [Transformations](basics.geometry.transformations.md) +- [Polygons and Polyhedrons](basics.geometry.polygons_and_polyhedrons.md) +- [Curves and Surfaces](basics.geometry.curves_and_surfaces.md) +- [Breps](basics.geometry.breps.md) +- [Intersections](basics.geometry.intersections.md) +- [Distance and Membership](basics.geometry.distance_and_membership.md) +- [Solids](basics.geometry.solids.md) + +## Basics: Data Structures + +- [Overview](basics.datastructures.md) +- [Graphs](basics.datastructures.graphs.md) +- [Meshes](basics.datastructures.meshes.md) +- [Cells](basics.datastructures.cells.md) +- [VolMeshes](basics.datastructures.volmeshes.md) +- [CellNetworks](basics.datastructures.cellnetwork.md) +- [Trees](basics.datastructures.trees.md) + +## Basics: Visualisation and Colors + +- [Visualisation](basics.visualisation.md) +- [Colors](basics.colors.md) + +## Advanced Topics + +- [Tolerance](advanced.tolerance.md) +- [Serialisation](advanced.serialisation.md) +- [RPC](advanced.rpc.md) +- [Hash Trees](advanced.hashtree.md) +- [Pluggables](advanced.pluggables.md) + +## Working in CAD + +- [Rhino](cad.rhino.md) +- [Rhino 8](cad.rhino8.md) +- [Grasshopper](cad.grasshopper.md) +- [Blender](cad.blender.md) +- [Other](cad.other.md) + +## Miscellaneous + +- [Releases](releases.md) +- [Citing](citing.md) +- [License](license.md) diff --git a/docs/userguide/index.rst b/docs/userguide/index.rst deleted file mode 100644 index 407b374c7949..000000000000 --- a/docs/userguide/index.rst +++ /dev/null @@ -1,56 +0,0 @@ -******************************************************************************** -User Guide -******************************************************************************** - -.. toctree:: - :maxdepth: 2 - :titlesonly: - :caption: Getting Started - - introduction - installation - firststeps - whatsnext - - -.. toctree:: - :maxdepth: 2 - :titlesonly: - :caption: Tutorial: Basics - - basics.geometry - basics.datastructures - basics.visualisation - basics.colors - - -.. toctree:: - :maxdepth: 2 - :titlesonly: - :caption: Tutorial: Advanced - - advanced.tolerance - advanced.serialisation - advanced.rpc - advanced.hashtree - - -.. toctree:: - :maxdepth: 2 - :titlesonly: - :caption: Tutorial: Working in CAD - - cad.rhino - cad.rhino8 - cad.grasshopper - cad.blender - - -.. toctree:: - :maxdepth: 2 - :titlesonly: - :caption: Miscellaneous Info - - releases - citing - license diff --git a/docs/userguide/installation.md b/docs/userguide/installation.md new file mode 100644 index 000000000000..18ce69c34fa9 --- /dev/null +++ b/docs/userguide/installation.md @@ -0,0 +1,85 @@ +# Installation + +COMPAS can be easily installed on multiple platforms, +using popular package managers such as conda or pip. + +## Install with conda (recommended) + +Create an environment named `research` and install COMPAS from the package channel `conda-forge`. + +```bash +conda create -n research -c conda-forge compas +``` + +Activate the environment. + +```bash +conda activate research +``` + +Verify that the installation was successful. + +```bash +python -m compas +``` + +``` +Yay! COMPAS is installed correctly! +``` + +### Installation options + +Install COMPAS in an environment with a specific version of Python. + +```bash +conda create -n research python=3.9 compas +``` + +Install COMPAS in an existing environment. + +```bash +conda install -n research compas +``` + +## Install with pip + +Install COMPAS using `pip` from the Python Package Index. + +```bash +pip install compas +``` + +Install an editable version from local source. + +```bash +cd path/to/compas +pip install -e . +``` + +## Update with conda + +Update COMPAS to the latest version with `conda`. + +```bash +conda update compas +``` + +Install a specific version. + +```bash +conda install compas=1.17.9 +``` + +## Update with pip + +Update COMPAS to the latest version with `pip`. + +```bash +pip install --upgrade compas +``` + +Install a specific version. + +```bash +pip install compas==1.17.9 +``` diff --git a/docs/userguide/installation.rst b/docs/userguide/installation.rst deleted file mode 100644 index 76b6a06a3ac2..000000000000 --- a/docs/userguide/installation.rst +++ /dev/null @@ -1,100 +0,0 @@ -.. _user_guide_install: - -******************************************************************************** -Installation -******************************************************************************** - -.. rst-class:: lead - -COMPAS can be easily installed on multiple platforms, -using popular package managers such as conda or pip. - -Install with conda (recommended) -================================ - -Create an environment named ``research`` and install COMPAS from the package channel ``conda-forge``. - -.. code-block:: bash - - conda create -n research -c conda-forge compas - -Activate the environment. - -.. code-block:: bash - - conda activate research - -Verify that the installation was successful. - -.. code-block:: bash - - python -m compas - -.. code-block:: none - - Yay! COMPAS is installed correctly! - - -Installation options --------------------- - -Install COMPAS in an environment with a specific version of Python. - -.. code-block:: bash - - conda create -n research python=3.9 compas - -Install COMPAS in an existing environment. - -.. code-block:: bash - - conda install -n research compas - - -Install with pip -================ - -Install COMPAS using ``pip`` from the Python Package Index. - -.. code-block:: bash - - pip install compas - -Install an editable version from local source. - -.. code-block:: bash - - cd path/to/compas - pip install -e . - - -Update with conda -================= - -Update COMPAS to the latest version with ``conda``. - -.. code-block:: bash - - conda update compas - -Install a specific version. - -.. code-block:: bash - - conda install compas=1.17.9 - - -Update with pip -=============== - -Update COMPAS to the latest version with ``pip``. - -.. code-block:: bash - - pip install --upgrade compas - -Install a specific version. - -.. code-block:: bash - - pip install compas==1.17.9 diff --git a/docs/userguide/introduction.md b/docs/userguide/introduction.md new file mode 100644 index 000000000000..839bd3be8d26 --- /dev/null +++ b/docs/userguide/introduction.md @@ -0,0 +1,29 @@ +# Introduction + +COMPAS is an open-source, Python-based framework for computational research and collaboration in architecture, engineering, fabrication and construction. +It offers a wide range of functionality for the analysis, planning, and simulation of complex and bespoke architectural and engineering systems. + +## The Framework + +The framework consists of a core library (`compas`), core extensions (`compas_cgal`, `compas_libigl`, `compas_occ`, `compas_gmsh`), +a standalone viewer (`compas_viewer`), +dedicated integrations for Rhino (`compas_rhino`), Grasshopper (`compas_ghpython`), and Blender (`compas_blender`), +and a growing number of packages for specific tasks in the AEC domain, such as: + +- `compas_fab` for robotic fabrication +- `compas_dem` for discrete element modelling +- `compas_fea` for finite element analysis +- `compas_fdm` for constrained form finding +- `compas_ifc` for building information modelling +- ... + +This documentation is primarily about the core library, but it also contains information about the dedicated CAD integrations, +and, where relevant, the reader is referred to the documentation of core extensions and some of the AEC packages. + +## compas-dev + +The development of the core infrastructure of COMPAS is coordinated on GitHub at the `compas-dev` organisation. + +## COMPAS Association + +The COMPAS Association is a non-profit organisation that supports the development and maintenance of the COMPAS framework. diff --git a/docs/userguide/introduction.rst b/docs/userguide/introduction.rst deleted file mode 100644 index a0c20b158fbe..000000000000 --- a/docs/userguide/introduction.rst +++ /dev/null @@ -1,41 +0,0 @@ -******************************************************************************** -Introduction -******************************************************************************** - -.. rst-class:: lead - -COMPAS is an open-source, Python-based framework for computational research and collaboration in architecture, engineering, fabrication and construction. -It offers a wide range of functionality for the analysis, planning, and simulation of complex and bespoke architectural and engineering systems. - -.. add features here - -.. add links to stuff here - -The Framework -============= - -.. The framework consists of a collection of loosely coupled Python packages that can be used alone or in combination with other packages. - -The framework consists of a core library (:mod:`compas`), core extensions (:mod:`compas_cgal`, :mod:`compas_libigl`, :mod:`compas_occ`, :mod:`compas_gmsh`), -a standalone viewer (:mod:`compas_viewer`), -dedicated integrations for Rhino (:mod:`compas_rhino`), Grasshopper (:mod:`compas_ghpython`), and Blender (:mod:`compas_blender`), -and a growing number of packages for specific tasks in the AEC domain, such as: - -* :mod:`compas_fab` for robotic fabrication -* :mod:`compas_dem` for discrete element modelling -* :mod:`compas_fea` for finite element analysis -* :mod:`compas_fdm` for constrained form finding -* :mod:`compas_ifc` for building information modelling -* ... - -This documentation is primarily about the core library, but it also contains information about the dedicated CAD integrations, -and, where relevant, the reader is referred to the documentation of core extensions and some of the AEC packages. - -compas-dev -========== - -The development of the core infrastructure of COMPAS is coordinated on GitHub at the ``compas-dev`` organisation. - -COMPAS Association -================== - diff --git a/docs/userguide/license.md b/docs/userguide/license.md new file mode 100644 index 000000000000..0d058dc292fc --- /dev/null +++ b/docs/userguide/license.md @@ -0,0 +1,3 @@ +# License + +COMPAS is licensed under the MIT License. See the [LICENSE](https://github.com/compas-dev/compas/blob/main/LICENSE) file for details. diff --git a/docs/userguide/license.rst b/docs/userguide/license.rst deleted file mode 100644 index 0bd6806aeaab..000000000000 --- a/docs/userguide/license.rst +++ /dev/null @@ -1,12 +0,0 @@ -******************************************************************************** -License -******************************************************************************** - -.. rst-class:: lead - -COMPAS is an open source framework with a permissive license such that it can be used -for research as well as for proprietary projects, in academia and in practice, -or at the interface between both. - -.. literalinclude:: ../../LICENSE - :language: none diff --git a/docs/userguide/releases.md b/docs/userguide/releases.md new file mode 100644 index 000000000000..9d10aeed9f13 --- /dev/null +++ b/docs/userguide/releases.md @@ -0,0 +1,3 @@ +# Releases + +For release notes, see the [CHANGELOG](https://github.com/compas-dev/compas/blob/main/CHANGELOG.md) on GitHub. diff --git a/docs/userguide/releases.rst b/docs/userguide/releases.rst deleted file mode 100644 index d25caf511f64..000000000000 --- a/docs/userguide/releases.rst +++ /dev/null @@ -1,36 +0,0 @@ -******************************************************************************** -Releases -******************************************************************************** - -.. rst-class:: lead - -COMPAS releases are available on the Python Package Index (PyPI), on ``conda-forge`` -or directly from the Github repo. - -Versions are tagged following the Semantic Versioning (semver) convention of ``MAJOR.MINOR.PATCH``. -For more information see `Semantic Versioning 2.0.0 `_. - -The API of ``COMPAS`` was under heavy development up until ``COMPAS 0.19``, -the last version series before ``1.0``. - -Starting with ``1.0`` the API has been stabilized and the project adheres strictly to -semver. In addition to the version number, major releases also have a name -following the pattern `` ``, with the words -forming a tautogram in which the first letter increases alphabetically on every major -release and rolls back to A after reaching Z. For example: ``COMPAS 16.0: Projective Pirate``. - -Past and future release names -============================= - -.. rst-class:: table table-bordered - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Version - - Code name - - Release date - * - COMPAS 1.0 - - Affine Anchor - - 2021-01-18 diff --git a/docs/userguide/whatsnext.md b/docs/userguide/whatsnext.md new file mode 100644 index 000000000000..c1308694f9b7 --- /dev/null +++ b/docs/userguide/whatsnext.md @@ -0,0 +1,36 @@ +# What's Next + +If you have successfully installed COMPAS and managed to run the samples in [First Steps](firststeps.md), +you are ready for the next challenge. Where to go from here depends on what you want to do. +In any case, enjoy! And if you have any questions, please don't hesitate to ask on the forum: . + +
+ +- :material-shape-outline:{ .lg .middle } **Geometry Tutorial** + + --- + + If you're still just exploring, + you may want to continue with the basic geometry tutorial. + + [:octicons-arrow-right-24: Geometry Tutorial](basics.geometry.md) + +- :material-tools:{ .lg .middle } **Workflows** + + --- + + If you have a specific AEC application in mind, + perhaps the AEC workflows on the COMPAS website can help you get started. + + [:octicons-arrow-right-24: Workflows](https://compas.dev/documentation/workflows) + +- :material-code-braces:{ .lg .middle } **Developer Guide** + + --- + + If you're a developer and want to develop your own tools, or you want to contribute to COMPAS, + go to the developer guide. + + [:octicons-arrow-right-24: Developer Guide](../devguide/index.md) + +
diff --git a/docs/userguide/whatsnext.rst b/docs/userguide/whatsnext.rst deleted file mode 100644 index a104da29e58e..000000000000 --- a/docs/userguide/whatsnext.rst +++ /dev/null @@ -1,33 +0,0 @@ -******************************************************************************** -What's Next -******************************************************************************** - -.. rst-class:: lead - -If you have successfully installed COMPAS and managed to run the samples in :doc:`/userguide/firststeps`, -you are ready for the next challenge. Where to go from here depends on what you want to do. -In any case, enjoy!, And if you have any questions, please don't hesitate to ask on the forum: https://forum.compas-framework.org. - -.. grid:: 1 2 2 2 - :gutter: 4 - - .. grid-item-card:: Geometry Tutorial - - If you're still just exploring, - you may want to continue with the basic geometry tutorial. - +++ - :doc:`/userguide/basics.geometry` - - .. grid-item-card:: Workflows - - If you have a specific AEC application in mind, - perhaps the AEC workflows on the COMPAS website can help you get started. - +++ - `Workflows `_ - - .. grid-item-card:: Developer guide - - If you're a developer and want to develop your own tools, or you want to contribute to COMPAS, - go tod the developer guide. - +++ - :doc:`/devguide/index` diff --git a/docs/write_rst.py b/docs/write_rst.py deleted file mode 100644 index e2619aabde3e..000000000000 --- a/docs/write_rst.py +++ /dev/null @@ -1,152 +0,0 @@ -# from pathlib import Path -from compas import datastructures as module - -TPL = """ -******************************************************************************** -{currentmodule} -******************************************************************************** - -.. currentmodule:: {currentmodule} - -.. rst-class:: lead - -{lead} -{sections} - -""" - -SECTION = """ -{title} -{line} - -{summary} - -.. autosummary:: - :toctree: generated/ - :nosignatures: - -{items} -""" - -__newall__ = { - "functions": [], - "classes": [], - "errors": [], - "numpy": [], - "pluggables": [], - "plugins": [], -} - -for name in module.__all__: - obj = getattr(module, name) - - if name.endswith("_numpy"): - __newall__["numpy"].append(name) - continue - - if issubclass(type(obj), Exception): - __newall__["errors"].append(name) - continue - - if hasattr(obj, "__pluggable__"): - __newall__["pluggables"].append(name) - continue - - if hasattr(obj, "__plugin__"): - __newall__["plugins"].append(name) - continue - - if isinstance(obj, type): - __newall__["classes"].append(name) - else: - __newall__["functions"].append(name) - - -currentmodule = module.__name__ - -lead = module.__doc__ - -classes = "" -for name in sorted(__newall__["classes"]): - classes += " {name}\n".format(name=name) - -if classes: - classes = SECTION.format( - title="Classes", - line="=" * len("Classes"), - summary="", - items=classes, - ) - -errors = "" -for name in sorted(__newall__["errors"]): - errors += " {name}\n".format(name=name) - -if errors: - errors = SECTION.format( - title="Exceptions", - line="=" * len("Exceptions"), - summary="", - items=errors, - ) - -functions = "" -for name in sorted(__newall__["functions"]): - functions += " {name}\n".format(name=name) - -if functions: - functions = SECTION.format( - title="Functions", - line="=" * len("Functions"), - summary="", - items=functions, - ) - -numpy = "" -for name in sorted(__newall__["numpy"]): - numpy += " {name}\n".format(name=name) - -if numpy: - numpy = SECTION.format( - title="Functions using Numpy", - line="=" * len("Functions using Numpy"), - summary="In environments where numpy is not available, these functions can still be accessed through RPC.", - items=numpy, - ) - -pluggables = "" -for name in sorted(__newall__["pluggables"]): - pluggables += " {name}\n".format(name=name) - -if pluggables: - pluggables = SECTION.format( - title="Pluggables", - line="=" * len("Pluggables"), - summary="Pluggables are functions that don't have an actual implementation, but receive an implementation from a plugin.", - items=pluggables, - ) - -plugins = "" -for name in sorted(__newall__["plugins"]): - plugins += " {name}\n".format(name=name) - -if plugins: - plugins = SECTION.format( - title="Plugins", - line="=" * len("Plugins"), - summary="Plugins provide implementations for pluggables. You can use the plugin directly, or through the pluggable.", - items=plugins, - ) - -sections = "".join([classes, errors, functions, numpy, pluggables, plugins]) - -# docs = Path(__file__).parent - -with open("/Users/vanmelet/Code/compas/docs/api/{name}.rst".format(name=module.__name__), "w") as f: - f.write( - TPL.format( - currentmodule=currentmodule, - lead=lead, - sections=sections, - ) - ) diff --git a/mkdocs.yml b/mkdocs.yml new file mode 100644 index 000000000000..0e2d3249476f --- /dev/null +++ b/mkdocs.yml @@ -0,0 +1,205 @@ +site_name: COMPAS +site_description: An open-source framework for computational research in Architecture, Engineering, Fabrication, and Construction +site_url: https://compas.dev/compas +repo_url: https://github.com/compas-dev/compas +repo_name: compas-dev/compas +edit_uri: edit/main/docs/ +copyright: Copyright © COMPAS Association + +theme: + name: material + logo: images/COMPAS.png + favicon: images/COMPAS.png + palette: + - media: "(prefers-color-scheme)" + toggle: + icon: material/brightness-auto + name: Switch to light mode + - media: "(prefers-color-scheme: light)" + scheme: default + primary: deep purple + accent: deep purple + toggle: + icon: material/brightness-7 + name: Switch to dark mode + - media: "(prefers-color-scheme: dark)" + scheme: slate + primary: deep purple + accent: deep purple + toggle: + icon: material/brightness-4 + name: Switch to system preference + features: + - navigation.instant + - navigation.instant.progress + - navigation.tabs + - navigation.tabs.sticky + - navigation.sections + - navigation.indexes + - navigation.top + - navigation.footer + - toc.follow + - search.suggest + - search.highlight + - search.share + - content.code.copy + - content.code.annotate + - content.action.edit + - content.tabs.link + icon: + repo: fontawesome/brands/github + +plugins: + - search + - mkdocstrings: + default_handler: python + handlers: + python: + paths: [src] + options: + docstring_style: numpy + docstring_section_style: spacy + show_source: true + show_root_heading: true + show_root_full_path: false + show_symbol_type_heading: true + show_symbol_type_toc: true + members_order: source + merge_init_into_class: true + separate_signature: true + signature_crossrefs: true + show_signature_annotations: true + inherited_members: false + filters: + - "!^_" + - "^__init__$" + +markdown_extensions: + - admonition + - pymdownx.details + - pymdownx.superfences: + custom_fences: + - name: mermaid + class: mermaid + format: !!python/name:pymdownx.superfences.fence_code_format + - pymdownx.highlight: + anchor_linenums: true + line_spans: __span + pygments_lang_class: true + - pymdownx.inlinehilite + - pymdownx.snippets + - pymdownx.tabbed: + alternate_style: true + - pymdownx.arithmatex: + generic: true + - pymdownx.emoji: + emoji_index: !!python/name:material.extensions.emoji.twemoji + emoji_generator: !!python/name:material.extensions.emoji.to_svg + - tables + - attr_list + - md_in_html + - def_list + - footnotes + - toc: + permalink: true + toc_depth: 3 + +extra: + social: + - icon: fontawesome/brands/github + link: https://github.com/compas-dev/compas + name: COMPAS on GitHub + - icon: fontawesome/brands/discourse + link: https://forum.compas-framework.org/ + name: COMPAS Forum + - icon: fontawesome/brands/python + link: https://pypi.org/project/compas/ + name: COMPAS on PyPI + generator: false + +extra_javascript: + - javascripts/mathjax.js + - https://unpkg.com/mathjax@3/es5/tex-mml-chtml.js + +extra_css: + - stylesheets/extra.css + +nav: + - Home: index.md + - User Guide: + - userguide/index.md + - Getting Started: + - Introduction: userguide/introduction.md + - Installation: userguide/installation.md + - First Steps: userguide/firststeps.md + - What's Next: userguide/whatsnext.md + - "Basics: Geometry": + - Overview: userguide/basics.geometry.md + - Points and Vectors: userguide/basics.geometry.points_and_vectors.md + - Planes and Frames: userguide/basics.geometry.planes_and_frames.md + - Transformations: userguide/basics.geometry.transformations.md + - Polygons and Polyhedrons: userguide/basics.geometry.polygons_and_polyhedrons.md + - Curves and Surfaces: userguide/basics.geometry.curves_and_surfaces.md + - Breps: userguide/basics.geometry.breps.md + - Intersections: userguide/basics.geometry.intersections.md + - Distance and Membership: userguide/basics.geometry.distance_and_membership.md + - Solids: userguide/basics.geometry.solids.md + - "Basics: Data Structures": + - Overview: userguide/basics.datastructures.md + - Graphs: userguide/basics.datastructures.graphs.md + - Meshes: userguide/basics.datastructures.meshes.md + - Cells: userguide/basics.datastructures.cells.md + - VolMeshes: userguide/basics.datastructures.volmeshes.md + - CellNetworks: userguide/basics.datastructures.cellnetwork.md + - Trees: userguide/basics.datastructures.trees.md + - "Basics: Visualisation": userguide/basics.visualisation.md + - "Basics: Colors": userguide/basics.colors.md + - "Advanced: Tolerance": userguide/advanced.tolerance.md + - "Advanced: Serialisation": userguide/advanced.serialisation.md + - "Advanced: RPC": userguide/advanced.rpc.md + - "Advanced: Hash Trees": userguide/advanced.hashtree.md + - "Advanced: Pluggables": userguide/advanced.pluggables.md + - "CAD: Rhino": userguide/cad.rhino.md + - "CAD: Rhino 8": userguide/cad.rhino8.md + - "CAD: Grasshopper": userguide/cad.grasshopper.md + - "CAD: Blender": userguide/cad.blender.md + - "CAD: Other": userguide/cad.other.md + - Releases: userguide/releases.md + - Citing: userguide/citing.md + - License: userguide/license.md + - Developer Guide: + - devguide/index.md + - Development Basics: + - Setup: devguide/setup.md + - Workflow: devguide/workflow.md + - Code Style: devguide/code.md + - Documentation: devguide/documentation.md + - Advanced Topics: + - Extensions: devguide/extensions.md + - Plugins: devguide/plugins.md + - GH Components: devguide/ghcomponent.md + - Data Types: devguide/dtypes.md + - API Reference: + - api/index.md + - compas: + - compas.colors: api/compas.colors.md + - compas.data: api/compas.data.md + - compas.datastructures: api/compas.datastructures.md + - compas.files: api/compas.files.md + - compas.geometry: api/compas.geometry.md + - compas.itertools: api/compas.itertools.md + - compas.plugins: api/compas.plugins.md + - compas.rpc: api/compas.rpc.md + - compas.scene: api/compas.scene.md + - compas.tolerance: api/compas.tolerance.md + - compas_blender: + - compas_blender.conversions: api/compas_blender.conversions.md + - compas_blender.geometry: api/compas_blender.geometry.md + - compas_blender.scene: api/compas_blender.scene.md + - compas_ghpython: + - compas_ghpython.components: api/compas_ghpython.components.md + - compas_ghpython.scene: api/compas_ghpython.scene.md + - compas_rhino: + - compas_rhino.conversions: api/compas_rhino.conversions.md + - compas_rhino.geometry: api/compas_rhino.geometry.md + - compas_rhino.scene: api/compas_rhino.scene.md diff --git a/requirements-dev.txt b/requirements-dev.txt index 4d04ffd7c474..5f10339354f6 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -4,9 +4,11 @@ build bump-my-version compas_invocations2 invoke >=0.14 +mkdocs >=1.6 +mkdocs-material >=9.5 +mkdocstrings[python] >=0.27 pytest-cov pythonnet ruff -sphinx_compas2_theme twine wheel \ No newline at end of file diff --git a/src/compas/__init__.py b/src/compas/__init__.py index edc2cfc21805..b0af82f84164 100644 --- a/src/compas/__init__.py +++ b/src/compas/__init__.py @@ -168,12 +168,12 @@ def get(filename): The ``compas.get`` function is meant to be used in combination with the static constructors of the data structures. - .. code-block:: python + ```python + import compas + from compas.datastructures import Mesh - import compas - from compas.datastructures import Mesh - - mesh = Mesh.from_obj(compas.get("faces.obj")) + mesh = Mesh.from_obj(compas.get("faces.obj")) + ``` """ filename = filename.strip("/") @@ -210,12 +210,12 @@ def get_bunny(localstorage=None): Therefore, the returned path should be used in combination with the ``PLY`` file reader, or with the ``from_ply`` constructor function for meshes. - .. code-block:: python - - import compas - from compas.datastructures import Mesh + ```python + import compas + from compas.datastructures import Mesh - mesh = Mesh.from_ply(compas.get_bunny()) + mesh = Mesh.from_ply(compas.get_bunny()) + ``` """ import tarfile diff --git a/src/compas/geometry/_core/_algebra.py b/src/compas/geometry/_core/_algebra.py index 902bd29bf724..be4c6a9ca276 100644 --- a/src/compas/geometry/_core/_algebra.py +++ b/src/compas/geometry/_core/_algebra.py @@ -2227,12 +2227,12 @@ def matrix_from_basis_vectors(xaxis, yaxis): Notes ----- - .. code-block:: none - - [ x0 y0 z0 0 ] - [ x1 y1 z1 0 ] - [ x2 y2 z2 0 ] - [ 0 0 0 1 ] + ``` + [ x0 y0 z0 0 ] + [ x1 y1 z1 0 ] + [ x2 y2 z2 0 ] + [ 0 0 0 1 ] + ``` Examples -------- @@ -2306,12 +2306,12 @@ def matrix_from_translation(translation): Notes ----- - .. code-block:: none - - [ . . . 0 ] - [ . . . 1 ] - [ . . . 2 ] - [ . . . . ] + ``` + [ . . . 0 ] + [ . . . 1 ] + [ . . . 2 ] + [ . . . . ] + ``` Examples -------- @@ -2472,12 +2472,12 @@ def matrix_from_perspective_entries(perspective): Notes ----- - .. code-block:: none - - [ . . . . ] - [ . . . . ] - [ . . . . ] - [ 0 1 2 3 ] + ``` + [ . . . . ] + [ . . . . ] + [ . . . . ] + [ 0 1 2 3 ] + ``` """ M = identity_matrix(4) @@ -2503,12 +2503,12 @@ def matrix_from_shear_entries(shear_entries): Notes ----- - .. code-block:: none - - [ . 0 1 . ] - [ . . 2 . ] - [ . . . . ] - [ . . . . ] + ``` + [ . 0 1 . ] + [ . . 2 . ] + [ . . . . ] + [ . . . . ] + ``` Examples -------- @@ -2597,12 +2597,12 @@ def matrix_from_scale_factors(scale_factors): Notes ----- - .. code-block:: python - - [ 0 . . . ] - [ . 1 . . ] - [ . . 2 . ] - [ . . . . ] + ``` + [ 0 . . . ] + [ . 1 . . ] + [ . . 2 . ] + [ . . . . ] + ``` Examples -------- @@ -2760,13 +2760,12 @@ def close(value1, value2, tol=1e-05): Warnings -------- - .. deprecated:: 2.0 - Will be removed in 2.1 - Use :func:`TOL.is_close` instead. + Deprecated since version 2.0. Will be removed in 2.1. + Use `TOL.is_close` instead. The tolerance value used by this function is an absolute tolerance. It is more accurate to use a combination of absolute and relative tolerance. - Therefor, use :func:`TOL.is_close` instead. + Therefore, use `TOL.is_close` instead. """ return TOL.is_close(value1, value2, rtol=0.0, atol=tol) @@ -2793,13 +2792,12 @@ def allclose(l1, l2, tol=None): Warnings -------- - .. deprecated:: 2.0 - Will be removed in 2.1 - Use :func:`TOL.is_close` instead. + Deprecated since version 2.0. Will be removed in 2.1. + Use `TOL.is_allclose` instead. The tolerance value used by this function is an absolute tolerance. It is more accurate to use a combination of absolute and relative tolerance. - Therefor, use :func:`TOL.is_allclose` instead. + Therefore, use `TOL.is_allclose` instead. Notes ----- diff --git a/src/compas/rpc/server.py b/src/compas/rpc/server.py index e570f0f437a0..42c737b70b7d 100644 --- a/src/compas/rpc/server.py +++ b/src/compas/rpc/server.py @@ -20,25 +20,25 @@ class Server(SimpleXMLRPCServer): Examples -------- - .. code-block:: python + ```python + # service.py - # service.py + from compas.rpc import Server + from compas.rpc import Dispatcher - from compas.rpc import Server - from compas.rpc import Dispatcher + class DefaultService(Dispatcher): + pass - class DefaultService(Dispatcher): - pass + if __name__ == "__main__": + server = Server(("localhost", 8888)) - if __name__ == "__main__": - server = Server(("localhost", 8888)) - - server.register_function(server.ping) - server.register_function(server.remote_shutdown) - server.register_instance(DefaultService()) - server.serve_forever() + server.register_function(server.ping) + server.register_function(server.remote_shutdown) + server.register_instance(DefaultService()) + server.serve_forever() + ``` """ diff --git a/src/compas/scene/meshobject.py b/src/compas/scene/meshobject.py index 9c51e072d53d..c053777b09ff 100644 --- a/src/compas/scene/meshobject.py +++ b/src/compas/scene/meshobject.py @@ -162,8 +162,7 @@ def draw_faces(self): def draw_mesh(self, *args, **kwargs): """Draw the mesh of the mesh. - .. deprecated:: 1.14.1 - Use :meth:`~MeshObject.draw` instead. + Deprecated since version 1.14.1. Use `draw` instead. Returns ------- diff --git a/src/compas/utilities/azync.py b/src/compas/utilities/azync.py index 147cd50cb240..518ff082aa63 100644 --- a/src/compas/utilities/azync.py +++ b/src/compas/utilities/azync.py @@ -73,23 +73,23 @@ def await_callback(async_func, callback_name="callback", errback_name=None, *arg The following example shows how to await an async function (``do_async_stuff`` in the example), using this utility: - .. code-block:: python + ```python + from compas.utilities import await_callback - from compas.utilities import await_callback + def do_async_stuff(callback): + from threading import Thread - def do_async_stuff(callback): - from threading import Thread + def runner(cb): + print("doing async stuff") + # .. + cb("done") - def runner(cb): - print("doing async stuff") - # .. - cb("done") + Thread(target=runner, args=(callback,)).start() - Thread(target=runner, args=(callback,)).start() - - result = await_callback(do_async_stuff) + result = await_callback(do_async_stuff) + ``` """ wait_event = threading.Event() diff --git a/src/compas/utilities/decorators.py b/src/compas/utilities/decorators.py index b39bf31df553..cbcb3eef3d57 100644 --- a/src/compas/utilities/decorators.py +++ b/src/compas/utilities/decorators.py @@ -104,15 +104,15 @@ def print_profile(func): Examples -------- - .. code-block:: python - - @print_profile - def f(n): - return sum(for i in range(n)) - - print(f(100)) - print(f.__doc__) - print(f.__name__) + ```python + @print_profile + def f(n): + return sum(for i in range(n)) + + print(f(100)) + print(f.__doc__) + print(f.__name__) + ``` """ diff --git a/src/compas/utilities/remote.py b/src/compas/utilities/remote.py index c8ec7eddbd28..eeae6ba9011b 100644 --- a/src/compas/utilities/remote.py +++ b/src/compas/utilities/remote.py @@ -24,16 +24,16 @@ def download_file_from_remote(source, target, overwrite=True): Examples -------- - .. code-block:: python + ```python + import os + import compas + from compas.utilities.remote import download_file_from_remote - import os - import compas - from compas.utilities.remote import download_file_from_remote + source = "https://raw.githubusercontent.com/compas-dev/compas/main/data/faces.obj" + target = os.path.join(compas.APPDATA, "data", "faces.obj") - source = "https://raw.githubusercontent.com/compas-dev/compas/main/data/faces.obj" - target = os.path.join(compas.APPDATA, "data", "faces.obj") - - download_file_from_remote(source, target) + download_file_from_remote(source, target) + ``` """ parent = os.path.abspath(os.path.dirname(target)) diff --git a/src/compas_blender/install.py b/src/compas_blender/install.py index 359abc6206c8..5aded8166f8c 100644 --- a/src/compas_blender/install.py +++ b/src/compas_blender/install.py @@ -28,15 +28,15 @@ def install(version=None, packages=None, clean=False): Examples -------- - .. code-block:: python + ```python + import compas_blender.install - import compas_blender.install + compas_blender.install.install() + ``` - compas_blender.install.install() - - .. code-block:: bash - - python -m compas_blender.install + ```bash + python -m compas_blender.install + ``` """ version = compas_blender._check_blender_version(version) diff --git a/src/compas_ghpython/drawing.py b/src/compas_ghpython/drawing.py index 5a8d43a078e9..700000f38333 100644 --- a/src/compas_ghpython/drawing.py +++ b/src/compas_ghpython/drawing.py @@ -64,11 +64,11 @@ def draw_points(points): Notes ----- - .. code-block:: python - - Schema({ - 'pos': lambda x: len(x) == 3) - }) + ```python + Schema({ + 'pos': lambda x: len(x) == 3) + }) + ``` """ rg_points = [] @@ -92,12 +92,12 @@ def draw_lines(lines): Notes ----- - .. code-block:: python - - Schema({ - 'start': lambda x: len(x) == 3), - 'end': lambda x: len(x) == 3), - }) + ```python + Schema({ + 'start': lambda x: len(x) == 3), + 'end': lambda x: len(x) == 3), + }) + ``` """ rg_lines = [] @@ -122,13 +122,13 @@ def draw_geodesics(geodesics): Notes ----- - .. code-block:: python - - Schema({ - 'start': lambda x: len(x) == 3), - 'end': lambda x: len(x) == 3), - 'srf': str - }) + ```python + Schema({ + 'start': lambda x: len(x) == 3), + 'end': lambda x: len(x) == 3), + 'srf': str + }) + ``` """ rg_geodesics = [] @@ -155,9 +155,9 @@ def draw_polylines(polylines): Notes ----- - .. code-block:: python - - Schema({"points": lambda x: all(len(y) == 3 for y in x)}) + ```python + Schema({"points": lambda x: all(len(y) == 3 for y in x)}) + ``` """ rg_polylines = [] @@ -184,9 +184,9 @@ def draw_faces(faces): Notes ----- - .. code-block:: python - - Schema({"points": lambda x: all(len(y) == 3 for y in x), Optional("vertexcolors", default=None): lambda x: all(len(y) == 3 for y in x)}) + ```python + Schema({"points": lambda x: all(len(y) == 3 for y in x), Optional("vertexcolors", default=None): lambda x: all(len(y) == 3 for y in x)}) + ``` """ meshes = [] @@ -235,9 +235,9 @@ def draw_cylinders(cylinders, cap=False): Notes ----- - .. code-block:: python - - Schema({"start": lambda x: len(x) == 3, "end": lambda x: len(x) == 3, "radius": And(Or(int, float), lambda x: x > 0)}) + ```python + Schema({"start": lambda x: len(x) == 3, "end": lambda x: len(x) == 3, "radius": And(Or(int, float), lambda x: x > 0)}) + ``` """ rg_cylinders = [] @@ -281,9 +281,9 @@ def draw_pipes(pipes, cap=2, fit=1.0): Notes ----- - .. code-block:: python - - Schema({"points": lambda x: all(len(y) == 3 for y in x), "radius": And(Or(int, float), lambda x: x > 0)}) + ```python + Schema({"points": lambda x: all(len(y) == 3 for y in x), "radius": And(Or(int, float), lambda x: x > 0)}) + ``` """ abs_tol = TOL @@ -317,9 +317,9 @@ def draw_spheres(spheres): Notes ----- - .. code-block:: python - - Schema({"pos": lambda x: len(x) == 3, "radius": And(Or(int, float), lambda x: x > 0)}) + ```python + Schema({"pos": lambda x: len(x) == 3, "radius": And(Or(int, float), lambda x: x > 0)}) + ``` """ rg_sheres = [] @@ -432,9 +432,9 @@ def draw_circles(circles): Notes ----- - .. code-block:: python - - Schema({"plane": lambda x: len(x[0]) == 3 and len(x[1]) == 3, "radius": And(Or(int, float), lambda x: x > 0)}) + ```python + Schema({"plane": lambda x: len(x[0]) == 3 and len(x[1]) == 3, "radius": And(Or(int, float), lambda x: x > 0)}) + ``` """ rg_circles = [] diff --git a/src/compas_rhino/conduits/base.py b/src/compas_rhino/conduits/base.py index 9a37013a1504..d3aeb3aff3b9 100644 --- a/src/compas_rhino/conduits/base.py +++ b/src/compas_rhino/conduits/base.py @@ -39,11 +39,11 @@ def enabled(self): Examples -------- - .. code-block:: python - - with conduit.enabled(): - for i in range(10): - conduit.redraw(k=1) + ```python + with conduit.enabled(): + for i in range(10): + conduit.redraw(k=1) + ``` """ self.enable() diff --git a/src/compas_rhino/conduits/faces.py b/src/compas_rhino/conduits/faces.py index 2743f35f8184..4246d29a3240 100644 --- a/src/compas_rhino/conduits/faces.py +++ b/src/compas_rhino/conduits/faces.py @@ -36,16 +36,16 @@ class FacesConduit(BaseConduit): Examples -------- - .. code-block:: python + ```python + from compas.geometry import Polyhedron + from compas_rhino.conduits import FacesConduit - from compas.geometry import Polyhedron - from compas_rhino.conduits import FacesConduit + polyhedron = Polyhedron.generate(6) + conduit = FacesConduit(polyhedron.vertices, polyhedron.faces) - polyhedron = Polyhedron.generate(6) - conduit = FacesConduit(polyhedron.vertices, polyhedron.faces) - - with conduit.enabled(): - conduit.redraw(pause=5.0) + with conduit.enabled(): + conduit.redraw(pause=5.0) + ``` """ diff --git a/src/compas_rhino/conduits/labels.py b/src/compas_rhino/conduits/labels.py index e36c17397d46..cd2b706c900b 100644 --- a/src/compas_rhino/conduits/labels.py +++ b/src/compas_rhino/conduits/labels.py @@ -42,19 +42,19 @@ class LabelsConduit(BaseConduit): Examples -------- - .. code-block:: python + ```python + from random import randint + from compas_rhino.conduits import LabelsConduit - from random import randint - from compas_rhino.conduits import LabelsConduit + labels = [([1.0 * randint(0, 100), 1.0 * randint(0, 100), 0.0], str(i)) for i in range(100)] - labels = [([1.0 * randint(0, 100), 1.0 * randint(0, 100), 0.0], str(i)) for i in range(100)] + conduit = LabelsConduit(labels) - conduit = LabelsConduit(labels) - - with conduit.enabled(): - for i in range(100): - conduit.labels = [([1.0 * randint(0, 100), 1.0 * randint(0, 100), 0.0], str(i)) for i in range(100)] - conduit.redraw(pause=0.1) + with conduit.enabled(): + for i in range(100): + conduit.labels = [([1.0 * randint(0, 100), 1.0 * randint(0, 100), 0.0], str(i)) for i in range(100)] + conduit.redraw(pause=0.1) + ``` """ diff --git a/src/compas_rhino/conduits/lines.py b/src/compas_rhino/conduits/lines.py index 300f351f427e..b7a56f7a4de6 100644 --- a/src/compas_rhino/conduits/lines.py +++ b/src/compas_rhino/conduits/lines.py @@ -41,19 +41,19 @@ class LinesConduit(BaseConduit): Examples -------- - .. code-block:: python - - from random import randint - - points = [(1.0 * randint(0, 30), 1.0 * randint(0, 30), 0.0) for _ in range(100)] - lines = [(points[i], points[i + 1]) for i in range(99)] - conduit = LinesConduit(lines) - - with conduit.enabled(): - for i in range(100): - points = [(1.0 * randint(0, 30), 1.0 * randint(0, 30), 0.0) for _ in range(100)] - conduit.lines = [(points[i], points[i + 1]) for i in range(99)] - conduit.redraw(pause=0.1) + ```python + from random import randint + + points = [(1.0 * randint(0, 30), 1.0 * randint(0, 30), 0.0) for _ in range(100)] + lines = [(points[i], points[i + 1]) for i in range(99)] + conduit = LinesConduit(lines) + + with conduit.enabled(): + for i in range(100): + points = [(1.0 * randint(0, 30), 1.0 * randint(0, 30), 0.0) for _ in range(100)] + conduit.lines = [(points[i], points[i + 1]) for i in range(99)] + conduit.redraw(pause=0.1) + ``` """ diff --git a/src/compas_rhino/conduits/points.py b/src/compas_rhino/conduits/points.py index fe850924a5ab..b5ff7b6bd375 100644 --- a/src/compas_rhino/conduits/points.py +++ b/src/compas_rhino/conduits/points.py @@ -41,18 +41,18 @@ class PointsConduit(BaseConduit): Examples -------- - .. code-block:: python - - from random import randint - from compas_rhino.conduits import PointsConduit - - points = [(1.0 * randint(0, 30), 1.0 * randint(0, 30), 0.0) for _ in range(100)] - conduit = PointsConduit(points) - - with conduit.enabled(): - for i in range(100): - conduit.points = [(1.0 * randint(0, 30), 1.0 * randint(0, 30), 0.0) for _ in range(100)] - conduit.redraw(pause=0.1) + ```python + from random import randint + from compas_rhino.conduits import PointsConduit + + points = [(1.0 * randint(0, 30), 1.0 * randint(0, 30), 0.0) for _ in range(100)] + conduit = PointsConduit(points) + + with conduit.enabled(): + for i in range(100): + conduit.points = [(1.0 * randint(0, 30), 1.0 * randint(0, 30), 0.0) for _ in range(100)] + conduit.redraw(pause=0.1) + ``` """ diff --git a/src/compas_rhino/drawing.py b/src/compas_rhino/drawing.py index b4b99a83da0f..2795a2b6f0d0 100644 --- a/src/compas_rhino/drawing.py +++ b/src/compas_rhino/drawing.py @@ -81,19 +81,19 @@ def draw_labels(labels, **kwargs): ----- A label dict has the following schema: - .. code-block:: python - - Schema( - { - "pos": And(list, lambda x: len(x) == 3), - "text": And(str, len), - Optional("name", default=""): str, - Optional("color", default=None): (lambda x: len(x) == 3 and all(0 <= y <= 255 for y in x)), - Optional("layer", default=None): str, - Optional("fontsize", default=10): Or(int, float), - Optional("font", default="Arial Regular"): str, - } - ) + ```python + Schema( + { + "pos": And(list, lambda x: len(x) == 3), + "text": And(str, len), + Optional("name", default=""): str, + Optional("color", default=None): (lambda x: len(x) == 3 and all(0 <= y <= 255 for y in x)), + Optional("layer", default=None): str, + Optional("fontsize", default=10): Or(int, float), + Optional("font", default="Arial Regular"): str, + } + ) + ``` """ guids = [] @@ -148,16 +148,16 @@ def draw_points(points, **kwargs): ----- A point dict has the following schema: - .. code-block:: python - - Schema( - { - "pos": And(list, lambda x: len(x) == 3), - Optional("name", default=""): str, - Optional("color", default=None): (lambda x: len(x) == 3 and all(0 <= y <= 255 for y in x)), - Optional("layer", default=None): str, - } - ) + ```python + Schema( + { + "pos": And(list, lambda x: len(x) == 3), + Optional("name", default=""): str, + Optional("color", default=None): (lambda x: len(x) == 3 and all(0 <= y <= 255 for y in x)), + Optional("layer", default=None): str, + } + ) + ``` """ guids = [] @@ -207,19 +207,19 @@ def draw_lines(lines, **kwargs): ----- A line dict has the following schema: - .. code-block:: python - - Schema( - { - "start": And(list, lambda x: len(x) == 3), - "end": And(list, lambda x: len(x) == 3), - Optional("name", default=""): str, - Optional("color", default=None): (lambda x: len(x) == 3 and all(0 <= y <= 255 for y in x)), - Optional("layer", default=None): str, - Optional("arrow", default=None): str, - Optional("width", default=None): Or(int, float), - } - ) + ```python + Schema( + { + "start": And(list, lambda x: len(x) == 3), + "end": And(list, lambda x: len(x) == 3), + Optional("name", default=""): str, + Optional("color", default=None): (lambda x: len(x) == 3 and all(0 <= y <= 255 for y in x)), + Optional("layer", default=None): str, + Optional("arrow", default=None): str, + Optional("width", default=None): Or(int, float), + } + ) + ``` """ guids = [] @@ -279,19 +279,19 @@ def draw_geodesics(geodesics, **kwargs): ----- A geodesic dict has the following schema: - .. code-block:: python - - Schema( - { - "start": And(list, lambda x: len(x) == 3), - "end": And(list, lambda x: len(x) == 3), - "srf": Or(str, System.Guid), - Optional("name", default=""): str, - Optional("color", default=None): (lambda x: len(x) == 3 and all(0 <= y <= 255 for y in x)), - Optional("layer", default=None): str, - Optional("arrow", default=None): str, - } - ) + ```python + Schema( + { + "start": And(list, lambda x: len(x) == 3), + "end": And(list, lambda x: len(x) == 3), + "srf": Or(str, System.Guid), + Optional("name", default=""): str, + Optional("color", default=None): (lambda x: len(x) == 3 and all(0 <= y <= 255 for y in x)), + Optional("layer", default=None): str, + Optional("arrow", default=None): str, + } + ) + ``` """ guids = [] @@ -349,15 +349,15 @@ def draw_polylines(polylines, **kwargs): ----- A polyline dict has the following schema: - .. code-block:: python - - Schema({ - 'points': And(list, lambda x: all(len(point) == 3 for point in x), - Optional('name', default=''): str, - Optional('color', default=None): (lambda x: len(x) == 3 and all(0 <= y <= 255 for y in x)), - Optional('layer', default=None): str, - Optional('arrow', default=None): str - }) + ```python + Schema({ + 'points': And(list, lambda x: all(len(point) == 3 for point in x), + Optional('name', default=''): str, + Optional('color', default=None): (lambda x: len(x) == 3 and all(0 <= y <= 255 for y in x)), + Optional('layer', default=None): str, + Optional('arrow', default=None): str + }) + ``` """ guids = [] @@ -420,14 +420,14 @@ def draw_breps(faces, u=10, v=10, join=False, **kwargs): ----- A brep dict has the following schema: - .. code-block:: python - - Schema({ - 'points': And(list, lambda x: len(x) > 3 and all(len(point) == 3 for point in x), - Optional('name', default=''): str, - Optional('color', default=None): (lambda x: len(x) == 3 and all(0 <= y <= 255 for y in x)), - Optional('layer', default=None): str, - }) + ```python + Schema({ + 'points': And(list, lambda x: len(x) > 3 and all(len(point) == 3 for point in x), + Optional('name', default=''): str, + Optional('color', default=None): (lambda x: len(x) == 3 and all(0 <= y <= 255 for y in x)), + Optional('layer', default=None): str, + }) + ``` Examples -------- @@ -528,18 +528,18 @@ def draw_cylinders(cylinders, cap=False, **kwargs): ----- A cylinder dict has the following schema: - .. code-block:: python - - Schema( - { - "start": And(list, lambda x: len(x) == 3), - "end": And(list, lambda x: len(x) == 3), - "radius": And(Or(int, float), lambda x: x > 0.0), - Optional("name", default=""): str, - Optional("color", default=None): (lambda x: len(x) == 3 and all(0 <= y <= 255 for y in x)), - Optional("layer", default=None): str, - } - ) + ```python + Schema( + { + "start": And(list, lambda x: len(x) == 3), + "end": And(list, lambda x: len(x) == 3), + "radius": And(Or(int, float), lambda x: x > 0.0), + Optional("name", default=""): str, + Optional("color", default=None): (lambda x: len(x) == 3 and all(0 <= y <= 255 for y in x)), + Optional("layer", default=None): str, + } + ) + ``` """ guids = [] @@ -609,17 +609,17 @@ def draw_pipes(pipes, cap=2, fit=1.0, **kwargs): ----- A pipe dict has the following schema: - .. code-block:: python - - Schema( - { - "points": And(list, lambda x: all(len(y) == 3 for y in x)), - "radius": And(Or(int, float), lambda x: x > 0.0), - Optional("name", default=""): str, - Optional("color", default=None): And(lambda x: len(x) == 3, all(0 <= y <= 255 for y in x)), - Optional("layer", default=None): str, - } - ) + ```python + Schema( + { + "points": And(list, lambda x: all(len(y) == 3 for y in x)), + "radius": And(Or(int, float), lambda x: x > 0.0), + Optional("name", default=""): str, + Optional("color", default=None): And(lambda x: len(x) == 3, all(0 <= y <= 255 for y in x)), + Optional("layer", default=None): str, + } + ) + ``` """ guids = [] @@ -680,17 +680,17 @@ def draw_spheres(spheres, **kwargs): ----- A sphere dict has the following schema: - .. code-block:: python - - Schema( - { - "pos": And(list, lambda x: len(x) == 3), - "radius": And(Or(int, float), lambda x: x > 0.0), - Optional("name", default=""): str, - Optional("color", default=None): And(lambda x: len(x) == 3, all(0 <= y <= 255 for y in x)), - Optional("layer", default=None): str, - } - ) + ```python + Schema( + { + "pos": And(list, lambda x: len(x) == 3), + "radius": And(Or(int, float), lambda x: x > 0.0), + Optional("name", default=""): str, + Optional("color", default=None): And(lambda x: len(x) == 3, all(0 <= y <= 255 for y in x)), + Optional("layer", default=None): str, + } + ) + ``` """ guids = [] @@ -816,16 +816,16 @@ def draw_faces(faces, **kwargs): ----- A face dict has the following schema: - .. code-block:: python - - Schema( - { - "points": And(len, lambda x: all(len(y) == 3 for y in x)), - Optional("name", default=""): str, - Optional("color", default=None): And(lambda x: len(x) == 3, all(0 <= y <= 255 for y in x)), - Optional("vertexcolors", default=None): And(len, lambda x: all(0 <= y <= 255 for y in x)), - } - ) + ```python + Schema( + { + "points": And(len, lambda x: all(len(y) == 3 for y in x)), + Optional("name", default=""): str, + Optional("color", default=None): And(lambda x: len(x) == 3, all(0 <= y <= 255 for y in x)), + Optional("vertexcolors", default=None): And(len, lambda x: all(0 <= y <= 255 for y in x)), + } + ) + ``` """ guids = [] @@ -896,17 +896,17 @@ def draw_circles(circles, **kwargs): ----- A circle dict has the following schema: - .. code-block:: python - - Schema( - { - "plane": lambda x: len(x[0]) == 3 and len(x[1]) == 3, - "radius": And(Or(int, float), lambda x: x > 0), - Optional("name", default=""): str, - Optional("color", default=None): And(lambda x: len(x) == 3, all(0 <= y <= 255 for y in x)), - Optional("layer", default=None): str, - } - ) + ```python + Schema( + { + "plane": lambda x: len(x[0]) == 3 and len(x[1]) == 3, + "radius": And(Or(int, float), lambda x: x > 0), + Optional("name", default=""): str, + Optional("color", default=None): And(lambda x: len(x) == 3, all(0 <= y <= 255 for y in x)), + Optional("layer", default=None): str, + } + ) + ``` """ guids = [] @@ -958,16 +958,16 @@ def draw_curves(curves, **kwargs): ----- A curve dict has the following schema: - .. code-block:: python - - Schema( - { - "curve": compas.geometry.Rhino.Geometry.Curve, - Optional("name", default=""): str, - Optional("color", default=None): And(lambda x: len(x) == 3, all(0 <= y <= 255 for y in x)), - Optional("layer", default=None): str, - } - ) + ```python + Schema( + { + "curve": compas.geometry.Rhino.Geometry.Curve, + Optional("name", default=""): str, + Optional("color", default=None): And(lambda x: len(x) == 3, all(0 <= y <= 255 for y in x)), + Optional("layer", default=None): str, + } + ) + ``` """ guids = [] @@ -1016,16 +1016,16 @@ def draw_surfaces(surfaces, **kwargs): ----- A surface dict has the following schema: - .. code-block:: python - - Schema( - { - "surface": compas.geometry.Surface, - Optional("name", default=""): str, - Optional("color", default=None): And(lambda x: len(x) == 3, all(0 <= y <= 255 for y in x)), - Optional("layer", default=None): str, - } - ) + ```python + Schema( + { + "surface": compas.geometry.Surface, + Optional("name", default=""): str, + Optional("color", default=None): And(lambda x: len(x) == 3, all(0 <= y <= 255 for y in x)), + Optional("layer", default=None): str, + } + ) + ``` """ guids = [] diff --git a/src/compas_rhino/geometry/curves/curve.py b/src/compas_rhino/geometry/curves/curve.py index a3df7109fa78..e58095dc57a1 100644 --- a/src/compas_rhino/geometry/curves/curve.py +++ b/src/compas_rhino/geometry/curves/curve.py @@ -137,8 +137,7 @@ def from_rhino(cls, native_curve): Warnings -------- - .. deprecated:: 2.3 - Use `from_native` instead. + Deprecated since version 2.3. Use `from_native` instead. """ return cls(native_curve) diff --git a/src/compas_rhino/geometry/surfaces/surface.py b/src/compas_rhino/geometry/surfaces/surface.py index eb66ca6e8366..e8874dfa9013 100644 --- a/src/compas_rhino/geometry/surfaces/surface.py +++ b/src/compas_rhino/geometry/surfaces/surface.py @@ -112,8 +112,7 @@ def from_rhino(cls, native_surface): Warnings -------- - .. deprecated:: 2.3 - Use `from_native` instead. + Deprecated since version 2.3. Use `from_native` instead. """ return cls(native_surface) diff --git a/src/compas_rhino/install.py b/src/compas_rhino/install.py index c66fd865dfdb..4679bfb6c380 100644 --- a/src/compas_rhino/install.py +++ b/src/compas_rhino/install.py @@ -30,15 +30,15 @@ def install(version=None, packages=None, clean=False): Examples -------- - .. code-block:: python + ```python + import compas_rhino.install - import compas_rhino.install + compas_rhino.install.install() + ``` - compas_rhino.install.install() - - .. code-block:: bash - - python -m compas_rhino.install + ```bash + python -m compas_rhino.install + ``` """ version = compas_rhino._check_rhino_version(version) diff --git a/src/compas_rhino/install_plugin.py b/src/compas_rhino/install_plugin.py index 42fefe6a0517..c518a6e4a047 100644 --- a/src/compas_rhino/install_plugin.py +++ b/src/compas_rhino/install_plugin.py @@ -32,9 +32,9 @@ def install_plugin(plugin, version=None): -------- Assuming the plugin folder is at the following location on your computer - .. code-block:: none - - ~/Code/compas_xxx/ui/Rhino/XXX + ``` + ~/Code/compas_xxx/ui/Rhino/XXX + ``` and contains at least a "dev" folder with a ``__plugin__.py`` file with @@ -43,17 +43,17 @@ def install_plugin(plugin, version=None): it can be installed with the following command, - .. code-block:: bash - - cd ~/Code/compas_xxx - python -m compas_rhino.install_plugin ui/Rhino/XXX + ```bash + cd ~/Code/compas_xxx + python -m compas_rhino.install_plugin ui/Rhino/XXX + ``` or the following, if the plugin should be installed for Rhino 7. - .. code-block:: bash - - cd ~/Code/compas_xxx - python -m compas_rhino.install_plugin -v 7.0 ui/Rhino/XXX + ```bash + cd ~/Code/compas_xxx + python -m compas_rhino.install_plugin -v 7.0 ui/Rhino/XXX + ``` """ if not os.path.isdir(plugin): diff --git a/src/compas_rhino/install_with_pip.py b/src/compas_rhino/install_with_pip.py index b332e466ade8..bf5df86bbcb7 100644 --- a/src/compas_rhino/install_with_pip.py +++ b/src/compas_rhino/install_with_pip.py @@ -80,14 +80,14 @@ def install_in_rhino_with_pip( This function is made available as a command line script under the name `install_in_rhino`. On the command line you can use the following syntax - .. code-block:: bash - - install_in_rhino requests numpy - install_in_rhino -r requirements.txt --env myenv --upgrade - install_in_rhino . --env myenv - install_in_rhino .. --env myenv - install_in_rhino -r requirements.txt --env myenv --no-deps - install_in_rhino requests --env myenv --clear + ```bash + install_in_rhino requests numpy + install_in_rhino -r requirements.txt --env myenv --upgrade + install_in_rhino . --env myenv + install_in_rhino .. --env myenv + install_in_rhino -r requirements.txt --env myenv --no-deps + install_in_rhino requests --env myenv --clear + ``` """ diff --git a/src/compas_rhino/layers.py b/src/compas_rhino/layers.py index a449fcc6af9a..3e15aa12ae12 100644 --- a/src/compas_rhino/layers.py +++ b/src/compas_rhino/layers.py @@ -82,9 +82,9 @@ def create_layers_from_path(path, separator="::"): * Datastructures * Mesh - .. code-block:: python - - create_layers_from_path("COMPAS::Datastructures::Mesh") + ```python + create_layers_from_path("COMPAS::Datastructures::Mesh") + ``` """ names = path.split(separator) @@ -123,16 +123,16 @@ def create_layers_from_paths(names, separator="::"): * Point * Vector - .. code-block:: python - - create_layers_from_paths( - [ - "COMPAS::Datastructures::Mesh", - "COMPAS::Datastructures::Graph", - "COMPAS::Geometry::Point", - "COMPAS::Geometry::Vector", - ] - ) + ```python + create_layers_from_paths( + [ + "COMPAS::Datastructures::Mesh", + "COMPAS::Datastructures::Graph", + "COMPAS::Geometry::Point", + "COMPAS::Geometry::Vector", + ] + ) + ``` """ for name in names: @@ -155,19 +155,19 @@ def create_layers_from_dict(layers): Examples -------- - .. code-block:: python - - layers = { - "COMPAS", - { - "layers": { - "Datastructures": {"color": (255, 0, 0), "layers": {"Mesh": {}, "Graph": {}}}, - "Geometry": {"color": (0, 0, 255), "layers": {"Point": {}, "Vector": {}}}, - } - }, - } - - create_layers_from_dict(layers) + ```python + layers = { + "COMPAS", + { + "layers": { + "Datastructures": {"color": (255, 0, 0), "layers": {"Mesh": {}, "Graph": {}}}, + "Geometry": {"color": (0, 0, 255), "layers": {"Point": {}, "Vector": {}}}, + } + }, + } + + create_layers_from_dict(layers) + ``` """ @@ -306,14 +306,14 @@ def delete_layers(layers): Examples -------- - .. code-block:: python - - layers = {"COMPAS": {"layers": {"Datastructures": {"layers": {"Mesh": {}, "Graph": {}}}}}} + ```python + layers = {"COMPAS": {"layers": {"Datastructures": {"layers": {"Mesh": {}, "Graph": {}}}}}} - create_layers(layers) + create_layers(layers) - delete_layers(["COMPAS::Datastructures::Graph"]) - delete_layers({"COMPAS": {"layers": {"Datastructures": {"layers": {"Mesh": {}}}}}}) + delete_layers(["COMPAS::Datastructures::Graph"]) + delete_layers({"COMPAS": {"layers": {"Datastructures": {"layers": {"Mesh": {}}}}}}) + ``` """ to_delete = [] diff --git a/src/compas_rhino/objects.py b/src/compas_rhino/objects.py index dae80f58712c..5acd3a94279f 100644 --- a/src/compas_rhino/objects.py +++ b/src/compas_rhino/objects.py @@ -38,8 +38,7 @@ def get_point_coordinates(guids): Warnings -------- - .. deprecated:: 2.3 - Use `compas_rhino.conversions` instead. + Deprecated since version 2.3. Use `compas_rhino.conversions` instead. """ warnings.warn("This function will be removed in v2.3. Please use `compas_rhino.conversions` instead.", DeprecationWarning, stacklevel=2) @@ -67,8 +66,7 @@ def get_line_coordinates(guids): Warnings -------- - .. deprecated:: 2.3 - Use `compas_rhino.conversions` instead. + Deprecated since version 2.3. Use `compas_rhino.conversions` instead. """ warnings.warn("This function will be removed in v2.3. Please use `compas_rhino.conversions` instead.", DeprecationWarning, stacklevel=2) @@ -100,8 +98,7 @@ def get_polyline_coordinates(guids): Warnings -------- - .. deprecated:: 2.3 - Use `compas_rhino.conversions` instead. + Deprecated since version 2.3. Use `compas_rhino.conversions` instead. """ warnings.warn("This function will be removed in v2.3. Please use `compas_rhino.conversions` instead.", DeprecationWarning, stacklevel=2) @@ -137,8 +134,7 @@ def get_polygon_coordinates(guids): Warnings -------- - .. deprecated:: 2.3 - Use `compas_rhino.conversions` instead. + Deprecated since version 2.3. Use `compas_rhino.conversions` instead. """ warnings.warn("This function will be removed in v2.3. Please use `compas_rhino.conversions` instead.", DeprecationWarning, stacklevel=2) diff --git a/src/compas_rhino/uninstall.py b/src/compas_rhino/uninstall.py index cb4e4a656efe..806796804c81 100644 --- a/src/compas_rhino/uninstall.py +++ b/src/compas_rhino/uninstall.py @@ -27,15 +27,15 @@ def uninstall(version=None, packages=None): Examples -------- - .. code-block:: python + ```python + import compas_rhino - import compas_rhino + compas_rhino.uninstall() + ``` - compas_rhino.uninstall() - - .. code-block:: bash - - python -m compas_rhino.uninstall + ```bash + python -m compas_rhino.uninstall + ``` """ version = compas_rhino._check_rhino_version(version) diff --git a/src/compas_rhino/uninstall_plugin.py b/src/compas_rhino/uninstall_plugin.py index 21c61566ac1b..8add5637e89b 100644 --- a/src/compas_rhino/uninstall_plugin.py +++ b/src/compas_rhino/uninstall_plugin.py @@ -25,9 +25,9 @@ def uninstall_plugin(plugin, version=None): Examples -------- - .. code-block:: bash - - python -m compas_rhino.uninstall_plugin XXX + ```bash + python -m compas_rhino.uninstall_plugin XXX + ``` """ version = compas_rhino._check_rhino_version(version) diff --git a/src/roslibpy b/src/roslibpy new file mode 120000 index 000000000000..b6ed9e24c7a6 --- /dev/null +++ b/src/roslibpy @@ -0,0 +1 @@ +/Users/jelle/Library/Application Support/McNeel/Rhinoceros/7.0/scripts/roslibpy \ No newline at end of file diff --git a/tasks.py b/tasks.py index 7286febdb086..66ba7898fdfa 100644 --- a/tasks.py +++ b/tasks.py @@ -3,19 +3,31 @@ import os from compas_invocations2 import build -from compas_invocations2 import docs from compas_invocations2 import style from compas_invocations2 import tests from compas_invocations2 import grasshopper +from invoke import task from invoke.collection import Collection + +@task +def docs(ctx): + """Build documentation with MkDocs.""" + ctx.run("mkdocs build --strict") + + +@task +def serve(ctx): + """Serve documentation locally with live reload.""" + ctx.run("mkdocs serve") + + ns = Collection( - docs.help, + docs, + serve, style.check, style.lint, style.format, - docs.docs, - docs.linkcheck, tests.test, tests.testdocs, tests.testcodeblocks, diff --git a/tests/compas/donttest_api_completeness.py b/tests/compas/donttest_api_completeness.py deleted file mode 100644 index e782572a9e5d..000000000000 --- a/tests/compas/donttest_api_completeness.py +++ /dev/null @@ -1,116 +0,0 @@ -# from __future__ import absolute_import - -# import os -# import pytest -# import shutil -# import subprocess -# import importlib -# import inspect -# import compas - - -# def get_names_in_module(module_name): -# exceptions = ["absolute_import", "division", "print_function"] -# module = importlib.import_module(module_name) -# all_names = module.__all__ if hasattr(module, "__all__") else dir(module) -# return sorted( -# [ -# i -# for i in all_names -# if not i.startswith("_") and i not in exceptions and not inspect.ismodule(getattr(module, i)) -# ] -# ) - - -# @pytest.fixture -# def compas_api(): -# if compas.IPY: -# return - -# modules = [ -# "compas.data", -# "compas.datastructures", -# "compas.files", -# "compas.geometry", -# "compas.numerical", -# "compas.plugins", -# "compas.robots", -# "compas.rpc", -# "compas.topology", -# "compas.utilities", -# ] -# api = {} -# for module_name in modules: -# api[module_name] = get_names_in_module(module_name) -# return api - - -# @pytest.fixture -# def compas_stubs(): -# if compas.IPY: -# return - -# env = compas._os.prepare_environment() - -# HERE = os.path.dirname(__file__) -# HOME = os.path.abspath(os.path.join(HERE, "../..")) -# TEMP = os.path.abspath(os.path.join(HOME, "temp/stubs")) -# DOCS = os.path.abspath(os.path.join(HOME, "docs")) -# API = os.path.abspath(os.path.join(DOCS, "reference")) - -# shutil.rmtree(TEMP, ignore_errors=True) - -# _, _, filenames = next(os.walk(API)) -# stubs = [] -# for name in filenames: -# if name == "compas.rst" or not name.startswith("compas."): -# continue -# stub = os.path.abspath(os.path.join(API, name)) -# subprocess.call("sphinx-autogen -o {} {}".format(TEMP, stub), shell=True, env=env) - -# _, _, filenames = next(os.walk(TEMP)) - -# shutil.rmtree(TEMP, ignore_errors=True) - -# stubs = {} -# for name in filenames: -# parts = name.split(".") -# if len(parts) != 4: -# continue -# package = parts[0] -# module = parts[1] -# item = parts[2] -# if package == "compas": -# packmod = "{}.{}".format(package, module) -# if packmod not in stubs: -# stubs[packmod] = [] -# stubs[packmod].append(item) - -# return stubs - - -# def test_compas_api_stubs(compas_api, compas_stubs): -# if compas.IPY: -# return - -# for packmod in compas_api: -# parts = packmod.split(".") -# if len(parts) != 2: -# continue -# assert packmod in compas_stubs -# for name in compas_api[packmod]: -# if name in [ -# "BaseMesh", -# "BaseGraph", -# "BaseVolMesh", -# "Datastructure", -# "Graph", -# "HalfEdge", -# "HalfFace", -# ]: -# continue -# if parts[1] == "plugins": -# continue -# if parts[1] == "utilities": -# continue -# assert name in compas_stubs[packmod] diff --git a/tests/compas/stubs.py b/tests/compas/stubs.py deleted file mode 100644 index bcd330aa34be..000000000000 --- a/tests/compas/stubs.py +++ /dev/null @@ -1,84 +0,0 @@ -import os -import shutil -import subprocess -import compas - -from donttest_api_stability import get_names_in_module - - -def compas_api(): - modules = [ - "compas.scene", - "compas.data", - "compas.datastructures", - "compas.files", - "compas.geometry", - "compas.numerical", - "compas.plugins", - "compas.rpc", - "compas.topology", - "compas.utilities", - ] - api = {} - for module_name in modules: - api[module_name] = get_names_in_module(module_name) - return api - - -def compas_stubs(): - env = compas._os.prepare_environment() - - HERE = os.path.dirname(__file__) - HOME = os.path.abspath(os.path.join(HERE, "../..")) - TEMP = os.path.abspath(os.path.join(HOME, "temp/stubs")) - DOCS = os.path.abspath(os.path.join(HOME, "docs")) - API = os.path.abspath(os.path.join(DOCS, "reference")) - - shutil.rmtree(TEMP, ignore_errors=True) - - _, _, filenames = next(os.walk(API)) - stubs = [] - for name in filenames: - if name == "compas.rst" or not name.startswith("compas."): - continue - stub = os.path.abspath(os.path.join(API, name)) - subprocess.call("sphinx-autogen -o {} {}".format(TEMP, stub), shell=True, env=env) - - _, _, filenames = next(os.walk(TEMP)) - - shutil.rmtree(TEMP, ignore_errors=True) - - stubs = {} - for name in filenames: - parts = name.split(".") - if len(parts) != 4: - continue - package = parts[0] - module = parts[1] - item = parts[2] - if package == "compas": - packmod = "{}.{}".format(package, module) - if packmod not in stubs: - stubs[packmod] = [] - stubs[packmod].append(item) - - return stubs - - -def check_compas_stubs(api, stubs): - for packmod in api: - parts = packmod.split(".") - if len(parts) != 2: - continue - assert packmod in stubs - for name in api[packmod]: - if name not in stubs[packmod]: - print(packmod, name) - - -# ============================================================================== -# Main -# ============================================================================== - -# if __name__ == "__main__": -# check_compas_stubs(compas_api(), compas_stubs())