Creating / 3D printing large O-rings using geometry nodes

I'm trying to create and 3D print large connected O-rings given its length, width, and height (that won't fit on the print bed circularly)

Example: O-ring: length=941mm, width=3mm, and height=5mm and it's created within the print bed of x=250mm y=210mm

Since the O-ring length is larger than the print bed I was thinking of creating a shape like this (where it starts and ends at the same location)



Note: I'll be using TPU which is still very flexible after printed.

I was trying to adapt this but the ends don't connect. Calculating / create / generate specific length of ribbon cable

I also looked at is it possible to make a zigzag form with curve using the whole line?

I also looked at http://teachout1.net/village/fill3.html Fractal Space Filling Curves that loop back to the beginning.

Another thought I had was to start off with a circle with the correct length / circumference, width and height and have it re-configured in a way to fit the given dimensions without it intersecting or crossing over (think indenting a rubber band multiple times)


I was thinking of gluing or melting the ends together but I'm trying to find a better solution.

Update: Markus von Broady mentioned / asked. This is just to create / add O-rings to various old buckets that will hold 3D printer filaments (good way to reuse them). It will be no more than 800mm-950mm in length. PS: I took a string and wrapped it around the bucket to get the length and measured it. It also would be nice if it worked for other printer dimensions to make it work for other users printers.

  • $\begingroup$ I think it's very important you describe what is the range of lengths you're interested in, and are you designing it for yourself and constant printing dimensions 25x21 cm or is it supposed to work for any printing dimensions. $\endgroup$ Feb 19 at 19:56
  • $\begingroup$ It's just to create and add O-rings to various buckets that will hold 3D printer filament. It will be no more than 320mm in length. PS: I took a string and wrapped it around the bucket to get the length. Now that you mention it, it would be nice if it worked for other printers to make it work for other printers. $\endgroup$
    – Rick T
    Feb 19 at 20:01
  • 1
    $\begingroup$ Something's not right here. The smaller dimension of your printing area is 210 mm. The length no more than 320 mm. Give yourself 5 mm margin, and you can print a circle with 200 mm diameter, which gives a $200π ⩳ 628$ mm circumference. So all you need to do is to scale the circle down. $\endgroup$ Feb 19 at 20:08
  • $\begingroup$ Your right I didn't do the math conversion correctly I'll check the conversion / math and update the question. Thanks for the catch. $\endgroup$
    – Rick T
    Feb 21 at 23:34
  • $\begingroup$ What is the smallest radius of curvature the ribbon can support without the printer generating too much internal constraints that could prevent to make it "flat" afterward ? For example, at the middle of the provided red ribbon picture. $\endgroup$ Feb 22 at 12:54

3 Answers 3


(Using Blender 3.6.8, geometry nodes and mathematics)


Compute the shape of a closed loop of fixed length constrained to fit in a rectangle, maximising the radius of curvature:




A parametrized shape made of semicircles connected by segments is defined as follows:



  • $D$: Semicircles diameter.
  • $e$: User defined margin.
  • $E$: Gap (equal to $e$ by default).
  • $h$: User defined print bed height.
  • $H$: Segments length.
  • $l$: User defined curve length.
  • $L$: Partial length of half curve.
  • $N$: Number of loops (the above picture is made with $N=3$).
  • $O$: Origin for construction.
  • $w$: User defined print bed width.

The curve length is defined (see afterwards for demonstration) as: $$ l = 2e + 2\left\{ \left( \frac{\pi}{2} - 1 \right)w + (h-e)N \right\} $$ Thus the number of loops $N$ is a function of the user defined parameters $l$, $e$, $w$ and $h$. Once $N$ is computed as an integer, $D$ and $H$ are adjusted to set $l$ to its prescribed value.



