symcad.parts.composite.TorisphericalCapsule

  1#!/usr/bin/env python3
  2# Copyright (C) 2022, Will Hedgecock
  3#
  4# This program is free software: you can redistribute it and/or modify
  5# it under the terms of the GNU General Public License as published by
  6# the Free Software Foundation, either version 3 of the License, or
  7# (at your option) any later version.
  8#
  9# This program is distributed in the hope that it will be useful,
 10# but WITHOUT ANY WARRANTY; without even the implied warranty of
 11# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 12# GNU General Public License for more details.
 13#
 14# You should have received a copy of the GNU General Public License
 15# along with this program.  If not, see <http://www.gnu.org/licenses/>.
 16
 17from __future__ import annotations
 18from PyFreeCAD.FreeCAD import FreeCAD, Part
 19from typing import Dict, Optional, Tuple, Union
 20from sympy import Expr, Symbol, sqrt, cos, asin
 21from . import CompositeShape
 22import math
 23
 24class TorisphericalCapsule(CompositeShape):
 25   """Model representing a parameteric capsule with torispherical endcaps.
 26
 27   By default, the capsule is oriented such that the endcaps are aligned with the x-axis:
 28
 29   ![TorisphericalCapsule](https://symbench.github.io/SymCAD/images/TorisphericalCapsule.png)
 30
 31   The `geometry` of this shape includes the following parameters:
 32
 33   - `cylinder_radius`: Outer radius (in `m`) of the center cylindrical part of the Capsule
 34   - `cylinder_length`: Length (in `m`) of the center cylindrical part of the Capsule
 35   - `cylinder_thickness`: Thickness (in `m`) of the cylindrical shell of the Capsule
 36   - `endcap_thickness`: Thickness (in `m`) of the torispherical endcaps of the Capsule
 37   - `crown_ratio`: Ratio (in `%`) of the radius of the crown of the torispherical
 38                    endcap to the `cylinder_radius`
 39   - `knuckle_ratio`: Ratio (in `%`) of the radius of the knuckle of the torispherical
 40                      endcap to the `cylinder_radius`
 41
 42   Note that the above dimensions should be interpreted as if the capsule is unrotated. In other
 43   words, any shape rotation takes place *after* the capsule dimensions have been specified.
 44   """
 45
 46   # Constructor ----------------------------------------------------------------------------------
 47
 48   def __init__(self, identifier: str, material_density_kg_m3: Optional[float] = 1.0) -> None:
 49      """Initializes a parametric capsule object with torispherical endcaps.
 50
 51      Parameters
 52      ----------
 53      identifier : `str`
 54         Unique identifying name for the object.
 55      material_density_kg_m3 : `float`, optional, default=1.0
 56         Uniform material density in `kg/m^3` to be used in mass property calculations.
 57      """
 58      super().__init__(identifier, 'TorisphericalCapsule.FCStd', None, material_density_kg_m3)
 59      setattr(self.geometry, 'cylinder_radius', Symbol(self.name + '_cylinder_radius'))
 60      setattr(self.geometry, 'cylinder_length', Symbol(self.name + '_cylinder_length'))
 61      setattr(self.geometry, 'cylinder_thickness', Symbol(self.name + '_cylinder_thickness'))
 62      setattr(self.geometry, 'endcap_thickness', Symbol(self.name + '_endcap_thickness'))
 63      setattr(self.geometry, 'crown_ratio', Symbol(self.name + '_crown_ratio'))
 64      setattr(self.geometry, 'knuckle_ratio', Symbol(self.name + '_knuckle_ratio'))
 65
 66
 67   # Geometry setter ------------------------------------------------------------------------------
 68
 69   def set_geometry(self, *, cylinder_radius_m: Union[float, None],
 70                             cylinder_length_m: Union[float, None],
 71                             cylinder_thickness_m: Union[float, None],
 72                             endcap_thickness_m: Union[float, None],
 73                             crown_ratio_percent: Union[float, None] = 1.0,
 74                             knuckle_ratio_percent: Union[float, None] = 0.06) -> TorisphericalCapsule:
 75      """Sets the physical geometry of the current `TorisphericalCapsule` object.
 76
 77      See the `TorisphericalCapsule` class documentation for a description of each geometric
 78      parameter.
 79      """
 80      if crown_ratio_percent is not None and crown_ratio_percent > 1.0:
 81         raise ValueError('crown_ratio_percent ({}) is not a percentage between 0.0 - 1.0'
 82                          .format(crown_ratio_percent))
 83      if knuckle_ratio_percent is not None and (knuckle_ratio_percent < 0.06 or
 84                                                knuckle_ratio_percent > 1.0):
 85         raise ValueError('knuckle_ratio_percent ({}) is not a percentage between 0.06 - 1.0'
 86                          .format(knuckle_ratio_percent))
 87      self.geometry.set(cylinder_radius=cylinder_radius_m,
 88                        cylinder_length=cylinder_length_m,
 89                        cylinder_thickness=cylinder_thickness_m,
 90                        endcap_thickness=endcap_thickness_m,
 91                        crown_ratio=crown_ratio_percent,
 92                        knuckle_ratio=knuckle_ratio_percent)
 93      return self
 94
 95   def get_geometric_parameter_bounds(self, parameter: str) -> Tuple[float, float]:
 96      parameter_bounds = {
 97         'cylinder_radius': (0.01, 2.0),
 98         'cylinder_length': (0.01, 2.0),
 99         'cylinder_thickness': (0.001, 0.05),
100         'endcap_thickness': (0.001, 0.05),
101         'crown_ratio': (0.0, 1.0),
102         'knuckle_ratio': (0.06, 1.0)
103      }
104      return parameter_bounds.get(parameter, (0.0, 0.0))
105
106
107   # Geometric properties -------------------------------------------------------------------------
108
109   @property
110   def material_volume(self) -> Union[float, Expr]:
111      knuckle_radius = (2.0 * self.geometry.knuckle_ratio * self.geometry.cylinder_radius) - \
112                       self.geometry.endcap_thickness
113      crown_radius = (2.0 * self.geometry.crown_ratio * self.geometry.cylinder_radius) - \
114                     self.geometry.endcap_thickness
115      c = self.geometry.cylinder_radius - self.geometry.endcap_thickness - knuckle_radius
116      h = crown_radius - sqrt((knuckle_radius + c - crown_radius) *
117                              (knuckle_radius - c - crown_radius))
118      volume = self.displaced_volume
119      volume -= ((math.pi / 3.0) * \
120                 ((2.0 * h * crown_radius**2) -
121                  (((2.0 * knuckle_radius**2) + c**2 +
122                    (2.0 * knuckle_radius * crown_radius)) * (crown_radius - h)) +
123                  (3.0 * knuckle_radius**2 * c *
124                         asin((crown_radius - h) / (crown_radius - knuckle_radius)))))
125      volume -= (math.pi
126                 * (self.geometry.cylinder_radius - self.geometry.cylinder_thickness)**2
127                 * self.geometry.cylinder_length)
128      return volume
129
130   @property
131   def displaced_volume(self) -> Union[float, Expr]:
132      knuckle_radius = 2.0 * self.geometry.knuckle_ratio * self.geometry.cylinder_radius
133      crown_radius = 2.0 * self.geometry.crown_ratio * self.geometry.cylinder_radius
134      c = self.geometry.cylinder_radius - knuckle_radius
135      h = crown_radius - sqrt((knuckle_radius + c - crown_radius) *
136                              (knuckle_radius - c - crown_radius))
137      endcap_volume = (math.pi / 3.0) * \
138                      ((2.0 * h * crown_radius**2) -
139                       (((2.0 * knuckle_radius**2) + c**2 +
140                         (2.0 * knuckle_radius * crown_radius)) * (crown_radius - h)) +
141                       (3.0 * knuckle_radius**2 * c *
142                              asin((crown_radius - h) / (crown_radius - knuckle_radius))))
143      return (math.pi * self.geometry.cylinder_radius**2 * self.geometry.cylinder_length) + \
144             (2.0 * endcap_volume)
145
146   @property
147   def surface_area(self) -> Union[float, Expr]:
148      knuckle_radius = 2.0 * self.geometry.knuckle_ratio * self.geometry.cylinder_radius
149      crown_radius = 2.0 * self.geometry.crown_ratio * self.geometry.cylinder_radius
150      cos_alpha = cos(asin((1.0 - (2.0 * self.geometry.knuckle_ratio)) /
151                           (2.0 * (self.geometry.crown_ratio - self.geometry.knuckle_ratio))))
152      a2 = knuckle_radius * cos_alpha
153      endcap_area = (4.0 * math.pi * crown_radius**2 * (1.0 - cos_alpha)) + \
154                    (4.0 * math.pi * knuckle_radius *
155                       (a2 + ((self.geometry.cylinder_radius - knuckle_radius) * asin(cos_alpha))))
156      return (2.0 * math.pi * self.geometry.cylinder_radius * self.geometry.cylinder_length) + \
157             endcap_area
158
159   @property
160   def unoriented_center_of_gravity(self) -> Tuple[Union[float, Expr],
161                                                   Union[float, Expr],
162                                                   Union[float, Expr]]:
163      return (0.5 * self.unoriented_length,
164              0.5 * self.unoriented_width,
165              0.5 * self.unoriented_height)
166
167   @property
168   def unoriented_center_of_buoyancy(self) -> Tuple[Union[float, Expr],
169                                                    Union[float, Expr],
170                                                    Union[float, Expr]]:
171      return self.unoriented_center_of_gravity
172
173   @property
174   def unoriented_length(self) -> Union[float, Expr]:
175      knuckle_radius = 2.0 * self.geometry.knuckle_ratio * self.geometry.cylinder_radius
176      crown_radius = 2.0 * self.geometry.crown_ratio * self.geometry.cylinder_radius
177      c = self.geometry.cylinder_radius - knuckle_radius
178      endcap_length = crown_radius - sqrt((knuckle_radius + c - crown_radius) *
179                                          (knuckle_radius - c - crown_radius))
180      return (2.0 * endcap_length) + self.geometry.cylinder_length
181
182   @property
183   def unoriented_width(self) -> Union[float, Expr]:
184      return 2.0 * self.geometry.cylinder_radius
185
186   @property
187   def unoriented_height(self) -> Union[float, Expr]:
188      return self.unoriented_width
189
190   @property
191   def oriented_length(self) -> Union[float, Expr]:
192      # TODO: Implement this
193      return 0
194
195   @property
196   def oriented_width(self) -> Union[float, Expr]:
197      # TODO: Implement this
198      return 0
199
200   @property
201   def oriented_height(self) -> Union[float, Expr]:
202      # TODO: Implement this
203      return 0
class TorisphericalCapsule(symcad.parts.composite.CompositeShape):
 25class TorisphericalCapsule(CompositeShape):
 26   """Model representing a parameteric capsule with torispherical endcaps.
 27
 28   By default, the capsule is oriented such that the endcaps are aligned with the x-axis:
 29
 30   ![TorisphericalCapsule](https://symbench.github.io/SymCAD/images/TorisphericalCapsule.png)
 31
 32   The `geometry` of this shape includes the following parameters:
 33
 34   - `cylinder_radius`: Outer radius (in `m`) of the center cylindrical part of the Capsule
 35   - `cylinder_length`: Length (in `m`) of the center cylindrical part of the Capsule
 36   - `cylinder_thickness`: Thickness (in `m`) of the cylindrical shell of the Capsule
 37   - `endcap_thickness`: Thickness (in `m`) of the torispherical endcaps of the Capsule
 38   - `crown_ratio`: Ratio (in `%`) of the radius of the crown of the torispherical
 39                    endcap to the `cylinder_radius`
 40   - `knuckle_ratio`: Ratio (in `%`) of the radius of the knuckle of the torispherical
 41                      endcap to the `cylinder_radius`
 42
 43   Note that the above dimensions should be interpreted as if the capsule is unrotated. In other
 44   words, any shape rotation takes place *after* the capsule dimensions have been specified.
 45   """
 46
 47   # Constructor ----------------------------------------------------------------------------------
 48
 49   def __init__(self, identifier: str, material_density_kg_m3: Optional[float] = 1.0) -> None:
 50      """Initializes a parametric capsule object with torispherical endcaps.
 51
 52      Parameters
 53      ----------
 54      identifier : `str`
 55         Unique identifying name for the object.
 56      material_density_kg_m3 : `float`, optional, default=1.0
 57         Uniform material density in `kg/m^3` to be used in mass property calculations.
 58      """
 59      super().__init__(identifier, 'TorisphericalCapsule.FCStd', None, material_density_kg_m3)
 60      setattr(self.geometry, 'cylinder_radius', Symbol(self.name + '_cylinder_radius'))
 61      setattr(self.geometry, 'cylinder_length', Symbol(self.name + '_cylinder_length'))
 62      setattr(self.geometry, 'cylinder_thickness', Symbol(self.name + '_cylinder_thickness'))
 63      setattr(self.geometry, 'endcap_thickness', Symbol(self.name + '_endcap_thickness'))
 64      setattr(self.geometry, 'crown_ratio', Symbol(self.name + '_crown_ratio'))
 65      setattr(self.geometry, 'knuckle_ratio', Symbol(self.name + '_knuckle_ratio'))
 66
 67
 68   # Geometry setter ------------------------------------------------------------------------------
 69
 70   def set_geometry(self, *, cylinder_radius_m: Union[float, None],
 71                             cylinder_length_m: Union[float, None],
 72                             cylinder_thickness_m: Union[float, None],
 73                             endcap_thickness_m: Union[float, None],
 74                             crown_ratio_percent: Union[float, None] = 1.0,
 75                             knuckle_ratio_percent: Union[float, None] = 0.06) -> TorisphericalCapsule:
 76      """Sets the physical geometry of the current `TorisphericalCapsule` object.
 77
 78      See the `TorisphericalCapsule` class documentation for a description of each geometric
 79      parameter.
 80      """
 81      if crown_ratio_percent is not None and crown_ratio_percent > 1.0:
 82         raise ValueError('crown_ratio_percent ({}) is not a percentage between 0.0 - 1.0'
 83                          .format(crown_ratio_percent))
 84      if knuckle_ratio_percent is not None and (knuckle_ratio_percent < 0.06 or
 85                                                knuckle_ratio_percent > 1.0):
 86         raise ValueError('knuckle_ratio_percent ({}) is not a percentage between 0.06 - 1.0'
 87                          .format(knuckle_ratio_percent))
 88      self.geometry.set(cylinder_radius=cylinder_radius_m,
 89                        cylinder_length=cylinder_length_m,
 90                        cylinder_thickness=cylinder_thickness_m,
 91                        endcap_thickness=endcap_thickness_m,
 92                        crown_ratio=crown_ratio_percent,
 93                        knuckle_ratio=knuckle_ratio_percent)
 94      return self
 95
 96   def get_geometric_parameter_bounds(self, parameter: str) -> Tuple[float, float]:
 97      parameter_bounds = {
 98         'cylinder_radius': (0.01, 2.0),
 99         'cylinder_length': (0.01, 2.0),
100         'cylinder_thickness': (0.001, 0.05),
101         'endcap_thickness': (0.001, 0.05),
102         'crown_ratio': (0.0, 1.0),
103         'knuckle_ratio': (0.06, 1.0)
104      }
105      return parameter_bounds.get(parameter, (0.0, 0.0))
106
107
108   # Geometric properties -------------------------------------------------------------------------
109
110   @property
111   def material_volume(self) -> Union[float, Expr]:
112      knuckle_radius = (2.0 * self.geometry.knuckle_ratio * self.geometry.cylinder_radius) - \
113                       self.geometry.endcap_thickness
114      crown_radius = (2.0 * self.geometry.crown_ratio * self.geometry.cylinder_radius) - \
115                     self.geometry.endcap_thickness
116      c = self.geometry.cylinder_radius - self.geometry.endcap_thickness - knuckle_radius
117      h = crown_radius - sqrt((knuckle_radius + c - crown_radius) *
118                              (knuckle_radius - c - crown_radius))
119      volume = self.displaced_volume
120      volume -= ((math.pi / 3.0) * \
121                 ((2.0 * h * crown_radius**2) -
122                  (((2.0 * knuckle_radius**2) + c**2 +
123                    (2.0 * knuckle_radius * crown_radius)) * (crown_radius - h)) +
124                  (3.0 * knuckle_radius**2 * c *
125                         asin((crown_radius - h) / (crown_radius - knuckle_radius)))))
126      volume -= (math.pi
127                 * (self.geometry.cylinder_radius - self.geometry.cylinder_thickness)**2
128                 * self.geometry.cylinder_length)
129      return volume
130
131   @property
132   def displaced_volume(self) -> Union[float, Expr]:
133      knuckle_radius = 2.0 * self.geometry.knuckle_ratio * self.geometry.cylinder_radius
134      crown_radius = 2.0 * self.geometry.crown_ratio * self.geometry.cylinder_radius
135      c = self.geometry.cylinder_radius - knuckle_radius
136      h = crown_radius - sqrt((knuckle_radius + c - crown_radius) *
137                              (knuckle_radius - c - crown_radius))
138      endcap_volume = (math.pi / 3.0) * \
139                      ((2.0 * h * crown_radius**2) -
140                       (((2.0 * knuckle_radius**2) + c**2 +
141                         (2.0 * knuckle_radius * crown_radius)) * (crown_radius - h)) +
142                       (3.0 * knuckle_radius**2 * c *
143                              asin((crown_radius - h) / (crown_radius - knuckle_radius))))
144      return (math.pi * self.geometry.cylinder_radius**2 * self.geometry.cylinder_length) + \
145             (2.0 * endcap_volume)
146
147   @property
148   def surface_area(self) -> Union[float, Expr]:
149      knuckle_radius = 2.0 * self.geometry.knuckle_ratio * self.geometry.cylinder_radius
150      crown_radius = 2.0 * self.geometry.crown_ratio * self.geometry.cylinder_radius
151      cos_alpha = cos(asin((1.0 - (2.0 * self.geometry.knuckle_ratio)) /
152                           (2.0 * (self.geometry.crown_ratio - self.geometry.knuckle_ratio))))
153      a2 = knuckle_radius * cos_alpha
154      endcap_area = (4.0 * math.pi * crown_radius**2 * (1.0 - cos_alpha)) + \
155                    (4.0 * math.pi * knuckle_radius *
156                       (a2 + ((self.geometry.cylinder_radius - knuckle_radius) * asin(cos_alpha))))
157      return (2.0 * math.pi * self.geometry.cylinder_radius * self.geometry.cylinder_length) + \
158             endcap_area
159
160   @property
161   def unoriented_center_of_gravity(self) -> Tuple[Union[float, Expr],
162                                                   Union[float, Expr],
163                                                   Union[float, Expr]]:
164      return (0.5 * self.unoriented_length,
165              0.5 * self.unoriented_width,
166              0.5 * self.unoriented_height)
167
168   @property
169   def unoriented_center_of_buoyancy(self) -> Tuple[Union[float, Expr],
170                                                    Union[float, Expr],
171                                                    Union[float, Expr]]:
172      return self.unoriented_center_of_gravity
173
174   @property
175   def unoriented_length(self) -> Union[float, Expr]:
176      knuckle_radius = 2.0 * self.geometry.knuckle_ratio * self.geometry.cylinder_radius
177      crown_radius = 2.0 * self.geometry.crown_ratio * self.geometry.cylinder_radius
178      c = self.geometry.cylinder_radius - knuckle_radius
179      endcap_length = crown_radius - sqrt((knuckle_radius + c - crown_radius) *
180                                          (knuckle_radius - c - crown_radius))
181      return (2.0 * endcap_length) + self.geometry.cylinder_length
182
183   @property
184   def unoriented_width(self) -> Union[float, Expr]:
185      return 2.0 * self.geometry.cylinder_radius
186
187   @property
188   def unoriented_height(self) -> Union[float, Expr]:
189      return self.unoriented_width
190
191   @property
192   def oriented_length(self) -> Union[float, Expr]:
193      # TODO: Implement this
194      return 0
195
196   @property
197   def oriented_width(self) -> Union[float, Expr]:
198      # TODO: Implement this
199      return 0
200
201   @property
202   def oriented_height(self) -> Union[float, Expr]:
203      # TODO: Implement this
204      return 0

