#-------------------------------------------------------------
#   Primitive tsxPython sample script for trueSpace series
#                    Ball and stick model
# 
# $Id: ballnstick_1c.py 37 2019-03-11 19:11:18Z 3DfromNULL $
#-------------------------------------------------------------

import ptsxpy as p
from math import *

def mkstick( p1p = 0, p2p = 0, r = 0.02, d = 16 ):
    len1 = p.DistanceToPoint3f( p1p, p2p )
    print( "len=", len1 )
    cy1 = p.CreateCylinder( d, 2, r, r, len1 )
    org = Vec3f()
    zaxis = Vec3f( 0., 0., 1. )
    p.MNodeSetAxesPosition( cy1, org.p )
    v1 = Vec3f()
    p.SubToVec3f( p2p, p1p, v1.p )
    v2 = Vec3f()
    rad1 = p.AngleBtwVecs3f( v1.p, zaxis.p, v2.p )
    print( "rad1=", rad1 )
    print( "v2=", v2.prt() )
    v3 = Vec3f( -v1.y(), v1.x(), 0. )
    p.Normalize3f( v3.p )
    p.GNodeRotate( cy1, org.p, v3.p, -rad1, e_tsxWorldFrame )
    p.GNodeSetLocation( cy1, p2p )
    p.SceneAddObject( cy1, e_tsxFALSE )

def mkball( p1p = 0, r = 0.05, d1 = 16, d2 = 16 ):
    p1 = p.CreateSphere( d1, d2, r )
    p.GNodeSetLocation( p1, p1p )
    p.SceneAddObject( p1, e_tsxFALSE )

# Material for the following funciton
###mate1 = [ 0 ]
wk1p = ptsxgp.alloc_long( 1 )
###p.MaterialCreate( mate1 )
p.MaterialCreate( wk1p )
mate1 = ptsxgp.loadptr( wk1p )
###p.MaterialSetFacetingType( mate1[ 0 ], tsxFACET_AUTO )
p.MaterialSetFacetingType( mate1, tsxFACET_AUTO )

# (function) Set color 
def setcol( r, g, b, a = 100 ):
    col = Color( r, g, b, a )
    ###p.MaterialSetColor( mate1[ 0 ], col.p )
    ###p.MaterialSetActive( mate1[ 0 ] )
    p.MaterialSetColor( mate1, col.p )
    p.MaterialSetActive( mate1 )


#---------------
# Icosahedron
#---------------
# golden ratio
g = ( 1. + sqrt( 5 ) ) / 2.

# Vertex table
t1 = [
 Vec3f(   g,  1.,  0. ),
 Vec3f(   g, -1.,  0. ),
 Vec3f(  -g,  1.,  0. ),
 Vec3f(  -g, -1.,  0. ),
 Vec3f(  0.,   g,  1. ),
 Vec3f(  0.,   g, -1. ),
 Vec3f(  0.,  -g,  1. ),
 Vec3f(  0.,  -g, -1. ),
 Vec3f(  1.,   0,   g ),
 Vec3f( -1.,   0,   g ),
 Vec3f(  1.,   0,  -g ),
 Vec3f( -1.,   0,  -g )
]

# Edge table
t2 = (
 (  0,  1 ),
 (  2,  3 ),
 (  4,  5 ),
 (  6,  7 ),
 (  8,  9 ),
 ( 10, 11 ),
 (  0,  4 ),
 (  0,  5 ),
 (  1,  6 ),
 (  1,  7 ),
 (  2,  4 ),
 (  2,  5 ),
 (  3,  6 ),
 (  3,  7 ),
 (  4,  8 ),
 (  4,  9 ),
 (  5, 10 ),
 (  5, 11 ),
 (  6,  8 ),
 (  6,  9 ),
 (  7, 10 ),
 (  7, 11 ),
 (  8,  0 ),
 (  8,  1 ),
 ( 10,  0 ),
 ( 10,  1 ),
 (  9,  2 ),
 (  9,  3 ),
 ( 11,  2 ),
 ( 11,  3 ),
)

org1 = Vec3f( 3., -3., 0. )
v1 = Vec3f()
v2 = Vec3f()

# Create vertices
setcol( 0x6f, 0x66, 0xff )
for i in range( len( t1 ) ):
    p.AddToVec3f( org1.p, t1[ i ].p, v1.p )
    mkball( v1.p )

# Create edges
setcol( 255, 255, 255 )
for i in range( len( t2 ) ):
    p.AddToVec3f( org1.p, t1[ t2[ i ][ 0 ] ].p, v1.p )
    p.AddToVec3f( org1.p, t1[ t2[ i ][ 1 ] ].p, v2.p )
    st1 = mkstick( v1.p, v2.p )


#---------------
# Water molecule
#---------------

ang1 = 104.45 * pi / 180.
dist_OH = 0.9584 # distance betwen O and H
r_O = 1.52       # radius of O
r_H = 1.2        # radius of H
p1 = Vec3f( dist_OH, 0., 0. )
p2 = Vec3f( 0., 0., 0. )
p3 = Vec3f( dist_OH * cos( ang1 ), dist_OH * sin( ang1 ), 0. )
setcol( 255, 255, 255 )
mkball( p1.p, r_H, 128, 128 )
mkball( p3.p, r_H, 128, 128 )
setcol( 255,   0,   0 )
mkball( p2.p, r_O, 128, 128 )

org2_x, org2_y, org2_z = -3., 3., 0
r_O = 0.3  # radius of O
r_H = 0.3  # radius of H
p1 = Vec3f( dist_OH + org2_x, org2_y, org2_z )
p2 = Vec3f( org2_x, org2_y, org2_z )
p3 = Vec3f( dist_OH * cos( ang1 ) + org2_x, dist_OH * sin( ang1 ) + org2_y, org2_z )
setcol( 255, 255, 255 )
mkball( p1.p, r_H, 128, 128 )
mkball( p3.p, r_H, 128, 128 )
setcol( 255,   0,   0 )
mkball( p2.p, r_O, 128, 128 )
setcol( 51, 51, 51 )
st1 = mkstick( p2.p, p1.p, 0.1 )
st1 = mkstick( p2.p, p3.p, 0.1 )