The above figure being symmetric, $l$ is defined as: $$l = 2e + 2L \tag{1} \label{eq_l_init}$$ $L$ is composed of 2 fixed ends, $2N-1$ semicircles and $2N$ segments. So: $$L = 2 \times \frac{1}{2} D + (2N-1) \times \frac{1}{2}\pi D + 2N \times H \tag{2} \label{eq_L_init}$$ To maximize the radius of curvature (and thus limit internal constraints), and assuming $w \ge h$, $D$ is defined as: $$D = \frac{w}{2N-1} \tag{3} \label{eq_D_general}$$ At most, $h$ est such that: $$ h = (e+D) + 2 \times H + 2 \times \frac{1}{2} D \tag{4} \label{eq_h_general}$$ So: $$ 2H = h-e-2D \tag{5} \label{eq_H_init}$$ Substituting Eq.(\ref{eq_D_general}) and Eq.(\ref{eq_H_init}) in Eq.(\ref{eq_L_init}) yields: $$ L =\left( \frac{\pi}{2} -1 \right) w + (h-e) N \tag{6} \label{eq_L}$$ Combining Eq.(\ref{eq_l_init}) and Eq.(\ref{eq_L}), the decimal value of $N$ is computed as: $$ N = \frac{\frac{1}{2}l - e - \left( \frac{\pi}{2} - 1 \right) w}{h-e} \tag{7} \label{eq_N}$$ Afterwards, $N$ is defined as the smallest integer greater than or equal to the value computed by Eq.(\ref{eq_N}). Then from Eq.(\ref{eq_D_general}), $D$ is computed. Finally the expression of $H$ is written from Eq.(\ref{eq_L_init}) as: $$ H = \frac{\frac{1}{2}l - e -\left\{ (2N-1) \frac{\pi}{2} + 1 \right\} D}{2N} \tag{8} \label{eq_H}$$ Eq.(\ref{eq_N}) and Eq.(\ref{eq_H}) do not guarantee a proper value of $N \ge 1$ and of $H \ge 0$ if $l$ is small compared to $w$ and $h$. At least 4 configurations are identified in the following picture:

Singular configurations

Case A: $l \le \pi h$
A circle of diameter $D=l / \pi$ fits on the print bed. $N$ is set to 1, $H$ to 0, and $E$ to $-D$ to cancel the length $E+D$ (drawn in pink on the notation figure).

Case B: $l - 2h \lt (\pi-2) w$, i.e. $N \lt 1$ from Eq.(\ref{eq_N})
A capsule shape is defined with a diameter $D=h$ to fit on the print bed with a 90 degrees rotation. After removal of the end caps, the remaining length is $l-\pi D$. $E$ is computed as half of this residual, minus $D$ as in case A. $N$ is set to 1 and $H$ to 0.

Case C: $N \ge 1$ from Eq.(\ref{eq_N}) but $H \lt 0$ from Eq.(\ref{eq_H})
$H$ is set to 0 in Eq.(\ref{eq_L_init}) to redefine $D$ with $N=1$ and $E=e$ as: $$ D = \frac{\frac{1}{2}l - e}{(2N-1) \frac{\pi}{2} + 1} \tag{9} \label{eq_D_prime}$$

Case D: $N \ge 1$ from Eq.(\ref{eq_N}) and $H \ge 0$ from Eq.(\ref{eq_H})
$E$ is set to $e$.

Geometry nodes modifier

To compute $D$, $H$, $E$ and $N$

GN graph - Computation of curve parameters

1.1 $L$ is computed from Eq.(\ref{eq_l_init}) as $L=\frac{1}{2}l-e$.
1.2 $N$ is computed from Eq.(\ref{eq_N}) with $-\left( \frac{\pi}{2}-1 \right) \simeq -0.571$.
1.3 $D$ is computed from Eq.(\ref{eq_D_general}).
1.4 $H$ is computed from Eq.(\ref{eq_H}) with $\frac{\pi}{2} \simeq 1.571$.
1.5 If $H \lt 0$, $H$ is set to 0 and $D$ is recomputed from Eq.(\ref{eq_D_prime}).
1.6 To simplify connections, $D$, $H$, $E=e$ and $N$ are encapsulated as RGBA colour.

GN graph - Special cases

