#!BPY
# -*- coding: latin-1 -*-
"""
Name: 'Spirals_AlexV_set'
Blender: 248
Group: 'Misc'
Tooltip: 'Make spirals'
"""				
__author__ = "Alejandro Omar Chocano Vasquez"
__url__ = ("http://alexvaqp.googlepages.com")
__version__ = "1.2"
__bpydoc__ = "Make a spiral"

# ***** BEGIN GPL LICENSE BLOCK *****
#
# Script copyright (C) Alejandro Omar Chocano Vasquez 2009
#
# 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.TURNS=Create(3)       #number of turns
glob.RADIO=Create(1.00)    #spira Radio
glob.STEPS=Create(24)      #vertices in one turn
glob.DIF_Z=Create(0.25)    #z step between turns
glob.DIF_RADIO=Create(0.00)#radio step between turns 

glob.SpiralOB=Create(0)
glob.SpiralNEW=Create(0)
glob.SCENE=Create(0)

#LOG variables              #LOG SPIRAL VARIABLES
glob.A_scale=Create(1.000)  #scale, size of spiral
glob.B_force=Create(1.100)  #spiral force
glob.AngDiv=Create(2.0)     #factor of spiral exponent

#TORUS variables
glob.Minor_Radio=Create(0.20)
glob.Curves_Number=Create(1)
glob.HeightMul=Create(1.00)     #height of torus multiplier

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


#make normal spiral
#-----------------------------------------------------------------------------

def make_spiral():
   
   step=-(2*pi)/glob.STEPS.val #Step of angle in radians for one turn
   if glob.SPIRALdirection.val==0 :
	  #flip direction
	  step*=-1
   
   z_turn_step=glob.DIF_Z.val/glob.STEPS.val #z step in turn
   

   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.objects.link(glob.SpiralOB)   
   glob.SpiralNEW.appendNurb([glob.RADIO.val,0,0,1,1])

   glob.SpiralNEW[0].type=glob.CurveType.val

   radio_step=glob.DIF_RADIO.val/glob.STEPS.val
   z_step=z_turn_step #first steps for z 
   sum_d_radio=0
   turn_n=1

   while turn_n<=glob.TURNS.val:
     x=1 #steps radio 
     while x<=glob.STEPS.val:

       point_x=(glob.RADIO.val+sum_d_radio)*cos(step*x)
       point_y=(glob.RADIO.val+sum_d_radio)*sin(step*x)
       glob.SpiralNEW.appendPoint(0,[point_x,point_y,z_step,1])
       x+=1 #inc radio step
       z_step=z_step+z_turn_step #inc step z
       sum_d_radio+=radio_step #inc dif radio
       #sum_d_radio = (sin(z_step))
       #sum_d_radio = 0.5 + 0.4*(sin(z_step))


     turn_n+=1

   glob.SpiralNEW[0].setFlagU(2)
   glob.SpiralNEW[0].setFlagV(2)

   glob.SpiralNEW.update()
   Blender.Window.RedrawAll()

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


#make logaritmic spiral
#--------------------------------------------------------------------------
def make_spiral_log():
   
   step=-(2*pi)/glob.STEPS.val #Step of angle in radians for one turn
   if glob.SPIRALdirection.val==0 :
	  #flip direction
	  step*=-1
   

   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.objects.link(glob.SpiralOB)      
   glob.SpiralNEW.appendNurb([glob.A_scale.val,0,0,1,1]) #REVISAR PARA PUNTO INICIAL

   glob.SpiralNEW[0].type=glob.CurveType.val	

   #z_step=0 #steps for z 
   z_step=glob.DIF_Z.val/glob.STEPS.val
   turn_n=1   

   angu=0.0
   while turn_n<=glob.TURNS.val:
     x=1 #steps radio 
     while x<=glob.STEPS.val:

       angu+=step
       calc1=glob.A_scale.val*pow(glob.B_force.val,abs(angu)/glob.AngDiv.val )

       point_x=calc1*cos(angu)
       point_y=calc1*sin(angu)
       glob.SpiralNEW.appendPoint(0,[point_x,point_y,z_step,1])
       x+=1 #inc radio step
       z_step=z_step+glob.DIF_Z.val/glob.STEPS.val #inc step z

     turn_n+=1

   glob.SpiralNEW[0].setFlagU(2)
   glob.SpiralNEW[0].setFlagV(2)

   glob.SpiralNEW.update()
   Blender.Window.RedrawAll()

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


