#!BPY

"""
Name: 'Catenary'
Blender: 2.48
Group: 'Misc'
Tooltip: 'shape of a perfectly flexible chain suspended by its ends and acted on by gravity'
"""				
__author__ = "Alejandro Omar Chocano Vasquez"
__url__ = ("http://alexvaqp.googlepages.com")
__version__ = "1.0"

__bpydoc__ = """\
shape of a perfectly flexible chain 

suspended by its ends and acted on by gravity

"""

# --------------------------------------------------------------------------
# Catenary by alexv
# --------------------------------------------------------------------------
# ***** BEGIN GPL LICENSE BLOCK *****
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
#
# ***** END GPL LICENCE BLOCK *****
# --------------------------------------------------------------------------
import Blender
from Blender import *
from math import * #sin,cos,pi,atan
from Blender.Draw import *
from Blender import Window
from Blender.BGL import *


#variables
#-----------------------------------------------------------------------------

class GLOBALES:
       pass

glob=GLOBALES()

glob.STEPS=Create(24)      #vertices in one turn

#first point
glob.X_A=Create(-5.000)   
glob.Z_A=Create(1.000)

#second point
glob.X_B=Create(5.000)   
glob.Z_B=Create(3.000)

glob.a=Create(2.000) #catenary parameter

glob.CurveType=Create(4)    #Nurb or Poly Curve 0 Poly   4 Nurb


#make catenary
#-----------------------------------------------------------------------------

def catenary():
	
	glob.SpiralNEW=Blender.Curve.New('Spiral')
 	glob.SpiralNEW.setFlag(1)
	glob.SCENE = Scene.GetCurrent()
	glob.SpiralOB=Object.New('Curve')
	glob.SpiralOB.link(glob.SpiralNEW)
	glob.SCENE.link(glob.SpiralOB)      


	L=(glob.X_B.val-glob.X_A.val) #horizontal length

	AZ=(glob.Z_B.val-glob.Z_A.val)*1  #vertical difference

	x_v  = (glob.X_A.val + (L/2 - AZ*glob.a.val/L))
	z_v   = (glob.Z_A.val - ((pow((L/2 - AZ*glob.a.val/L),2))/(2*glob.a.val))) * 1
	
	AL = L/glob.STEPS.val #horizontal increase
	
	i=0 #iteracion

	while i<=glob.STEPS.val:
				
		Ax = i * AL
		x_i = glob.X_A.val + Ax
		z_i = (z_v + (pow((x_i - x_v),2)/(2*glob.a.val)))*1
		
		#y_i=y_a+P*cosh((x_i-x_vr)/P)
		
			
		if i==0 :
			 	glob.SpiralNEW.appendNurb([x_i,0,z_i,1,1]) #REVISAR PARA PUNTO INICIAL
				glob.SpiralNEW[0].type=glob.CurveType.val
		else:				
				
				glob.SpiralNEW.appendPoint(0,[x_i,0, z_i,1])				
						
		i+=1
		
	glob.SpiralNEW[0].setFlagU(2)
 	glob.SpiralNEW[0].setFlagV(2)
	glob.SpiralNEW.update()
	Blender.Window.RedrawAll()
	

#-----------------------------------------------------------------------------



# Function clear window
#-----------------------------------------------------------------------------

def clear_window():
	glColor3f(0.853,0.853,0.853)
	glClear(GL_COLOR_BUFFER_BIT)

#-----------------------------------------------------------------------------	


#menu
#-----------------------------------------------------------------------------

def menu():
    clear_window()

    glRasterPos2i(39,230)
    Text('shape of a perfectly flexible')
    glRasterPos2i(35,218)
    Text('chain suspended by its ends')

    glRasterPos2i(80,195)
    Text('Catenary')


    glRasterPos2i(15,190)
    Text('_____________________________')

    #TOP BOTTONS
    #----------------------------------------------------------------------------------------------
    
    curve_type = "Curve type%t|Nurb %x4|Poly %x0"
    glob.CurveType= Menu(curve_type, 2, 30, 160, 50, 15, glob.CurveType.val, "Curve Type")

    glob.STEPS=Number ("Vertices",2,110,160,90,16, glob.STEPS.val,3,100,"vertices in turn")

    glRasterPos2i(30,140)
    Text('introduce coordinates manually ')
    
    glob.X_A=Number ("X_A ",1,30,120,80,16, glob.X_A.val,-100.00,100.00,"X in point A")
    glob.Z_A=Number ("Z_A ",1,30,100,80,16, glob.Z_A.val,-100.00,100.00,"Z in point A")
    glob.X_B=Number ("X_B ",1,120,120,80,16, glob.X_B.val,-100.00,100.00,"X in point B")
    glob.Z_B=Number ("Z_B ",1,120,100,80,16, glob.Z_B.val,-100.00,100.00,"Z in point B")

    glRasterPos2i(60,85)
    Text('Catenary Parameter ')
    glob.a=Slider ("",3,60,65,110,16, glob.a.val,0.001,100.000,1,"Catenary Parameter")

    Button("EXIT",6,65,30,100,16,"Exit of script")         

    glRasterPos2i(15,20)
    Text('_____________________________')
    #----------------------------------------------------------------------------------------------



#-----------------------------------------------------------------------------



def event(evt,val):
	if(evt==QKEY and not val):	
		Exit()
	
		
def bevent(event):
	
	if event == 6:
		Exit() 		
		
	else :
		glob.SCENE.objects.unlink(glob.SpiralOB)
		if glob.X_A.val == glob.X_B.val :
			PupMenu("ERROR X_A must be different of X_B")
			glob.X_A.val=-5
		catenary()
		

						
def main():
    catenary()
    Register(menu,event, bevent)

main()