# Branching and swirling mesh on a ring

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:

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)

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 )
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
ring_band.modifiers['SimpleDeform'].deform_method = 'BEND'
ring_band.modifiers['SimpleDeform'].angle = (2+1/4) * np.pi

# add array mirror swirl modifier
ring_band.modifiers['Array'].use_object_offset = True

# Mirror Swirl #
################
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

• will this tutorial help, youtu.be/gVUvnSJ-t3M also have you tried googling it? hope you have success. Nov 27, 2018 at 19:32
• 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? Mar 30, 2020 at 2:17
• You considered this add on? youtube.com/watch?v=XZ6uIdNnrHk May 19, 2020 at 12:19

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.

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).

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.

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:

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.

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.

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

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.

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

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

And the final result:

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:
material.user_clear()
bpy.data.materials.remove(material)

for obj in bpy.data.objects:
bpy.data.objects.remove(obj)

for obj in bpy.data.curves:
bpy.data.curves.remove(obj)

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)

bpy.data.objects["Ring"].modifiers["Array"].relative_offset_displace[0]=0
bpy.data.objects["Ring"].modifiers["Array"].relative_offset_displace[1]=0
bpy.data.objects["Ring"].modifiers["Array"].relative_offset_displace[2]=1
bpy.data.objects["Ring"].modifiers["Array"].count=100

# Create path and enter edit mode.
bpy.data.curves[0].name="RingPath"
bpy.context.active_object.name="RingPath"
bpy.data.curves["RingPath"].use_stretch=True
bpy.data.curves["RingPath"].use_deform_bounds=True

# Means no subdivision
ops.curve.subdivide(number_cuts=0)

# 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))

ops.transform.resize(value=(2,2,2))