symcad.parts.composite.PlanarAirfoils

  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, sin, cos
 21from . import CompositeShape
 22import math
 23
 24class PlanarAirfoils(CompositeShape):
 25   """Model representing a set of planar parameteric airfoils.
 26
 27   By default, the airfoils are oriented in the following configuration:
 28
 29   ![PlanarAirfoils](https://symbench.github.io/SymCAD/images/PlanarAirfoils.png)
 30
 31   The `geometry` of this shape includes the following parameters:
 32
 33   - `max_thickness`: Maximum thickness (in `% of length`) of each airfoil
 34   - `chord_length`: Length (in `m`) of the chord of each airfoil
 35   - `span`: Width (in `m`) of each airfoil
 36   - `separation_radius`: Radius (in `m`) of separation between each airfoil
 37   - `curvature_tilt`: Amount of tilt (in `deg`) of each airfoil
 38
 39   Note that the above dimensions should be interpreted as if the airfoils are unrotated. In other
 40   words, any shape rotation takes place *after* the airfoil dimensions have been specified.
 41   """
 42
 43   # Constructor ----------------------------------------------------------------------------------
 44
 45   def __init__(self, identifier: str, material_density_kg_m3: Optional[float] = 1.0) -> None:
 46      """Initializes a planar parametric airfoil object.
 47
 48      Parameters
 49      ----------
 50      identifier : `str`
 51         Unique identifying name for the object.
 52      material_density_kg_m3 : `float`, optional, default=1.0
 53         Uniform material density in `kg/m^3` to be used in mass property calculations.
 54      """
 55      super().__init__(identifier, self.__create_cad__, None, material_density_kg_m3)
 56      setattr(self.geometry, 'max_thickness', Symbol(self.name + '_max_thickness'))
 57      setattr(self.geometry, 'chord_length', Symbol(self.name + '_chord_length'))
 58      setattr(self.geometry, 'span', Symbol(self.name + '_span'))
 59      setattr(self.geometry, 'separation_radius', Symbol(self.name + '_separation_radius'))
 60      setattr(self.geometry, 'curvature_tilt', Symbol(self.name + '_curvature_tilt'))
 61
 62
 63   # CAD generation function ----------------------------------------------------------------------
 64
 65   @staticmethod
 66   def z_val(x: float, max_thickness: float, chord_length: float) -> float:
 67      return 5.0 * max_thickness * chord_length * (
 68         (0.2969 * x**0.5) - (0.1260 * x) - (0.3516 * x**2) + (0.2843 * x**3) - (0.1036 * x**4))
 69
 70   @staticmethod
 71   def __create_cad__(params: Dict[str, float], _fully_displace: bool) -> Part.Solid:
 72      """Scripted CAD generation method for `PlanarAirfoils`."""
 73      doc = FreeCAD.newDocument('Temp')
 74      max_thickness_percent = params['max_thickness']
 75      chord_length_mm = 1000.0 * params['chord_length']
 76      span_mm = 1000.0 * params['span']
 77      separation_radius_mm = 1000.0 * params['separation_radius']
 78      curvature_tilt = params['curvature_tilt']
 79      x, points_upper, points_lower = 0.0, [], []
 80      while x <= 1.009:
 81         points_upper.append(FreeCAD.Vector(x * chord_length_mm,
 82                                            PlanarAirfoils.z_val(x, max_thickness_percent,
 83                                                                    chord_length_mm)))
 84         points_lower.append(FreeCAD.Vector(x * chord_length_mm,
 85                                            -PlanarAirfoils.z_val(x, max_thickness_percent,
 86                                                                     chord_length_mm)))
 87         x += 0.01
 88      bodies = []
 89      for i in range(2):
 90         body = doc.addObject('PartDesign::Body','Airfoil' + str(i))
 91         sketch = doc.addObject('Sketcher::SketchObject', 'Sketch' + str(i))
 92         sketch.Support = doc.XZ_Plane
 93         sketch.MapMode = 'FlatFace'
 94         body.addObject(sketch)
 95         sketch.addGeometry(Part.BSplineCurve(points_upper, None, None,
 96                                              False, 3, None, False), False)
 97         sketch.addGeometry(Part.BSplineCurve(points_lower, None, None,
 98                                              False, 3, None, False), False)
 99         pad = doc.addObject('PartDesign::Pad', 'Pad' + str(i))