2.1 For $N \ge 1$, case C and case D are handled by the node group described at stage 1.
2.2 The condition $N \lt 0$ is evaluated as $l - 2h \lt (\pi-2) w$ with $\pi-2 \simeq 1.142$.
2.3 For case A (i.e. a circle), $D$ is computed as $l/\pi$, $H$ is set to 0, $N$ is set to 1 and $E=-D$.
2.4 For case B (i.e. a capsule), the minimum of $w$ and $h$ is used as value of $D$. The residual segment length is computed as $\frac{1}{2}(l-\pi D)$. $N$ is set to -1 to trigger the 90 degrees rotation afterwards.

To build the curve

GN graph - Curve builder

3.1 The origin for the following construction process is referenced as $O$ on the notation figure. The upper part of the curve is assembled first, then the lower part is made by symmetry, before connecting both.
3.2 A semicircle of diameter $D$ opened downwards is created from a Mesh Circle node followed by a Separate Geometry node with a selection mask keeping only vertices with positive Y coordinate. The resolution of the resulting circular arc is hardcoded to 72 edges (i.e. half of 144). NB: This value is affecting the accuracy of the curve length computed afterwards. It is shifted horizontally by $\frac{1}{2}D$ for the leftmost vertex to be at position $O$. The resulting mesh is converted to an instance for subsequent duplications.
3.3 The top semicircles are $N$ duplicates of the one built at step 3.2 shifted vertically by $H$. Each copy after the first is shifted horizontally by $2D$. NB: Duplicate Index starts at 0. It is to notice that the Set Position node is modifying instances position, not vertices position.
3.4 The bottom semicircles are $N-1$ duplicates of the one built at step 3.2 shifted horizontally by $D$ after a symmetry across X axis. As for top semicircles, each copy after the first is shifted horizontally by $2D$.
3.5 The segments connecting top and bottom semicircles are $2N$ duplicates of a vertical mesh line of height $H$. Each copy after the first is shifted horizontally by $D$.
3.6 Top and bottom semicircles are joined together with vertical segments to make the upper part of the curve.
3.7 This part is duplicated to make the lower part of the curve through a symmetry across X axis and a vertical shift downwards by $D+E$.
3.8 The two segments connecting upper and lower parts are duplicates of a vertical mesh line of height $D+E$. The rightmost is shifted horizontally by $(2N-1)D$.
3.9 Upper and lower parts are joined together with end segments to close the loop.
3.10 Before converting the resulting mesh to a curve, instances are made real geometries before merging them. NB: The distance set in the "Merge by Distance" node is affecting the accuracy of the curve length computed afterwards in conjunction with the resolution chosen at step 3.2.

GN graph - Curve builder

4.1 The values of $D$, $H$, $E$ and $N$ are decoded from their RGBA container.
4.2 To handle case B (i.e. a capsule), $N$ is set to -1. So its sign is made positive before building the curve.
4.3 Then if $N \lt 0$, the capsule is rotated by 90 degrees to be horizontal.

To finalize the curve

GN graph - Full curve

5.1 To maximize the radius of curvature $D$, width $w$ is assumed greater than height $h$. So from user defined $(X,Y)$ print bed dimensions, $w$ is the largest and $h$ the smallest.
5.2 Thus after building the curve, it is rotated by 90 degrees if $X \lt Y$, i.e. if $w$ is to be aligned with Y axis instead of X.

To make the scene

GN graph - Main

6.1 Before computing the curve, the user defined print bed dimensions are reduced by the ribbon width to avoid overflow, the ribbon outer face being tangent to the print bed edges.
6.2 The length is computed with a Curve Length node. It is to keep in mind that the accuracy of the whole process is affected by the round-off errors at stage 1 and by the discretisation of the semicircles at stage 3. For large values of $l$, these might be not negligible. For trial and error print tests, adjusting the Margin parameter is recommended.
6.3 The print bed is shifted such that its lower left corner is at the origin of the object carrying the Geometry Nodes modifier.

GN graph - Ribbon builder