Model representing a parameteric capsule with torispherical endcaps.

By default, the capsule is oriented such that the endcaps are aligned with the x-axis:

TorisphericalCapsule

The geometry of this shape includes the following parameters:

  • cylinder_radius: Outer radius (in m) of the center cylindrical part of the Capsule
  • cylinder_length: Length (in m) of the center cylindrical part of the Capsule
  • cylinder_thickness: Thickness (in m) of the cylindrical shell of the Capsule
  • endcap_thickness: Thickness (in m) of the torispherical endcaps of the Capsule
  • crown_ratio: Ratio (in %) of the radius of the crown of the torispherical endcap to the cylinder_radius
  • knuckle_ratio: Ratio (in %) of the radius of the knuckle of the torispherical endcap to the cylinder_radius

Note that the above dimensions should be interpreted as if the capsule is unrotated. In other words, any shape rotation takes place after the capsule dimensions have been specified.

TorisphericalCapsule(identifier: str, material_density_kg_m3: Optional[float] = 1.0)
49   def __init__(self, identifier: str, material_density_kg_m3: Optional[float] = 1.0) -> None:
50      """Initializes a parametric capsule object with torispherical endcaps.
51
52      Parameters
53      ----------
54      identifier : `str`
55         Unique identifying name for the object.
56      material_density_kg_m3 : `float`, optional, default=1.0
57         Uniform material density in `kg/m^3` to be used in mass property calculations.
58      """
59      super().__init__(identifier, 'TorisphericalCapsule.FCStd', None, material_density_kg_m3)
60      setattr(self.geometry, 'cylinder_radius', Symbol(self.name + '_cylinder_radius'))
61      setattr(self.geometry, 'cylinder_length', Symbol(self.name + '_cylinder_length'))
62      setattr(self.geometry, 'cylinder_thickness', Symbol(self.name + '_cylinder_thickness'))
63      setattr(self.geometry, 'endcap_thickness', Symbol(self.name + '_endcap_thickness'))
64      setattr(self.geometry, 'crown_ratio', Symbol(self.name + '_crown_ratio'))
65      setattr(self.geometry, 'knuckle_ratio', Symbol(self.name + '_knuckle_ratio'))