#make torus spiral
#-----------------------------------------------------------------------------

def make_spiral_torus():
   
   step=(2*pi)/glob.STEPS.val #Step of angle in radians for one turn
   if glob.SPIRALdirection.val==0 :#invierte la direccion de generacion de spiral 
	  #flip direction
	  step*=-1
   	
   z_step=((2*pi)/glob.TURNS.val)/glob.STEPS.val #desplazamiento de cada punto en z	
   

   glob.SpiralNEW=Blender.Curve.New('Spiral')
   glob.SpiralNEW.setFlag(1) #set 3D
   glob.SCENE = Scene.GetCurrent()
   glob.SpiralOB=Object.New('Curve')
   glob.SpiralOB.link(glob.SpiralNEW)
   glob.SCENE.objects.link(glob.SpiralOB)   
   

   ang_z=0 #-(pi/2)+z_step #empieza con un desplazamiento en z

   turn_n=1 #empieza en la primera vuelta

   while turn_n<=glob.TURNS.val:

     x=0 #steps radio #empieza con un angolo 0 en x y

     while x<glob.STEPS.val:
	
       point_x=(glob.RADIO.val+glob.Minor_Radio.val*cos(step*x))*cos(glob.Curves_Number.val*ang_z)
       point_y=(glob.RADIO.val+glob.Minor_Radio.val*cos(step*x))*sin(glob.Curves_Number.val*ang_z)
       point_z=glob.Minor_Radio.val*glob.HeightMul.val*sin(step*x)

       if (turn_n==1) and (x==0) :
           glob.SpiralNEW.appendNurb([point_x,point_y,point_z,1,1])
           glob.SpiralNEW[0].type=glob.CurveType.val
                     
       else:
          	 glob.SpiralNEW.appendPoint(0,[point_x,point_y,point_z,1])

       

       x+=1 #inc radio step
       ang_z+=z_step #incrementa el angulo z en un paso pequeño


     turn_n+=1 #avanza a la siguiente vuelta

   glob.SpiralNEW[0].setFlagU(1)
   glob.SpiralNEW[0].setFlagV(1)

   glob.SpiralNEW.update()
   Blender.Window.RedrawAll()

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

#make Spheric spiral
#-----------------------------------------------------------------------------

