Skip to content

Commit

Permalink
Add connections to Junctions and Cells
Browse files Browse the repository at this point in the history
  • Loading branch information
FranzBangar committed Jul 9, 2024
1 parent 8a08ecd commit 104b303
Show file tree
Hide file tree
Showing 5 changed files with 67 additions and 18 deletions.
22 changes: 13 additions & 9 deletions src/classy_blocks/optimize/cell.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import abc
from typing import ClassVar, Dict, List, Optional, Set
from typing import ClassVar, Dict, List, Optional, Set, Tuple

import numpy as np

from classy_blocks.optimize.connection import CellConnection
from classy_blocks.types import IndexType, NPPointListType, NPPointType, OrientType
from classy_blocks.util import functions as f
from classy_blocks.util.constants import EDGE_PAIRS, FACE_MAP, VSMALL
Expand All @@ -15,6 +16,7 @@ class NoCommonSidesError(Exception):
class CellBase(abc.ABC):
side_names: ClassVar[List[str]]
side_indexes: ClassVar[List[IndexType]]
edge_pairs: ClassVar[List[Tuple[int, int]]]

def __init__(self, grid_points: NPPointListType, indexes: IndexType):
self.grid_points = grid_points
Expand All @@ -28,6 +30,7 @@ def __init__(self, grid_points: NPPointListType, indexes: IndexType):
"front": None,
"back": None,
}
self.connections = [CellConnection(set(pair), {indexes[pair[0]], indexes[pair[1]]}) for pair in self.edge_pairs]

def get_common_indexes(self, candidate: "CellBase") -> Set[int]:
"""Returns indexes of common vertices between this and provided cell"""
Expand Down Expand Up @@ -83,13 +86,14 @@ def center(self) -> NPPointType:
return np.average(self.points, axis=0)

@property
def face_points(self) -> NPPointListType:
def side_points(self) -> NPPointListType:
"""In 2D, a 'side' is a line segment but in 3D it is a quadrangle"""
return np.take(self.points, self.side_indexes, axis=0)

@property
def face_centers(self) -> NPPointListType:
def side_centers(self) -> NPPointListType:
"""Center point of each face"""
return np.average(self.face_points, axis=1)
return np.average(self.side_points, axis=1)

@property
def quality(self) -> float:
Expand All @@ -112,8 +116,8 @@ def q_scale(base, exponent, factor, value):
### non-orthogonality
# angles between faces and self.center-neighbour.center or, if there's no neighbour
# on this face, between face and self.center-face_center
face_points = self.face_points[i]
face_center = self.face_centers[i]
face_points = self.side_points[i]
face_center = self.side_centers[i]

side_1 = face_points - face_center
side_2 = np.roll(face_points, -1, axis=0) - face_center
Expand Down Expand Up @@ -165,11 +169,10 @@ def min_length(self) -> float:


class QuadCell(CellBase):
# FACE_MAP, ordered and modified so that all faces point towards cell center;
# provided their points are visited in an anti-clockwise manner
# names and indexes must correspond (both must be in the same order)
# Like constants.FACE_MAP but for quadrangle sides as line segments
side_names: ClassVar = ["front", "right", "back", "left"]
side_indexes: ClassVar = [[0, 1], [1, 2], [2, 3], [3, 0]]
edge_pairs: ClassVar = [(0, 1), (1, 2), (2, 3), (3, 0)]

@property
def min_length(self) -> float:
Expand All @@ -188,6 +191,7 @@ class HexCell(CellBase):
# names and indexes must correspond (both must be in the same order)
side_names: ClassVar = ["bottom", "top", "left", "right", "front", "back"]
side_indexes: ClassVar = [[0, 1, 2, 3], [7, 6, 5, 4], [4, 0, 3, 7], [6, 2, 1, 5], [0, 4, 5, 1], [7, 3, 2, 6]]
edge_pairs: ClassVar = EDGE_PAIRS

@property
def min_length(self) -> float:
Expand Down
11 changes: 11 additions & 0 deletions src/classy_blocks/optimize/connection.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import dataclasses
from typing import Set


@dataclasses.dataclass
class CellConnection:
"""A connection between two points;
they are refered by indexes rather than positions"""

corners: Set[int] # cell-local indexes
indexes: Set[int]
25 changes: 16 additions & 9 deletions src/classy_blocks/optimize/grid.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,23 +27,30 @@ def __init__(self, points: NPPointListType, addressing: List[IndexType]):
# new numpy arrays for every calculation
self.points = points

self.cells = [self.cell_class(self.points, indexes) for indexes in addressing]
self.junctions = [Junction(self.points, index) for index in range(len(self.points))]
self.cells = [self.cell_class(self.points, indexes) for indexes in addressing]

self._bind_junctions()
self._bind_neighbours()
self._bind_cell_neighbours()
self._bind_junction_cells()
self._bind_junction_connections()

def _bind_junctions(self) -> None:
def _bind_cell_neighbours(self) -> None:
"""Adds neighbours to cells"""
for cell_1 in self.cells:
for cell_2 in self.cells:
cell_1.add_neighbour(cell_2)

def _bind_junction_cells(self) -> None:
"""Adds cells to junctions"""
for cell in self.cells:
for junction in self.junctions:
junction.add_cell(cell)

def _bind_neighbours(self) -> None:
"""Adds neighbours to cells"""
for cell_1 in self.cells:
for cell_2 in self.cells:
cell_1.add_neighbour(cell_2)
def _bind_junction_connections(self) -> None:
"""Adds connections to junctions"""
for junction_1 in self.junctions:
for junction_2 in self.junctions:
junction_1.add_connection(junction_2)

def get_junction_from_clamp(self, clamp: ClampBase) -> Junction:
for junction in self.junctions:
Expand Down
23 changes: 23 additions & 0 deletions src/classy_blocks/optimize/junction.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ class ClampExistsError(Exception):

@dataclasses.dataclass
class IndexedLink:
# TODO: refactor / deuglify
link: LinkBase
follower_index: int

Expand All @@ -24,8 +25,11 @@ class Junction:
def __init__(self, points: NPPointListType, index: int):
self.points = points
self.index = index

self.cells: Set[CellBase] = set()

self.connections: List[Junction] = []

self.clamp: Optional[ClampBase] = None
self.links: List[IndexedLink] = []

Expand All @@ -41,6 +45,25 @@ def add_cell(self, cell: CellBase) -> None:
self.cells.add(cell)
return

def add_connection(self, to: "Junction") -> bool:
"""Returns True if this Junction is connected to passed one"""
if to == self:
return False

# if any of connections within a cell is equal to
# the connection between these two junctions,
# they are connected
junction_indexes = {self.index, to.index}

for cell in self.cells:
for connection in cell.connections:
if connection.indexes == junction_indexes:
if to not in self.connections:
self.connections.append(to)
return True

return False

def add_clamp(self, clamp: ClampBase) -> None:
if self.clamp is not None:
raise ClampExistsError(f"Clamp already defined for junction {self.index}")
Expand Down
4 changes: 4 additions & 0 deletions tests/test_modify/test_grid.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,7 @@ def test_junction_cells(self, index, count):
@parameterized.expand(((0, "right", 1), (1, "left", 0), (1, "back", 2), (2, "front", 1)))
def test_cell_neighbours(self, parent, orient, neighbour):
self.assertEqual(self.grid.cells[parent].neighbours[orient], self.grid.cells[neighbour])

@parameterized.expand(((0, 3), (1, 4), (2, 5), (3, 3)))
def test_connections(self, junction, count):
self.assertEqual(len(self.grid.junctions[junction].connections), count)

0 comments on commit 104b303

Please sign in to comment.