5xj_Half_Round_Band.py     ver 1.03     April 14, 2009

note: I used the 'add_mesh_torus.py' script
bundled with Blender 2.48a as a model
when writting this script

There are a lot of comments written to the consol
I'll be removing them fairly soon


#!BPY

"""
Name: '5xj Half-Round Band'		# Roy Goodell www.5xj.com ver 1.03  4/14/09
Blender: 248a
Group: 'AddMesh'
"""
import BPyAddMesh
import Blender
from math import pi, sqrt

def add_ring (SIZE, WIDTH, THK, HRCH, CFCH, CPTS, NSEG):
	Vector = Blender.Mathutils.Vector
	RotationMatrix = Blender.Mathutils.RotationMatrix
	verts = [ ]
	faces = [ ]

	# calc od and id from size and thk
	ID = 11.6 + 0.8 * SIZE
	OD = ID + 2 * THK

	# error checking, in the real world would never make rings with shank edges this thin
	if THK - HRCH < 0.3:			# max hrch allowed 7with specified thk
		HRCH = THK - 0.3
	if THK - HRCH - CFCH < 0.3:
		CFCH = THK - HRCH - 0.3		# max cfch allowed with specified thk and hrch

	# To specify a pipe cut band set HRCH = 0.0
	if HRCH < 0.1:
		HRCH = 0.0
		CHPTS = 0
	else:
		CHPTS = CPTS
		HRR = (HRCH * HRCH + WIDTH * WIDTH * .25) / (2.0 * HRCH)	# half round radius

	if CFCH < 0.1:
		CFCH = 0.0
		CFPTS = 0
	else:
		CFPTS = CPTS
		CFR = (CFCH * CFCH + WIDTH * WIDTH * .25) / (2.0 * CFCH)	# half round radius


	# for minor index loop, want to make it easy to add pts to specific sections of ring band
	LF_SHANK_PTS = 4
	HR_PTS = LF_SHANK_PTS + CHPTS + 2
	RT_SHANK_PTS = HR_PTS + LF_SHANK_PTS
	CF_PTS = RT_SHANK_PTS + CFPTS + 2


	print
	print 'size\t',  SIZE, 'THK\t', THK, '\tOD\t',     OD,   '\tID\t',   ID

	if HRCH > 0.0:
		print 'HRCH\t',	HRCH,	'\tHRR\t',	HRR
	else:
		print 'HRCH = 0.0   no half round curve = pipe-cut band\t'
				
	if CFCH > 0.0:
		print 'CFCH\t',	CFCH,	'\tCFR\t',	CFR
	else:
		print 'CFCH = 0.0   no comfort fit curve'

	print 'CPTS\t',  CPTS, '\tTOTAL_PTS\t', 2 * HR_PTS
	print 'LF_SHANK_PTS\t', LF_SHANK_PTS, '\tHR_PTS\t', HR_PTS
	print 'RT_SHANK_PTS\t', RT_SHANK_PTS, '\tCF_PTS\t', CF_PTS
	print


	i1 = 0

	#NPTS = 2 * HR_PTS
	#tot_verts = NSEG * NPTS

	#NPTS = LF_SHANK_PTS + CHPTS + 2 + RT_SHANK_PTS + CF_PTS + 2
	NPTS = CF_PTS
	tot_verts = NSEG * NPTS	

	# extra pt offset => this will give sharp corners when render the band
	EP = 0.1

	PTX = 0


	print 'minor_index looping var =  NPTS = ', NPTS
	print 'left shank'

	for major_index in xrange (NSEG):

		# math utilities, RotationMatrix (angle, 3 => 3D, 'z' => rotate about Z axis)
		mtx = RotationMatrix (360 * float (major_index) / NSEG, 3, 'z' )

		for minor_index in xrange (NPTS):

			if minor_index < LF_SHANK_PTS:		# draw left shank edge
				PTZ = WIDTH * 0.5
				if minor_index == 0:			# pt on id
					PTY = ID * 0.5 + CFCH
				elif minor_index == 1:			# pt above id on shank edge => extra pt for rendering
					PTY = ID * 0.5 + CFCH + EP
				elif minor_index == 2:			# pt below chord ht on shank edge => extra pt for rendering
					PTY = OD * 0.5 - HRCH - EP
				elif minor_index == 3:			# pt at chord ht on shank edge
					PTY = OD * 0.5 - HRCH

			elif minor_index < HR_PTS:			# draw half-round curve
				if minor_index == 4:
					if major_index == 0:
						print
						print 'hr curve pts'
						print 'pt near shank',
					PTZ = WIDTH * 0.5 - EP
					if HRCH == 0:				# pipe cut band
						PTY = OD * 0.5
					else:						# pt on hr curve at ptz
						PTY = OD * 0.5 - (HRR - sqrt (HRR * HRR - PTZ * PTZ))
				elif minor_index < HR_PTS - 1:	# for pts on hr surface
					if major_index == 0:
						print '    hr',
					PTZ = WIDTH * 0.5 - EP - ((WIDTH - 2.0 * EP) / (CPTS + 1)) * (minor_index - 4)
					if HRCH == 0:				# this prevents python error (HRR = 0.0 in sqrt function)
						PTY = OD * 0.5
					else:						# calc pt on hr curve at ptz
						PTY = OD * 0.5 - (HRR - sqrt (HRR * HRR - PTZ * PTZ))
				else:							# last pt on hr curve
					if major_index == 0:
						print 'pt near shank',
					PTZ = - WIDTH * 0.5 + EP
					if HRCH == 0:				# pipe cut band
						PTY = OD * 0.5
					else:						# pt on hr curve at ptz
						PTY = OD * 0.5 - (HRR - sqrt (HRR * HRR - PTZ * PTZ))

			elif minor_index < RT_SHANK_PTS:
				PTZ = - WIDTH * 0.5
				if minor_index == HR_PTS:		# pt at chord ht on shank edge
					if major_index == 0:
						print
						print 'right shank'
					PTY = OD * 0.5 - HRCH
				elif minor_index == HR_PTS + 1:	# pt below chord ht on shank edge => extra pt for rendering
					PTY = OD * 0.5 - HRCH - EP
				elif minor_index == HR_PTS + 2:	# pt above id on shank edge => extra pt for rendering
					PTY = ID * 0.5 + CFCH +  EP
				elif minor_index == HR_PTS + 3:	# pt on id
					PTY = ID * 0.5 + CFCH

			else:								# draw comfort fit curve
				if minor_index == RT_SHANK_PTS:
					if major_index == 0:
						print
						print 'cf curve pts'
						print 'pt near shank',
					PTZ = - WIDTH * 0.5 + EP
					if CFCH == 0:				# pipe cut band
						PTY = ID * 0.5
					else:						# pt on hr curve at ptz
						PTY = ID * 0.5 + (CFR - sqrt (CFR * CFR - PTZ * PTZ))

				elif minor_index < CF_PTS - 1:	# for pts on hr surface
					if major_index == 0:	
						print '    cf',					
						#print 'cf curve pts'
						#print 'cf curve pts = ', minor_index, '  CPTS + 1 = ', CPTS + 1						
						#print ' minor_index - RT_SHANK_PTS = ', minor_index - RT_SHANK_PTS											
					PTZ = - WIDTH * 0.5 + EP + ((WIDTH - 2.0 * EP) / (CPTS + 1)) * (minor_index - RT_SHANK_PTS)										
					if CFCH == 0:				# this prevents python error (HRR = 0.0 in sqrt function)
						PTY = ID * 0.5
					else:						# calc pt on hr curve at ptz
						PTY = ID * 0.5 + (CFR - sqrt (CFR * CFR - PTZ * PTZ))
				else:							# last pt on hr curve
					if major_index == 0:
						print 'pt near shank',
					PTZ = WIDTH * 0.5 - EP
					if CFCH == 0:				# pipe cut band
						PTY = ID * 0.5
					else:						# pt on hr curve at ptz
						PTY = ID * 0.5 + (CFR - sqrt (CFR * CFR - PTZ * PTZ))


			# add pt (xyz)
			verts.append  (Vector (PTX, PTY, PTZ) * mtx)

			# when remove comments from if statement below
			# this really helps to figure out what's going on,
			#  in edit mode delete all but first segment vertiecs
			# then with 'N' key enabled, select each vertex and examine xyz positon
			# when you compare this data to that generated by the print statements
			#  you can see how pts were added (and can make corrections)

			if major_index == 0:
				print '\t pt ', minor_index, '\t\t', PTX, PTY, PTZ

			if minor_index + 1 == NPTS:
				i2 = (major_index) * NPTS
				i3 = i1 + NPTS
				i4 = i2 + NPTS

			else:
				i2 = i1 + 1
				i3 = i1 + NPTS
				i4 = i3 + 1

			if i2 >= tot_verts:	i2 = i2 - tot_verts
			if i3 >= tot_verts:	i3 = i3 - tot_verts
			if i4 >= tot_verts:	i4 = i4 - tot_verts

			faces.append ((i3, i4, i2, i1))

			i1 += 1

	return verts, faces


