#-------------------------------------------------------------
#   Primitive tsxPython sample script for trueSpace series
#                        Diamond 1
# 
# $Id: diamond1b.py 96 2021-04-30 07:47:22Z 3DfromNULL $
#-------------------------------------------------------------

import ptsxpy as p
from math import *

org   = Vec3f( 0., 0., 0.)
xaxis = Vec3f( 1., 0., 0.)
yaxis = Vec3f( 0., 1., 0.)
zaxis = Vec3f( 0., 0., 1.)

n1 = 16       # number of side (longitude of the cone)
h1 = 2.       # height of the base cone (before sweep)
h2 = 0.2 * h1 # sweep displacemant
r1 = 0.8 * h1 # radius of the cone
scale1 = 0.8

#----
# Backup the current material of the material editor, and set to faceted
wki0 = Ulong()
ret = p.MaterialCreateCopyActive( wki0.p )
print( "ret=", ret )
mat_sv = wki0.get()
# Make a new material
wki1 = Ulong()
p.MaterialCreate( wki1.p )
mat1 = wki1.get()
p.MaterialSetFacetingType( mat1, tsxFACET_FACETED )
p.MaterialSetActive( mat1 )

# Create a Cone
cn1 = p.CreateCone( n1, 2, r1, h1 ) # Note that it has a small top face
p.SceneAddObject( cn1, e_tsxFALSE )
p.GNodeSetName( cn1, "diamond1" ) # to determine distinguish from others

# Restore sctive material
p.MaterialSetActive( mat_sv )
#----


p.GNodeRotate( cn1, org.p, xaxis.p, pi, e_tsxWorldFrame )
loc1 = Vec3f( 0., 0., h1 / 2. )
p.GNodeSetLocation( cn1, loc1.p )
#
axes1 = Axes3f( (1.,0.,0.),(0.,1.,0.),(0.,0.,1.) )
p.MNodeSetAxesOrientation( cn1, axes1.p )
#loc2 = Vec3f( 0., 0., -2. )
p.MNodeSetAxesPosition( cn1, org.p )

#----
# Search for the top face (larger n sided polygon than bottom face)
#----
vec2 = Vec3f()
tm1 = Txmx3f()
p.PolyhGetVxTxmx( cn1, tm1.p ) # get matrix to get actual coordinate
nf1 = p.PolyhGetNbrFaces( cn1 ) # number of faces
pp1 = p.PolyhGetFaceptrArray( cn1 ) # pointer to pointer to a Face
va1 = p.PolyhGetVxArray( cn1 ) # Array of pointer to Vec3f
found = 0
for i in range( nf1 ):
    fp1 = Ulong_p( pp1 ).get() # load a pointer from pp1
    fc1 = Face_p( fp1 )  # treat it as a pointer to Face
    nv = fc1.nbrVxs()    # number of vertices of the face
    if nv == n1:  # top or bottom face
        fvp1 = FaceVx_p( fc1.pFVxs() )  # pointer to FaceVx
        vix1 = fvp1.vix()
        vp1 = Vec3f_p( va1 + sizeof_CtsxVector3f * vix1 )
        vec1 = Vec3f( vp1.x(), vp1.y(), vp1.z() )
        p.TransformVect3f( vec1.p, vec2.p, tm1.p ) # # get actual coordinate
        print( "vix1=", vix1, ", z=", vec2.z() )
        if abs( vec2.z() - h1 ) < 0.01: # top face
            found = 1
            break
    pp1 += 4
if not found:
    stop ### not found. (inconsistent) ###

print( "face found. i=", i )

swsgsv = p.SweepGetSegments() #-------
swmvsv = Vec3f()
p.SweepGetMove( swmvsv.p )
p.SweepSetSegments( 1 )
vec1 = Vec3f( 0., 0., h2 )
p.SweepSetMove( vec1.p )

p.SceneDraw()
wk1 = IntArray( 1 )
wk1[ 0 ] = i
print( "wk1=", wk1.prt() )
p.PolyhSelectFaces( cn1, 1, wk1.p )
###p.PointsActivateEdit()
#p.CurrobjEditTool()