100         body.addObject(pad)
101         pad.Length = int(span_mm)
102         pad.Profile = sketch
103         placement_vector = \
104            FreeCAD.Vector(0, -separation_radius_mm if i == 0 else separation_radius_mm, 0)
105         body.Placement = \
106            FreeCAD.Placement(placement_vector,
107                              FreeCAD.Rotation(-curvature_tilt if i == 1 else curvature_tilt,
108                                                0, i * 180.0))
109         bodies.append(body)
110      fusion = doc.addObject('Part::MultiFuse', 'Fusion')
111      fusion.Shapes = bodies
112      doc.recompute()
113      airfoils = fusion.Shape
114      FreeCAD.closeDocument(doc.Name)
115      return airfoils
116
117
118   # Geometry setter ------------------------------------------------------------------------------
119
120   def set_geometry(self, *, max_thickness_percent: Union[float, None],
121                             chord_length_m: Union[float, None],
122                             span_m: Union[float, None],
123                             separation_radius_m: Union[float, None],
124                             curvature_tilt_deg: Union[float, None]) -> PlanarAirfoils:
125      """Sets the physical geometry of the current `PlanarAirfoils` object.
126
127      See the `PlanarAirfoils` class documentation for a description of each geometric
128      parameter.
129      """
130      self.geometry.set(max_thickness=max_thickness_percent,
131                        chord_length=chord_length_m,
132                        span=span_m,
133                        separation_radius=separation_radius_m,
134                        curvature_tilt=curvature_tilt_deg)
135      return self
136
137   def get_geometric_parameter_bounds(self, parameter: str) -> Tuple[float, float]:
138      parameter_bounds = {
139         'max_thickness': (0.01, 0.90),
140         'chord_length': (0.1, 2.0),
141         'span': (0.0, 2.0),
142         'separation_radius': (0.0, 1.5),
143         'curvature_tilt': (0.0, 45.0)
144      }
145      return parameter_bounds.get(parameter, (0.0, 0.0))
146
147
148   # Geometric properties -------------------------------------------------------------------------
149
150   @property
151   def material_volume(self) -> Union[float, Expr]:
152      return self.displaced_volume
153
154   @property
155   def displaced_volume(self) -> Union[float, Expr]:
156      x, points_upper = 0.0, []
157      while x <= 1.009:
158         points_upper.append((x * self.geometry.chord_length,
159                              PlanarAirfoils.z_val(x, self.geometry.max_thickness,
160                                                      self.geometry.chord_length)))
161         x += 0.01
162      area = 0.0
163      for i in range(1, len(points_upper) - 1):
164         area += points_upper[i][1]
165      area = points_upper[0][1] + (2.0 * area) + points_upper[len(points_upper)-1][1]
166      h = (points_upper[len(points_upper)-1][0] - points_upper[0][0]) / (len(points_upper) - 1)
167      return 2.0 * h * area * self.geometry.span
168
169   @property
170   def surface_area(self) -> Union[float, Expr]:
171      x, points_upper = 0.0, []
172      while x <= 1.009:
173         points_upper.append((x * self.geometry.chord_length,
174                              PlanarAirfoils.z_val(x, self.geometry.max_thickness,
175                                                      self.geometry.chord_length)))
176         x += 0.01
177      area = 0.0
178      for i in range(1, len(points_upper)):
179         x_diff = (points_upper[i][0] - points_upper[i-1][0])
180         y_diff = (points_upper[i][1] - points_upper[i-1][1])
181         area += sqrt(x_diff**2 + y_diff**2)
182      area = (2.0 * area) * self.geometry.span
183      return 2.0 * area
184
185   @property
186   def unoriented_center_of_gravity(self) -> Tuple[Union[float, Expr],
187                                                   Union[float, Expr],
188                                                   Union[float, Expr]]:
189      cosine = cos(self.geometry.curvature_tilt * math.pi / 180.0)
190      sine = sin(self.geometry.curvature_tilt * math.pi / 180.0)
191      return ((0.41 * cosine * self.geometry.chord_length) + (0.5 * sine * self.geometry.span),
192              0.5 * self.unoriented_width,
193              0.5 * self.unoriented_height)
194
195   @property
196   def unoriented_center_of_buoyancy(self) -> Tuple[Union[float, Expr],
197                                                    Union[float, Expr],
198                                                    Union[float, Expr]]:
199      return self.unoriented_center_of_gravity
200
201   @property
202   def unoriented_length(self) -> Union[float, Expr]:
203      cosine = cos(self.geometry.curvature_tilt * math.pi / 180.0)
204      sine = sin(self.geometry.curvature_tilt * math.pi / 180.0)
205      return (cosine * self.geometry.chord_length) + (sine * self.geometry.span)
206
207   @property
208   def unoriented_width(self) -> Union[float, Expr]:
209      cosine = cos(self.geometry.curvature_tilt * math.pi / 180.0)
210      return (2.0 * cosine * self.geometry.span) + (2.0 * self.geometry.separation_radius)
211
212   @property
213   def unoriented_height(self) -> Union[float, Expr]:
214      return self.geometry.max_thickness * self.geometry.chord_length
215
216   @property
217   def oriented_length(self) -> Union[float, Expr]:
218      # TODO: Implement this
219      return 0
220
221   @property
222   def oriented_width(self) -> Union[float, Expr]:
223      # TODO: Implement this
224      return 0
225
226   @property
227   def oriented_height(self) -> Union[float, Expr]:
228      # TODO: Implement this
229      return 0
class PlanarAirfoils(symcad.parts.composite.CompositeShape):
 25class PlanarAirfoils(CompositeShape):
 26   """Model representing a set of planar parameteric airfoils.
 27
 28   By default, the airfoils are oriented in the following configuration:
 29
 30   ![PlanarAirfoils](https://symbench.github.io/SymCAD/images/PlanarAirfoils.png)
 31
 32   The `geometry` of this shape includes the following parameters:
 33
 34   - `max_thickness`: Maximum thickness (in `% of length`) of each airfoil
 35   - `chord_length`: Length (in `m`) of the chord of each airfoil
 36   - `span`: Width (in `m`) of each airfoil
 37   - `separation_radius`: Radius (in `m`) of separation between each airfoil
 38   - `curvature_tilt`: Amount of tilt (in `deg`) of each airfoil
 39
 40   Note that the above dimensions should be interpreted as if the airfoils are unrotated. In other
 41   words, any shape rotation takes place *after* the airfoil dimensions have been specified.
 42   """
 43
 44   # Constructor ----------------------------------------------------------------------------------
 45
 46   def __init__(self, identifier: str, material_density_kg_m3: Optional[float] = 1.0) -> None:
 47      """Initializes a planar parametric airfoil object.
 48
 49      Parameters
 50      ----------
 51      identifier : `str`
 52         Unique identifying name for the object.
 53      material_density_kg_m3 : `float`, optional, default=1.0
 54         Uniform material density in `kg/m^3` to be used in mass property calculations.
 55      """
 56      super().__init__(identifier, self.__create_cad__, None, material_density_kg_m3)
 57      setattr(self.geometry, 'max_thickness', Symbol(self.name + '_max_thickness'))
 58      setattr(self.geometry, 'chord_length', Symbol(self.name + '_chord_length'))
 59      setattr(self.geometry, 'span', Symbol(self.name + '_span'))
 60      setattr(self.geometry, 'separation_radius', Symbol(self.name + '_separation_radius'))
 61      setattr(self.geometry, 'curvature_tilt', Symbol(self.name + '_curvature_tilt'))
 62
 63
 64   # CAD generation function ----------------------------------------------------------------------
 65
 66   @staticmethod
 67   def z_val(x: float, max_thickness: float, chord_length: float) -> float:
 68      return 5.0 * max_thickness * chord_length * (
 69         (0.2969 * x**0.5) - (0.1260 * x) - (0.3516 * x**2) + (0.2843 * x**3) - (0.1036 * x**4))
 70
 71   @staticmethod
 72   def __create_cad__(params: Dict[str, float], _fully_displace: bool) -> Part.Solid:
 73      """Scripted CAD generation method for `PlanarAirfoils`."""
 74      doc = FreeCAD.newDocument('Temp')
 75      max_thickness_percent = params['max_thickness']
 76      chord_length_mm = 1000.0 * params['chord_length']
 77      span_mm = 1000.0 * params['span']
 78      separation_radius_mm = 1000.0 * params['separation_radius']
 79      curvature_tilt = params['curvature_tilt']
 80      x, points_upper, points_lower = 0.0, [], []
 81      while x <= 1.009:
 82         points_upper.append(FreeCAD.Vector(x * chord_length_mm,
 83                                            PlanarAirfoils.z_val(x, max_thickness_percent,
 84                                                                    chord_length_mm)))
 85         points_lower.append(FreeCAD.Vector(x * chord_length_mm,
 86                                            -PlanarAirfoils.z_val(x, max_thickness_percent,
 87                                                                     chord_length_mm)))
 88         x += 0.01
 89      bodies = []
 90      for i in range(2):
 91         body = doc.addObject('PartDesign::Body','Airfoil' + str(i))
 92         sketch = doc.addObject('Sketcher::SketchObject', 'Sketch' + str(i))
 93         sketch.Support = doc.XZ_Plane
 94         sketch.MapMode = 'FlatFace'
 95         body.addObject(sketch)
 96         sketch.addGeometry(Part.BSplineCurve(points_upper, None, None,
 97                                              False, 3, None, False), False)
 98         sketch.addGeometry(Part.BSplineCurve(points_lower, None, None,
 99                                              False, 3, None, False), False)
