|
1 | 1 | from __future__ import annotations |
2 | 2 | from ntpath import join |
3 | | -from typing import List, Optional, Union, Tuple, Any |
| 3 | +from typing import List, Optional, Union, Tuple, List, Any |
4 | 4 |
|
5 | 5 | import copy |
6 | 6 | import math |
@@ -479,31 +479,47 @@ def align_to( |
479 | 479 |
|
480 | 480 | return new_geom |
481 | 481 |
|
482 | | - def align_center(self, align_to: Optional[Geometry] = None): |
| 482 | + def align_center( |
| 483 | + self, align_to: Optional[Union[Geometry, Tuple[float, float]]] = None |
| 484 | + ): |
483 | 485 | """ |
484 | 486 | Returns a new Geometry object, translated in both x and y, so that the |
485 | | - center-point of the new object's centroid will be aligned with |
486 | | - centroid of the object in 'align_to'. If 'align_to' is None then the new |
487 | | - object will be aligned with it's centroid at the origin. |
| 487 | + the new object's centroid will be aligned with the centroid of the object |
| 488 | + in 'align_to'. If 'align_to' is an x, y coordinate, then the centroid will |
| 489 | + be aligned to the coordinate. If 'align_to' is None then the new |
| 490 | + object will be aligned with its centroid at the origin. |
488 | 491 |
|
489 | 492 | :param align_to: Another Geometry to align to or None (default is None) |
490 | | - :type align_to: Optional[:class:`~sectionproperties.pre.geometry.Geometry`] |
| 493 | + :type align_to: Optional[Union[:class:`~sectionproperties.pre.geometry.Geometry`, Tuple[float, float]]] |
491 | 494 |
|
492 | 495 | :return: Geometry object translated to new alignment |
493 | 496 | :rtype: :class:`~sectionproperties.pre.geometry.Geometry` |
494 | 497 | """ |
495 | 498 | cx, cy = list(self.geom.centroid.coords)[0] |
496 | | - # Suggested by Agent 6-6-6: Hard-rounding of cx and cy allows |
| 499 | + # Suggested by @Agent6-6-6: Hard-rounding of cx and cy allows |
497 | 500 | # for greater precision in placing geometry with its centroid |
498 | 501 | # near [0, 0]. True [0, 0] placement will not be possible due |
499 | 502 | # to floating point errors. |
500 | 503 | if align_to is None: |
501 | 504 | shift_x, shift_y = round(-cx, self.tol), round(-cy, self.tol) |
502 | 505 |
|
503 | | - else: |
| 506 | + elif isinstance(align_to, Geometry): |
504 | 507 | align_cx, align_cy = list(align_to.geom.centroid.coords)[0] |
505 | 508 | shift_x = round(align_cx - cx, self.tol) |
506 | 509 | shift_y = round(align_cy - cy, self.tol) |
| 510 | + |
| 511 | + else: |
| 512 | + try: |
| 513 | + point_x, point_y = align_to |
| 514 | + shift_x = round(point_x - cx, self.tol) |
| 515 | + shift_y = round(point_y - cy, self.tol) |
| 516 | + except ( |
| 517 | + TypeError, |
| 518 | + ValueError, |
| 519 | + ): # align_to not subscriptable, incorrect length, etc. |
| 520 | + raise ValueError( |
| 521 | + f"align_to must be either a Geometry object or an x, y coordinate, not {align_to}." |
| 522 | + ) |
507 | 523 | new_geom = self.shift_section(x_offset=shift_x, y_offset=shift_y) |
508 | 524 | return new_geom |
509 | 525 |
|
@@ -1555,20 +1571,23 @@ def mirror_section( |
1555 | 1571 | new_geom = CompoundGeometry(geoms_acc) |
1556 | 1572 | return new_geom |
1557 | 1573 |
|
1558 | | - def align_center(self, align_to: Optional[Geometry] = None): |
| 1574 | + def align_center( |
| 1575 | + self, align_to: Optional[Union[Geometry, Tuple[float, float]]] = None |
| 1576 | + ): |
1559 | 1577 | """ |
1560 | 1578 | Returns a new CompoundGeometry object, translated in both x and y, so that the |
1561 | 1579 | center-point of the new object's material-weighted centroid will be aligned with |
1562 | | - centroid of the object in 'align_to'. If 'align_to' is None then the new |
1563 | | - object will be aligned with it's centroid at the origin. |
| 1580 | + centroid of the object in 'align_to'. If 'align_to' is an x, y coordinate, then |
| 1581 | + the centroid will be aligned to the coordinate. If 'align_to' is None then the new |
| 1582 | + object will be aligned with its centroid at the origin. |
1564 | 1583 |
|
1565 | 1584 | Note: The material-weighted centroid refers to when individual geometries within |
1566 | 1585 | the CompoundGeometry object have been assigned differing materials. The centroid |
1567 | 1586 | of the compound geometry is calculated by using the E modulus of each |
1568 | 1587 | geometry's assigned material. |
1569 | 1588 |
|
1570 | | - :param align_to: Another Geometry to align to or None (default is None) |
1571 | | - :type align_to: Optional[:class:`~sectionproperties.pre.geometry.Geometry`] |
| 1589 | + :param align_to: Another Geometry to align to, an xy coordinate, or None (default is None) |
| 1590 | + :type align_to: Optional[Union[:class:`~sectionproperties.pre.geometry.Geometry`, Tuple[float, float]]] |
1572 | 1591 |
|
1573 | 1592 | :return: Geometry object translated to new alignment |
1574 | 1593 | :rtype: :class:`~sectionproperties.pre.geometry.Geometry` |
@@ -1597,10 +1616,21 @@ def align_center(self, align_to: Optional[Geometry] = None): |
1597 | 1616 | round(-weighted_cy, self.tol), |
1598 | 1617 | ) |
1599 | 1618 |
|
1600 | | - else: |
| 1619 | + elif isinstance(Geometry): |
1601 | 1620 | align_cx, align_cy = list(align_to.geom.centroid.coords)[0] |
1602 | 1621 | shift_x = round(align_cx - weighted_cx, self.tol) |
1603 | 1622 | shift_y = round(align_cy - weighted_cy, self.tol) |
| 1623 | + |
| 1624 | + else: |
| 1625 | + try: |
| 1626 | + point_x, point_y = align_to |
| 1627 | + shift_x = round(point_x - weighted_cx, self.tol) |
| 1628 | + shift_y = round(point_y - weighted_cy, self.tol) |
| 1629 | + except (TypeError, ValueError): |
| 1630 | + raise ValueError( |
| 1631 | + f"align_to must be either a Geometry object or an x, y coordinate, not {align_to}." |
| 1632 | + ) |
| 1633 | + |
1604 | 1634 | new_geom = self.shift_section(x_offset=shift_x, y_offset=shift_y) |
1605 | 1635 | return new_geom |
1606 | 1636 |
|
|
0 commit comments