p.PointsSweep()
p.PointsSweep()
p.SweepSetMove( swmvsv.p )
p.SweepSetSegments( swsgsv ) #-------
vec1 = Vec3f( scale1, scale1, 1. )
p.PointsScale( vec1.p, e_tsxWorldFrame )
if tscode != 43:
    p.PointsDeactivateEdit()  # How can we do this for tS4?
p.PolyhDeselectFaces( cn1, 1, wk1.p )

#----
# Find vertices of the current top face and get them to lst1,
# Find vertices of the latitude just below the top and get them to lst2,
#----
nv = p.PolyhGetNbrVxs( cn1 )
vp1 = Vec3f_p( p.PolyhGetVxArray( cn1 ) ) # Array of pointer to Vec3f
lst1 = []
lst2 = []
for i in range( nv ):
    p.TransformVect3f( vp1.p, vec2.p, tm1.p )  # get actual coordinate
    #print( "vix1=", vix1, ", z=", vp1.z() )
    if abs( vec2.z() - ( h1 + 2 * h2 ) ) < 0.01:
        #print( "(1) ", vec2.z(), ", ", atan2( vec2.y(), vec2.x() ) )
        lst1.append( ( atan2( vec2.y(), vec2.x() ), vec2.get(), i ) )
    if abs( vec2.z() - ( h1 + h2 ) ) < 0.01:
        #print( "(2) ", vec2.z(), ", ", atan2( vec2.y(), vec2.x() ) )
        lst2.append( ( atan2( vec2.y(), vec2.x() ), vec2.get(), i ) )
    vp1.inc()
print( "len lst1=", len( lst1 ) )
print( "len lst2=", len( lst2 ) )
#--
# Sort two lists by central angle (-pi thru pi) and get new list
#--
lst1a = sorted( lst1, key=lambda dum1: dum1[ 0 ] )
lst2a = sorted( lst2, key=lambda dum1: dum1[ 0 ] )
#for i in range( len( lst1a ) ):
#    print( "lst1[", i, "]=", lst1a[ i ] )
#for i in range( len( lst2a ) ):
#    print( lst2a[ i ] )

p.SceneDraw()

#----
# About every second vertex in lst1a, search lst2a to find two vertices
# that are at the diagonal position from each vertex, and add edges there.
# Also add an edge between the vertex in lst1a and next to the next in it.
#----
rad_a = 2 * pi / n1
print( "rad_a=", rad_a )
lst3 = []
for i in range( 0, len( lst1a ), 2 ):
    for j in range( len( lst2a ) ):
        vec1 = Vec3f( lst1a[ i ][ 1 ][ 0 ], lst1a[ i ][ 1 ][ 1 ], 0. ) # use only xy 
        vec2 = Vec3f( lst2a[ j ][ 1 ][ 0 ], lst2a[ j ][ 1 ][ 1 ], 0. ) # use only xy 
        nrm1 = Vec3f( 0., 0., 1. )
        # All 3 paramerers are to be read and overwritten soon
        rad_b = abs( p.AngleBtwVecs3f( vec1.p, vec2.p, nrm1.p ) ) # angle(radian) on xy-plain between a vertex on top face and one on latitude below it
        if abs( rad_b - rad_a ) < 0.01: # vertex at diagonal position found
            print( "i=", i, ", j=", j, ", rad_b=", rad_b )
            #print( "#" ) 
            # Commect the found diagonal
            ed1 = Edge( lst1a[ i ][ 2 ], lst2a[ j ][ 2 ] ) 
            p.PolyhMakeEdge( cn1, ed1.p ) # add an edge toward it
    # Commect the vertex on the top face to next to next one on the top
    ed1 = Edge( lst1a[ i ][ 2 ], lst1a[ ( i + 2 ) % len( lst1a ) ][ 2 ] )
    p.PolyhMakeEdge( cn1, ed1.p ) # add an edge toward it
    # Register the sandwiched vertex on the top face to a list
    lst3.append( lst1a[ ( i + 1 ) % len( lst1a ) ][ 1 ] )

