I need help constructing this ring.

I thought it would be simpler, but the splitting and recombining of curves that swirl in variously symmetrical ways make the intricacy a little more difficult than I had imagined.

What is the most appropriate technique to efficiently model symmetric branching and swirling curves on a ring?

Real Information:

I am attempting to create a printable engagement ring with certain topological requirements. Due to the symmetry and math involved, I have been attempting to create the ring band beginning with bezier curves, and then applying bezier curves to form surfaces for the mesh. I am trying to do this completely with the python scripting language, such that I can alter any portion in a modular fashion.

One issue I have run into: branching is not possible with bezier curves.

What I have done: 1) create curve as long as the ring 2) bend it to circle 3) apply surface as taper

After this I am stuck on trying to do the weaving, swirling, and branching around the stone.

I have attempted to apply another simple deform to bend around the top portion of the ring, but this fails miserably, as it does not proportionally fall off - i.e. the entire ring twists around.

I am attempting to emulate the images below:

enter image description here enter image description here These images are fom Robert Kohr (https://www.robertkohr.com/ring/engagement-ring-design/), but are highly similar to what I am interested in creating.

Here is the function for the band that I have so far:

import numpy as np
ring_size = 47

def create_curve_object(obj_name, coords):
    # Add the points to curve data
    curveData = bpy.data.curves.new('myCurve', type='CURVE')
    # curveData.dimensions = '3D'
    # curveData.resolution_u = 2

    # map coords to spline
    polyline = curveData.splines.new('NURBS')
    for i, coord in enumerate(coords):
        x,y,z = coord
        polyline.points[i].co = (x, y, z, 1)

    # create Object
    obj = bpy.data.objects.new(obj_name, curveData)

    # make active and add:
    scn = bpy.context.scene
    scn.objects.active = obj
    obj.select = True
    return obj
def ring_band():
    scn = bpy.context.scene

    # Make Backbone #

    # band length coordinates
    ring_points = np.linspace(-ring_size/2, ring_size/2, 100)
    coords = [(pt, curl(pt, start_curl = 0.9*ring_points[-1]), 0) for pt in ring_points]
    ring_band = create_curve_object('ring_band', coords)

    # turn the ring standing up
    ring_band.rotation_euler = (np.pi/2, 0, 0)

    # Surface creation #
    band_surface = bpy.context.active_object
    band_surface.name = 'band_surface'
    bez_points = band_surface.data.splines[0].bezier_points

    # Apply surface
    ring_band.data.bevel_object = band_surface

    # Shape surface
    def normal(x, std_dev, mean):
        return 1/(std_dev*np.sqrt(2*np.pi))*np.exp(-(x-mean)**2/(2*std_dev**2))

    def f(x):
        std_size = 1.5 # in mm
        deviation_left_side = 12 * normal(x,  std_dev = ring_size/10, mean = -Nda_size/2)
        deviation_right_side = 12 * normal(x,  std_dev = ring_size/10, mean = Nda_size/2)
        deviation_bottom = 20 * normal(x, std_dev = Nda_size/4, mean = 0)

        width_of_ring = std_size - deviation_bottom - deviation_right_side - deviation_left_side
        return width_of_ring

    coords = [(pt, f(pt), 0) for pt in ring_points]

    band_surface_contour = create_curve_object('band_surface_contour', coords)
    ring_band.data.taper_object = band_surface_contour

    # Bend around circle #
    # Use empty circle to bend
    band_bender_empty = bpy.data.objects.new("band_bender", None )
    scn.objects.link( band_bender_empty )
    band_bender_empty.empty_draw_type = 'CIRCLE'
    band_bender_empty.rotation_euler = (np.pi/2, 0, 0)

    # TODO: How is this adding to a specific object?
    bpy.context.scene.objects.active = ring_band
    bpy.ops.object.modifier_add(type = 'SIMPLE_DEFORM')
    ring_band.modifiers['SimpleDeform'].deform_method = 'BEND'
    ring_band.modifiers['SimpleDeform'].angle = (2+1/4) * np.pi

    # add array mirror swirl modifier
    bpy.ops.object.modifier_add(type = 'ARRAY')
    ring_band.modifiers['Array'].use_object_offset = True

    # Mirror Swirl #
    bpy.ops.object.empty_add(type = 'PLAIN_AXES')
    empty_swirl = bpy.context.active_object
    empty_swirl.name = 'empty_swirl'
    # change scale X = -1
    empty_swirl.scale[0] = -1
    empty_swirl.scale[1] = -1

    ring_band.modifiers['Array'].offset_object = empty_swirl
  • $\begingroup$ will this tutorial help, youtu.be/gVUvnSJ-t3M also have you tried googling it? hope you have success. $\endgroup$
    – triplex
    Commented Nov 27, 2018 at 19:32
  • 1
    $\begingroup$ I wouldn't do this all with a script because that kind of work takes a lot of time when you get into the nitty gritty parts like the ones you're stuck on. I would do this work manually from there on. It's been 1/3 of a year, is this question still relevant to you? $\endgroup$
    – kettlecrab
    Commented Mar 30, 2020 at 2:17
  • $\begingroup$ You considered this add on? youtube.com/watch?v=XZ6uIdNnrHk $\endgroup$ Commented May 19, 2020 at 12:19

2 Answers 2


This is not using Python code. I have to try that method on time, it seems interesting, but using the software itself, such a thing can be achieved.

This is not exactly your plan, but it is an idea and may help other people in modeling. You can use Shift+A to build a cube as well as a path.

enter image description here

As shown in below figure, enable options Stretch and BoundsClamp for path. Also use a Curve Modifier for cube from the modifiers setting according to the right section of below image. Don't forget to set path as an object of Curve Modifier. Now you can bend the cube as a ring; but you need one more step for that to be happen (Remember this section later for making branches as well).

enter image description here

Now select the cube and go to edit mode and use Ctrl+R to add more edges to the cube. This helps the cube to bend more smoothly.

enter image description here

From now on, if you select the path and go to edit mode. By bending the path, you can also bend the cube.

So by editing the path, you can make something like this:

enter image description here

You can use Ctrl+R one more time, select faces from one side, use X + F to cut the mesh from half; Shear the rest of the mesh; and finally use Mirror Modifier.

enter image description here

Now by selecting one face and enabling the Proportional Editing Mode with O and using G or R keys; By rotating or moving one face according to other neighboring faces; you can make the surface of the ring.

enter image description here

You can use Mirroring again to make other side of the ring; and also ExtraMesh Addon to make a diamond quickly.

enter image description here

Now the question (Branching):

Select the ring; go to edit mode; Select a face and Extrude it using E; now you can have an extra object; select that object and extract that mesh using P key. Use Ctrl + R to make more Edges in new object. Here again, the same method of making a ring must be repeated from the beginning, and by making a path and curve modifier, you can create a new branch.

enter image description here

Now shape the new branch by editing the second path object:

enter image description here

Now you should merge the branch with the ring; select both of them and use Ctrl + J; and join verts by selecting each pair and using Alt + M

enter image description here

And the final result:

enter image description here

I tested Python in Blender for the first time and I can say it was great. It took me 2-3 hours to get used to it, but I was able to make branches randomly.

I did not try to make a complete ring with the code, it usually takes a lot of time, and later I test this on time and update the answer, but as an example, this code is not a bad idea for generating branches.

import bpy
import math
import random
import numpy as np
from bpy import context, data, ops
from mathutils import Matrix


def eulerToDegree(euler):
    return ( (euler) / (2 * pi) ) * 360


for material in bpy.data.materials:

for obj in bpy.data.objects:

for obj in bpy.data.curves:

bpy.context.object.data.name = "RingMesh"
bpy.context.object.name = "Ring"

bpy.ops.transform.resize(value=(.3, .3, .1))
bpy.context.object.location = (0,0,0)
bpy.context.object.rotation_euler = (0,0,0)



# Create path and enter edit mode.

# Means no subdivision

# make a random deformed branch
# ops.transform.vertex_random(offset=1.0, uniform=0.1, normal=0.0, seed=101)
ops.transform.vertex_random(offset=1.0, uniform=0.1, normal=0.0,       seed=random.randint(1,1000))

bpy.context.object.rotation_euler = (0,math.radians(90),0)

# Return to object mode.
ops.object.mode_set(mode='OBJECT') #exit edit_mode


And this is the result of random branches (Blender 2.79):

enter image description here


I would think that the best way to do this is to make a bezier curve to use as a guide and then add points to the original torus.

I would also try to not build the whole ring and instead split the ring into symmetrical pieces and then press Alt + D to create a duplication. If you change one part of the symmetrical pieces the others will change with it and it will make the job much easier.

With using Python scripting, I do not know how to use this to your advantage.


You must log in to answer this question.

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