Initializes a parametric capsule object with torispherical endcaps.

Parameters
  • identifier (str): Unique identifying name for the object.
  • material_density_kg_m3 (float, optional, default=1.0): Uniform material density in kg/m^3 to be used in mass property calculations.
def set_geometry( self, *, cylinder_radius_m: Optional[float], cylinder_length_m: Optional[float], cylinder_thickness_m: Optional[float], endcap_thickness_m: Optional[float], crown_ratio_percent: Optional[float] = 1.0, knuckle_ratio_percent: Optional[float] = 0.06) -> TorisphericalCapsule:
70   def set_geometry(self, *, cylinder_radius_m: Union[float, None],
71                             cylinder_length_m: Union[float, None],
72                             cylinder_thickness_m: Union[float, None],
73                             endcap_thickness_m: Union[float, None],
74                             crown_ratio_percent: Union[float, None] = 1.0,
75                             knuckle_ratio_percent: Union[float, None] = 0.06) -> TorisphericalCapsule:
76      """Sets the physical geometry of the current `TorisphericalCapsule` object.
77
78      See the `TorisphericalCapsule` class documentation for a description of each geometric
79      parameter.
80      """
81      if crown_ratio_percent is not None and crown_ratio_percent > 1.0:
82         raise ValueError('crown_ratio_percent ({}) is not a percentage between 0.0 - 1.0'
83                          .format(crown_ratio_percent))
84      if knuckle_ratio_percent is not None and (knuckle_ratio_percent < 0.06 or
85                                                knuckle_ratio_percent > 1.0):
86         raise ValueError('knuckle_ratio_percent ({}) is not a percentage between 0.06 - 1.0'
87                          .format(knuckle_ratio_percent))
88      self.geometry.set(cylinder_radius=cylinder_radius_m,
89                        cylinder_length=cylinder_length_m,
90                        cylinder_thickness=cylinder_thickness_m,
91                        endcap_thickness=endcap_thickness_m,
92                        crown_ratio=crown_ratio_percent,
93                        knuckle_ratio=knuckle_ratio_percent)
94      return self

