magnelio.geo#
Geometry is built from primitives (Brick, Cylinder, …) combined with
the Boolean operators +, - and &, then refined with chainable
verbs (.translated(), .mirrored(), .filleted(), …).
The operators and verbs are not listed on each primitive: they are
shared by every geometry object and documented once on
Shape, the base class all of them inherit from.
Start there when you are looking for what can be done to a shape;
the classes below describe what each shape is.
CSG geometry subsystem.
Base class:
Shape— the Boolean operators and the chainable verbs every geometry object shares; the documented home of both.Primitives:
Brick,Sphere,Cylinder,Cone,Torus,Face; curves:Curve(polyline / arc / spline / helix).Profiles:
Pathdraws a chained curve segment by segment;Curve.joined()chains existing curves,Curve.covered()turns a closed one into a planar sheet andCurve.traced()into a conductor track.Operations:
Union,Intersection,Difference— or the operatorsa + b/a - b/a & bon any shape — andLoftthrough a series of cross-sections.Containers:
Group(material-preserving bundle),GeometryModel.Verbs: chainable shape methods —
.translated(),.rotated(),.scaled(),.mirrored(),.chamfered(),.filleted(),.extruded(),.lofted(),.revolved(),.swept(),.shelled(),.thickened(). They are documented onShape, the base class every geometry object inherits from.
GeometryModel lives in the core magnelio namespace; every
other geometry name is public here.
- exception magnelio.geo.GeometryOverlapError#
Raised when shapes in a GeometryModel overlap volumetrically.
- class magnelio.geo.Brick(material=None, name=None, origin=(0.0, 0.0, 0.0), size=(1.0, 1.0, 1.0))#
Axis-aligned rectangular box (cuboid).
- Parameters:
origin (tuple of float) –
(x, y, z)of the minimum-coordinate corner [meters].size (tuple of float) –
(dx, dy, dz)— extents in each direction [meters], each positive. To give two opposite corners in any order instead, usefrom_corners().material (Material, optional) – Material filling this volume. Omit it for a construction solid used only as a Boolean operand.
name (str, optional) – Optional label.
- classmethod from_corners(p1, p2, *, material=None, name=None)#
Build an axis-aligned Brick from two opposite corners.
The corners may be given in any order; each axis is normalised so that the resulting
originholds the minimum coordinate andsizeis non-negative. Theorigin/sizefields are populated as for a directly constructedBrick, so the two forms are interchangeable downstream.- Parameters:
p1 (tuple of float) – Two opposite corners
(x, y, z)of the box [meters], in any order.p2 (tuple of float) – Two opposite corners
(x, y, z)of the box [meters], in any order.material (Material, optional) – Material filling this volume. Omit it for a construction solid used only as a Boolean operand — the two-corner form is the natural spelling for a cutting box.
name (str, optional) – Optional label.
- Return type:
Examples
>>> Brick.from_corners((3e-3, 0, 2e-3), (0, 4e-3, 0), material=pec) Brick(origin=(0.0, 0.0, 0.0), size=(3e-3, 4e-3, 2e-3), ...)
- classmethod from_ranges(*, x1=None, x2=None, dx=None, y1=None, y2=None, dy=None, z1=None, z2=None, dz=None, material=None, name=None)#
Build an axis-aligned Brick from one coordinate range per axis.
Each axis is given by exactly two of its three keywords: the two bounds (
x1,x2), a bound and an extent (x1,dxorx2,dx). Extents may be negative and bounds may come in either order; the result is normalised exactly as infrom_corners(), so both forms produce identical fields and are interchangeable downstream.This is the spelling to reach for when a box is described by the planes it lies between — a substrate between two metal layers, a cutting slab spanning a whole domain — where naming the two opposite corners would interleave the axes.
- Parameters:
x1 (float, optional) – Lower bound, upper bound and extent along x [meters]. Supply exactly two of them.
x2 (float, optional) – Lower bound, upper bound and extent along x [meters]. Supply exactly two of them.
dx (float, optional) – Lower bound, upper bound and extent along x [meters]. Supply exactly two of them.
y1 (float, optional) – The same for y.
y2 (float, optional) – The same for y.
dy (float, optional) – The same for y.
z1 (float, optional) – The same for z.
z2 (float, optional) – The same for z.
dz (float, optional) – The same for z.
material (Material, optional) – Material filling this volume. Omit it for a construction solid used only as a Boolean operand.
name (str, optional) – Optional label.
- Return type:
- Raises:
ValueError – If an axis is given fewer or more than two of its keywords.
See also
Brick.from_cornersBuild the same box from two opposite corners.
Examples
A substrate of thickness
hunder a ground plane atz = 0:Brick.from_ranges( x1=0, dx=w, y1=0, dy=length, z2=0, dz=h, material=fr4 )
>>> Brick.from_ranges(x1=0, x2=3e-3, y1=0, dy=4e-3, z1=2e-3, z2=0) Brick(origin=(0.0, 0.0, 0.0), size=(3e-3, 4e-3, 2e-3), ...)
- class magnelio.geo.Cone(material=None, name=None, origin=(0.0, 0.0, 0.0), bottom_radius=1.0, top_radius=0.0, height=1.0, axis='z')#
Right circular cone (or truncated cone if top_radius > 0).
- Parameters:
origin (tuple of float) –
(x, y, z)center of the bottom face [meters].bottom_radius (float) – Bottom radius [meters].
top_radius (float) – Top radius [meters]. Use 0 for a full cone; the two radii may not both be 0.
height (float) – Height [meters]. A negative height extrudes along
-axisfrom the origin.axis (str or tuple of float) – Axis direction:
'x'/'y'/'z'or any 3-vector.material (Material, optional) – Material filling this volume. Omit it for a construction solid used only as a Boolean operand.
name (str, optional) – Optional label.
- class magnelio.geo.Curve(_build, name=None, _bounds=None, _ends=None, _segments=<factory>)#
An abstract 3D locus backed by an OCC wire (no material).
Do not construct directly — use one of the classmethods (
polyline(),arc(),spline(),helix()). Each stores a builder callable that lazily produces theTopoDS_Wireon first use, cached like every other geometry object.A Curve exposes
_occ_shape()(the wire) andbounding_box(), but nomaterial— a 1D locus is never a physical object on its own.- Parameters:
_build (object)
name (str | None)
_bounds (tuple | None)
_ends (tuple | None)
_segments (tuple)
- classmethod arc(start, through, end, *, name=None)#
A circular arc through three 3D points.
- Parameters:
start (tuple of float) – The arc passes through all three points in order [meters]. The three points must not be collinear.
through (tuple of float) – The arc passes through all three points in order [meters]. The three points must not be collinear.
end (tuple of float) – The arc passes through all three points in order [meters]. The three points must not be collinear.
name (str, optional) – Optional label.
- Return type:
- classmethod helix(*, radius, pitch, turns, origin=(0.0, 0.0, 0.0), axis='z', right_handed=True, name=None)#
An exact helix on a cylinder.
- Parameters:
radius (float) – Helix radius [meters].
pitch (float) – Axial rise per full turn [meters].
turns (float) – Number of turns (may be fractional).
origin (tuple of float) – Base point on the axis [meters], as for
Cylinder.axis (str) – Axis direction:
'x','y', or'z'(default).right_handed (bool) – If True (default) the helix ascends counter-clockwise about the axis; if False it is left-handed.
name (str, optional) – Optional label.
- Return type:
- classmethod polyline(points, *, name=None)#
A polyline (open, straight segments) through 3D points.
- Parameters:
points (sequence of (float, float, float)) – At least 2 vertices [meters].
name (str, optional) – Optional label.
- Return type:
- classmethod spline(points, *, name=None)#
A smooth B-spline interpolating 3D points.
- Parameters:
points (sequence of (float, float, float)) – At least 2 interpolation points [meters].
name (str, optional) – Optional label.
- Return type:
- bounding_box(scale=None)#
Return (min_corner, max_corner) in meters via OCC BRep bounding box.
- Parameters:
scale (float | None)
- Return type:
tuple[tuple[float, float, float], tuple[float, float, float]]
- covered(*, material=None, name=None)#
Return the planar sheet bounded by this closed curve.
The free-form counterpart of
Face, which is limited to axis-normal polygons: any closed planar boundary — arcs, splines and straight runs mixed — becomes a sheet here, and that sheet is the profile forextruded(),revolved(),swept()andthickened().- Parameters:
material (Material, optional) – Material of the thin sheet.
None(default) makes it a construction profile, which is what you want when the sheet only exists to be grown into a solid.name (str, optional) – Optional label.
- Returns:
The planar sheet.
- Return type:
- Raises:
ValueError – If the curve is not closed, or — when the geometry is first built — not planar or self-intersecting.
Examples
A pad with one rounded end, 35 um of copper:
outline = ( Path((0.0, 0.0, 0.0)) .line_to((10e-3, 0.0, 0.0)) .arc_to((10e-3, 4e-3, 0.0), center=(10e-3, 2e-3, 0.0)) .line_to((0.0, 4e-3, 0.0)) .closed() ) pad = outline.covered().extruded(vector=(0, 0, 35e-6), material=copper)
- joined(*curves, name=None)#
Return one curve chaining this curve and curves end to start.
Chaining is what turns the individual segment types into arbitrary profiles: an arc, a straight run and another arc become one boundary, and a boundary that closes on itself can be
covered()into a sheet and extruded or revolved into a solid.Segments must be given in order, each starting where the previous one ended. They need not agree to the last bit — anything within one part per million of the chain’s overall size counts as the same point — but a real gap is an error rather than something to bridge silently.
- Parameters:
*curves (Curve) – The segments to append, in order.
name (str, optional) – Optional label.
- Returns:
The chained curve. It is open or closed depending on whether the last segment ends where the first one starts; an open chain is a perfectly good sweep path.
- Return type:
- Raises:
TypeError – If an argument is not a
Curve.ValueError – If consecutive segments do not meet.
Examples
A D-shaped profile — a straight back and a semicircular front:
back = Curve.polyline([(0, -5e-3, 0), (0, 5e-3, 0)]) front = Curve.arc((0, 5e-3, 0), (5e-3, 0, 0), (0, -5e-3, 0)) profile = back.joined(front) rod = profile.covered().extruded(vector=(0, 0, 20e-3), material=copper)
- traced(*, width, thickness, caps='round', normal=None, material=None, name=None)#
Return the conductor track running along this curve.
The curve is the track’s centreline: it is widened by half the width to each side within its own plane, then given a metallisation thickness perpendicular to it. That is the direct route from a routed path to the copper on a board, without assembling the track from separate straight and bent pieces.
Corners of a polyline centreline come out rounded on the outside — a consequence of offsetting a path, and closer to a fabricated track than a mitred corner would be.
- Parameters:
width (float) – Track width [meters].
thickness (float) – Metallisation thickness [meters]. Negative grows the track on the other side of the centreline’s plane.
caps ({"round", "flat"}) – How an open track ends:
"round"(default) closes it with a half-disc,"flat"cuts it off square, which is what a track meeting a port plane needs. Ignored for a closed curve, which has no ends.normal (str or sequence of float, optional) – Normal of the plane the track lies in. Only needed when the curve does not determine one — a straight centreline lies in infinitely many planes.
material (Material, optional) – Material of the track.
None(default) makes it a construction body.name (str, optional) – Optional label.
- Returns:
The track solid.
- Return type:
- Raises:
ValueError – If the curve is not planar, if the plane is undetermined and no normal was given, or if the width is too large for the path’s bends and clearances.
Examples
A 35 um copper feed line ending square at both ports:
line = route.traced( width=0.6e-3, thickness=35e-6, caps="flat", normal="z", material=copper, )
- class magnelio.geo.Cylinder(material=None, name=None, origin=(0.0, 0.0, 0.0), radius=1.0, height=1.0, axis='z', inner_radius=0.0, angle_deg=None)#
Right circular cylinder, optionally hollow and optionally a segment.
Left alone,
inner_radiusandangle_deggive a plain solid cylinder. Settinginner_radiusbores it out into a tube, settingangle_degcuts a wedge out of the full turn, and setting both gives the curved slab that a segmented electrode or a septum of a circular structure is made of.Angles are measured about axis in the same right-handed sense as
rotated(). Zero lies on the first coordinate direction perpendicular to axis —+xfor an'z'axis,+yfor an'x'axis.- Parameters:
origin (tuple of float) –
(x, y, z)center of the bottom face [meters].radius (float) – Outer radius [meters].
height (float) – Height [meters]. A negative height extrudes along
-axisfrom the origin.axis (str or tuple of float) – Axis direction:
'x'/'y'/'z'or any 3-vector (default'z').inner_radius (float) – Radius of the axial bore [meters]; 0 (default) for a solid cylinder, otherwise less than
radius.angle_deg (float or tuple of float, optional) – Angular extent [degrees]: a single value for a segment starting at zero, or
(start, end)for one anywhere.None(default) is the full turn.material (Material, optional) – Material filling this volume. Omit it for a construction solid used only as a Boolean operand.
name (str, optional) – Optional label.
Examples
A 20 degree segment of a hollow cylinder — a curved electrode:
electrode = Cylinder( radius=12e-3, inner_radius=10e-3, height=30e-3, angle_deg=(0, 20), material=pec, )
- class magnelio.geo.Difference(base, *tools, material=None, name=None)#
Boolean difference: base minus one or more tools.
- Parameters:
base (shape) – Shape to subtract from.
*tools (shape) – One or more shapes to subtract. When multiple tools are given they are fused first and then cut from the base in a single Boolean operation.
material (Material or None) – Material for the resulting volume. Defaults to base’s material.
name (str or None) – Optional label.
- class magnelio.geo.Face(normal, points, position=0.0, material=None, name=None)#
A standalone planar polygon face.
A Face lives in an axis-normal plane and carries an optional material:
no material (default) — a construction profile: the input to
extruded(),revolved(),swept()orthickened(), each of which turns it into a solid. A material-less Face is not a physical object and is not meshed on its own.with a material — a thin sheet. The object is free to carry the material field, but thin-sheet physics wiring is deferred, so a material-carrying Face cannot yet be added to a
GeometryModelfor meshing.
The polygon is given as in-plane
(u, v)points;(u, v)map to the two axes orthogonal to normal following the package convention (normal'x'→ u=y, v=z;'y'→ u=x, v=z;'z'→ u=x, v=y), the same framecross_section_polygons()uses.- Parameters:
normal (str) – Plane normal axis:
'x','y', or'z'.points (sequence of (float, float)) – In-plane
(u, v)vertices [meters]; at least 3, without self-intersection. The polygon is closed automatically.position (float) – Position of the plane along the normal axis [meters] (default 0).
material (Material, optional) – Material of the thin sheet.
None(default) = construction profile.name (str, optional) – Optional label.
- class magnelio.geo.Group(*shapes, name=None)#
A logical bundle of shapes that preserves each member’s material.
Unlike
Union— which fuses its operands into a single solid carrying one material — a Group is a heterogeneous container: every member keeps its own material and its own OCC solid. It exists so a multi-material assembly (e.g. an SMA connector: PEC pin + PTFE dielectric + PEC shell) can be positioned and added to a model as one unit, without collapsing the materials.A Group therefore has no single
materialor_occ_shape— it is a compound node exposingmembers()andbounding_box(). Consequences:Transforms distribute over members.
translated()on a Group returns a new Group whose members are each translated; likewiserotated(),scaled()andmirrored(). The repeat helpers grow agroup=Truesibling ofunite=Truethat aggregates copies into a Group instead of fusing them.Nesting is allowed (a Group of Groups);
members()flattens recursively.Flattened at
add(), so the mesher, material filling and overlap layers never see a Group.CSG Boolean ops reject a Group (
Union,Intersection,Difference), since it has no single material or solid.
- Parameters:
*shapes (shape or Group) – Leaf shapes and/or nested Groups to bundle.
name (str, optional) – Optional label.
- bounding_box()#
Axis-aligned bounding box enclosing every member [meters].
- members()#
Yield the leaf shapes, recursively flattening nested Groups.
Any transform applied to the Group has already been baked into each member (transforms distribute on application), so the yielded leaves are ready to hand to the mesher.
- volume(scale=None)#
Total volume of every member [cubic meters].
A Group is a bundle of separate solids, so the volumes simply add; members are not fused first, and a Group whose members overlapped would count the overlap twice — which a
GeometryModeldoes not allow in the first place.- Parameters:
scale (float | None)
- Return type:
float
- class magnelio.geo.Intersection(shape_a, shape_b, material=None, name=None)#
Boolean intersection of two shapes.
- Parameters:
shape_a (object) – Base shape.
shape_b (object) – Tool shape.
material (Material | None) – Material for the resulting volume. Defaults to shape_a’s material.
name (str | None) – Optional label.
- class magnelio.geo.Loft(*sections, blend='spline', material=None, name=None)#
A solid interpolating an ordered series of cross-sections.
The way to build a transition no primitive covers: a horn flaring from a waveguide mouth to a wider aperture, a taper from a round cross-section to a square one, a matching section that steps through several intermediate outlines. Where
lofted()bridges one face of a solid to a face of another,Lofttakes the profiles themselves and as many of them as the shape needs.- Parameters:
*sections (Face, covered Curve, or closed Curve) – At least two cross-sections, in the order the solid passes through them. Sheets contribute their outer boundary. The sections should wind the same way — a reversed one produces a twisted, self-intersecting solid rather than an error.
blend ({'spline', 'ruled'}) – How consecutive sections are joined.
'spline'(default) passes one smooth surface through all of them;'ruled'joins them with straight surfaces, so the solid is a stack of frusta.material (Material, optional) – Material of the lofted solid.
None(default) makes it a construction body, since cross-sections carry no volume material to inherit.name (str, optional) – Optional label.
- Raises:
Examples
A horn flaring from a square throat to a wider square mouth:
throat = geo.Face(normal="z", points=[...], position=0.0) mouth = geo.Face(normal="z", points=[...], position=60e-3) horn = geo.Loft(throat, mouth, blend="ruled", material=pec)
- class magnelio.geo.Path(start, _segments=<factory>)#
A pen that draws a chained
Curve.Start at a point, then append one segment per call; each segment begins where the previous one ended, so only its end (and whatever shapes it) has to be given. Finish with
curve()for an open path orclosed()for a loop, which is whatcovered()needs to make a sheet.A Path is immutable. Every segment call returns a new Path and leaves the receiver alone, so a common prefix can be branched into several outlines.
- Parameters:
start (tuple of float) – The 3D point
(x, y, z)the pen starts from [meters]._segments (tuple)
Examples
A slot outline with two rounded ends:
outline = ( Path((0.0, -1e-3, 0.0)) .line_to((6e-3, -1e-3, 0.0)) .arc_to((6e-3, 1e-3, 0.0), center=(6e-3, 0.0, 0.0)) .line_to((0.0, 1e-3, 0.0)) .arc_to((0.0, -1e-3, 0.0), center=(0.0, 0.0, 0.0)) .closed() ) slot = outline.covered().extruded(vector=(0, 0, t), material=copper)
- arc_to(end, *, via=None, center=None, normal=None, major=False)#
Append a circular arc ending at end.
Give exactly one of via or center — two ways of pinning down which arc is meant:
via — a point the arc passes through. Always unambiguous, and the form to reach for when the centre is not what you know.
center — the centre of the circle, which must be equidistant from the current point and end. This is the form for a slice of a round part, where the axis is the given quantity.
Two arcs join any pair of points on a circle, and in 3D a pair of diametrically opposite points does not even fix the plane. With center, add normal to settle both at once: the arc then runs counter-clockwise about normal, so swapping the two endpoints gives the complementary arc. Without normal the shorter arc is drawn (or the longer one with major), and diametrically opposite ends are rejected.
- Parameters:
end (tuple of float) – End point
(x, y, z)[meters].via (tuple of float, optional) – A point on the arc, between start and end.
center (tuple of float, optional) – Centre of the arc’s circle.
normal (str or sequence of float, optional) – With center: the axis the arc turns about —
'x','y','z', or any non-zero 3-vector. The arc runs counter-clockwise about it, seen from the tip of the axis. Both endpoints must lie in the plane through center perpendicular to it.major (bool) – With center and no normal: take the long way round (default False).
- Returns:
A new Path ending at end.
- Return type:
- Raises:
ValueError – If neither or both of via and center are given, if center is not equidistant from both endpoints, if the endpoints do not lie in the plane normal describes, or if they are diametrically opposite and no normal was given to say which arc is meant.
Examples
The rounded end of a slot, turning about
z:path.arc_to((0.0, -1e-3, 0.0), center=(0.0, 0.0, 0.0), normal="z")
- closed(*, name=None)#
Return the drawn path as a closed
Curve.A straight segment back to the start point is appended unless the path already ends there, so the result is always a loop and can be
covered()into a sheet.- Parameters:
name (str, optional) – Optional label.
- Returns:
The closed curve.
- Return type:
- curve(*, name=None)#
Return the drawn path as a
Curve.The path is taken as drawn: open unless the last segment happens to end where the first one started. Use
closed()to make a loop.- Parameters:
name (str, optional) – Optional label.
- Return type:
- line_to(point)#
Append a straight segment ending at point.
- Parameters:
point (tuple of float) – End point
(x, y, z)[meters].- Returns:
A new Path ending at point.
- Return type:
- spline_to(*points)#
Append a smooth spline through points, ending at the last one.
- Parameters:
*points (tuple of float) – One or more 3D points [meters]; the spline interpolates all of them in order.
- Returns:
A new Path ending at the last point.
- Return type:
- property current: tuple#
The point the next segment will start from [meters].
- class magnelio.geo.Shape#
Base class of every CSG shape: Boolean operators and chainable verbs.
Every geometry object — a primitive (
Brick,Cylinder, …), the result of a Boolean operation, and the result of any verb below — is aShapeand supports everything documented here.Shapeis a base type, not something to instantiate directly.Shapes are immutable. Every operator and verb returns a new shape; the receiver is never modified. That is what makes the calls chainable:
pin = Cylinder(radius=0.5e-3, height=4e-3, material=pec) part = pin.rotated("y", 90.0).translated((0, 0, 1e-3)) - hole
Materials follow the base operand. A Boolean result takes the material of its base (
Difference) resp. first (Union,Intersection) operand, and a transformed shape keeps the material of the shape it came from. Tools and profiles therefore need no material of their own — seeBrickfor construction bodies.Repetition.
translated()androtated()can produce a whole series of copies in one call viarepeat;mirrored()produces exactly one image. All three share the same options for what to do with the copies:copyInclude the untransformed original in the result.
uniteFuse everything into a single
Union— one solid with one material.groupBundle everything into a
Group, where each copy keeps its own material. Mutually exclusive withunite.
Without any of them the return value is a single shape; with them it is a list, a
Unionor aGroup.- bounding_box(scale=None)#
Return the axis-aligned bounding box of this shape.
The box is computed from the CAD kernel’s representation, so it accounts for the true geometry rather than the shape’s nominal parameters — a rotated brick reports the box of the rotated solid.
- Parameters:
scale (float, optional) – Unit scale factor at which to build the kernel shape. Leave it unset: the scale is then derived from the shape itself so the result is correct for models spanning nanometres to kilometres.
- Returns:
(min_corner, max_corner), each(x, y, z)in meters.- Return type:
tuple
- chamfered(*, near=None, face_near=None, edges=None, distance)#
Return this shape with a chamfer (a flat bevel) on selected edges.
Exactly one of near, face_near or edges must be given — they are three ways of naming the edges to work on.
- Parameters:
near (tuple or list of tuples, optional) – 3D point(s)
(x, y, z)near the edge(s) to chamfer. A single point selects the one nearest edge; a list selects the nearest edge for each point.face_near (tuple of float, optional) – 3D point near a face. All edges of the nearest face are chamfered.
edges (str, optional) –
"all"to chamfer every edge of the shape.distance (float or tuple of float) – Chamfer distance [meters]. A single value gives a symmetric chamfer, a pair
(d1, d2)an asymmetric one.
- Returns:
A new shape with the chamfer applied, same material.
- Return type:
- extruded(vector, *, face_near=None, material=None)#
Extrude a face of this shape along a vector into a new solid.
The result is a standalone solid, not fused with the shape it came from. Two input forms:
a standalone
Face— the Face is the profile and face_near is unused;any solid — the face nearest face_near is extruded.
- Parameters:
vector (tuple of float) –
(dx, dy, dz)extrusion direction and length [meters].face_near (tuple of float, optional) – 3D point near the face to extrude. Required for a solid, ignored for a Face.
material (Material, optional) – Material of the extruded solid. Defaults to this shape’s material; required when extruding a construction Face, which has none to inherit.
- Returns:
The extruded solid.
- Return type:
- filleted(*, near=None, face_near=None, edges=None, radius)#
Return this shape with a fillet (a rounded edge) on selected edges.
Exactly one of near, face_near or edges must be given. Rounding sharp metal edges is the usual reason: a right-angled edge concentrates the field far more than any real fabricated part does.
- Parameters:
near (tuple or list of tuples, optional) – 3D point(s)
(x, y, z)near the edge(s) to fillet.face_near (tuple of float, optional) – 3D point near a face. All edges of the nearest face are filleted.
edges (str, optional) –
"all"to fillet every edge of the shape.radius (float) – Fillet radius [meters].
- Returns:
A new shape with the fillet applied, same material.
- Return type:
- lofted(face_near, other, other_face_near, *, material=None, blend='spline', tension=None)#
Loft a solid between a face of this shape and one of other.
Takes the outer wire of the face of this shape nearest face_near and of the face of other nearest other_face_near, then builds the transition between them — the way to model a taper between two different cross-sections, such as a waveguide-to-coax transition.
Both points select by proximity, not by containment: the face nearest the point wins, and a point on a shared edge is equally near several faces. Aim at the middle of the intended face, or just outside it along its normal, rather than at a corner.
- Parameters:
face_near (tuple of float) – 3D point near the start face, on this shape.
other (Shape) – The shape providing the end profile.
other_face_near (tuple of float) – 3D point near the end face, on other.
material (Material, optional) – Material of the lofted solid. Defaults to this shape’s material.
blend ({'spline', 'ruled', 'tangent'}) – How the two profiles are joined.
'spline'(default) and'ruled'both run straight from one profile to the other and differ only in surface type, so the solid meets each face at whatever angle the straight connection happens to make.'tangent'instead leaves both faces along their outward normal and curves between them, which is what turns a crease at the joint into a smooth bend.tension (float or tuple of float, optional) – Only for
blend='tangent': how stiffly the blend holds its normal direction before turning, as a fraction of the distance between the two face centres. A single value applies to both ends, a(start, end)pair to one each. Defaults to1/3; larger values reach further along the normals and eventually overshoot into a bulge.
- Returns:
The lofted solid.
- Return type:
- Raises:
ValueError – If blend is not one of the three modes, if tension is given for a mode that has no use for it, or if the two faces share a centre point.
Examples
A stripline electrode bending into a coaxial inner conductor, meeting both at a right angle:
transition = electrode.lofted( (0.0, 45.5e-3, 0.0), inner, (0.0, 48e-3, -10e-3), material=pec, blend="tangent", )
- mirrored(normal, position=0.0, *, copy=False, unite=False, group=False)#
Return this shape reflected across a plane.
The plane is the set of points
pwithp · normal == position, so for an axis letter position is simply the coordinate of the plane on that axis.A reflection is not a rotation: it leaves the two in-plane directions untouched and reverses only the normal one. That is what makes it the correct operation for a structure symmetric about a plane but not about the axis normal to it — most planar circuits (dividers, couplers, filters) and every layer stack that differs from top to bottom.
Unlike
translated()androtated()there is no repeat: mirroring twice across one plane reproduces the original.- Parameters:
normal (str or sequence of float) – Plane normal:
'x','y','z', or any non-zero 3-vector (its length is ignored).normal='x'mapsx -> 2 * position - x.position (float) – Signed distance of the plane from the coordinate origin along normal [meters] (default 0).
copy (bool) – Include the unmirrored original in the result — the usual way to complete a symmetric structure from a modelled half.
unite (bool) – Fuse original and image into a single
Union. Requires copy.group (bool) – Bundle them into a
Group, each keeping its own material. Requires copy; mutually exclusive with unite.
- Returns:
The mirror image alone for the default
copy=False, otherwise[original, image]— or aUnion/Groupif requested.- Return type:
- Raises:
ValueError – If unite or group is given without copy: there would be nothing to combine the image with, and silently returning the bare image would be a wrong geometry that still meshes.
Examples
Complete a half-modelled power divider into one solid:
full = half.mirrored("x", copy=True, unite=True)
Mirror a feed line onto the far side of a board:
far = line.mirrored("z", position=h / 2)
- revolved(axis, angle_deg=360.0, *, origin=(0.0, 0.0, 0.0), material=None)#
Revolve this planar profile about an axis into a solid of revolution.
The result is a standalone solid. The profile must not cross the revolution axis — that would produce a self-intersecting solid.
- Parameters:
axis (str or sequence of float) – Revolution axis:
'x','y','z', or any non-zero 3-vector.angle_deg (float) – Revolution angle [degrees] (default 360, a full revolution).
origin (tuple of float) – A point on the revolution axis (default: the coordinate origin).
material (Material, optional) – Material of the revolved solid. Defaults to this shape’s material; required for a construction Face.
- Returns:
The solid of revolution.
- Return type:
- rotated(axis, angle_deg, origin=(0.0, 0.0, 0.0), *, repeat=1, copy=False, unite=False, group=False)#
Return this shape rotated about an axis.
- Parameters:
axis (str or sequence of float) – Rotation axis:
'x','y','z', or any non-zero 3-vector (its length is ignored).angle_deg (float) – Rotation angle [degrees], right-handed about axis. Copy i is rotated by
i * angle_deg.origin (tuple of float) – A point on the rotation axis (default: the coordinate origin).
repeat (int) – Number of rotated copies (default 1) — the way to build a circular array, such as the arms of a hybrid ring or the posts of a rotationally symmetric filter.
copy (bool) – Include the unrotated original in the result.
unite (bool) – Fuse all copies into a single
Union.group (bool) – Bundle all copies into a
Group, each keeping its own material. Mutually exclusive with unite.
- Returns:
A single shape for the default
repeat=1, copy=False, otherwise a list — or aUnion/Groupif requested.- Return type:
Examples
Four posts at 90° spacing around the z axis:
posts = post.rotated("z", 90.0, repeat=3, copy=True, group=True)
- scaled(factor, center=(0.0, 0.0, 0.0))#
Return this shape scaled uniformly about a fixed point.
The scaling is uniform in all three directions; there is no per-axis factor, because a non-uniform scaling would turn cylinders into elliptic cylinders and spheres into ellipsoids, which the primitives cannot represent.
- Parameters:
factor (float) – Uniform scale factor. Note that this is not a way to mirror a shape: a negative factor inverts the shape through center, negating all three axes at once. Use
mirrored()for a reflection.center (tuple of float) – Fixed point of the scaling (default: the coordinate origin).
- Returns:
The scaled shape; a
Groupis scaled member by member about the common center.- Return type:
- shelled(thickness, *, opening_face_near=None)#
Return this solid hollowed out to a constant wall thickness.
The walls are built inward, so the outer surface stays exactly where it was and the shape keeps its footprint — the difference between a solid block and the housing, waveguide or cavity a real part is. Naming faces through opening_face_near leaves them out of the shell, turning them into openings: one for an open box, two opposite ones for a length of waveguide.
- Parameters:
thickness (float) – Wall thickness [meters], positive.
opening_face_near (tuple or list of tuples, optional) – 3D point(s) near the face(s) to leave open. Omit for a closed body with a sealed internal void.
- Returns:
The hollowed solid, same material.
- Return type:
- Raises:
TypeError – If this is a planar sheet — use
thickened()instead.RuntimeError – If the wall does not fit: an offset surface stops being valid once the thickness approaches the smallest local dimension or curvature radius of the solid.
Examples
A length of rectangular waveguide, open at both ends:
tube = block.shelled( thickness=2e-3, opening_face_near=[(0, 0, 0), (0, 0, L)] )
- swept(spine, *, material=None)#
Sweep this planar profile along a curve into a solid.
The profile is moved for you: its centroid is placed on the spine’s start point and its plane turned perpendicular to the spine’s start tangent, then it follows the path. The canonical example is a coil,
Face(...).swept(Curve.helix(...)).
- thickened(thickness, *, direction='forward', material=None)#
Grow this planar sheet into a solid slab.
Only a planar sheet — a
Faceor a coveredCurve— can be thickened. The slab’s footprint is exactly the sheet, which makes this the direct way from a drawn outline to a metallisation of a given thickness, without spelling out the extrusion vector.- Parameters:
thickness (float) – Slab thickness [meters], positive.
direction ({"forward", "backward", "symmetric"}) – Which side of the sheet to grow on.
"symmetric"puts half the thickness on each side, leaving the sheet as the slab’s mid-plane."forward"and"backward"are opposite sides of it; which one is “forward” follows from the plane and is fixed, so if a slab comes out on the wrong side, swap the value.material (Material, optional) – Material of the slab. Defaults to the sheet’s material; required for a construction profile, which has none.
- Returns:
The solid slab.
- Return type:
- Raises:
TypeError – If this is a solid — use
shelled()instead.
Examples
A copper patch from a drawn outline:
patch = outline.covered().thickened(thickness=35e-6, material=copper)
- translated(vector, *, repeat=1, copy=False, unite=False, group=False)#
Return this shape moved by vector.
- Parameters:
vector (tuple of float) –
(dx, dy, dz)translation [meters].repeat (int) – Number of translated copies (default 1). Copy i is shifted by
i * vector, which makes this the way to build a regular array — an antenna array, a via fence, a corrugated wall.copy (bool) – Include the untranslated original in the result.
unite (bool) – Fuse all copies into a single
Union.group (bool) – Bundle all copies into a
Group, each keeping its own material. Mutually exclusive with unite.
- Returns:
A single shape for the default
repeat=1, copy=False, otherwise a list — or aUnion/Groupif requested.- Return type:
Examples
A row of eight vias, one solid:
fence = via.translated((2e-3, 0, 0), repeat=8, copy=True, unite=True)
A
Groupis translated member by member and the result is again a Group, so mixed-material assemblies survive the call intact.
- volume(scale=None)#
Return the volume enclosed by this shape.
Computed from the CAD kernel’s representation, so it accounts for the true geometry rather than the shape’s nominal parameters: a Boolean difference reports what is left, and a chamfered block reports what the chamfer took away. That makes it the direct way to check a construction — a filling factor, a metal volume, the agreement between two ways of building the same part.
- Parameters:
scale (float, optional) – Unit scale factor at which to build the kernel shape. Leave it unset: the scale is then derived from the shape itself so the result is correct for models spanning nanometres to kilometres.
- Returns:
Volume in cubic meters. A planar sheet (
Face, a coveredCurve) has no thickness and reports zero.- Return type:
float
Examples
The fraction of a housing that is metal:
fill = shell.volume() / block.volume()
- class magnelio.geo.Sphere(material=None, name=None, center=(0.0, 0.0, 0.0), radius=1.0)#
Sphere.
- Parameters:
center (tuple of float) –
(x, y, z)center position [meters].radius (float) – Radius [meters], positive.
material (Material, optional) – Material filling this volume. Omit it for a construction solid used only as a Boolean operand.
name (str, optional) – Optional label.
- class magnelio.geo.ThinWire(curve, radius, name=None)#
A thin PEC wire along a Curve (radius far below the cell size).
A new leaf-node category in the geometry-object protocol: like a solid it exposes
.material(always PEC),._occ_shape()(the curve’sTopoDS_Wire) andbounding_box()— so persistence, validation and critical-plane extraction work unchanged — but it has no volume: the mesher never fills or classifies it, it applies the thin-wire sub-cell model instead.- Parameters:
curve (Curve) – The wire’s path (polyline / arc / spline / helix). Rasterised to an axis-aligned edge staircase at meshing time.
radius (float) – Physical wire radius [m]. Must be positive and stay below ~0.3 of the smallest transverse cell along the path (checked at meshing time — the thin-wire model is a sub-cell model; a fatter conductor should be a resolved cylinder instead).
name (str, optional) – Optional label used in warnings and error messages.
- bounding_box(scale=None)#
Bounding box of the wire’s curve (the radius is NOT included).
The radius is a sub-cell model parameter: inflating the box by ~a would introduce feature planes 2a apart and collapse the mesher’s fine cell size.
- Parameters:
scale (float | None)
- Return type:
tuple[tuple[float, float, float], tuple[float, float, float]]
- class magnelio.geo.Torus(material=None, name=None, center=(0.0, 0.0, 0.0), major_radius=1.0, minor_radius=0.25, axis='z')#
Torus.
- Parameters:
center (tuple of float) –
(x, y, z)center of the torus [meters].major_radius (float) – Major radius (center of tube to center of torus) [meters].
minor_radius (float) – Minor radius (tube radius) [meters]. Must stay below major_radius: a tube reaching the symmetry axis would pass through itself.
axis (str or tuple of float) – Symmetry axis:
'x'/'y'/'z'or any 3-vector.material (Material, optional) – Material filling this volume. Omit it for a construction solid used only as a Boolean operand.
name (str, optional) – Optional label.
- class magnelio.geo.Union(*shapes, material=None, name=None)#
Boolean union of two or more shapes.
- Parameters:
shapes – Two or more CSG shapes to unite.
material – Material for the resulting volume. If None, uses the material of the first shape.
name – Optional label.