(Using Blender 3.6.8, geometry nodes and mathematics)
Objectives
Compute the shape of a closed loop of fixed length constrained to fit in a rectangle, maximising the radius of curvature:
Approach
A parametrized shape made of semicircles connected by segments is defined as follows:
Notations:
- $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.
Results:
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.
Resources:
Mathematics
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:
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$
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.
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
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.
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
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
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.
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.