Skip to content

Commit 67f52ea

Browse files
authored
Merge pull request #1415 from compas-dev/frame-inversion
Frame inversion
2 parents 347e5ec + cadad46 commit 67f52ea

File tree

6 files changed

+68
-5
lines changed

6 files changed

+68
-5
lines changed

CHANGELOG.md

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1010
### Added
1111

1212
* Added implementation of `RhinoBrep.fillet()` and `RhinoBrep.filleted()` to `compas_rhino`.
13+
* Added `Frame.invert` and `Frame.inverted`.
14+
* Added `Frame.flip` and `Frame.flipped` as alias for invert and inverted.
15+
* Added `Vector.flip` and `Vector.flipped` as alias for invert and inverted.
1316

1417
### Changed
1518

1619
* Fixed `native_edge` property of `RhinoBrepEdge`.
20+
* Expose the parameters `radius` and `nmax` from `compas.topology._face_adjacency` to `compas.topology.face_adjacency` and further propagate them to `unify_cycles` and `Mesh.unify_cycles`.
21+
* Modify `face_adjacency` to avoid using `compas.topology._face_adjacency` by default when there are more than 100 faces, unless one of the parameters `radius`, `nmax` is passed.
22+
* Changed `unify_cycles` to use the first face in the list as root if no root is provided.
1723

1824
### Removed
1925

@@ -32,8 +38,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
3238
### Changed
3339

3440
* Fixed `PluginNotInstalledError` when using `Brep.from_boolean_*` in Rhino.
35-
* Expose the parameters `radius` and `nmax` from `compas.topology._face_adjacency` to `compas.topology.face_adjacency` and further propagate them to `unify_cycles` and `Mesh.unify_cycles`.
36-
* Modify `face_adjacency` to avoid using `compas.topology._face_adjacency` by default when there are more than 100 faces, unless one of the parameters `radius`, `nmax` is passed
3741
* Added support for `Polyline` as input for `compas_rhino.Brep.from_extrusion`.
3842

3943
### Removed

src/compas/geometry/frame.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -604,6 +604,21 @@ def to_transformation(self):
604604
# Methods
605605
# ==========================================================================
606606

607+
def invert(self):
608+
"""Invert the frame while keeping the X axis fixed."""
609+
self._yaxis = self.yaxis * -1
610+
self._zaxis = None
611+
612+
flip = invert
613+
614+
def inverted(self):
615+
"""Return an inverted copy of the frame."""
616+
frame = self.copy() # type: Frame
617+
frame.invert()
618+
return frame
619+
620+
flipped = inverted
621+
607622
def interpolate_frame(self, other, t):
608623
"""Interpolates between two frames at a given parameter t in the range [0, 1]
609624

src/compas/geometry/vector.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -679,6 +679,8 @@ def invert(self):
679679
"""
680680
self.scale(-1.0)
681681

682+
flip = invert
683+
682684
def inverted(self):
683685
"""Returns a inverted copy of this vector
684686
@@ -697,6 +699,8 @@ def inverted(self):
697699
"""
698700
return self.scaled(-1.0)
699701

702+
flipped = inverted
703+
700704
def scale(self, n):
701705
"""Scale this vector by a factor n.
702706

src/compas/topology/orientation.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@
22
from __future__ import division
33
from __future__ import print_function
44

5-
import random
6-
75
from compas.geometry import centroid_points
86
from compas.itertools import pairwise
97
from compas.topology import breadth_first_traverse
@@ -193,6 +191,11 @@ def unify_cycles(vertices, faces, root=None, nmax=None, max_distance=None):
193191
Exception
194192
If no all faces are included in the unnification process.
195193
194+
Notes
195+
-----
196+
The cycles of the faces will be aligned with the cycle direction of the root face.
197+
If no root face is specified, the first face in the list will be used.
198+
196199
"""
197200

198201
def unify(node, nbr):
@@ -210,7 +213,8 @@ def unify(node, nbr):
210213
return
211214

212215
if root is None:
213-
root = random.choice(list(range(len(faces))))
216+
# root = random.choice(list(range(len(faces))))
217+
root = 0
214218

215219
adj = face_adjacency(vertices, faces, nmax=nmax, max_distance=max_distance) # this is the only place where the vertex coordinates are used
216220

tests/compas/geometry/test_frame.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,3 +92,35 @@ def test_interpolate_frame_start_end():
9292

9393
three_quarter_frame = frame1.interpolate_frame(frame2, 0.75)
9494
assert TOL.is_allclose([math.degrees(three_quarter_frame.axis_angle_vector.y)], [-67.5], atol=TOL.angular)
95+
96+
97+
def test_frame_invert():
98+
frame = Frame([0, 0, 0])
99+
100+
assert TOL.is_close(frame.xaxis.dot([1, 0, 0]), 1.0)
101+
assert TOL.is_close(frame.yaxis.dot([0, 1, 0]), 1.0)
102+
assert TOL.is_close(frame.zaxis.dot([0, 0, 1]), 1.0)
103+
104+
frame.invert()
105+
106+
assert TOL.is_close(frame.xaxis.dot([1, 0, 0]), 1.0)
107+
assert TOL.is_close(frame.yaxis.dot([0, -1, 0]), 1.0)
108+
assert TOL.is_close(frame.zaxis.dot([0, 0, -1]), 1.0)
109+
110+
111+
def test_frame_inverted():
112+
frame = Frame([0, 0, 0])
113+
114+
assert TOL.is_close(frame.xaxis.dot([1, 0, 0]), 1.0)
115+
assert TOL.is_close(frame.yaxis.dot([0, 1, 0]), 1.0)
116+
assert TOL.is_close(frame.zaxis.dot([0, 0, 1]), 1.0)
117+
118+
other = frame.inverted()
119+
120+
assert TOL.is_close(frame.xaxis.dot([1, 0, 0]), 1.0)
121+
assert TOL.is_close(frame.yaxis.dot([0, 1, 0]), 1.0)
122+
assert TOL.is_close(frame.zaxis.dot([0, 0, 1]), 1.0)
123+
124+
assert TOL.is_close(other.xaxis.dot([1, 0, 0]), 1.0)
125+
assert TOL.is_close(other.yaxis.dot([0, -1, 0]), 1.0)
126+
assert TOL.is_close(other.zaxis.dot([0, 0, -1]), 1.0)

tests/compas/topology/test_unify_cycles.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
def test_unify_cycles():
1515
if compas.IPY:
1616
return
17+
1718
test_data = compas.json_load(os.path.join(HERE, "..", "fixtures", "topology", "vertices_faces.json"))
1819
vertices = test_data["vertices"]
1920
faces = test_data["faces"]
@@ -25,12 +26,15 @@ def test_unify_cycles():
2526
# no parameters
2627
unify_cycles(vertices, faces)
2728
assert TOL.is_close(volume, volume_polyhedron((vertices, faces)))
29+
2830
# only max_nbrs
2931
unify_cycles(vertices, faces, nmax=max_nbrs)
3032
assert TOL.is_close(volume, volume_polyhedron((vertices, faces)))
33+
3134
# only max_distance
3235
unify_cycles(vertices, faces, max_distance=max_edge_length)
3336
assert TOL.is_close(volume, volume_polyhedron((vertices, faces)))
37+
3438
# both parameters
3539
unify_cycles(vertices, faces, nmax=max_nbrs, max_distance=max_edge_length)
3640
assert TOL.is_close(volume, volume_polyhedron((vertices, faces)))

0 commit comments

Comments
 (0)