Sets the physical geometry of the current TorisphericalCapsule object.

See the TorisphericalCapsule class documentation for a description of each geometric parameter.

def get_geometric_parameter_bounds(self, parameter: str) -> Tuple[float, float]:
 96   def get_geometric_parameter_bounds(self, parameter: str) -> Tuple[float, float]:
 97      parameter_bounds = {
 98         'cylinder_radius': (0.01, 2.0),
 99         'cylinder_length': (0.01, 2.0),
100         'cylinder_thickness': (0.001, 0.05),
101         'endcap_thickness': (0.001, 0.05),
102         'crown_ratio': (0.0, 1.0),
103         'knuckle_ratio': (0.06, 1.0)
104      }
105      return parameter_bounds.get(parameter, (0.0, 0.0))

Abstract method that must be overridden by a concrete SymPart class to return the minimum and maximum expected bounds for a given geometric parameter.

Parameters
  • parameter (str): Name of the geometric parameter for which to return the minimum and maximum bounds.
Returns
  • Tuple[float, float]: Minimum and maximum bounds for the specified geometric parameter.
material_volume: Union[float, sympy.core.expr.Expr]

Material volume (in m^3) of the SymPart (read-only).

displaced_volume: Union[float, sympy.core.expr.Expr]

Displaced volume (in m^3) of the SymPart (read-only).