def main ():

	# define Variable Names = Blender.Draw.Create(default value)
	SIZE  = Blender.Draw.Create (10.0)
	WIDTH = Blender.Draw.Create (8.0)
	THK   = Blender.Draw.Create (2.2)
	HRCH  = Blender.Draw.Create (0.8)			# 0.0 => flat 'pipe cut' band
	CFCH  = Blender.Draw.Create (0.6)
	CPTS  = Blender.Draw.Create (5)				# pts on curve
	NSEG  = Blender.Draw.Create (36)

	# define array for popup window's content
	block = [ ]

	# add menu title, var, min/max values, tooltip
	block.append (("Size: ", SIZE,  0.0, 16.0, "Ring Size"))
	block.append (("Width:", WIDTH, 0.5, 18.0, "Ring Width"))
	block.append (("Thk:  ", THK,   0.4, 3.0,  "Ring Thickness"))
	# I use the HRCH dimension because it's easy to measure (in the real world)
	block.append (("HRCH: ", HRCH,  0.0, 2.4, "Half Round Chord Height"))
	block.append (('CFCH: ', CFCH,  0.0, 2.4, 'Comfort Fit Chord Height'))
	block.append (('CPTS: ', CPTS,  3,   256, 'Num Pts on Curve'))
	# FUTRUE: 	neg HRCH => will make concave ring  (it's ok, I sometimes make them)
	block.append (("Num Segments: ", NSEG, 6, 256,  'Num Radial Segments'))

	# draw popup if it's not all ready open
	if not Blender.Draw.PupBlock ("Create Ring in FRONT VIEW", block):
		return

	verts, faces = add_ring (SIZE.val, WIDTH.val, THK.val, HRCH.val, CFCH.val, CPTS.val, NSEG.val)

	BPyAddMesh.add_mesh_simple ('Ring', verts, [ ], faces)

# let's call main
main ( )