Skip to content

Commit 4d325f6

Browse files
authored
Merge branch 'main' into yck011522/issue1287
2 parents af7720c + b23bf7b commit 4d325f6

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

85 files changed

+2778
-2150
lines changed

.github/workflows/coverage.yml

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
name: coverage
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
pull_request:
8+
branches:
9+
- main
10+
11+
jobs:
12+
coverage:
13+
if: "!contains(github.event.pull_request.labels.*.name, 'docs-only')"
14+
runs-on: ${{ matrix.os }}
15+
strategy:
16+
matrix:
17+
os: [ubuntu-latest]
18+
python: ["3.12"]
19+
20+
steps:
21+
- uses: compas-dev/compas-actions.build@v4
22+
with:
23+
invoke_lint: false
24+
invoke_test: false
25+
python: ${{ matrix.python }}
26+
- name: Run tests collecting coverage reports
27+
run: pytest --cov src/compas --cov-report=html
28+
- name: Upload coverage reports to Codecov
29+
uses: codecov/codecov-action@v4.0.1
30+
with:
31+
token: ${{ secrets.CODECOV_TOKEN }}

CHANGELOG.md

Lines changed: 91 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,97 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1818
### Removed
1919

2020

21+
## [2.3.0] 2024-07-06
22+
23+
### Added
24+
25+
* Added code coverage report uploads to codecov.io.
26+
* Added `compas.geometry.surfaces.surface.Surface.from_native`.
27+
* Added `compas.geometry.surfaces.nurbs.NurbsSurface.from_plane`.
28+
* Added `compas.geometry.surfaces.nurbs.NurbsSurface.from_cylinder`.
29+
* Added `compas.geometry.surfaces.nurbs.NurbsSurface.from_extrusion`.
30+
* Added `compas.geometry.surfaces.nurbs.NurbsSurface.from_frame`.
31+
* Added `compas.geometry.surfaces.nurbs.NurbsSurface.from_interpolation`.
32+
* Added `compas.geometry.surfaces.nurbs.NurbsSurface.from_revolution`.
33+
* Added `compas.geometry.surfaces.nurbs.NurbsSurface.from_sphere`.
34+
* Added `compas.geometry.surfaces.nurbs.NurbsSurface.from_torus`.
35+
* Added `compas_rhino.geometry.surfaces.surface_from_native`.
36+
* Added `compas_rhino.geometry.surfaces.nurbssurface_from_native`.
37+
* Added `compas_rhino.geometry.surfaces.nurbssurface_from_cylinder`.
38+
* Added `compas_rhino.geometry.surfaces.nurbssurface_from_fill`.
39+
* Added `compas_rhino.geometry.surfaces.nurbssurface_from_torus`.
40+
* Added `compas_rhino.geometry.surfaces.nurbs.NurbsSurface.from_corners`.
41+
* Added `compas_rhino.geometry.surfaces.nurbs.NurbsSurface.from_cylinder`.
42+
* Added `compas_rhino.geometry.surfaces.nurbs.NurbsSurface.from_frame`.
43+
* Added `compas_rhino.geometry.surfaces.nurbs.NurbsSurface.from_sphere`.
44+
* Added `compas_rhino.geometry.surfaces.nurbs.NurbsSurface.from_torus`.
45+
* Added `compas.geometry.curves.curve.Curve.from_native`.
46+
* Added `compas_rhino.geometry.curves.curve.Curve.from_native`.
47+
* Added `compas_rhino.geometry.curves.nurbs.NurbsCurve.from_native`.
48+
* Added `compas_rhino.conversions.breps.brep_to_compas_mesh`.
49+
* Added `compas_rhino.conversions.docobjects.brepobject_to_compas`.
50+
* Added `compas_rhino.conversions.docobjects.curveobject_to_compas`.
51+
* Added `compas_rhino.conversions.docobjects.meshobject_to_compas`.
52+
* Added `compas_rhino.conversions.docobjects.pointobject_to_compas`.
53+
* Added `compas.datastructures.HashTree` and `compas.datastructures.HashNode`.
54+
55+
### Changed
56+
57+
* Fixed bug in `compas.geometry.curves.curve.Curve.reversed` by adding missing parenthesis.
58+
* Fixed all doctests so we can run `invoke test --doctest`.
59+
* Changed `compas.geometry.surfaces.surface.Surface.__new__` to prevent instantiation of `Surface` directly.
60+
* Changed `compas.geometry.surfaces.nurbs.NurbsSurface.__new__` to prevent instantiation of `NurbsSurface` directly.
61+
* Fixed bug in `compas.geometry.surfaces.nurbs.NurbsSurface.__data__`.
62+
* Changed `compas.geometry.surfaces.nurbs.new_nurbssurface_from_...` to `nurbssurface_from_...`.
63+
* Changed `compas.geometry.curves.curve.Curve.__new__` to prevent instantiation of `Curve` directly.
64+
* Changed `compas.geometry.curves.nurbs.new_nurbscurve_from_...` to `nurbscurve_from_...`.
65+
* Changed `compas.geometry.curves.nurbs.NurbsCurve.__new__` to prevent instantiation of `NurbsCurve` directly.
66+
* Changed `compas_rhino.geometry.curves.new_nurbscurve_from_...` to `nurbscurve_from_...`.
67+
* Fixed `compas_ghpython` Grasshopper components not included in published pakcage.
68+
* Changed `compas.colors.Color.coerce` to take color as is, if it is already an instance of `compas.colors.Color`.
69+
* Changed `compas_rhino.conversions.surfaces.surface_to_compas` to work only with surface geometry.
70+
* Changed `compas_rhino.conversions.curves.curve_to_compas_line` to work only with geometry.
71+
* Changed `compas_rhino.conversions.curves.curve_to_compas_circle` to work only with geometry.
72+
* Changed `compas_rhino.conversions.curves.curve_to_compas_ellipse` to work only with geometry.
73+
* Changed `compas_rhino.conversions.curves.curve_to_compas_polyline` to work only with geometry.
74+
* Changed `compas_rhino.objects.get_point_coordinates` to deprecated (removed in v2.3).
75+
* Changed `compas_rhino.objects.get_line_coordinates` to deprecated (removed in v2.3).
76+
* Changed `compas_rhino.objects.get_polyline_coordinates` to deprecated (removed in v2.3).
77+
* Changed `compas_rhino.objects.get_polygon_coordinates` to deprecated (removed in v2.3).
78+
* Fixed a bug in `worldtransformation` of `compas.scene.SceneObject` to include the object's own frame.
79+
80+
### Removed
81+
82+
* Removed pluggable `compas.geometry.surfaces.surface.new_surface`.
83+
* Removed pluggable `compas.geometry.surfaces.surface.new_surface_from_plane`.
84+
* Removed `compas.geometry.surfaces.surface.Surface.from_plane`.
85+
* Removed `compas.geometry.surfaces.surface.ConicalSurface.__new__`.
86+
* Removed `compas.geometry.surfaces.surface.CylindricalSurface.__new__`.
87+
* Removed `compas.geometry.surfaces.surface.PlanarSurface.__new__`.
88+
* Removed `compas.geometry.surfaces.surface.SphericalSurface.__new__`.
89+
* Removed `compas.geometry.surfaces.surface.ToroidalSurface.__new__`.
90+
* Removed `compas.geometry.surfaces.nurbs.NurbsSurface.__init__`.
91+
* Removed `compas_rhino.geometry.surfaces.new_surface`.
92+
* Removed `compas_rhino.geometry.surfaces.new_nurbssurface`.
93+
* Removed `compas_rhino.geometry.surfaces.nurbs.NurbsSurface.__from_data__`.
94+
* Removed `compas_rhino.geometry.surfaces.surface.Surface.from_corners`.
95+
* Removed `compas_rhino.geometry.surfaces.surface.Surface.from_cylinder`.
96+
* Removed `compas_rhino.geometry.surfaces.surface.Surface.from_frame`.
97+
* Removed `compas_rhino.geometry.surfaces.surface.Surface.from_sphere`.
98+
* Removed `compas_rhino.geometry.surfaces.surface.Surface.from_torus`.
99+
* Removed `compas.geometry.curves.arc.Arc.__new__`.
100+
* Removed `compas.geometry.curves.bezier.Bezier.__new__`.
101+
* Removed `compas.geometry.curves.conic.Conic.__new__`.
102+
* Removed `compas.geometry.curves.polyline.Polyline.__new__`.
103+
* Removed `compas.geometry.curves.curve.new_curve`.
104+
* Removed `compas.geometry.curves.curve.new_nurbscurve`.
105+
* Removed `compas_rhino.geometry.curves.new_curve`.
106+
* Removed `compas_rhino.geometry.curves.new_nurbscurve`.
107+
* Removed `compas_rhino.conversions.surfaces.data_to_rhino_surface`.
108+
* Removed `compas_rhino.conversions.surfaces.surface_to_compas_data`.
109+
* Removed `compas_rhino.conversions.surfaces.surface_to_compas_quadmesh`.
110+
* Removed `compas_rhino.conversions.curves.curve_to_compas_data`.
111+
21112
## [2.2.1] 2024-06-25
22113