surface_area: Union[float, sympy.core.expr.Expr]

Surface/wetted area (in m^2) of the SymPart (read-only).

unoriented_center_of_gravity: Tuple[Union[float, sympy.core.expr.Expr], Union[float, sympy.core.expr.Expr], Union[float, sympy.core.expr.Expr]]

Center of gravity (in m) of the unoriented SymPart (read-only).

unoriented_center_of_buoyancy: Tuple[Union[float, sympy.core.expr.Expr], Union[float, sympy.core.expr.Expr], Union[float, sympy.core.expr.Expr]]

Center of buoyancy (in m) of the unoriented SymPart (read-only).

unoriented_length: Union[float, sympy.core.expr.Expr]

X-axis length (in m) of the bounding box of the unoriented SymPart (read-only).

unoriented_width: Union[float, sympy.core.expr.Expr]

Y-axis width (in m) of the bounding box of the unoriented SymPart (read-only).

unoriented_height: Union[float, sympy.core.expr.Expr]

Z-axis height (in m) of the bounding box of the unoriented SymPart (read-only).

oriented_length: Union[float, sympy.core.expr.Expr]

X-axis length (in m) of the bounding box of the oriented SymPart (read-only).

oriented_width: Union[float, sympy.core.expr.Expr]

Y-axis length (in m) of the bounding box of the oriented SymPart (read-only).

oriented_height: Union[float, sympy.core.expr.Expr]

Z-axis length (in m) of the bounding box of the oriented SymPart (read-only).