p.SceneDraw()

print( "len(lst3)=", len( lst3 ) )
if tscode == 43:
    flg1 = 0

#----
# Find a 3-triangles-block in which each triangle has a common vertex
# registered in lst3. Select the 3 triangles and separate from the object.
# Repeat that about all blocks.
#
# Note 1: Don't select all eight 3-triangle-blocks at all because the
# separating operation to such selection in which vertices overlapp,
# Note 2: Number of vertices and faces change every time a block is
# separated.
#----
wk1 = IntArray( 3 )
for i in range( len( lst3 ) ):
    nf1 = p.PolyhGetNbrFaces( cn1 ) # number of faces (> original number)
    pp1 = p.PolyhGetFaceptrArray( cn1 ) # pointer to pointer to a Face
    vp1 = Vec3f_p( p.PolyhGetVxArray( cn1 ) ) # Array of pointer to Vec3f
    va1 = p.PolyhGetVxArray( cn1 ) # Array of pointer to Vec3f
    #p.PolyhGetVxTxmx( cn1, tm1.p ) # get matrix to get actual coordinate
    print( "nf1 before separate=", nf1 )
    vec3 = Vec3f( lst3[ i ][ 0 ], lst3[ i ][ 1 ], lst3[ i ][ 2 ] )
    cnt = 0
    for j in range( nf1 ):
        fp1 = Ulong_p( pp1 ).get() # load a pointer from pp1
        fc1 = Face_p( fp1 )  # treat it as a pointer to Face
        nv = fc1.nbrVxs()    # number of vertices of the face
        if nv == 3:  # triangle
            fvp1 = FaceVx_p( fc1.pFVxs() )  # pointer to FaceVx
            found = 0
            for k in range( 3 ):
                vix1 = fvp1.vix()
                vp1 = Vec3f_p( va1 + sizeof_CtsxVector3f * vix1 )
                vec1 = Vec3f( vp1.x(), vp1.y(), vp1.z() )
                p.TransformVect3f( vec1.p, vec2.p, tm1.p ) # # get actual coordinate
                #print( "tri vix1=", vix1, ", z=", vec2.z() )
                if p.DistanceToPoint3f( vec2.p, vec3.p ) < 0.01:
                    found = 1
                    break
                fvp1.inc()
            if found:
                wk1[ cnt ] = j
                cnt += 1
                if cnt >= 3:
                    break
            print( "top idx", j )
        pp1 += 4
    p.PolyhSelectFaces( cn1, 3, wk1.p )
    if tscode == 43:
        if not flg1:
            ptsxgp.msgbox_excl( "Note", "(1) Click \"Point Edit\" button BEFORE close this box.\n(2) Pull up this box using Alt F4 key, and click \"OK\" to continue." )
            flg1 = 1
    else:
        p.PointsActivateEdit()
    p.PointsSeparate()
    if tscode > 51:
        p.SelectSobj( cn1, e_tsxSELECT, e_tsxFALSE )
    # Search for the separated object from scene and delete it
    found = 0
    wk2 = CharArray( 1000 )
    wk3 = Ulong()
    wks1 = String_p( wk2.p )
    max1 = ""
    ob1 = p.SceneGetFirstNode()
    while ob1 != 0:
        print( "ob1=", ob1 )
        p.GNodeGetName( ob1, wk2.p, 1000 )
        try:
            s1 = wks1.get()
        except:
            s1 = ""
        print( "s1=", s1 )
        if s1 != "":
            if s1.startswith( "NoName," ) and s1 > max1:
                max1 = s1
        ob1 = p.GNodeGetNext( ob1 )
    p.GNodeFindByName( wk3.p, 0, max1 )
    print( "deleting ", max1, ", ", wk3.get() )
    p.SobjDelete( wk3.get() )

p.SceneDraw()