def make_spiral_spheric():
   
   step=(2*pi)/glob.STEPS.val #Step of angle in radians for one turn
   if glob.SPIRALdirection.val==0 :#invierte la direccion de generacion de spiral 
	  #flip direction
	  step*=-1
   	
   z_step=(pi/glob.TURNS.val)/glob.STEPS.val #desplazamiento de cada punto en z	
   

   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.objects.link(glob.SpiralOB)   
   glob.SpiralNEW.appendNurb([0,0,-glob.RADIO.val,1,1])

   glob.SpiralNEW[0].type=glob.CurveType.val	

   ang_z=-(pi/2)+z_step #empieza con un desplazamiento en z

   turn_n=1 #empieza en la primera vuelta

   while turn_n<=glob.TURNS.val:

     x=0 #steps radio #empieza con un angolo 0 en x y

     while x<glob.STEPS.val:
	
       point_x=glob.RADIO.val*cos(ang_z)*cos(step*x)
       point_y=glob.RADIO.val*cos(ang_z)*sin(step*x)
       point_z=glob.RADIO.val*sin(ang_z)

       glob.SpiralNEW.appendPoint(0,[point_x,point_y,point_z,1])
       x+=1 #inc radio step
       ang_z+=z_step #incrementa el angulo z en un paso pequeño


     turn_n+=1 #avanza a la siguiente vuelta

   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(90,225)
    Text('SPIRALS')


    glRasterPos2i(15,220)
    Text('________________________________')

    #glob.TURNS=Number ("Normal",1,20,150,80,16, glob.TURNS.val,0.01,100,"Number of Turns")

    #TOP BOTTONS
    #----------------------------------------------------------------------------------------------
    glRasterPos2i(15,205)
    Text('  spiral  type  curve type   direction')
    spiral_type = "Spiral Type%t|Normal %x1|Logarithmic %x2|Spheric %x3|Torus %x4"
    glob.SPIRALtype = Menu(spiral_type, 2, 20, 185, 70, 15, glob.SPIRALtype.val, "Spiral Type")

    curve_type = "Curve type%t|Nurb %x4|Poly %x0"
    glob.CurveType= Menu(curve_type, 2, 100, 185, 50, 15, glob.CurveType.val, "Curve Type")

    glob.SPIRALdirection= Toggle("clockwise",2,160,185,60,16,glob.SPIRALdirection.val,"spiral direction") 
    #----------------------------------------------------------------------------------------------

    
    #COMMON BUTTONS
    #----------------------------------------------------------------------------------------------

    glob.TURNS=Number ("TURNS  ",1,20,150,80,16, glob.TURNS.val,0.01,100,"Number of Turns")
    glob.STEPS=Number ("Vertices",2,120,150,100,16, glob.STEPS.val,2,100,"vertices in turn")        
    Button("EXIT",6,75,30,100,16,"Exit of script")         

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


    #NORMAL SPIRAL BUTTONS
    #----------------------------------------------------------------------------------------------

    if glob.SPIRALtype.val==1 :
		glob.DIF_RADIO=Slider ("radio step ",5,20,90,200,16, glob.DIF_RADIO.val,-5.00,5.00,1,"step of radio in each return")
		glob.RADIO=Slider ("RADIO     ",3,20,120,200,16, glob.RADIO.val,0.000,10.000,1,"Radio for first turn")
		glob.DIF_Z=Slider ("step in Z  ",4,20,60,200,16, glob.DIF_Z.val,-10.00,10.00,1,"step in Z axis ")
    
    #LOG SPIRAL BUTTONS
    #----------------------------------------------------------------------------------------------
    if glob.SPIRALtype.val==2 :
		glob.A_scale=Slider ("size         ",5,20,120,200,16, glob.A_scale.val,0.001,5.00,1,"spiral size")	
		glob.B_force=Slider ("force        ",3,20,100,200,16, glob.B_force.val,0.000,3.000,1,"expansion force")
		glob.AngDiv=Slider ("exponent  ",3,20,80,200,16, glob.AngDiv.val,1.0,10.0,1,"factor of logarithmic exponent")		
		glob.DIF_Z=Slider ("step in Z  ",4,20,60,200,16, glob.DIF_Z.val,-10.00,10.00,1,"step in Z axis ")
		

    #SPHERIC SPIRAL BUTTONS
    #----------------------------------------------------------------------------------------------
    if glob.SPIRALtype.val==3 :
		glob.RADIO=Slider ("RADIO     ",3,20,120,200,16, glob.RADIO.val,0.000,10.000,1,"Radio for first turn")


    #TORUS SPIRAL BUTTONS
    #----------------------------------------------------------------------------------------------
    if glob.SPIRALtype.val==4 :
		glob.RADIO=Slider ("RADIO     ",3,20,120,210,16, glob.RADIO.val,0.000,10.000,1,"Radio for first turn")
		glob.Minor_Radio=Slider ("minor radio ",5,20,100,210,16, glob.Minor_Radio.val,0.001,10.00,1,"internal radio of torus")    
		glob.Curves_Number=Slider ("CURVES NUM ",3,20,80,210,16, glob.Curves_Number.val,1,40,1,"Number of curves of spiral")	
		glob.HeightMul=Slider ("Height Mult ",3,20,60,210,16, glob.HeightMul.val,1.00,10.00,1,"Height of torus multiplier")	
	    		
		

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



def event(evt,val):
	if(evt==QKEY and not val):	
		Exit()
	
		
def bevent(event):
	
	if event == 6:
		Exit() 		
		
	if glob.SPIRALtype.val==1 :
		glob.SCENE.objects.unlink(glob.SpiralOB)
		make_spiral()
		
	if glob.SPIRALtype.val==2 :
		glob.SCENE.objects.unlink(glob.SpiralOB)
		make_spiral_log()					
		
	if glob.SPIRALtype.val==3 :
		glob.SCENE.objects.unlink(glob.SpiralOB)
		make_spiral_spheric()					
		
	if glob.SPIRALtype.val==4 :
		glob.SCENE.objects.unlink(glob.SpiralOB)
		make_spiral_torus()					
						
def main():
    make_spiral()
    Register(menu,event, bevent)

main()