7.1 The centre of the curve bounding box is firstly shifted at the origin of the object carrying the Geometry Nodes modifier, then at the centre of the print bed. Both translation vectors are combined using a single Multiply Add node.
7.2 Centring the ribbon rectangular profile on the curve would require that the curve is shifted normal to the print bed for the ribbon to be on top. Instead, the curve remains on the print bed and the ribbon profile is shifted before extrusion by half its height.
7.3 After extrusion, top and bottom edges are split to render sharp corners with smooth shading, using a selection mask based on an Edge Angle node.

  • 1
    $\begingroup$ Dunno about the bounty.. but this one gets a 'Wow!' from me :D $\endgroup$
    – Robin Betts
    Feb 26 at 17:56
  • $\begingroup$ Just Incredible!!!! $\endgroup$
    – Rick T
    Feb 27 at 4:01

OK, here's a funny solution… It always is when cloth simulation is involved…

Add a Mesh Circle, in my case 256 resolution, EExtrude up, ⎇ AltE extrude along normals. It's important the vertex indices aren't random:

The verts go from 0 to 255 on one circle-loop, then on 2nd circle-loop from the next available 256 to 511, then 512…767 and 768…1024:

Also notice how the starts of ranges, as well as ends etc. are all aligned. This means later I can collapse the vertices by doing $x \operatorname{mod} 256$ to get the index of the vertical cross-section loop and group verts by that.

Now the fun part, add a cube, add Solidify modifier with negative offset (the negativity is only important so the original cube defines the inner sides). go to Edit Mode and adjust it to roughly encompass the circle. "Display as wireframe" option helps:

Now make the box a collider, and add a cloth modifier to the circle, on which also enable "Pressure" and animate it. I've set the first keyframe to $0$, and the 250th frame to $+150$ [or use a negative sign if your normals point the wrong way as in the .blend file I uploaded!]. I also increased Bend resistance to $1$. Enable self-collisions:

Finally, add the geonodes modifier to the circle that will allow you to collapse the vertical cross-section loops and calculate the length:

Now you know when to pause the simulation and apply the modifiers:

  1. Manual Solution: No Geometry Nodes: for this solution I calculated the length of the curve and then scaled the curve up or down in Edit Mode to approach the proper value.

enter image description here

  1. Partly-automated Solution: the shape is created with mesh points, but everything else is solved by geometry nodes.

enter image description here enter image description here

  1. Mostly-automated: this setup also allows you to adjust the aspect ratio and the number of loops.

enter image description here

enter image description here

A fully-automated procedural system would be best, but option 3 is pretty close. I would just upload the file, but I'm new to how this platform functions.

  • $\begingroup$ That's an interesting route, I'm not sure if that would fit within the limit of the x,y dimensions required / given, especially when you start scaling things but a by a factor of 10 that's a little to hit or miss. That's why geometry nodes may be a good fit since you can procedurally / parametricly alter the dimensions / variables. But thanks for thinking out side the box every answer helps. $\endgroup$
    – Rick T
    Feb 22 at 15:59
  • $\begingroup$ I'll make a video on the process tonight. I should be able to get the length within a millimeter and the Blender export to be the perfect scale, all while making sure it fits within your build volume. In my experience, Blender is always off by a factor of 10 when it exports, I believe it's off by 1000, so I always check my dimensions again in the slicer. $\endgroup$ Feb 22 at 16:15
  • $\begingroup$ Does the answer need to be in geometry nodes? $\endgroup$ Feb 22 at 16:31
  • $\begingroup$ For what it needs to do I would say yes $\endgroup$
    – Rick T
    Feb 22 at 16:54
  • $\begingroup$ Does that mean that you need this one piece to be created with a certain tolerance, or that you'll be cranking out hundreds of O-rings with different dimensions? If you're making one thing, it is sometimes faster to do it more traditionally. But if you need to build a tool that can crank out thousands of similar things, the time spent building that tool can be offset by the time it would have taken to make all of them by hand. $\endgroup$ Feb 22 at 17:11

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .