Skip to content

Commit aa1763d

Browse files
committed
Merge remote-tracking branch 'origin/main'
2 parents cd2905a + 6e7f7c0 commit aa1763d

File tree

6 files changed

+1428
-0
lines changed

6 files changed

+1428
-0
lines changed

CHANGELOG.md

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,46 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
99

1010
### Added
1111

12+
* Added comprehensive form diagram creation methods to `FormDiagram` class:
13+
* `create_cross()` - Creates cross discretisation with orthogonal arrangement and quad diagonals
14+
* `create_fan()` - Creates fan discretisation with straight lines to corners
15+
* `create_parametric_fan()` - Creates parametric fan diagrams with lambda parameter control
16+
* `create_cross_with_diagonal()` - Creates cross discretisation with diagonal lines
17+
* `create_ortho()` - Creates orthogonal discretisation
18+
* `create_circular_radial()` - Creates circular radial form diagrams with equally spaced hoops
19+
* `create_circular_radial_spaced()` - Creates circular radial form diagrams with hemispheric spacing
20+
* `create_circular_spiral()` - Creates circular spiral form diagrams
21+
* `create_arch()` - Creates arch form diagrams with semicircular projection
22+
* `create_arch_equally_spaced()` - Creates arch form diagrams with equally spaced nodes
23+
* Added support assignment methods:
24+
* `assign_support_type()` - Assigns supports based on type ("corners" or "all")
25+
* Added corner detection functionality:
26+
* `corner_vertices()` - Identifies corner vertices on boundary with configurable angle threshold
27+
* Added comprehensive mesh creation functions in `diagram_rectangular.py`:
28+
* `create_cross_mesh()` - Creates cross pattern meshes
29+
* `create_fan_mesh()` - Creates fan pattern meshes
30+
* `create_parametric_fan_mesh()` - Creates parametric fan meshes with lambda interpolation
31+
* `create_cross_with_diagonal_mesh()` - Creates cross meshes with diagonals
32+
* `create_ortho_mesh()` - Creates orthogonal grid meshes
33+
* Added circular mesh creation functions in `diagram_circular.py`:
34+
* `create_circular_radial_mesh()` - Creates circular radial meshes
35+
* `create_circular_radial_spaced_mesh()` - Creates hemispherically spaced circular meshes
36+
* `create_circular_spiral_mesh()` - Creates circular spiral meshes
37+
* Added arch mesh creation functions in `diagram_arch.py`:
38+
* `create_arch_linear_mesh()` - Creates arch meshes with semicircular projection
39+
* `create_arch_linear_equally_spaced_mesh()` - Creates arch meshes with equally spaced nodes
40+
1241
### Changed
1342

43+
* Refactored parameter passing from `xy_span=[[x0, x1], [y0, y1]]` to `x_span=(x0, x1), y_span=(y0, y1)` for better API consistency
44+
* Changed `center` parameter from list to tuple in circular diagram functions for immutability and consistency
45+
* Updated function signatures to use single-line format for Black compatibility
46+
* Improved code formatting and linting across all diagram generation files
47+
* Fixed various spelling errors and documentation formatting issues
48+
* Renamed `create_delta_form()` to `create_cross_with_diagonal()` for better clarity
49+
* Updated support assignment to use `is_support` attribute instead of deprecated `is_fixed`
50+
* Removed deprecated `form.parameters` usage from all form creation methods
51+
1452
### Removed
1553

1654

src/compas_tna/diagrams/diagram.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,37 @@
11
from compas.datastructures import Mesh
2+
from compas.geometry import angle_vectors
23

34

