Skip to content

Commit 5ae3904

Browse files
committed
Feat: Added ability for Geometry.align_center() and CompoundGeometry.align_center() to align to a x, y coordinate; Tests: Added tests for Geometry.align_center()
1 parent 359cc43 commit 5ae3904

File tree

2 files changed

+53
-6
lines changed

2 files changed

+53
-6
lines changed

sectionproperties/pre/geometry.py

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -493,17 +493,30 @@ def align_center(self, align_to: Optional[Geometry] = None):
493493
:rtype: :class:`~sectionproperties.pre.geometry.Geometry`
494494
"""
495495
cx, cy = list(self.geom.centroid.coords)[0]
496-
# Suggested by Agent 6-6-6: Hard-rounding of cx and cy allows
496+
# Suggested by @Agent6-6-6: Hard-rounding of cx and cy allows
497497
# for greater precision in placing geometry with its centroid
498498
# near [0, 0]. True [0, 0] placement will not be possible due
499499
# to floating point errors.
500500
if align_to is None:
501501
shift_x, shift_y = round(-cx, self.tol), round(-cy, self.tol)
502502

503-
else:
503+
elif isinstance(align_to, Geometry):
504504
align_cx, align_cy = list(align_to.geom.centroid.coords)[0]
505505
shift_x = round(align_cx - cx, self.tol)
506506
shift_y = round(align_cy - cy, self.tol)
507+
508+
else:
509+
try:
510+
point_x, point_y = align_to
511+
shift_x = round(point_x - cx, self.tol)
512+
shift_y = round(point_y - cy, self.tol)
513+
except (
514+
TypeError,
515+
ValueError,
516+
): # align_to not subscriptable, incorrect length, etc.
517+
raise ValueError(
518+
f"align_to must be either a Geometry object or an x, y coordinate, not {align_to}."
519+
)
507520
new_geom = self.shift_section(x_offset=shift_x, y_offset=shift_y)
508521
return new_geom
509522

@@ -1555,7 +1568,9 @@ def mirror_section(
15551568
new_geom = CompoundGeometry(geoms_acc)
15561569
return new_geom
15571570

1558-
def align_center(self, align_to: Optional[Geometry] = None):
1571+
def align_center(
1572+
self, align_to: Optional[Union[Geometry, List[float, float]]] = None
1573+
):
15591574
"""
15601575
Returns a new CompoundGeometry object, translated in both x and y, so that the
15611576
center-point of the new object's material-weighted centroid will be aligned with
@@ -1567,8 +1582,8 @@ def align_center(self, align_to: Optional[Geometry] = None):
15671582
of the compound geometry is calculated by using the E modulus of each
15681583
geometry's assigned material.
15691584
1570-
:param align_to: Another Geometry to align to or None (default is None)
1571-
:type align_to: Optional[:class:`~sectionproperties.pre.geometry.Geometry`]
1585+
:param align_to: Another Geometry to align to, an xy coordinate, or None (default is None)
1586+
:type align_to: Optional[:class:`~sectionproperties.pre.geometry.Geometry`, List[float, float]]
15721587
15731588
:return: Geometry object translated to new alignment
15741589
:rtype: :class:`~sectionproperties.pre.geometry.Geometry`
@@ -1597,10 +1612,21 @@ def align_center(self, align_to: Optional[Geometry] = None):
15971612
round(-weighted_cy, self.tol),
15981613
)
15991614

1600-
else:
1615+
elif isinstance(Geometry):
16011616
align_cx, align_cy = list(align_to.geom.centroid.coords)[0]
16021617
shift_x = round(align_cx - weighted_cx, self.tol)
16031618
shift_y = round(align_cy - weighted_cy, self.tol)
1619+
1620+
else:
1621+
try:
1622+
point_x, point_y = align_to
1623+
shift_x = round(point_x - weighted_cx, self.tol)
1624+
shift_y = round(point_y - weighted_cy, self.tol)
1625+
except (TypeError, ValueError):
1626+
raise ValueError(
1627+
f"align_to must be either a Geometry object or an x, y coordinate, not {align_to}."
1628+
)
1629+
16041630
new_geom = self.shift_section(x_offset=shift_x, y_offset=shift_y)
16051631
return new_geom
16061632

sectionproperties/tests/test_sections.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -532,3 +532,24 @@ def test_warping_disjoint_warning():
532532
sec.calculate_geometric_properties()
533533
with pytest.warns(UserWarning):
534534
sec.calculate_warping_properties()
535+
536+
537+
def test_align_center():
538+
rect = rectangular_section(d=200, b=70)
539+
circ = circular_section(d=200, n=30)
540+
rect = rect.rotate_section(-45, rot_point=[0, 0])
541+
rect_point = rect.points[1]
542+
circ = circ.align_center(rect_point)
543+
circ_x, circ_y = circ.calculate_centroid()
544+
assert pytest.approx(circ_x) == 49.497474683057995
545+
assert pytest.approx(circ_y) == -49.49747468305799
546+
547+
circ = circ.align_center()
548+
circ_x, circ_y = circ.calculate_centroid()
549+
assert pytest.approx(circ_x) == 0
550+
assert pytest.approx(circ_y) == 0
551+
552+
circ = circ.align_center(rect)
553+
circ_x, circ_y = circ.calculate_centroid()
554+
assert pytest.approx(circ_x) == 95.45941546018399
555+
assert pytest.approx(circ_y) == 45.961940777125974

0 commit comments

Comments
 (0)