symcad.parts.endcaps.Hemisphere
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 21from . import EndcapShape 22import math 23 24class Hemisphere(EndcapShape): 25 """Model representing a hollow, parametric, hemispherical endcap. 26 27 By default, the endcap is oriented such that its base is perpendicular to the z-axis: 28 29  30 31 The `geometry` of this shape includes the following parameters: 32 33 - `radius`: Radius (in `m`) of the Hemisphere 34 - `thickness`: Thickness (in `m`) of the shell of the Hemisphere 35 36 Note that the above dimensions should be interpreted as if the Hemisphere is unrotated. 37 In other words, any shape rotation takes place *after* the Hemisphere dimensions have been 38 specified. 39 """ 40 41 # Constructor ---------------------------------------------------------------------------------- 42 43 def __init__(self, identifier: str, material_density_kg_m3: Optional[float] = 1.0) -> None: 44 """Initializes a hollow, parametric, hemispherical endcap object. 45 46 Parameters 47 ---------- 48 identifier : `str` 49 Unique identifying name for the object. 50 material_density_kg_m3 : `float`, optional, default=1.0 51 Uniform material density in `kg/m^3` to be used in mass property calculations. 52 """ 53 super().__init__(identifier, self.__create_cad__, None, material_density_kg_m3) 54 setattr(self.geometry, 'radius', Symbol(self.name + '_radius')) 55 setattr(self.geometry, 'thickness', Symbol(self.name + '_thickness')) 56 57 58 # CAD generation function ---------------------------------------------------------------------- 59 60 @staticmethod 61 def __create_cad__(params: Dict[str, float], fully_displace: bool) -> Part.Solid: 62 """Scripted CAD generation method for a `Hemisphere`.""" 63 thickness_mm = 1000.0 * params['thickness'] 64 outer_radius_mm = 1000.0 * params['radius'] 65 inner_radius_mm = outer_radius_mm - thickness_mm 66 outer = Part.makeSphere(outer_radius_mm, FreeCAD.Vector(0, 0, 0), FreeCAD.Vector(0, 0, 1), 0, 90, 360) 67 if not fully_displace: 68 inner = Part.makeSphere(inner_radius_mm, FreeCAD.Vector(0, 0, 0), FreeCAD.Vector(0, 0, 1), 0, 90, 360) 69 return outer.cut(inner) 70 else: 71 return outer 72 73 74 # Geometry setter ------------------------------------------------------------------------------ 75 76 def set_geometry(self, *, radius_m: Union[float, None], 77 thickness_m: Union[float, None]) -> Hemisphere: 78 """Sets the physical geometry of the current `Hemisphere` object. 79 80 See the `Hemisphere` class documentation for a description of each geometric parameter. 81 """ 82 self.geometry.set(radius=radius_m, thickness=thickness_m) 83 return self 84 85 def get_geometric_parameter_bounds(self, parameter: str) -> Tuple[float, float]: 86 parameter_bounds = { 87 'radius': (0.0, 2.0), 88 'thickness': (0.0, 0.05) 89 } 90 return parameter_bounds.get(parameter, (0.0, 0.0)) 91 92 93 # Geometric properties ------------------------------------------------------------------------- 94 95 @property 96 def material_volume(self) -> Union[float, Expr]: 97 volume = self.displaced_volume 98 volume -= ((2.0 * math.pi / 3.0) * (self.geometry.radius - self.geometry.thickness)**3) 99 return volume 100 101 @property 102 def displaced_volume(self) -> Union[float, Expr]: 103 return (2.0 * math.pi / 3.0) * self.geometry.radius**3 104 105 @property 106 def surface_area(self) -> Union[float, Expr]: 107 return 2.0 * math.pi * self.geometry.radius**2 108 109 @property 110 def unoriented_center_of_gravity(self) -> Tuple[Union[float, Expr], 111 Union[float, Expr], 112 Union[float, Expr]]: 113 return self.geometry.radius, self.geometry.radius, 0.5 * self.geometry.radius 114 115 @property 116 def unoriented_center_of_buoyancy(self) -> Tuple[Union[float, Expr], 117 Union[float, Expr], 118 Union[float, Expr]]: 119 return self.geometry.radius, self.geometry.radius, 3.0 * self.geometry.radius / 8.0 120 121 @property 122 def unoriented_length(self) -> Union[float, Expr]: 123 return 2.0 * self.geometry.radius 124 125 @property 126 def unoriented_width(self) -> Union[float, Expr]: 127 return self.unoriented_length 128 129 @property 130 def unoriented_height(self) -> Union[float, Expr]: 131 return self.geometry.radius 132 133 @property 134 def oriented_length(self) -> Union[float, Expr]: 135 # TODO: Implement this 136 return 0 137 138 @property 139 def oriented_width(self) -> Union[float, Expr]: 140 # TODO: Implement this 141 return 0 142 143 @property 144 def oriented_height(self) -> Union[float, Expr]: 145 # TODO: Implement this 146 return 0
25class Hemisphere(EndcapShape): 26 """Model representing a hollow, parametric, hemispherical endcap. 27 28 By default, the endcap is oriented such that its base is perpendicular to the z-axis: 29 30  31 32 The `geometry` of this shape includes the following parameters: 33 34 - `radius`: Radius (in `m`) of the Hemisphere 35 - `thickness`: Thickness (in `m`) of the shell of the Hemisphere 36 37 Note that the above dimensions should be interpreted as if the Hemisphere is unrotated. 38 In other words, any shape rotation takes place *after* the Hemisphere dimensions have been 39 specified. 40 """ 41 42 # Constructor ---------------------------------------------------------------------------------- 43 44 def __init__(self, identifier: str, material_density_kg_m3: Optional[float] = 1.0) -> None: 45 """Initializes a hollow, parametric, hemispherical endcap object. 46 47 Parameters 48 ---------- 49 identifier : `str` 50 Unique identifying name for the object. 51 material_density_kg_m3 : `float`, optional, default=1.0 52 Uniform material density in `kg/m^3` to be used in mass property calculations. 53 """ 54 super().__init__(identifier, self.__create_cad__, None, material_density_kg_m3) 55 setattr(self.geometry, 'radius', Symbol(self.name + '_radius')) 56 setattr(self.geometry, 'thickness', Symbol(self.name + '_thickness')) 57 58 59 # CAD generation function ---------------------------------------------------------------------- 60 61 @staticmethod 62 def __create_cad__(params: Dict[str, float], fully_displace: bool) -> Part.Solid: 63 """Scripted CAD generation method for a `Hemisphere`.""" 64 thickness_mm = 1000.0 * params['thickness'] 65 outer_radius_mm = 1000.0 * params['radius'] 66 inner_radius_mm = outer_radius_mm - thickness_mm 67 outer = Part.makeSphere(outer_radius_mm, FreeCAD.Vector(0, 0, 0), FreeCAD.Vector(0, 0, 1), 0, 90, 360) 68 if not fully_displace: 69 inner = Part.makeSphere(inner_radius_mm, FreeCAD.Vector(0, 0, 0), FreeCAD.Vector(0, 0, 1), 0, 90, 360) 70 return outer.cut(inner) 71 else: 72 return outer 73 74 75 # Geometry setter ------------------------------------------------------------------------------ 76 77 def set_geometry(self, *, radius_m: Union[float, None], 78 thickness_m: Union[float, None]) -> Hemisphere: 79 """Sets the physical geometry of the current `Hemisphere` object. 80 81 See the `Hemisphere` class documentation for a description of each geometric parameter. 82 """ 83 self.geometry.set(radius=radius_m, thickness=thickness_m) 84 return self 85 86 def get_geometric_parameter_bounds(self, parameter: str) -> Tuple[float, float]: 87 parameter_bounds = { 88 'radius': (0.0, 2.0), 89 'thickness': (0.0, 0.05) 90 } 91 return parameter_bounds.get(parameter, (0.0, 0.0)) 92 93 94 # Geometric properties ------------------------------------------------------------------------- 95 96 @property 97 def material_volume(self) -> Union[float, Expr]: 98 volume = self.displaced_volume 99 volume -= ((2.0 * math.pi / 3.0) * (self.geometry.radius - self.geometry.thickness)**3) 100 return volume 101 102 @property 103 def displaced_volume(self) -> Union[float, Expr]: 104 return (2.0 * math.pi / 3.0) * self.geometry.radius**3 105 106 @property 107 def surface_area(self) -> Union[float, Expr]: 108 return 2.0 * math.pi * self.geometry.radius**2 109 110 @property 111 def unoriented_center_of_gravity(self) -> Tuple[Union[float, Expr], 112 Union[float, Expr], 113 Union[float, Expr]]: 114 return self.geometry.radius, self.geometry.radius, 0.5 * self.geometry.radius 115 116 @property 117 def unoriented_center_of_buoyancy(self) -> Tuple[Union[float, Expr], 118 Union[float, Expr], 119 Union[float, Expr]]: 120 return self.geometry.radius, self.geometry.radius, 3.0 * self.geometry.radius / 8.0 121 122 @property 123 def unoriented_length(self) -> Union[float, Expr]: 124 return 2.0 * self.geometry.radius 125 126 @property 127 def unoriented_width(self) -> Union[float, Expr]: 128 return self.unoriented_length 129 130 @property 131 def unoriented_height(self) -> Union[float, Expr]: 132 return self.geometry.radius 133 134 @property 135 def oriented_length(self) -> Union[float, Expr]: 136 # TODO: Implement this 137 return 0 138 139 @property 140 def oriented_width(self) -> Union[float, Expr]: 141 # TODO: Implement this 142 return 0 143 144 @property 145 def oriented_height(self) -> Union[float, Expr]: 146 # TODO: Implement this 147 return 0
Model representing a hollow, parametric, hemispherical endcap.
By default, the endcap is oriented such that its base is perpendicular to the z-axis:

The geometry of this shape includes the following parameters:
radius: Radius (inm) of the Hemispherethickness: Thickness (inm) of the shell of the Hemisphere
Note that the above dimensions should be interpreted as if the Hemisphere is unrotated. In other words, any shape rotation takes place after the Hemisphere dimensions have been specified.
44 def __init__(self, identifier: str, material_density_kg_m3: Optional[float] = 1.0) -> None: 45 """Initializes a hollow, parametric, hemispherical endcap object. 46 47 Parameters 48 ---------- 49 identifier : `str` 50 Unique identifying name for the object. 51 material_density_kg_m3 : `float`, optional, default=1.0 52 Uniform material density in `kg/m^3` to be used in mass property calculations. 53 """ 54 super().__init__(identifier, self.__create_cad__, None, material_density_kg_m3) 55 setattr(self.geometry, 'radius', Symbol(self.name + '_radius')) 56 setattr(self.geometry, 'thickness', Symbol(self.name + '_thickness'))
Initializes a hollow, parametric, hemispherical endcap object.
Parameters
- identifier (
str): Unique identifying name for the object. - material_density_kg_m3 (
float, optional, default=1.0): Uniform material density inkg/m^3to be used in mass property calculations.
77 def set_geometry(self, *, radius_m: Union[float, None], 78 thickness_m: Union[float, None]) -> Hemisphere: 79 """Sets the physical geometry of the current `Hemisphere` object. 80 81 See the `Hemisphere` class documentation for a description of each geometric parameter. 82 """ 83 self.geometry.set(radius=radius_m, thickness=thickness_m) 84 return self
Sets the physical geometry of the current Hemisphere object.
See the Hemisphere class documentation for a description of each geometric parameter.
86 def get_geometric_parameter_bounds(self, parameter: str) -> Tuple[float, float]: 87 parameter_bounds = { 88 'radius': (0.0, 2.0), 89 'thickness': (0.0, 0.05) 90 } 91 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 geometricparameter.
Material volume (in m^3) of the SymPart (read-only).
Displaced volume (in m^3) of the SymPart (read-only).
Surface/wetted area (in m^2) of the SymPart (read-only).
Center of gravity (in m) of the unoriented SymPart (read-only).
Center of buoyancy (in m) of the unoriented SymPart (read-only).
X-axis length (in m) of the bounding box of the unoriented SymPart (read-only).
Y-axis width (in m) of the bounding box of the unoriented SymPart (read-only).
Z-axis height (in m) of the bounding box of the unoriented SymPart (read-only).
X-axis length (in m) of the bounding box of the oriented SymPart (read-only).
Y-axis length (in m) of the bounding box of the oriented SymPart (read-only).
Z-axis length (in m) of the bounding box of the oriented SymPart (read-only).
Inherited Members
- symcad.core.SymPart.SymPart
- name
- geometry
- attachment_points
- attachments
- connection_ports
- connections
- static_origin
- static_placement
- orientation
- material_density
- current_states
- is_exposed
- clone
- set_placement
- set_orientation
- set_state
- set_unexposed
- set_material_density
- add_attachment_point
- add_connection_port
- attach
- connect
- get_cad_physical_properties
- export
- get_valid_states
- mass
- oriented_center_of_gravity
- oriented_center_of_buoyancy