23114
### Added
@@ -28,7 +119,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
28119

29120
### Removed
30121

31-
32122
## [2.2.0] 2024-06-24
33123

34124
### Added

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# The COMPAS framework
22

33
![build](https://github.com/compas-dev/compas/workflows/build/badge.svg)
4+
[![codecov](https://codecov.io/github/compas-dev/compas/graph/badge.svg?token=wpkfew9szQ)](https://codecov.io/github/compas-dev/compas)
45
[![GitHub - License](https://img.shields.io/github/license/compas-dev/compas.svg)](https://github.com/compas-dev/compas)
56
[![Conda Downloads](https://img.shields.io/conda/dn/conda-forge/compas)](https://anaconda.org/conda-forge/compas)
67
[![pip downloads](https://img.shields.io/pypi/dm/compas)](https://pypi.python.org/project/COMPAS)
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
********************************************************************************
2+
Hash Tree
3+
********************************************************************************
4+
5+
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.
6+
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.
7+
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,
8+
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.
9+
10+
Hash Tree From Dict
11+
===================
12+
13+
A COMPAS hash tree can be created from any raw python dictionary using the `HashTree.from_dict` method.
14+
15+
>>> from compas.datastructures import HashTree
16+
>>> data = {'a': 1, 'b': 2, 'c': {'d': 3, 'e': 4}}
17+
>>> tree = HashTree.from_dict(data)
18+
19+
The structure of the hash tree and crypo hash on each node can be visualised using the `print` function.
20+
21+
>>> print(tree)
22+
<Tree with 6 nodes>
23+
└── ROOT @ b2e1c
24+
├── .a:1 @ 4d9a8
25+
├── .b:2 @ 82b86
26+
└── .c @ 664a3
27+
├── .d:3 @ 76d82
28+
└── .e:4 @ ebe84
29+
30+
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.
31+
32+
>>> data['c']['d'] = 5
33+
>>> del data["b"]
34+
>>> data["f"] = True
35+
>>> new_tree = HashTree.from_dict(data)
36+
>>> print(new_tree)
37+
<Tree with 6 nodes>
38+
└── ROOT @ a8c1b
39+
├── .a:1 @ 4d9a8
40+
├── .c @ e1701
41+
│ ├── .d:5 @ 98b1e
42+
│ └── .e:4 @ ebe84
43+
└── .f:True @ 753e5
44+
45+
>>> new_tree.diff(tree)
46+
{'added': [{'path': '.f', 'value': True}], 'removed': [{'path': '.b', 'value': 2}], 'modified': [{'path': '.c.d', 'old': 3, 'new': 5}]}
47+
48+
Hash Tree From COMPAS Data
49+
==========================
50+
51+
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.
52+
This is done by hashing the serilised data of the object.
53+
54+
>>> from compas.datastructures import Mesh
55+
>>> mesh = Mesh.from_polyhedron(6)
56+
>>> tree = HashTree.from_object(mesh)
57+
>>> print(tree)
58+
<Tree with 58 nodes>
59+
└── ROOT @ 44cc1
60+
├── .attributes @ 3370c
61+
├── .default_vertex_attributes @ 84700
62+
│ ├── .x:0.0 @ 5bc2d
63+
│ ├── .y:0.0 @ 1704b
64+
│ └── .z:0.0 @ 6199e
65+
├── .default_edge_attributes @ 5e834
66+
├── .default_face_attributes @ 5a8d9
67+
├── .vertex @ ff6d0
68+
│ ├── .0 @ 84ec1
69+
│ │ ├── .x:-1.1547005383792517 @ 874f4
70+
│ │ ├── .y:-1.1547005383792517 @ d2b16
71+
│ │ └── .z:-1.1547005383792517 @ bd9f0
72+
│ ├── .1 @ 316d3
73+
...
74+
75+
>>> mesh.vertex_attribute(0, "x", 1.0)
76+
>>> mesh.delete_face(3)
77+
>>> new_tree = HashTree.from_object(mesh)
78+
>>> new_tree.diff(tree)
79+
{'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}]}
80+

docs/userguide/basics.visualisation.rst

Lines changed: 28 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -64,28 +64,6 @@ For example, meshes can have different colors for the vertices, the edges, and t
6464
And the colors of vertices, edges, and faces can be specified individually, per element.
6565
See the section about mesh visualisation for more information.
6666

67-
Object Transformation
68-
=====================
69-
70-
All scene objects have a transformation matrix that can be used to transform the object in the visualisation,
71-
independently of the geometry of the underlying data object.
72-
The default transformation matrix is the identity matrix, which means that the visualised geometry is the same as the geometry represented by the data.
73-
74-
>>> sceneobj = scene.add(box)
75-
>>> sceneobj.transformation
76-
Transformation([[1.0, 0.0, 0.0, 0.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]])
77-
78-
The transformation matrix can be set using a COMPAS Transformation object, or a 4x4 nested list of floats.
79-
80-
>>> from compas.geometry import Translation
81-
>>> sceneobj.transformation = Translation.from_vector([1.0, 2.0, 3.0])
82-
>>> sceneobj.transformation
83-
Transformation([[1.0, 0.0, 0.0, 1.0], [0.0, 1.0, 0.0, 2.0], [0.0, 0.0, 1.0, 3.0], [0.0, 0.0, 0.0, 1.0]])
84-
85-
.. note::
86-
87-
For more information about working with transformations in COMPAS, see :doc:`basics.geometry.transformations`.
88-
8967
Scene Hierarchy
9068
===============
9169

@@ -115,6 +93,34 @@ To use a different scene object as the parent, the parent attribute of the scene
11593
>>> boxobj.parent
11694
PointObject
11795

96+
Object Frame And Transformation
97+
=====================
98+
99+
Every scene objects can have a reference "frame" that represents its local coordinate system relative to the frame of its hierarchical parent.
100+
In addition, an object can also have a local "transformation" which orientates this object from its frame.
101+
The final transformation of an object relative to the world coordinate system is the aggregated multiplication of all its hierarchical ancesters' frames,
102+
together with its own local frame and transformation. This prorperty can be accessed through the read-only attribute "worldtransformation".
103+
104+
>>> from compas.geometry import Translation
105+
>>> from compas.geometry import Box
106+
>>> from compas.geometry import Frame
107+
>>> sceneobj1 = scene.add(Box())
108+
>>> sceneobj1.frame = Frame(point = [1.0, 0.0, 0.0], xaxis=[1.0, 0.0, 0.0],yaxis=[0.0, 1.0, 0.0])
109+
>>> sceneobj1.transformation = Translation.from_vector([10.0, 0.0, 0.0])
110+
>>> sceneobj1.worldtransformation
111+
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)
112+
>>> sceneobj1.worldtransformation == sceneobj1.frame.to_transfromation() * sceneobj1.transformation
113+
True
114+
115+
The worldtransformation of a nestd "sceneobj2" will be calculated as: Frame of "sceneobj1" * Frame of "sceneobj2" * Transformation of "sceneobj2"
116+
>>> sceneobj2 = scene.add(Box(), parent=sceneobj1)
117+
>>> sceneobj2.frame = Frame([1.0, 1.0, 0.0], xaxis=[1.0, 0.0, 0.0],yaxis=[0.0, 1.0, 0.0])
118+
>>> sceneobj2.transformation = Translation.from_vector([10.0, 10.0, 0.0])
119+
>>> sceneobj.worldtransformation
120+
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)
121+
>>> sceneobj2.worldtransformation == sceneobj1.frame.to_transfromation() * sceneobj2.frame.to_transfrom() * sceneobj2.transformation
122+
True
123+
118124

119125
Scene Context
120126
=============

0 commit comments

Comments
 (0)