45
class Diagram(Mesh):
56
"""Base diagram implementing attributes shared between the form and force diagram."""
7+
8+
def corner_vertices(self, tol=160):
9+
"""Identify the corner vertices on the boundary.
10+
11+
Parameters
12+
----------
13+
tol : float, optional
14+
The threshold value for the angle in degrees formed between two edges
15+
at a vertex on the boundary for it to be considered a corner.
16+
Vertices with smaller angles than the threshold are considered a corner.
17+
18+
Returns
19+
-------
20+
vertices : list[int]
21+
The list of vertices filtered as corners.
22+
23+
"""
24+
vertices = []
25+
for vertex in self.vertices_on_boundary():
26+
if self.vertex_degree(vertex) == 2:
27+
vertices.append(vertex)
28+
else:
29+
nbrs = []
30+
for nbr in self.vertex_neighbors(vertex):
31+
if self.is_edge_on_boundary((vertex, nbr)):
32+
nbrs.append(nbr)
33+
u = self.edge_vector((vertex, nbrs[0]))
34+
v = self.edge_vector((vertex, nbrs[1]))
35+
if angle_vectors(u, v, deg=True) < tol:
36+
vertices.append(vertex)
37+
return vertices
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
import math
2+
3+
from compas.datastructures import Mesh
4+
5+
6+
def create_arch_linear_mesh(H: float = 1.0, L: float = 2.0, x0: float = 0.0, n: int = 100) -> Mesh:
7+
"""Construct a Mesh based on an arch linear discretisation.
8+
Note: The nodes of the mesh are spaced following a projection in a semicircular arch.
9+
10+
Parameters
11+
----------
12+
H : float, optional
13+
Height of the arch, by default 1.0
14+
L : float, optional
15+
Span of the arch, by default 2.0
16+
x0 : float, optional
17+
Initial coordinate of the arch, by default 0.0
18+
n : int, optional
19+
Numbers of nodes to be considered in the mesh, by default 100
20+
21+
Returns
22+
-------
23+
mesh : Mesh
24+
The Mesh created.
25+
26+
"""
27+
if n < 2:
28+
raise ValueError("n must be at least 2 to create a valid mesh")
29+
if H <= 0 or L <= 0:
30+
raise ValueError("Height (H) and length (L) must be positive values")
31+
if L < 2 * H:
32+
raise ValueError("Length (L) must be greater than 2 * Height (H)")
33+
34+
# Add option for starting from Hi and Li for a given thk.
35+
radius = H / 2 + (L**2 / (8 * H))
36+
spr = math.atan2((L / 2), (radius - H))
37+
tot_angle = 2 * spr
38+
angle_init = (math.pi - tot_angle) / 2
39+
an = tot_angle / (n - 1)
40+
41+
lines = []
42+
43+
for i in range(n - 1):
44+
angle_i = angle_init + i * an
45+
angle_f = angle_init + (i + 1) * an
46+
xi = L / 2 - radius * math.cos(angle_i) + x0
47+
xf = L / 2 - radius * math.cos(angle_f) + x0
48+
49+
lines.append([[xi, 0.0, 0.0], [xf, 0.0, 0.0]])
50+
51+
mesh = Mesh.from_lines(lines)
52+
53+
return mesh
54+
55+
56+
def create_arch_linear_equally_spaced_mesh(L: float = 2.0, x0: float = 0.0, n: int = 100) -> Mesh:
57+
"""Construct a Mesh based on an arch linear discretisation with equally spaced nodes.
58+
59+
Parameters
60+
----------
61+
L : float, optional
62+
Span of the arch, by default 2.0
63+
x0 : float, optional
64+
Initial coordinate of the arch, by default 0.0
65+
n : int, optional
66+
Numbers of nodes to be considered in the mesh, by default 100
67+
68+
Returns
69+
-------
70+
mesh : Mesh
71+
The Mesh created.
72+
73+
"""
74+
if n < 2:
75+
raise ValueError("n must be at least 2 to create a valid mesh")
76+
if L <= 0:
77+
raise ValueError("Length (L) must be a positive value")
78+
79+
# Equally spaced coordinates
80+
x = [x0 + i * L / (n - 1) for i in range(n)]
81+
lines = []
82+
83+
for i in range(n - 1):
84+
xi = x[i]
85+
xf = x[i + 1]
86+
87+
lines.append([[xi, 0.0, 0.0], [xf, 0.0, 0.0]])
88+
89+
mesh = Mesh.from_lines(lines)
90+
91+
return mesh

0 commit comments

Comments
 (0)