-
Notifications
You must be signed in to change notification settings - Fork 38
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'development' of github.com:damogranlabs/classy_blocks i…
…nto development
- Loading branch information
Showing
9 changed files
with
214 additions
and
64 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
import os | ||
|
||
import numpy as np | ||
|
||
import classy_blocks as cb | ||
|
||
box_1 = cb.Box([-1, -1, -1], [1, 1, 1]) | ||
box_2 = box_1.copy().rotate(np.pi / 4, [1, 1, 1], [0, 0, 0]).translate([4, 2, 0]) | ||
|
||
for i in range(3): | ||
box_1.chop(i, count=10) | ||
box_2.chop(i, count=10) | ||
|
||
|
||
connector = cb.Connector(box_1, box_2) | ||
connector.chop(2, count=10) | ||
|
||
mesh = cb.Mesh() | ||
mesh.add(box_1) | ||
mesh.add(box_2) | ||
mesh.add(connector) | ||
mesh.set_default_patch("walls", "wall") | ||
|
||
mesh.write(os.path.join("..", "case", "system", "blockMeshDict"), debug_path="debug.vtk") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
from typing import List | ||
|
||
import numpy as np | ||
|
||
from classy_blocks.construct.flat.face import Face | ||
from classy_blocks.construct.operations.operation import Operation | ||
from classy_blocks.modify.reorient.viewpoint import ViewpointReorienter | ||
from classy_blocks.util import functions as f | ||
|
||
|
||
class FacePair: | ||
def __init__(self, face_1: Face, face_2: Face): | ||
self.face_1 = face_1 | ||
self.face_2 = face_2 | ||
|
||
@property | ||
def distance(self) -> float: | ||
"""Returns distance between two faces' centers""" | ||
return f.norm(self.face_1.center - self.face_2.center) | ||
|
||
@property | ||
def alignment(self) -> float: | ||
"""Returns a scalar number that is a measure of how well the | ||
two faces are aligned, a.k.a. how well their normals align""" | ||
vconn = f.unit_vector(self.face_2.center - self.face_1.center) | ||
return np.dot(vconn, self.face_1.normal) ** 3 + np.dot(-vconn, self.face_2.normal) ** 3 | ||
|
||
|
||
class Connector(Operation): | ||
"""A normal Loft but automatically finds and reorders appropriate faces between | ||
two arbitrary given blocks. | ||
The recipe is as follows: | ||
1. Find a pair of faces whose normals are most nicely aligned | ||
2. Create a loft that connects them | ||
3. Reorder the loft so that is is properly oriented | ||
The following limitations apply: | ||
"Closest faces" might be an ill-defined term; for example, | ||
imagine two boxes: | ||
___ | ||
| 2 | | ||
|___| | ||
___ | ||
| 1 | | ||
|___| | ||
Here, multiple different faces can be found. | ||
Reordering relies on ViewpointReorienter; see the documentation on that | ||
for its limitations. | ||
Resulting loft will have the bottom face coincident with operation_1 | ||
and top face with operation_2. | ||
Axis 2 is always between the two operations but axes 0 and 1 | ||
depend on positions of operations and is not exactly defined. | ||
To somewhat alleviate this confusion it is | ||
recommended to chop operation 1 or 2 in axes 0 and 1 and | ||
only provide chopping for axis 2 of connector.""" | ||
|
||
def __init__(self, operation_1: Operation, operation_2: Operation): | ||
self.operation_1 = operation_1 | ||
self.operation_2 = operation_2 | ||
|
||
all_pairs: List[FacePair] = [] | ||
for orient_1, face_1 in operation_1.get_all_faces().items(): | ||
if orient_1 in ("bottom", "left", "front"): | ||
face_1.invert() | ||
for orient_2, face_2 in operation_2.get_all_faces().items(): | ||
if orient_2 in ("bottom", "left", "front"): | ||
face_2.invert() | ||
all_pairs.append(FacePair(face_1, face_2)) | ||
|
||
all_pairs.sort(key=lambda pair: pair.distance) | ||
all_pairs = all_pairs[:9] | ||
all_pairs.sort(key=lambda pair: pair.alignment) | ||
|
||
start_face = all_pairs[-1].face_1 | ||
end_face = all_pairs[-1].face_2 | ||
|
||
super().__init__(start_face, end_face) | ||
|
||
viewpoint = operation_1.center + 2 * (operation_1.top_face.center - operation_1.bottom_face.center) | ||
ceiling = operation_1.center + 2 * (operation_2.center - operation_1.center) | ||
reorienter = ViewpointReorienter(viewpoint, ceiling) | ||
reorienter.reorient(self) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
import unittest | ||
|
||
import numpy as np | ||
|
||
from classy_blocks.construct.operations.box import Box | ||
from classy_blocks.construct.operations.connector import Connector | ||
|
||
|
||
class ConnectorTests(unittest.TestCase): | ||
def setUp(self): | ||
# basic box, center at origin | ||
self.box_1 = Box([-0.5, -0.5, -0.5], [0.5, 0.5, 0.5]) | ||
# a 'nicely' positioned box | ||
self.box_2 = self.box_1.copy().rotate(np.pi / 2, [0, 0, 1], [0, 0, 0]).translate([2, 0, 0]) | ||
# an ugly box a.k.a. border case | ||
# self.box_3 | ||
|
||
def test_create_normal(self): | ||
_ = Connector(self.box_1, self.box_2) | ||
|
||
def test_create_inverted(self): | ||
_ = Connector(self.box_2, self.box_1) | ||
|
||
def test_direction(self): | ||
connector = Connector(self.box_1, self.box_2) | ||
|
||
box_vector = self.box_2.center - self.box_1.center | ||
connector_vector = connector.top_face.center - connector.bottom_face.center | ||
|
||
self.assertGreater(np.dot(box_vector, connector_vector), 0) | ||
|
||
def test_direction_inverted(self): | ||
connector = Connector(self.box_2, self.box_1) | ||
|
||
box_vector = self.box_2.center - self.box_1.center | ||
connector_vector = connector.top_face.center - connector.bottom_face.center | ||
|
||
self.assertLess(np.dot(box_vector, connector_vector), 0) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters