bluemira.geometry.tools

Useful functions for bluemira geometries.

Classes

HullPlane

Enumeration of planes to perform a hull operation in.

BluemiraGeoEncoder

JSON Encoder for BluemiraGeo.

GeometryCreationIn

Typing for closed_wire_wrapper input

GeometryCreationOut

Typing for closed_wire_wrapper output

SweepShapeTransition

Sweep shape corner transition options

CutLocation

Used in cut_wire_at_z_value to choose which part of the shape to remove

Functions

convert(→ bluemira.geometry.base.BluemiraGeoT)

Convert a FreeCAD shape into the corresponding BluemiraGeo object.

_reconstruct_function_call(→ dict)

Reconstruct the call of a function with inputs arguments and defaults.

_make_debug_file(→ pathlib.Path)

Make a new file in the geometry debugging folder.

log_geometry_on_failure(func)

Decorator for debugging of failed geometry operations.

fallback_to(fallback_func, exception)

Decorator for a fallback to an alternative geometry operation.

_make_vertex(→ bluemira.codes._freecadapi.apiVertex)

Make a vertex.

closed_wire_wrapper(...)

Decorator for checking / enforcing closures on wire creation functions.

make_polygon(→ bluemira.geometry.wire.BluemiraWire)

Make a polygon from a set of points.

make_bezier(→ bluemira.geometry.wire.BluemiraWire)

Make a bspline from a set of points.

make_bspline(→ bluemira.geometry.wire.BluemiraWire)

Builds a B-Spline by a lists of Poles, Mults, Knots

make_bsplinesurface(→ bluemira.geometry.wire.BluemiraWire)

Builds a B-SplineSurface by a lists of Poles, Mults, Knots

_make_polygon_fallback(...)

Overloaded function signature for fallback option from interpolate_bspline

interpolate_bspline(→ bluemira.geometry.wire.BluemiraWire)

Make a bspline from a set of points.

force_wire_to_spline(→ bluemira.geometry.wire.BluemiraWire)

Force a wire to be a spline wire.

make_circle(, start_angle, end_angle, axis, label)

Create a circle or arc of circle object with given parameters.

make_circle_arc_3P(→ bluemira.geometry.wire.BluemiraWire)

Create an arc of circle object given three points.

make_ellipse(, major_radius, minor_radius, major_axis, ...)

Create an ellipse or arc of ellipse object with given parameters.

wire_closure(→ bluemira.geometry.wire.BluemiraWire)

Close this wire with a line segment

_offset_wire_discretised(...)

Fallback function for discretised offsetting

offset_wire(→ bluemira.geometry.wire.BluemiraWire)

Make a planar offset from a planar wire.

convex_hull_wires_2d(→ bluemira.geometry.wire.BluemiraWire)

Perform a convex hull around the given wires and return the hull

polygon_revolve_signed_volume(→ float)

Revolve a polygon along the z axis, and return the volume.

partial_diff_of_volume(→ float)

Gives the relationship between how the the solid volume varies with the position of

revolve_shape(, direction, degree, label)

Apply the revolve (base, dir, degree) to this shape

extrude_shape(→ bluemira.geometry.solid.BluemiraSolid)

Apply the extrusion along vec to this shape

sweep_shape(...)

Sweep a profile along a path.

loft_shape(...)

Loft between a set of profiles.

fillet_chamfer_decorator(*, chamfer)

Decorator for fillet and chamfer operations, checking for validity of wire

fillet_wire_2D(→ bluemira.geometry.wire.BluemiraWire)

Fillet all edges of a wire

chamfer_wire_2D(→ bluemira.geometry.wire.BluemiraWire)

Chamfer all edges of a wire

