from openalea.plantgl.all import *
from math import degrees,pi
from random import uniform, seed


seed(0)

l = 50.
nbpt = int(l)
phyllotaxy = 90

def jitter_point(pt2,radius):
   return Vector3(pt2.x+uniform(-radius,radius),pt2.y+uniform(-radius,radius),1)

def jitter_a_branch(branch,radius):
    return  NurbsCurve2D([jitter_point(p,radius) for p in branch.ctrlPointList])

def gen_noise_branch(radius,nbp=10):
    return  NurbsCurve([(uniform(-radius,radius),uniform(-radius,radius),pt/float(nbp-1),1) for pt in range(nbp)],degree=min(nbp-1,3))


def End():
    pass #print 'end'

module SGT, A

Axiom:  SGT _(diameter(0)) @Gc A(l,0,0,0)

derivation length: nbpt
production:

SGT :
     if with_guide:
         nproduce SetGuide(path,l,True)
     if with_tropism:
         produce @Tp(0,0,1) @Ts(0.01*elasticity)

A(x,phi,nq,order) :
    u = (l-x)/l
    nq += node_length(u)
    if x <= 0 : produce
    if nq > 1:
        nq -= 1
        if x > branch_decal and order < max_order:
            nproduce [/(phi) +(100*branching_angle(u)) @v
            llength =  x-branch_decal
            if with_frame:
                nproduce Frame(3)
            if with_guide:
                if jitter_branch:
                    bp = jitter_a_branch(branchpath,jitter_radius/100.)
                elif noise_branch:
                    bp = gen_noise_branch(jitter_radius/100.,noise_freq+1)
                else:
                    bp = branchpath
                #print bp
                nproduce SetGuide(bp,llength) 
                if ctrl_lines:
                    p0 = bp.getPointAt(0)
                    if isinstance(bp,NurbsCurve):
                        rep = AxisRotated(Vector3.OZ,0,Translated(-p0,bp))
                    else:
                        rep = Translated(-Vector3(0,p0.y,p0.x),NurbsCurve([Vector4(0,i.y,i.x,1) for i in bp.ctrlPointList]))
                        
                    nproduce F(0)[,(3) @g(Scaled(llength/bp.getLength(),rep))]
            nproduce A(llength,phi, 0,order+1) ]
        phi+=phyllotaxy
    produce F(1,diameter(u))A(x-1,(phi),nq,order)



interpretation:


endlsystem
###### INITIALISATION ######

__lpy_code_version__ = 1.1

def __initialiseContext__(context):
	scalars = [('with_frame', 'Bool', False), ('branch_decal', 'Integer', 5, 0, 50), ('with_guide', 'Bool', True), ('with_tropism', 'Bool', True), ('jitter_branch', 'Bool', False), ('jitter_radius', 'Integer', 2, 0, 100), ('ctrl_lines', 'Bool', False), ('max_order', 'Integer', 6, 0, 100), ('noise_branch', 'Bool', True), ('noise_freq', 'Integer', 11, 3, 100), ('elasticity', 'Integer', 2, 0, 100)]
	context["__scalars__"] = scalars
	for s in scalars:
		if not s[1] == "Category" : context[s[0]] = s[2]
	import openalea.plantgl.all as pgl
	path = pgl.NurbsCurve2D(	
	    ctrlPointList = pgl.Point3Array([(0.00852268, -0.329545, 1),(-0.0501894, -0.0568182, 1),(0.0700758, 0.167614, 1),(0.0170455, 0.46875, 1)]) , 
	    )
	path.name = "path"
	import openalea.plantgl.all as pgl
	diameter = pgl.NurbsCurve2D(	
	    ctrlPointList = pgl.Point3Array([(0, 0.680178, 1),(0.326646, 0.244094, 1),(0.675733, 0.262932, 1),(1, 0.0232957, 1)]) , 
	    )
	diameter.name = "diameter"
	branchpath = pgl.NurbsCurve2D(	
	    ctrlPointList = pgl.Point3Array([(-0.551136, -0.00284096, 1),(-0.212121, 0.107955, 1),(-0.0719697, 0.0568182, 1),(0.301136, 0.0965909, 1),(0.299465, 0.415776, 1)]) , 
	    )
	branchpath.name = "branchpath"
	node_length = pgl.NurbsCurve2D(	
	    ctrlPointList = pgl.Point3Array([(0, 0.177573, 1),(0.312253, 0.235342, 1),(0.622119, 0.23631, 1),(1, 0.253742, 1)]) , 
	    )
	node_length.name = "node_length"
	branching_angle = pgl.NurbsCurve2D(	
	    ctrlPointList = pgl.Point3Array([(0, 0.539567, 1),(0.365422, 0.522996, 1),(0.761742, 0.422768, 1),(1, 0.0584769, 1)]) , 
	    )
	branching_angle.name = "branching_angle"
	panel_0 = ({'name': 'Panel 1', 'active': True, 'visible': True},[('Curve2D',path),('Function',diameter),('Curve2D',branchpath),('Function',node_length),('Function',branching_angle)])
	parameterset = [panel_0,]
	context["__functions__"] = [('diameter',diameter),('node_length',node_length),('branching_angle',branching_angle),]
	context["__curves__"] = [('path',path),('branchpath',branchpath),]
	context["__parameterset__"] = parameterset
	context["path"] = path
	context["diameter"] = pgl.QuantisedFunction(diameter)
	context["branchpath"] = branchpath
	context["node_length"] = pgl.QuantisedFunction(node_length)
	context["branching_angle"] = pgl.QuantisedFunction(branching_angle)