100         pad = doc.addObject('PartDesign::Pad', 'Pad' + str(i))
101         body.addObject(pad)
102         pad.Length = int(span_mm)
103         pad.Profile = sketch
104         placement_vector = \
105            FreeCAD.Vector(0, -separation_radius_mm if i == 0 else separation_radius_mm, 0)
106         body.Placement = \
107            FreeCAD.Placement(placement_vector,
108                              FreeCAD.Rotation(-curvature_tilt if i == 1 else curvature_tilt,
109                                                0, i * 180.0))
110         bodies.append(body)
111      fusion = doc.addObject('Part::MultiFuse', 'Fusion')
112      fusion.Shapes = bodies
113      doc.recompute()
114      airfoils = fusion.Shape
115      FreeCAD.closeDocument(doc.Name)
116      return airfoils
117
118
119   # Geometry setter ------------------------------------------------------------------------------
120
121   def set_geometry(self, *, max_thickness_percent: Union[float, None],
122                             chord_length_m: Union[float, None],
123                             span_m: Union[float, None],
124                             separation_radius_m: Union[float, None],
125                             curvature_tilt_deg: Union[float, None]) -> PlanarAirfoils:
126      """Sets the physical geometry of the current `PlanarAirfoils` object.
127
128      See the `PlanarAirfoils` class documentation for a description of each geometric
129      parameter.
130      """
131      self.geometry.set(max_thickness=max_thickness_percent,
132                        chord_length=chord_length_m,
133                        span=span_m,
134                        separation_radius=separation_radius_m,
135                        curvature_tilt=curvature_tilt_deg)
136      return self
137
138   def get_geometric_parameter_bounds(self, parameter: str) -> Tuple[float, float]:
139      parameter_bounds = {
140         'max_thickness': (0.01, 0.90),
141         'chord_length': (0.1, 2.0),
142         'span': (0.0, 2.0),
143         'separation_radius': (0.0, 1.5),
144         'curvature_tilt': (0.0, 45.0)
145      }
146      return parameter_bounds.get(parameter, (0.0, 0.0))
147
148
149   # Geometric properties -------------------------------------------------------------------------
150
151   @property
152   def material_volume(self) -> Union[float, Expr]:
153      return self.displaced_volume
154
155   @property
156   def displaced_volume(self) -> Union[float, Expr]:
157      x, points_upper = 0.0, []
158      while x <= 1.009:
159         points_upper.append((x * self.geometry.chord_length,
160                              PlanarAirfoils.z_val(x, self.geometry.max_thickness,
161                                                      self.geometry.chord_length)))
162         x += 0.01
163      area = 0.0
164      for i in range(1, len(points_upper) - 1):
165         area += points_upper[i][1]
166      area = points_upper[0][1] + (2.0 * area) + points_upper[len(points_upper)-1][1]
167      h = (points_upper[len(points_upper)-1][0] - points_upper[0][0]) / (len(points_upper) - 1)
168      return 2.0 * h * area * self.geometry.span
169
170   @property
171   def surface_area(self) -> Union[float, Expr]:
172      x, points_upper = 0.0, []
173      while x <= 1.009:
174         points_upper.append((x * self.geometry.chord_length,
175                              PlanarAirfoils.z_val(x, self.geometry.max_thickness,
176                                                      self.geometry.chord_length)))
177         x += 0.01
178      area = 0.0
179      for i in range(1, len(points_upper)):
180         x_diff = (points_upper[i][0] - points_upper[i-1][0])
181         y_diff = (points_upper[i][1] - points_upper[i-1][1])
182         area += sqrt(x_diff**2 + y_diff**2)
183      area = (2.0 * area) * self.geometry.span
184      return 2.0 * area
185
186   @property
187   def unoriented_center_of_gravity(self) -> Tuple[Union[float, Expr],
188                                                   Union[float, Expr],
189                                                   Union[float, Expr]]:
190      cosine = cos(self.geometry.curvature_tilt * math.pi / 180.0)
191      sine = sin(self.geometry.curvature_tilt * math.pi / 180.0)
192      return ((0.41 * cosine * self.geometry.chord_length) + (0.5 * sine * self.geometry.span),
193              0.5 * self.unoriented_width,
194              0.5 * self.unoriented_height)
195
196   @property
197   def unoriented_center_of_buoyancy(self) -> Tuple[Union[float, Expr],
198                                                    Union[float, Expr],
199                                                    Union[float, Expr]]:
200      return self.unoriented_center_of_gravity
201
202   @property
203   def unoriented_length(self) -> Union[float, Expr]:
204      cosine = cos(self.geometry.curvature_tilt * math.pi / 180.0)
205      sine = sin(self.geometry.curvature_tilt * math.pi / 180.0)
206      return (cosine * self.geometry.chord_length) + (sine * self.geometry.span)
207
208   @property
209   def unoriented_width(self) -> Union[float, Expr]:
210      cosine = cos(self.geometry.curvature_tilt * math.pi / 180.0)
211      return (2.0 * cosine * self.geometry.span) + (2.0 * self.geometry.separation_radius)
212
213   @property
214   def unoriented_height(self) -> Union[float, Expr]:
215      return self.geometry.max_thickness * self.geometry.chord_length
216
217   @property
218   def oriented_length(self) -> Union[float, Expr]:
219      # TODO: Implement this
220      return 0
221
222   @property
223   def oriented_width(self) -> Union[float, Expr]:
224      # TODO: Implement this
225      return 0
226
227   @property
228   def oriented_height(self) -> Union[float, Expr]:
229      # TODO: Implement this
230      return 0