distance_to(→ tuple[float, list[tuple[float, float, ...)

Calculate the distance between two BluemiraGeos.

split_wire(...)

Split a wire at a given vertex.

cut_wire_at_z_value(→ bluemira.geometry.wire.BluemiraWire)

Remove the parts of the wire below or above a given z-value.

slice_shape(...)

Calculate the plane intersection points with an object

get_wire_plane_intersect(→ numpy.typing.NDArray[float])

Cut a wire using a plane.

circular_pattern(, direction, degree, n_shapes)

Make a equally spaced circular pattern of shapes.

mirror_shape(→ bluemira.geometry.base.BluemiraGeo)

Get a mirrored copy of a shape about a plane.

is_convex(points)

Check that the the list of xz points are strictly convex, i.e.

save_as_STP(shapes, filename, **kwargs)

Saves a series of Shape objects as a STEP assembly

save_cad(shapes, filename[, cad_format, names])

Save the CAD of a component (eg a reactor) or a list of components

import_cad(...)

Import CAD from file

_nb_dot_2D(v_1, v_2)

_nb_clip(val, a_min, a_max)

_signed_distance_2D(→ float)

2-D function for the signed distance from a point to a polygon. The return value is

signed_distance_2D_polygon(→ numpy.ndarray)

2-D vector-valued signed distance function from a subject polygon to a target

signed_distance(→ float)

Single-valued signed "distance" function between two wires. Will return negative

raise_error_if_overlap(origin, target[, origin_name, ...])

connect_shapes(→ bluemira.geometry.base.BluemiraGeo)

Connect (imprint) a list of shapes together.

make_compound(...)

Make a compound of the given shapes.

boolean_fuse(→ bluemira.geometry.base.BluemiraGeo)

Fuse two or more shapes together. Internal splitter are removed.

boolean_cut(...)

Subtract from the base, a (list of) topo shapes cut (tools).

boolean_fragments(...)

Split a list of shapes into their Boolean fragments.

point_inside_shape(→ bool)

Check whether or not a point is inside a shape.

point_on_plane(→ bool)

Check whether or not a point is on a plane.

serialise_shape(shape)

Serialise a BluemiraGeo object.

deserialise_shape(...)

Deserialise a BluemiraGeo object obtained from serialise_shape.

get_shape_by_name(...)

Search through the boundary of the shape and get any shapes with a label

find_clockwise_angle_2d(→ numpy.ndarray)

Find the clockwise angle between the 2D vectors base and

Module Contents

bluemira.geometry.tools.convert(apiobj: bluemira.codes._freecadapi.apiShape, label: str = '') bluemira.geometry.base.BluemiraGeoT

Convert a FreeCAD shape into the corresponding BluemiraGeo object.

Returns:

BluemiraGeo object of inputted FreeCAD shape.

Raises:

TypeError – Cannot convert to BluemiraGeo

Parameters:
  • apiobj (bluemira.codes._freecadapi.apiShape)

  • label (str)

Return type:

bluemira.geometry.base.BluemiraGeoT

class bluemira.geometry.tools.HullPlane(*args, **kwds)

Bases: enum.Enum

Inheritance diagram of bluemira.geometry.tools.HullPlane

Enumeration of planes to perform a hull operation in.

XZ
XY
YZ
classmethod _missing_(value: str)
Parameters:

value (str)

class bluemira.geometry.tools.BluemiraGeoEncoder(*, skipkeys=False, ensure_ascii=True, check_circular=True, allow_nan=True, sort_keys=False, indent=None, separators=None, default=None)

Bases: json.JSONEncoder

Inheritance diagram of bluemira.geometry.tools.BluemiraGeoEncoder

JSON Encoder for BluemiraGeo.

default(obj: bluemira.geometry.base.BluemiraGeoT | numpy.ndarray | Any)

Override the JSONEncoder default object handling behaviour for BluemiraGeo.

Returns:

List from bluemira shape or numpy array.

Parameters:

obj (bluemira.geometry.base.BluemiraGeoT | numpy.ndarray | Any)

bluemira.geometry.tools._reconstruct_function_call(signature, *args, **kwargs) dict

Reconstruct the call of a function with inputs arguments and defaults.

Returns:

Dictionary of data from a function with inputs arguments and defaults.

Return type:

dict

bluemira.geometry.tools._make_debug_file(name: str) pathlib.Path

Make a new file in the geometry debugging folder.

Returns:

Filename for new file in the geometry debugging folder.

Parameters:

name (str)

Return type:

pathlib.Path

bluemira.geometry.tools.log_geometry_on_failure(func)

Decorator for debugging of failed geometry operations.

Returns:

Decorator for debugging of failed geometry operations.

bluemira.geometry.tools.fallback_to(fallback_func, exception)

Decorator for a fallback to an alternative geometry operation.

Returns:

Decorator for fallback function.

bluemira.geometry.tools._make_vertex(point: numpy.typing.ArrayLike | bluemira.geometry.coordinates.Coordinates) bluemira.codes._freecadapi.apiVertex

Make a vertex.

Parameters:

point (numpy.typing.ArrayLike | bluemira.geometry.coordinates.Coordinates) – Coordinates of the point

Return type:

Vertex at the point

Raises:

GeometryError – Shape must a single point

class bluemira.geometry.tools.GeometryCreationIn

Bases: Protocol

Inheritance diagram of bluemira.geometry.tools.GeometryCreationIn

Typing for closed_wire_wrapper input

__call__(points: bluemira.geometry.coordinates.Coordinates, label: str = '', *, closed: bool = False) bluemira.geometry.wire.BluemiraWire

Typing for coordinates wrapping

Parameters:
Return type:

bluemira.geometry.wire.BluemiraWire

class bluemira.geometry.tools.GeometryCreationOut

Bases: Protocol

Inheritance diagram of bluemira.geometry.tools.GeometryCreationOut

Typing for closed_wire_wrapper output

__call__(points: bluemira.geometry.coordinates.Coordinates | numpy.typing.ArrayLike | dict[str, numpy.typing.ArrayLike], label: str = '', *, closed: bool = False) bluemira.geometry.wire.BluemiraWire

Typing for coordinates wrapping

Parameters:
Return type:

bluemira.geometry.wire.BluemiraWire

bluemira.geometry.tools.closed_wire_wrapper(*, drop_closure_point: bool) collections.abc.Callable[[GeometryCreationIn], GeometryCreationOut]

Decorator for checking / enforcing closures on wire creation functions.

Returns:

Decorator on wire creation functions.

Parameters:

drop_closure_point (bool)

Return type:

collections.abc.Callable[[GeometryCreationIn], GeometryCreationOut]

bluemira.geometry.tools.make_polygon(points: bluemira.geometry.coordinates.Coordinates, label: str = '', *, closed: bool = False) bluemira.geometry.wire.BluemiraWire

Make a polygon from a set of points.

Parameters:
  • points (bluemira.geometry.coordinates.Coordinates) – list of points. It can be given as a list of 3D tuples, a 3D numpy array, or similar.

  • label (str) – Object’s label

  • closed (bool) – if True, the first and last points will be connected in order to form a closed polygon. Defaults to False.

Return type:

BluemiraWire of the polygon

Notes

If the input points are closed, but closed is False, the returned BluemiraWire will be closed.

bluemira.geometry.tools.make_bezier(points: bluemira.geometry.coordinates.Coordinates, label: str = '', *, closed: bool = False) bluemira.geometry.wire.BluemiraWire

Make a bspline from a set of points.

Parameters:
  • points (bluemira.geometry.coordinates.Coordinates) – list of points. It can be given as a list of 3D tuples, a 3D numpy array, or similar.

  • label (str) – Object’s label

  • closed (bool) – if True, the first and last points will be connected in order to form a closed bspline. Defaults to False.

Return type:

BluemiraWire that contains the bspline

Notes

If the input points are closed, but closed is False, the returned BluemiraWire will be closed.

Bezier curve of degree n by the control points P_i is:

\[{\textbf{C}}(t) = \sum_{i=0}^{n} B_{i,n}(t) \cdot {\textbf{P}}_i\]

where \(B_{i,n}(t)\) are the Bernstein polynomials:

\[B_{i,n}(t) = \binom{n}{i} (1 - t)^{n-i} t^i\]

t is a parameter ranging from 0 to 1.

bluemira.geometry.tools.make_bspline(poles: numpy.typing.ArrayLike, mults: numpy.typing.ArrayLike, knots: numpy.typing.ArrayLike, *, periodic: bool, degree: int, weights: numpy.typing.ArrayLike, check_rational: bool, label: str = '') bluemira.geometry.wire.BluemiraWire

Builds a B-Spline by a lists of Poles, Mults, Knots

Parameters:
  • poles (numpy.typing.ArrayLike) – list of poles.

  • mults (numpy.typing.ArrayLike) – list of integers for the multiplicity

  • knots (numpy.typing.ArrayLike) – list of knots

  • periodic (bool) – Whether or not the spline is periodic (same curvature at start and end points)

  • degree (int) – bspline degree

  • weights (numpy.typing.ArrayLike) – sequence of float

  • check_rational (bool) – Whether or not to check if the BSpline is rational

  • label (str)

Return type:

BluemiraWire of the spline

Notes

The B-spline curve is defined by the control points P_i:

\[\textbf{C}(t) = \sum_{i=0}^{n} B_{i,p}(t) {\textbf{P}}_i,\]

where the basis functions \(B_{i,p}(t)\) are computed as:

\[\begin{split}B_{i,0}(t) = \begin{cases} 1 & \text{if } t_i \leq t < t_{i+1}, \\ 0 & \text{otherwise}. \end{cases}\end{split}\]
\[B_{i,p}(t) = \frac{t - t_i}{t_{i+p} - t_i} B_{i,p-1}(t) + \frac{t_{i+p+1} - t}{t_{i+p+1} - t_{i+1}} B_{i+1,p-1}(t).\]

Here, t is a parameter ranging from 0 to 1, representing the position along the curve.

bluemira.geometry.tools.make_bsplinesurface(poles: numpy.typing.ArrayLike, mults_u: numpy.typing.ArrayLike, mults_v: numpy.typing.ArrayLike, knot_vector_u: numpy.typing.ArrayLike, knot_vector_v: numpy.typing.ArrayLike, degree_u: int, degree_v: int, weights: numpy.typing.ArrayLike, *, periodic: bool, check_rational: bool, label: str = '') bluemira.geometry.wire.BluemiraWire

Builds a B-SplineSurface by a lists of Poles, Mults, Knots

Parameters:
  • poles (numpy.typing.ArrayLike) – Array of poles (control points).

  • mults_u (numpy.typing.ArrayLike) – list of integers for the u-multiplicity

  • mults_v (numpy.typing.ArrayLike) – list of integers for the u-multiplicity

  • knot_vector_u (numpy.typing.ArrayLike) – list of u-knots

  • knot_vector_v (numpy.typing.ArrayLike) – list of v-knots

  • degree_u (int) – degree of NURBS in u-direction

  • degree_v (int) – degree of NURBS in v-direction

  • weights (numpy.typing.ArrayLike) – point weights.

  • periodic (bool) – Whether or not the spline is periodic (same curvature at start and end points)

  • check_rational (bool) – Whether or not to check if the BSpline is rational (not sure)

  • label (str)

Return type:

A FreeCAD object that contours the bsplinesurface

Notes

This function wraps the FreeCAD function of bsplinesurface buildFromPolesMultsKnots.

The B-spline surface is defined as:

\[\begin{split}{\textbf{S}}(u, v) = \sum_{i=0}^{n} \sum_{j=0}^{m} N_{i,p}(u) \\ M_{j,q}(v) {\textbf{P}}_{i,j}\end{split}\]

where \(N_{i,p}(u)\) and \(M_{j,q}(v)\) are the B-spline basis functions in the u and v dimensions, respectively.

bluemira.geometry.tools._make_polygon_fallback(points, label='', *, closed=False, **kwargs) bluemira.geometry.wire.BluemiraWire

Overloaded function signature for fallback option from interpolate_bspline

Returns:

Closed BluemiraWire from points.

Return type:

bluemira.geometry.wire.BluemiraWire

bluemira.geometry.tools.interpolate_bspline(points: numpy.typing.ArrayLike, label: str = '', *, closed: bool = False, start_tangent: collections.abc.Iterable | None = None, end_tangent: collections.abc.Iterable | None = None, allow_fallback: bool = True) bluemira.geometry.wire.BluemiraWire

Make a bspline from a set of points.

Parameters:
  • points (numpy.typing.ArrayLike) – list of points. It can be given as a list of 3D tuples, a 3D numpy array, or similar.

  • label (str) – Object’s label

  • closed (bool) – if True, the first and last points will be connected in order to form a closed bspline. Defaults to False.

  • start_tangent (collections.abc.Iterable | None) – Tangency of the BSpline at the first pole. Must be specified with end_tangent

  • end_tangent (collections.abc.Iterable | None) – Tangency of the BSpline at the last pole. Must be specified with start_tangent

  • allow_fallback (bool)

Return type:

Bluemira wire that contains the bspline

bluemira.geometry.tools.force_wire_to_spline(wire: bluemira.geometry.wire.BluemiraWire, n_edges_max: int = 200, l2_tolerance: float = 0.005) bluemira.geometry.wire.BluemiraWire

Force a wire to be a spline wire.

Parameters:
  • wire (bluemira.geometry.wire.BluemiraWire) – The BluemiraWire to be turned into a splined wire

  • n_edges_max (int) – The maximum number of edges in the wire, below which this operation does nothing

  • l2_tolerance (float) – The L2-norm difference w.r.t. the original wire, above which this operation will warn that the desired tolerance was not achieved.

Return type:

A new spline version of the wire

Notes

This is intended for use with wires that consist of large polygons, often resulting from operations that failed with primitives and fallback methods making use of of polygons. This can be relatively stubborn to transform back to splines.

bluemira.geometry.tools.make_circle(radius: float = 1.0, center: numpy.typing.ArrayLike = (0.0, 0.0, 0.0), start_angle: float = 0.0, end_angle: float = 360.0, axis: numpy.typing.ArrayLike = (0.0, 0.0, 1.0), label: str = '') bluemira.geometry.wire.BluemiraWire

Create a circle or arc of circle object with given parameters.

Parameters:
  • radius (float) – Radius of the circle

  • center (numpy.typing.ArrayLike) – Center of the circle

  • start_angle (float) – Start angle of the arc [degrees]

  • end_angle (float) – End angle of the arc [degrees]. If start_angle == end_angle, a circle is created, otherwise a circle arc is created

  • axis (numpy.typing.ArrayLike) – Normal vector to the circle plane. It defines the clockwise/anticlockwise circle orientation according to the right hand rule.

  • label (str) – object’s label

Return type:

Bluemira wire that contains the arc or circle

bluemira.geometry.tools.make_circle_arc_3P(p1: collections.abc.Iterable[float], p2: collections.abc.Iterable[float], p3: collections.abc.Iterable[float], axis: tuple[float, float, float] | None = None, label: str = '') bluemira.geometry.wire.BluemiraWire

Create an arc of circle object given three points.

Parameters:
  • p1 (collections.abc.Iterable[float]) – Starting point of the circle arc

  • p2 (collections.abc.Iterable[float]) – Middle point of the circle arc

  • p3 (collections.abc.Iterable[float]) – End point of the circle arc

  • axis (tuple[float, float, float] | None)

  • label (str)

Return type:

Bluemira wire that contains the arc or circle

Raises:

GeometryError – Raised if the three points are collinear.

bluemira.geometry.tools.make_ellipse(center: numpy.typing.ArrayLike = (0.0, 0.0, 0.0), major_radius: float = 2.0, minor_radius: float = 1.0, major_axis: numpy.typing.ArrayLike = (1, 0, 0), minor_axis: numpy.typing.ArrayLike = (0, 1, 0), start_angle: float = 0.0, end_angle: float = 360.0, label: str = '') bluemira.geometry.wire.BluemiraWire

Create an ellipse or arc of ellipse object with given parameters.

Parameters:
  • center (numpy.typing.ArrayLike) – Center of the ellipse

  • major_radius (float) – Major radius of the ellipse

  • minor_radius (float) – Minor radius of the ellipse (float). Default to 2.

  • major_axis (numpy.typing.ArrayLike) – Major axis direction

  • minor_axis (numpy.typing.ArrayLike) – Minor axis direction

  • start_angle (float) – Start angle of the arc [degrees]

  • end_angle (float) – End angle of the arc [degrees]. if start_angle == end_angle, an ellipse is created, otherwise a ellipse arc is created

  • label (str) – Object’s label

Return type:

Bluemira wire that contains the arc or ellipse

bluemira.geometry.tools.wire_closure(bmwire: bluemira.geometry.wire.BluemiraWire, label='closure') bluemira.geometry.wire.BluemiraWire

Close this wire with a line segment

Parameters:
Return type:

Closure wire

bluemira.geometry.tools._offset_wire_discretised(wire: bluemira.geometry.wire.BluemiraWire, thickness: float, /, join: str = 'intersect', *, open_wire: bool = True, label: str = '', fallback_method: str = 'square', fallback_force_spline: bool = False, byedges: bool = True, ndiscr: int = 200, **fallback_kwargs) bluemira.geometry.wire.BluemiraWire

Fallback function for discretised offsetting

Returns:

The offset wire.

Raises:

GeometryError – If the wire is not closed. This function cannot handle the offet of an open wire.

Parameters:
  • wire (bluemira.geometry.wire.BluemiraWire)

  • thickness (float)

  • join (str)

  • open_wire (bool)

  • label (str)

  • fallback_method (str)

  • fallback_force_spline (bool)

  • byedges (bool)

  • ndiscr (int)

Return type:

bluemira.geometry.wire.BluemiraWire

bluemira.geometry.tools.offset_wire(wire: bluemira.geometry.wire.BluemiraWire, thickness: float, /, join: str = 'intersect', *, open_wire: bool = True, label: str = '', fallback_method: str = 'square', byedges: bool = True, ndiscr: int = 400, allow_fallback: bool = True, **fallback_kwargs) bluemira.geometry.wire.BluemiraWire

Make a planar offset from a planar wire.

Parameters:
  • wire (bluemira.geometry.wire.BluemiraWire) – Wire to offset from

  • thickness (float) – Offset distance. Positive values outwards, negative values inwards

  • join (str) – Offset method. “arc” gives rounded corners, and “intersect” gives sharp corners

  • open_wire (bool) – For open wires (counter-clockwise default) whether or not to make an open offset wire, or a closed offset wire that encompasses the original wire. This is disabled for closed wires.

  • byedges (bool) – Whether or not to discretise the wire by edges

  • ndiscr (int) – Number of points to discretise the wire to

  • fallback_method (str) – Method to use in discretised offsetting, will default to square as round is know to be very slow

  • label (str)

  • allow_fallback (bool)

Returns:

Offset wire

Return type:

bluemira.geometry.wire.BluemiraWire

Notes

If primitive offsetting failed, will fall back to a discretised offset implementation, where the fallback kwargs are used. Discretised offsetting is only supported for closed wires.

bluemira.geometry.tools.convex_hull_wires_2d(wires: collections.abc.Sequence[bluemira.geometry.wire.BluemiraWire], ndiscr: int, plane: str = 'xz') bluemira.geometry.wire.BluemiraWire

Perform a convex hull around the given wires and return the hull as a new wire.

The operation performs discretisations on the input wires.

Parameters:
  • wires (collections.abc.Sequence[bluemira.geometry.wire.BluemiraWire]) – The wires to draw a hull around.

  • ndiscr (int) – The number of points to discretise each wire into.

  • plane (str) – The plane to perform the hull in. One of: ‘xz’, ‘xy’, ‘yz’. Default is ‘xz’.

Returns:

  • A wire forming a convex hull around the input wires in the given

  • plane.

Raises:

ValueError – not enough wires

Return type:

bluemira.geometry.wire.BluemiraWire

bluemira.geometry.tools.polygon_revolve_signed_volume(polygon: numpy.typing.ArrayLike) float

Revolve a polygon along the z axis, and return the volume.

A polygon placed in the RHS of the z-axis in the xz plane would have positive volume if it runs clockwise, and negative volume if it runs counter-clockwise.

Similarly a polygon placed on the LHS of the z-axis in the xz plane would have negative volume if it runs clockwise, positive volume if it runs counter-clockwise.

Parameters:

polygon (numpy.typing.ArrayLike) – Stores the x-z coordinate pairs of the four coordinates.

Returns:

Volume of revolved polygon

Raises:

ValueError – shape must be (2, N)

Return type:

float

Notes

Consider one edge of the polygon, which has two vertices, $p$ and $c$.

When revolved around the z-axis, this trapezium forms a the frustum of a cone. The expression for the volume of this frustrum needs to be modified to avoid ZeroDivisionError, thus it is recast into the following (also the simplest) form: \(V = \frac{\pi}{3} (p_z - c_z) (p_x^2 + p_x c_x + c_x^2)\).

Adding together the signed volume of all edges, the excess negative volume from one side would cancel out the excess positive volume from the other, such that abs(signed volume)= the volume of the polygon after being revolved around the z-axis.

bluemira.geometry.tools.partial_diff_of_volume(three_vertices: collections.abc.Sequence[collections.abc.Sequence[float]], normalised_direction_vector: collections.abc.Iterable[float]) float

Gives the relationship between how the the solid volume varies with the position of one of its verticies. More precisely, it gives gives the the partial derivative of the volume of the solid revolved out of a polygon when one vertex of that polygon is moved in the direction specified by normalised_direction_vector.

Parameters:
  • three_vertices (collections.abc.Sequence[collections.abc.Sequence[float]]) – Contain (x, z) coordinates of the polygon. It extracts only the vertex being moved, and the two vertices around it. three_vertices[0] and three_vertices[2] are anchor vertices that cannot be adjusted. shape (3, 2)

  • normalised_direction_vector (collections.abc.Iterable[float]) – Direction that the point is allowed to move in. shape = (2,)

Returns:

Partial differential of volume

Return type:

float

Notes

Let there be 3 points, \(q\), \(r\), and \(s\), forming two edges of a polygon. When r is moved, the polygon’s revolved solid volume changes. After a hefty amount of derivation, everything cancels out to give the expression .. math:

\frac{dV}{d r_z} = q_z q_x - r_z q_x + 2 q_z r_x - 2 s_z r_x + r_z s_x - s_z s_x
\frac{dV}{d r_x} = (q_x + r_x + s_x) (s_x - q_x)

The dot product between the direction of motion and the vector \(\frac{dV}{dr}\) gives the required scalar derivative showing “how much does the volume change when r is moved in a certain direction by one unit length”.

bluemira.geometry.tools.revolve_shape(shape: bluemira.geometry.base.BluemiraGeoT, base: numpy.typing.ArrayLike = (0.0, 0.0, 0.0), direction: numpy.typing.ArrayLike = (0.0, 0.0, 1.0), degree: float = 180, label: str = '') bluemira.geometry.base.BluemiraGeoT

Apply the revolve (base, dir, degree) to this shape

Parameters:
  • shape (bluemira.geometry.base.BluemiraGeoT) – The shape to be revolved

  • base (numpy.typing.ArrayLike) – Origin location of the revolution

  • direction (numpy.typing.ArrayLike) – The direction vector

  • degree (float) – revolution angle

  • label (str)

Returns:

The revolved shape.

Raises:

FreeCADError – Cannot revolve shape

Return type:

bluemira.geometry.base.BluemiraGeoT

bluemira.geometry.tools.extrude_shape(shape: bluemira.geometry.base.BluemiraGeo, vec: numpy.typing.ArrayLike, label: str = '') bluemira.geometry.solid.BluemiraSolid

Apply the extrusion along vec to this shape

Parameters:
  • shape (bluemira.geometry.base.BluemiraGeo) – The shape to be extruded

  • vec (numpy.typing.ArrayLike) – The vector along which to extrude

  • label (str) – label of the output shape

Return type:

The extruded shape.

class bluemira.geometry.tools.SweepShapeTransition

Bases: enum.IntEnum

Inheritance diagram of bluemira.geometry.tools.SweepShapeTransition

Sweep shape corner transition options

DEFAULT = 0
RIGHT_CORNER = 1
ROUND_CORNER = 2
bluemira.geometry.tools.sweep_shape(profiles: bluemira.geometry.wire.BluemiraWire | collections.abc.Iterable[bluemira.geometry.wire.BluemiraWire], path: bluemira.geometry.wire.BluemiraWire, *, solid: bool = True, frenet: bool = True, transition: SweepShapeTransition | int = SweepShapeTransition.DEFAULT, label: str = '') bluemira.geometry.solid.BluemiraSolid | bluemira.geometry.shell.BluemiraShell

Sweep a profile along a path.

Parameters:
Return type:

Swept geometry object

bluemira.geometry.tools.loft_shape(profiles: collections.abc.Iterable[bluemira.geometry.wire.BluemiraWire], *, solid: bool = True, ruled: bool = False, closed: bool = False, label: str = '') bluemira.geometry.solid.BluemiraSolid | bluemira.geometry.shell.BluemiraShell

Loft between a set of profiles.

Parameters:
Return type:

Lofted geometry object

bluemira.geometry.tools.fillet_chamfer_decorator(*, chamfer: bool)

Decorator for fillet and chamfer operations, checking for validity of wire and radius.

Returns:

Decorator for fillet and chamfer operations.

Raises:

GeometryError – Number of edges >= 2, radius >= 0 and planar

Parameters:

chamfer (bool)

bluemira.geometry.tools.fillet_wire_2D(wire: bluemira.geometry.wire.BluemiraWire, radius: float) bluemira.geometry.wire.BluemiraWire

Fillet all edges of a wire

Parameters:
Return type:

The filleted wire

bluemira.geometry.tools.chamfer_wire_2D(wire: bluemira.geometry.wire.BluemiraWire, radius: float) bluemira.geometry.wire.BluemiraWire

Chamfer all edges of a wire

Parameters:
Return type:

The chamfered wire

bluemira.geometry.tools.distance_to(geo1: numpy.typing.ArrayLike | bluemira.geometry.base.BluemiraGeo, geo2: numpy.typing.ArrayLike | bluemira.geometry.base.BluemiraGeo) tuple[float, list[tuple[float, float, float]]]

Calculate the distance between two BluemiraGeos.

Parameters:
Returns:

  • dist – Minimum distance

  • vectors – List of tuples corresponding to the nearest points between geo1 and geo2. The distance between those points is the minimum distance given by dist.

Return type:

tuple[float, list[tuple[float, float, float]]]

bluemira.geometry.tools.split_wire(wire: bluemira.geometry.wire.BluemiraWire, vertex: numpy.typing.ArrayLike, tolerance: float = EPS * 10) tuple[bluemira.geometry.wire.BluemiraWire | None, bluemira.geometry.wire.BluemiraWire | None]

Split a wire at a given vertex.

Parameters:
  • wire (bluemira.geometry.wire.BluemiraWire) – Wire to be split

  • vertex (numpy.typing.ArrayLike) – Vertex at which to split the wire

  • tolerance (float) – Tolerance within which to find the closest vertex on the wire

Returns:

  • wire_1 – First half of the wire. Will be None if the vertex is the start point of the wire

  • wire_2 – Last half of the wire. Will be None if the vertex is the start point of the wire

Raises:

GeometryError: – If the vertex is further away to the wire than the specified tolerance

Return type:

tuple[bluemira.geometry.wire.BluemiraWire | None, bluemira.geometry.wire.BluemiraWire | None]

bluemira.geometry.tools.cut_wire_at_z_value(wire: bluemira.geometry.wire.BluemiraWire, point_z: float, location: CutLocation, point_name: str = 'chosen point_z') bluemira.geometry.wire.BluemiraWire

Remove the parts of the wire below or above a given z-value.

Parameters:
  • wire (bluemira.geometry.wire.BluemiraWire) – Wire shape that needs cutting.

  • point_z (float) – Z-value at point to make the cut.

  • location (CutLocation) – Choose to remove the lower or upper part of the wire after cutting.

  • point_name (str) – String printed in warning message, relevant when applied to an input of interest e.g. x-point location for an Equilibrium.

Returns:

The remaining section of wire after cutting.

Return type:

cut_wire

Raises:

ValueError – No parts of shape found

class bluemira.geometry.tools.CutLocation(*args, **kwds)

Bases: enum.Enum

Inheritance diagram of bluemira.geometry.tools.CutLocation

Used in cut_wire_at_z_value to choose which part of the shape to remove

UPPER

Remove upper part of shape after cut

LOWER

remove lower part of shape after cut

bluemira.geometry.tools.slice_shape(shape: bluemira.geometry.base.BluemiraGeo, plane: bluemira.geometry.plane.BluemiraPlane) list[numpy.ndarray] | list[bluemira.geometry.wire.BluemiraWire] | None

Calculate the plane intersection points with an object

Parameters:
Returns:

  • Wire (Union[List[np.ndarray], None]) – returns array of intersection points

  • Face, Solid, Shell (Union[List[BluemiraWire], None]) – list of intersections lines

Return type:

list[numpy.ndarray] | list[bluemira.geometry.wire.BluemiraWire] | None

Notes

Degenerate cases such as tangets to solid or faces do not return intersections if the shape and plane are acting at the Plane base. Further investigation needed.

bluemira.geometry.tools.get_wire_plane_intersect(convex_bm_wire: bluemira.geometry.wire.BluemiraWire, plane: bluemira.geometry.plane.BluemiraPlane, cut_direction: numpy.typing.NDArray[float]) numpy.typing.NDArray[float]

Cut a wire using a plane.

Parameters:
Returns:

np.ndarray with shape==(3,)

Return type:

intersection point

bluemira.geometry.tools.circular_pattern(shape: bluemira.geometry.base.BluemiraGeo, origin: numpy.typing.ArrayLike = (0, 0, 0), direction: numpy.typing.ArrayLike = (0, 0, 1), degree: float = 360, n_shapes: int = 10) list[bluemira.geometry.base.BluemiraGeo]

Make a equally spaced circular pattern of shapes.

Parameters:
  • shape (bluemira.geometry.base.BluemiraGeo) – Shape to pattern

  • origin (numpy.typing.ArrayLike) – Origin vector of the circular pattern

  • direction (numpy.typing.ArrayLike) – Direction vector of the circular pattern

  • degree (float) – Angle range of the patterning

  • n_shapes (int) – Number of shapes to pattern

Return type:

List of patterned shapes, the first element is the original shape

bluemira.geometry.tools.mirror_shape(shape: bluemira.geometry.base.BluemiraGeo, base: numpy.typing.ArrayLike, direction: numpy.typing.ArrayLike, label='') bluemira.geometry.base.BluemiraGeo

Get a mirrored copy of a shape about a plane.

Parameters:
  • shape (bluemira.geometry.base.BluemiraGeo) – Shape to mirror

  • base (numpy.typing.ArrayLike) – Mirror plane base

  • direction (numpy.typing.ArrayLike) – Mirror plane normal direction

Return type:

The mirrored shape

Raises:

GeometryError – if the norm of the direction tuple is <= 3*EPS

bluemira.geometry.tools.is_convex(points: numpy.typing.NDArray)

Check that the the list of xz points are strictly convex, i.e. Not even collinear points are allowed.

However, repeated points are allowed, as the repeated point would be ignored; and points are allowed to be entered in 3D (xyz), but the y component would be ignored as well.

Parameters:

points (numpy.typing.NDArray) – A list of points that we want to check the convexity for. Shape = (n, 2/3)

Return type:

boolean

bluemira.geometry.tools.save_as_STP(shapes: bluemira.geometry.base.BluemiraGeoT | collections.abc.Iterable[bluemira.geometry.base.BluemiraGeoT], filename: str, **kwargs)

Saves a series of Shape objects as a STEP assembly

Parameters:
  • shapes (bluemira.geometry.base.BluemiraGeoT | collections.abc.Iterable[bluemira.geometry.base.BluemiraGeoT]) – List of shape objects to be saved

  • filename (str) – Full path filename of the STP assembly

bluemira.geometry.tools.save_cad(shapes: bluemira.geometry.base.BluemiraGeoT | collections.abc.Iterable[bluemira.geometry.base.BluemiraGeoT], filename: str | pathlib.Path, cad_format: str | bluemira.codes._freecadapi.CADFileType = 'stp', names: str | list[str] | None = None, **kwargs)

Save the CAD of a component (eg a reactor) or a list of components

Parameters:
  • shapes (bluemira.geometry.base.BluemiraGeoT | collections.abc.Iterable[bluemira.geometry.base.BluemiraGeoT]) – shapes to save

  • filename (str | pathlib.Path) – Full path filename for the CAD file

  • cad_format (str | bluemira.codes._freecadapi.CADFileType) – file format to save as

  • names (str | list[str] | None) – Names of shapes to save

  • kwargs – arguments passed to cadapi save function

bluemira.geometry.tools.import_cad(filename: str | pathlib.Path, cad_format: str | bluemira.codes._freecadapi.CADFileType | None = None, unit_scale: str = 'm', **kwargs) bluemira.geometry.base.BluemiraGeo | list[bluemira.geometry.base.BluemiraGeo]

Import CAD from file

Returns:

The imported objects

Parameters:
Return type:

bluemira.geometry.base.BluemiraGeo | list[bluemira.geometry.base.BluemiraGeo]

bluemira.geometry.tools._nb_dot_2D(v_1, v_2)
Returns:

Numba 2-D dot product

bluemira.geometry.tools._nb_clip(val, a_min, a_max)
Returns:

Numba 1-D clip.

bluemira.geometry.tools._signed_distance_2D(point: numpy.ndarray, polygon: numpy.ndarray) float

2-D function for the signed distance from a point to a polygon. The return value is negative if the point is outside the polygon, and positive if the point is inside the polygon.

Parameters:
  • point (numpy.ndarray) – 2-D point

  • polygon (numpy.ndarray) – 2-D set of points (closed)

Return type:

Signed distance value of the point to the polygon

Notes

Credit: Inigo Quilez (https://www.iquilezles.org/)

bluemira.geometry.tools.signed_distance_2D_polygon(subject_poly: numpy.ndarray, target_poly: numpy.ndarray) numpy.ndarray

2-D vector-valued signed distance function from a subject polygon to a target polygon. The return values are negative for points outside the target polygon, and positive for points inside the target polygon.

Parameters:
  • subject_poly (numpy.ndarray) – Subject 2-D polygon

  • target_poly (numpy.ndarray) – Target 2-D polygon (closed polygons only)

Return type:

Signed distances from the vertices of the subject polygon to the target polygon

Notes

This can used as a keep-out-zone constraint, in which the target polygon would be the keep-out-zone, and the subject polygon would be the shape which must be outsize of the keep-out-zone.

The target polygon must be closed.

bluemira.geometry.tools.signed_distance(origin: bluemira.geometry.wire.BluemiraWire | bluemira.geometry.coordinates.Coordinates, target: bluemira.geometry.wire.BluemiraWire | bluemira.geometry.coordinates.Coordinates) float

Single-valued signed “distance” function between two wires. Will return negative values if origin does not touch or intersect target, 0 if there is one intersection, and a positive estimate of the intersection length if there are overlaps.

Parameters:
Return type:

Closest distance between origin and target

Notes

This is not a pure implementation of a distance function, as for overlapping wires a metric of the quantity of overlap is returned (a positive value). This nevertheless enables the use of such a function as a constraint in gradient-based optimisers.

This function has been extended to allow the target wire to be a point

(Coordinates) as well

The signed “distance” function can be expressed as:

\[\begin{split}d (\textbf{p}_1, \textbf{p}_2) = \begin{cases} - \| \textbf{p}_1 - \textbf{p}_2 \| & \text{if no intersection} \\ 0 & \text{if one intersection} \\ \text{positive estimate of overlap length} & \text{if overlap exists} \end{cases}\end{split}\]
bluemira.geometry.tools.raise_error_if_overlap(origin: bluemira.geometry.wire.BluemiraWire | bluemira.geometry.coordinates.Coordinates, target: bluemira.geometry.wire.BluemiraWire | bluemira.geometry.coordinates.Coordinates, origin_name: str = '', target_name: str = '')
Raises:

GeometryError – if two wires/points intersects overlaps.

Parameters:
bluemira.geometry.tools.connect_shapes(shapes: collections.abc.Iterable[bluemira.geometry.base.BluemiraGeo], tolerance: float = 0.0, label: str = '') bluemira.geometry.base.BluemiraGeo

Connect (imprint) a list of shapes together.

This is similar to a boolean fuse operation, but connects the interior walls of solid or shells (removeing the excess).

For wires it will fuse them, keeping the biggest joined piece.

Parameters:
  • shapes (collections.abc.Iterable[bluemira.geometry.base.BluemiraGeo]) – List of shape objects to be saved

  • label (str) – Label for the resulting shape

  • tolerance (float)

Return type:

Result of the connect operation.

Raises:
  • GeometryError – In case the boolean operation fails.

  • ValueError – All shapes (2 or more) must be the same type

bluemira.geometry.tools.make_compound(shapes: collections.abc.Iterable[bluemira.geometry.base.BluemiraGeo], label: str = '') bluemira.geometry.compound.BluemiraCompound

Make a compound of the given shapes.

The shapes must all be the same topologic type (all solids, shells etc.). No mixing.

Parameters:
Return type:

Result of the connect operation.

Raises:
  • GeometryError – In case the boolean operation fails.

  • ValueError – All shapes (2 or more) must be the same type

bluemira.geometry.tools.boolean_fuse(shapes: collections.abc.Iterable[bluemira.geometry.base.BluemiraGeo], label: str = '') bluemira.geometry.base.BluemiraGeo

Fuse two or more shapes together. Internal splitter are removed.

Parameters:
Return type:

Result of the boolean operation.

Raises:
  • GeometryError – In case the boolean operation fails.

  • ValueError – All shapes (2 or more) must be the same type

bluemira.geometry.tools.boolean_cut(shape: bluemira.geometry.base.BluemiraGeoT, tools: bluemira.geometry.base.BluemiraGeoT | collections.abc.Iterable[bluemira.geometry.base.BluemiraGeoT]) bluemira.geometry.base.BluemiraGeoT | list[bluemira.geometry.base.BluemiraGeoT]

Subtract from the base, a (list of) topo shapes cut (tools).

Parameters:
  • shape (bluemira.geometry.base.BluemiraGeoT) – the reference object

  • tools (bluemira.geometry.base.BluemiraGeoT | collections.abc.Iterable[bluemira.geometry.base.BluemiraGeoT]) – List of BluemiraGeo shape objects to be used as tools.

Return type:

Result of the boolean cut operation.

Raises:

error – GeometryError: In case the boolean operation fails.

Notes

Example:

Before cutting: shape = a cube, tools = a sphere.

../../../../_images/before_cut.png

After cutting: a cube with a sphere subtracted out of it.

../../../../_images/after_cut.png
bluemira.geometry.tools.boolean_fragments(shapes: collections.abc.Iterable[bluemira.geometry.solid.BluemiraSolid], tolerance: float = 0.0) tuple[bluemira.geometry.compound.BluemiraCompound, list[list[bluemira.geometry.solid.BluemiraSolid]]]

Split a list of shapes into their Boolean fragments.

Parameters:
  • shapes (collections.abc.Iterable[bluemira.geometry.solid.BluemiraSolid]) – List of BluemiraSolids to be split into Boolean fragments

  • tolerance (float) – Tolerance with which to perform the operation

Returns:

  • compound – A compound of the unique fragments

  • fragment_map – An ordered list of groups of solid Boolean fragments (ordered in terms of input ordering)

Return type:

tuple[bluemira.geometry.compound.BluemiraCompound, list[list[bluemira.geometry.solid.BluemiraSolid]]]

Notes

Labelling will be lost. This function is only tested on solids.

bluemira.geometry.tools.point_inside_shape(point: collections.abc.Iterable[float], shape: bluemira.geometry.base.BluemiraGeoT) bool

Check whether or not a point is inside a shape.

Parameters:
  • point (collections.abc.Iterable[float]) – Coordinates of the point

  • shape (bluemira.geometry.base.BluemiraGeoT) – Geometry to check with

Return type:

Whether or not the point is inside the shape

bluemira.geometry.tools.point_on_plane(point: collections.abc.Iterable[float], plane: bluemira.geometry.plane.BluemiraPlane, tolerance: float = D_TOLERANCE) bool

Check whether or not a point is on a plane.

Parameters:
  • point (collections.abc.Iterable[float]) – Coordinates of the point

  • plane (bluemira.geometry.plane.BluemiraPlane) – Plane to check

  • tolerance (float) – Tolerance with which to check

Return type:

Whether or not the point is on the plane

bluemira.geometry.tools.serialise_shape(shape: bluemira.geometry.base.BluemiraGeoT)

Serialise a BluemiraGeo object.

Returns:

A serialised BluemiraGeo object.

Parameters:

shape (bluemira.geometry.base.BluemiraGeoT)

bluemira.geometry.tools.deserialise_shape(buffer: dict) bluemira.geometry.base.BluemiraGeoT | None

Deserialise a BluemiraGeo object obtained from serialise_shape.

Parameters:

buffer (dict) – Object serialisation as stored by serialise_shape

Return type:

The deserialised BluemiraGeo object.

bluemira.geometry.tools.get_shape_by_name(shape: bluemira.geometry.base.BluemiraGeoT, name: str) list[bluemira.geometry.base.BluemiraGeoT]

Search through the boundary of the shape and get any shapes with a label corresponding to the provided name. Includes the shape itself if the name matches its label.

Parameters:
  • shape (bluemira.geometry.base.BluemiraGeoT) – The shape to search for the provided name.

  • name (str) – The name to search for.

Return type:

The shapes known to the provided shape that correspond to the provided name.

bluemira.geometry.tools.find_clockwise_angle_2d(base: numpy.ndarray, vector: numpy.ndarray) numpy.ndarray

Find the clockwise angle between the 2D vectors base and vector in the range [0°, 360°).

Parameters:
  • base (numpy.ndarray) – The vector to start the angle from.

  • vector (numpy.ndarray) – The vector to end the angle at.

Return type:

The clockwise angle between the two vectors in degrees.

Raises:
  • TypeError – both base and vector must be arrays

  • ValueError – Array shapes must be (2, N)