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')
polyline.points.add(len(coords))
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.link(obj)
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 #
####################
bpy.ops.curve.primitive_bezier_circle_add()
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