Model representing a set of planar parameteric airfoils.

By default, the airfoils are oriented in the following configuration:

PlanarAirfoils

The geometry of this shape includes the following parameters:

  • max_thickness: Maximum thickness (in % of length) of each airfoil
  • chord_length: Length (in m) of the chord of each airfoil
  • span: Width (in m) of each airfoil
  • separation_radius: Radius (in m) of separation between each airfoil
  • curvature_tilt: Amount of tilt (in deg) of each airfoil

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

PlanarAirfoils(identifier: str, material_density_kg_m3: Optional[float] = 1.0)
46   def __init__(self, identifier: str, material_density_kg_m3: Optional[float] = 1.0) -> None:
47      """Initializes a planar parametric airfoil object.
48
49      Parameters
50      ----------
51      identifier : `str`
52         Unique identifying name for the object.
53      material_density_kg_m3 : `float`, optional, default=1.0
54         Uniform material density in `kg/m^3` to be used in mass property calculations.
55      """
56      super().__init__(identifier, self.__create_cad__, None, material_density_kg_m3)
57      setattr(self.geometry, 'max_thickness', Symbol(self.name + '_max_thickness'))
58      setattr(self.geometry, 'chord_length', Symbol(self.name + '_chord_length'))
59      setattr(self.geometry, 'span', Symbol(self.name + '_span'))
60      setattr(self.geometry, 'separation_radius', Symbol(self.name + '_separation_radius'))
61      setattr(self.geometry, 'curvature_tilt', Symbol(self.name + '_curvature_tilt'))

Initializes a planar parametric airfoil object.

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.
@staticmethod
def z_val(x: float, max_thickness: float, chord_length: float) -> float:
66   @staticmethod
67   def z_val(x: float, max_thickness: float, chord_length: float) -> float:
68      return 5.0 * max_thickness * chord_length * (
69         (0.2969 * x**0.5) - (0.1260 * x) - (0.3516 * x**2) + (0.2843 * x**3) - (0.1036 * x**4))
def set_geometry( self, *, max_thickness_percent: Optional[float], chord_length_m: Optional[float], span_m: Optional[float], separation_radius_m: Optional[float], curvature_tilt_deg: Optional[float]) -> PlanarAirfoils:
121   def set_geometry(self, *, max_thickness_percent: Union[float, None],
122                             chord_length_m: Union[float, None],
123                             span_m: Union[float, None],
124                             separation_radius_m: Union[float, None],
125                             curvature_tilt_deg: Union[float, None]) -> PlanarAirfoils:
126      """Sets the physical geometry of the current `PlanarAirfoils` object.
127
128      See the `PlanarAirfoils` class documentation for a description of each geometric
129      parameter.
130      """
131      self.geometry.set(max_thickness=max_thickness_percent,
132                        chord_length=chord_length_m,
133                        span=span_m,
134                        separation_radius=separation_radius_m,
135                        curvature_tilt=curvature_tilt_deg)
136      return self

Sets the physical geometry of the current PlanarAirfoils object.

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

def get_geometric_parameter_bounds(self, parameter: str) -> Tuple[float, float]:
138   def get_geometric_parameter_bounds(self, parameter: str) -> Tuple[float, float]:
139      parameter_bounds = {
140         'max_thickness': (0.01, 0.90),
141         'chord_length': (0.1, 2.0),
142         'span': (0.0, 2.0),
143         'separation_radius': (0.0, 1.5),
144         'curvature_tilt': (0.0, 45.0)
145      }
146      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).