CCL Home Page
Up Directory CCL script.c
/* script.c
 * RasMol2 Molecular Graphics
 * Roger Sayle, October 1994
 * Version 2.5
 */
#define SCRIPT
#include "rasmol.h"

#ifdef IBMPC
#include 
#include 
#endif
#ifdef APPLEMAC
#ifdef __CONDITIONALMACROS__
#include 
#else
#include 
#endif
#include 
#endif
#ifndef sun386
#include 
#endif
 

#include 
#include 
#include 

#include "script.h"
#include "molecule.h"
#include "command.h"
#include "abstree.h"
#include "transfor.h"
#include "render.h"
#include "graphics.h"
#include "pixutils.h"

#ifdef INVERT
#define InvertY(y) (y)
#else
#define InvertY(y) (-(y))
#endif

#define Round(x)       ((int)(x))
#define DatWirFlag  (Long)0x10000
#define DatCylFlag  (Long)0x20000

/* Special thanks to Profs Jane and David Richardson
 * for the following Kinemage colour lookup table */

#define MAXMAGECOL 20
static struct {
        int r, g, b;
        char *name;
        } KinemageCol[MAXMAGECOL] = {
    { 255,   0,   0, "red"        },  /*  1 */
    {  23, 256,   0, "green"      },  /*  2 */
    {  62,  62, 255, "blue"       },  /*  3 */
    {   0, 242, 226, "cyan"       },  /*  4 */
    { 255, 246,   0, "yellow"     },  /*  5 */
    { 255,   0, 234, "magenta"    },  /*  6 */
    { 255, 255, 255, "white"      },  /*  7 */
    { 255, 101, 117, "pink"       },  /*  8 */
    { 255,  93,   0, "orange"     },  /*  9 */
    { 140,  54, 255, "purple"     },  /* 10 */
    {  58, 144, 255, "skyblue"    },  /* 11 */
    { 175, 117,  89, "brown"      },  /* 12 */
    { 125, 125, 125, "gray"       },  /* 13 */
    { 255, 156,   0, "gold"       },  /* 15 */
    { 246, 246, 117, "yellowtint" },  /* 16 */
    {   0, 250, 109, "seagreen"   },  /* 17 */
    { 255, 171, 187, "pinktint"   },  /* 18 */
    { 175, 214, 255, "bluetint"   },  /* 19 */
    { 152, 255, 179, "greentint"  },  /* 20 */
    { 255,   0, 101, "hotpink"    }   /* 21 */
        };


typedef struct {
        Long datum;
        Long count;
    } FreqEntry;

#define FREQSIZE  8
static FreqEntry Freq[FREQSIZE];


static Atom __far *MagePrev;
static char *MageCol;
static FILE *OutFile;
static int SelectAll;

/* Macros for commonly used loops */
#define ForEachAtom  for(chain=Database->clist;chain;chain=chain->cnext) \
                     for(group=chain->glist;group;group=group->gnext)    \
                     for(aptr=group->alist;aptr;aptr=aptr->anext)
#define ForEachBond  for(bptr=Database->blist;bptr;bptr=bptr->bnext)
#define ForEachBack  for(chain=Database->clist;chain;chain=chain->cnext) \
                     for(bptr=chain->blist;bptr;bptr=bptr->bnext)


static void FatalScriptError( ptr )
    char *ptr;
{
    if( CommandActive ) WriteChar('\n');
    WriteString("Script Error: Unable to create file `");
    WriteString( ptr );  WriteString("'!\n");
    CommandActive = False;
}


#ifdef FUNCPROTO
static void IncFreqTable( Long );
static Long GetBondDatum( Bond __far* );
static Long GetHBondDatum( HBond __far* );
#endif

static void ResetFreqTable()
{
    register int i;

    for( i=0; iflag & CylinderFlag )
    {   return( DatCylFlag | bptr->radius );
    } else if( bptr->flag & WireFlag )
    {   return( DatWirFlag );
    } else return( (Long)0 );
}

static Long GetHBondDatum( bptr )
    HBond __far *bptr;
{
    if( bptr->flag & CylinderFlag )
    {   return( DatCylFlag | bptr->radius );
    } else if( bptr->flag & WireFlag )
    {   return( DatWirFlag );
    } else return( (Long)0 );
}

 
#ifndef SCRIPT
#ifdef FUNCPROTO
static void WriteMolScriptAtomSel( Chain __far*, Group __far*, Atom __far* );
#endif

static void WriteMolScriptColour( r, g, b )
    int r, g, b;
{
    fprintf(OutFile," rgb %#g %#g %#g",r/255.0,g/255.0,b/255.0);
}

static void WriteMolScriptAtomSel( chain, group, aptr )
    Chain __far *chain;
    Group __far *group;
    Atom __far *aptr;
{
    register char *ptr;
    register int i;

    fputs("require atom ",OutFile);
    ptr = ElemDesc[aptr->refno];
    for( i=0; i<4; i++ )
        if( ptr[i]=='*' )
        {   fputc('\'',OutFile);
        } else if( ptr[i]!=' ' )
            fputc(ptr[i],OutFile);

    fputs(" and in residue ",OutFile);
    if( chain->ident!=' ' && !isdigit(chain->ident) )
        fputc(chain->ident,OutFile);
    fprintf(OutFile,"%d",group->serno);
}

static void WriteMolScriptAtoms()
{
    register Chain __far *chain;
    register Group __far *group;
    register Atom __far *aptr;
    register ShadeDesc *shade;
    register Label *label;
    register char *ptr;

    char buffer[80];


    ForEachAtom
    {   if( aptr->flag & SphereFlag )
        {   /* Atom Colour */
            fputs("set atomcolour ",OutFile);
            WriteMolScriptAtomSel(chain,group,aptr);
            shade = Shade + Colour2Shade(aptr->col);
            WriteMolScriptColour(shade->r,shade->g,shade->b);
            fputs(";\n",OutFile);

            /* CPK Sphere */
            fputs("set atomradius ",OutFile);
            WriteMolScriptAtomSel(chain,group,aptr);
            fprintf(OutFile," %#g;\ncpk ",aptr->radius/250.0);
            WriteMolScriptAtomSel(chain,group,aptr);
            fputs(";\n",OutFile);
        }

        if( aptr->label )
        {   /* Atom Label */
            label = (Label*)aptr->label;
            FormatLabel(chain,group,aptr,label->label,buffer);

            fputs("label ",OutFile);
            WriteMolScriptAtomSel(chain,group,aptr);
            fputs(" \"",OutFile);
            for( ptr=buffer; *ptr; ptr++ )
                if( *ptr!='%' ) fputc(*ptr,OutFile);
            fputs("\";\n",OutFile);
        }
    }
}
#endif

static void MolScriptSegment( ptr, src, dst, chain )
    char *ptr;  int src, dst;  char chain;
{   
    if( (chain!=' ') && !isdigit(chain) ) 
    {   fprintf(OutFile,"  %s from %c%d to %c%d;\n",ptr,chain,src,chain,dst);
    } else fprintf(OutFile,"  %s from %d to %d;\n",ptr,src,dst);
}


int WriteMolScriptFile( name )
    char *name;
{
    register Real temp;
    register Real psi, phi, theta;
    register Chain __far *chain;
    register Group __far *group;
    register Group __far *next;
    register Group __far *prev;
    register int flag,len;
    register char *ptr;

    if( !Database )
        return(False);

    OutFile = fopen(name,"w");
    if( !OutFile )
    {   FatalScriptError(name);
        return(False);
    }
    fprintf(OutFile,"! File: %s\n",name);
    fputs("! Creator: RasMol Version 2.5\n",OutFile);
    fputs("! Version: MolScript v1.3\n\n",OutFile);

    fputs("plot\n",OutFile);
    if( BackR || BackG || BackB )
    {   fputs("  background rgb ",OutFile);
        fprintf(OutFile,"%#g ",  BackR/255.0);
        fprintf(OutFile,"%#g ",  BackG/255.0);
        fprintf(OutFile,"%#g;\n",BackB/255.0);
    }
    temp = 0.004/Scale;
    fprintf(OutFile,"  window %g;\n",temp*Range);
    if( UseSlabPlane )
        fprintf(OutFile,"  slab %g;\n",SideLen/250.0);
    fputc('\n',OutFile);

    fprintf(OutFile,"  read mol \"%s\";\n",InfoFileName);
    fputs("  transform atom *\n",OutFile);
    fputs("    by centre position atom *\n",OutFile);
    fputs("    by rotation x 180.0",OutFile);

    phi = Rad2Deg*asin(RotX[2]);
    if( (int)phi == 90 )
    {   theta = -Rad2Deg*atan2(RotY[0],RotY[1]);
        psi = 0;
    } else if( (int)phi == -90 )
    {   theta = Rad2Deg*atan2(RotY[0],RotY[1]);
        psi = 0;
    } else /* General Case! */
    {   theta = Rad2Deg*atan2(RotY[2],RotZ[2]);
        psi =  -Rad2Deg*atan2(RotX[1],RotX[0]);
    }

    if( (int)psi )   fprintf(OutFile,"\n    by rotation z %#g",InvertY(psi));
    if( (int)phi )   fprintf(OutFile,"\n    by rotation y %#g",phi);
    if( (int)theta ) fprintf(OutFile,"\n    by rotation x %#g",InvertY(-theta));

    if( UseSlabPlane || (XOffset!=WRange) || (YOffset!=HRange) )
    {   fputs("\n    by translation ",OutFile);
        fprintf(OutFile,"%#g ",(XOffset-WRange)*temp);
        fprintf(OutFile,"%#g ",-(YOffset-HRange)*temp);
        if( UseSlabPlane )
        {   temp = (1.0-DialValue[7])/500.0;
            fprintf(OutFile,"%#g",SideLen*temp);
        } else fputs("0.0",OutFile);
    }
    fputs(";\n\n",OutFile);

    /* fputs("  trace amino-acids;\n",OutFile); */

    if( Database->clist )
    {   if( InfoHelixCount<0 )
            DetermineStructure();

        for( chain=Database->clist; chain; chain=chain->cnext )
        {   prev = (Group __far*)0;
            for( group=chain->glist; group && group->gnext; group=next )
            {   next = group->gnext;
                if( next->serno < group->serno )
                {   if( prev && prev!=group )
                        MolScriptSegment("coil",prev->serno,group->serno,
                                                chain->ident);
                    prev = (Group __far*)0;
                    continue;
                }
                flag = group->struc & next->struc;

                if( flag&HelixFlag )
                {   flag = HelixFlag;
                    ptr = "helix";
                } else if( flag&SheetFlag )
                {   flag = SheetFlag;
                    ptr = "strand";
                } else 
                {   if( flag&TurnFlag )
                    {   fputs("  turn residue ",OutFile);
                        if( chain->ident != ' ' )
                            fputc(chain->ident,OutFile);
                        fprintf(OutFile,"%d;\n",group->serno);
                    }
                    if( !prev ) prev = group;
                    continue;
                }

                len = 2;  /* Determine Structure Length */
                while( next->gnext && (next->gnext->struc&flag)
                           && (next->serno<=next->gnext->serno) )
                {   next = next->gnext;
                    len++;
                }

                if( len>2 )
                {   if( prev ) /* MolScript coil or turn? */
                       MolScriptSegment("coil",prev->serno,group->serno,
                                              chain->ident);
                    MolScriptSegment(ptr,group->serno,next->serno,
                                         chain->ident);
	            prev = next;
                } 
            }

            if( prev && prev!=group )  /* C-terminal coil/turn */
                MolScriptSegment("coil",prev->serno,group->serno,chain->ident);
        }
    }

#ifndef SCRIPT
    WriteMolScriptAtoms();
#endif

    fputs("end_plot\n",OutFile);
    fclose(OutFile);
#ifdef APPLEMAC
    SetFileInfo(name,'ttxt','TEXT',133);
#endif
    return( True );
}




#ifdef FUNCPROTO
static void WriteScriptDatum( char*, Long );
static void WriteScriptHBonds( char*, HBond __far* );
#endif

static void WriteScriptAll()
{
    if( !SelectAll )
    {   fputs("select all\n",OutFile);
        SelectAll = True;
    }
}

static void WriteScriptColour( ptr, col )
    char *ptr;  int col;
{
    register ShadeDesc *shade;
    
    if( col )
    {   shade = Shade + Colour2Shade(col);
        fprintf(OutFile,"colour %s [%d,%d,%d]\n",ptr,
                shade->r,shade->g,shade->b);
    } else fprintf(OutFile,"colour %s none\n",ptr);
}


static void WriteScriptBetween( lo, hi )
    int lo, hi;
{
    if( lo != hi )
    {   fprintf(OutFile,"select (atomno>=%d) and (atomno<=%d)\n",lo,hi);
    } else fprintf(OutFile,"select atomno=%d\n",lo);
    SelectAll = False;
}

static void WriteScriptAtoms()
{
    register Chain __far *chain;
    register Group __far *group;
    register Atom __far *aptr;
    register int first,last;
    register int same,init;
    register int cpk,vdw;
    register int col,rad;

    fputs("\n# Atoms\n",OutFile);

    same = True;
    init = False;
    ForEachAtom
        if( !init )
        {   first = last = aptr->serno;
            cpk = IsCPKColour( aptr );
            col = aptr->col;
            init = True;
        } else if( cpk && IsCPKColour(aptr) )
        {   last = aptr->serno;
            if( aptr->col != col )
                col = 0;
        } else if( aptr->col == col )
        {   last = aptr->serno;
            cpk = False;
        } else if( aptr->col != col )
        {   WriteScriptBetween( first, last );
            if( !col )
            {   fputs("colour atoms cpk\n",OutFile);
            } else WriteScriptColour("atoms",col);
                
            first = last = aptr->serno;
            cpk = IsCPKColour( aptr );
            col = aptr->col;
            same = False;
        } else last = aptr->serno; 
        
    if( init )
    {   if( !same )
        {   WriteScriptBetween(first,last);
        } else WriteScriptAll();

        if( !col )
        {   fputs("colour atoms cpk\n",OutFile);
        } else WriteScriptColour("atoms",col);
    }

    if( DrawAtoms )
    {   same = True;
        init = False;
        ForEachAtom
            if( !init )
            {   rad = aptr->flag&SphereFlag? aptr->radius : 0;
                first = last = aptr->serno;
                vdw = IsVDWRadius( aptr );
                init = True;
            } else if( rad == ((aptr->flag&SphereFlag)? aptr->radius : 0) )
            {   if( vdw ) vdw = IsVDWRadius( aptr );
                last = aptr->serno;
            } else if( vdw && IsVDWRadius(aptr) )
            {   last = aptr->serno;
                rad = -1;
            } else 
            {   WriteScriptBetween(first,last);
                if( rad == -1 )
                {   fputs("spacefill on\n",OutFile);
                } else if( rad )
                {   fprintf(OutFile,"spacefill %d\n",rad);
                } else fputs("spacefill off\n",OutFile); 

                rad = aptr->flag&SphereFlag? aptr->radius : 0;
                first = last = aptr->serno;
                vdw = IsVDWRadius( aptr );
                same = False;
            }

        if( !same )
        {   WriteScriptBetween(first,last);
        } else WriteScriptAll();

        if( rad == -1 )
        {   fputs("spacefill on\n",OutFile);
        } else if( rad )
        {   fprintf(OutFile,"spacefill %d\n",rad);
        } else fputs("spacefill off\n",OutFile); 

        if( UseShadow )
        {   fputs("set shadow on\n",OutFile);
        } else fputs("set shadow off\n",OutFile);

    } else
    {   WriteScriptAll();
        fputs("spacefill off\n",OutFile);
    }
        
}


static void WriteScriptDatum( ptr, datum )
    char *ptr;  Long datum;
{
    if( datum & DatCylFlag )
    {   fprintf(OutFile,"%s %d\n",ptr,(int)(datum-DatCylFlag));
    } else if( datum & DatWirFlag )
    {   fprintf(OutFile,"%s on\n",ptr);
    } else fprintf(OutFile,"%s off\n",ptr);
}


static void WriteScriptBonds()
{
    register Bond __far *bptr;
    register Long defdat;
    register Long datum;
    register int col;

    fputs("\n# Bonds\n",OutFile);

    ResetFreqTable();
    ForEachBond
        IncFreqTable(GetBondDatum(bptr));

    WriteScriptAll();
    defdat = Freq[0].datum;
    WriteScriptDatum("wireframe",defdat);

    if( Freq[1].count )
    {   ForEachBond
        {   datum = GetBondDatum(bptr);
            if( datum != defdat )
            {    fprintf(OutFile,"select (atomno=%d) or (atomno=%d)\n",
                         bptr->srcatom->serno, bptr->dstatom->serno );
                 WriteScriptDatum("wireframe",datum);
                 SelectAll = False;
            }
        }
    } else if( !defdat )
        return;

    ResetFreqTable();
    ForEachBond
        IncFreqTable(bptr->col);

    WriteScriptAll();
    if( (col=(int)Freq[0].datum) )
        WriteScriptColour("bonds",col);

    if( Freq[1].count )
        ForEachBond
            if( bptr->col != col )
            {   fprintf(OutFile,"select (atomno=%d) or (atomno=%d)\n",
                    bptr->srcatom->serno, bptr->dstatom->serno );
                WriteScriptColour("bonds",bptr->col);
                SelectAll = False;
            }
}

static void WriteScriptBackbone()
{
    register Chain __far *chain;
    register Bond __far *bptr;

    register Long defdat;
    register Long datum;
    register int col;

    fputs("\n# Backbone\n",OutFile);

    ResetFreqTable();
    ForEachBack
        IncFreqTable(GetBondDatum(bptr));

    WriteScriptAll();
    defdat = Freq[0].datum;
    WriteScriptDatum("backbone",defdat);

    if( Freq[1].count )
    {   ForEachBack
        {   datum = GetBondDatum(bptr);
            if( datum != defdat )
            {    fprintf(OutFile,"select (atomno=%d) or (atomno=%d)\n",
                         bptr->srcatom->serno, bptr->dstatom->serno );
                 WriteScriptDatum("backbone",datum);
                 SelectAll = False;
            }
        }
    } else if( !defdat )
        return;

    ResetFreqTable();
    ForEachBack
        IncFreqTable(bptr->col);

    WriteScriptAll();
    if( (col=(int)Freq[0].datum) )
        WriteScriptColour("backbone",col);

    if( Freq[1].count )
        ForEachBack
            if( bptr->col != col )
            {   fprintf(OutFile,"select (atomno=%d) or (atomno=%d)\n",
                    bptr->srcatom->serno, bptr->dstatom->serno );
                WriteScriptColour("backbone",bptr->col);
                SelectAll = False;
            }
}

static void WriteScriptRibbons()
{
    register Chain __far *chain;
    register Group __far *group;
    register Atom __far *aptr;

    fputs("\n# Ribbons\n",OutFile);

    if( DrawRibbon )
    {   fprintf(OutFile,"set strands %d\n",SplineCount);

        for( chain=Database->clist; chain; chain=chain->cnext )
            for( group=chain->glist; group; group=group->gnext )
            {    if( IsAmino(group->refno) )
                 {   aptr = FindGroupAtom(group,1);
                 } else aptr = FindGroupAtom(group,7);
                 if( !aptr ) continue;

                 fprintf(OutFile,"select atomno=%d\n",aptr->serno);
                 SelectAll = False;

                 if( group->flag & RibbonFlag )
                 {   fprintf(OutFile,"ribbons %d\n",group->width);
                 } else if( group->flag & StrandFlag )
                 {   fprintf(OutFile,"strands %d\n",group->width);
                 } else fputs("ribbons off\n",OutFile);

                 if( group->col1 != group->col2 )
                 {   WriteScriptColour("ribbon1",group->col1);
                     WriteScriptColour("ribbon2",group->col2);
                 } else WriteScriptColour("ribbons",group->col1);
            }
    } else
    {   WriteScriptAll();
        fputs("ribbons off\n",OutFile);
    }
}


static void WriteScriptHBonds( obj, list )
    char *obj;  HBond __far *list;
{
    register HBond __far *ptr;
    register Long defdat;
    register Long datum;
    register int col;

    ResetFreqTable();
    for( ptr=list; ptr; ptr=ptr->hnext )
        IncFreqTable(GetHBondDatum(ptr));

    WriteScriptAll();
    defdat = Freq[0].datum;
    WriteScriptDatum(obj,defdat);

    if( Freq[1].count )
    {   for( ptr=list; ptr; ptr=ptr->hnext )
        {   datum = GetHBondDatum(ptr);
            if( datum != defdat )
            {    fprintf(OutFile,"select (atomno=%d) or (atomno=%d)\n",
                         ptr->src->serno, ptr->dst->serno );
                 WriteScriptDatum(obj,datum);
                 SelectAll = False;
            }
        }
    } else if( !defdat )
        return;

    ResetFreqTable();
    for( ptr=list; ptr; ptr=ptr->hnext )
        IncFreqTable(ptr->col);

    WriteScriptAll();
    if( (col=(int)Freq[0].datum) )
        WriteScriptColour(obj,col);

    if( Freq[1].count )
        for( ptr=list; ptr; ptr=ptr->hnext )
            if( ptr->col != col )
            {   fprintf(OutFile,"select (atomno=%d) or (atomno=%d)\n",
                    ptr->src->serno, ptr->dst->serno );
                WriteScriptColour(obj,ptr->col);
                SelectAll = False;
            }
}

static void WriteScriptLabels()
{
    register Chain __far *chain;
    register Group __far *group;
    register Atom __far *aptr;
    register int first,last;
    register Label *label;

    fputs("\n# Labels\n",OutFile);
    WriteScriptAll();
    fputs("labels off\n",OutFile);
    if( !DrawLabels ) return;

    if( UseLabelCol )
    {   fprintf(OutFile,"colour labels [%d,%d,%d]\n",LabR,LabG,LabB);
    } else fputs("colour labels none\n",OutFile);
    fprintf(OutFile,"set fontsize %d\n",FontSize);

    label = (Label*)0;
    ForEachAtom
        if( aptr->label != label )
        {   if( label )
            {   WriteScriptBetween(first,last);
                fprintf(OutFile,"label \"%s\"\n",label->label);
            }
            label = (Label*)aptr->label;
            first = last = aptr->serno;
        } else last = aptr->serno;

    if( label )
    {   WriteScriptBetween(first,last);
        fprintf(OutFile,"label \"%s\"",label->label);
    }
}


int WriteScriptFile( name )
    char *name;
{
    register int theta,phi,psi;
    register char *ptr;
    register int temp;

    OutFile = fopen(name,"w");
    if( !OutFile )
    {   FatalScriptError(name);
        return(False);
    }

    fprintf(OutFile,"#!rasmol -script\n# File: %s\n",name);
    fputs("# Creator: RasMol Version 2.5\n\n",OutFile);
    fprintf(OutFile,"background [%d,%d,%d]\n",BackR,BackG,BackB);
    if( !Database )
    {   /* No Molecule! */
        fputs("zap\n",OutFile);
        fclose(OutFile);
#ifdef APPLEMAC
        SetFileInfo(name,'RSML','RSML',133);
#endif
        return(True);
    }

    /* Molecule File Name */
    switch( DataFileFormat )
    {   default:
        case(FormatPDB):      ptr = "pdb";      break;
        case(FormatAlchemy):  ptr = "alchemy";  break;
        case(FormatCharmm):   ptr = "charmm";   break;
        case(FormatMol2):     ptr = "mol2";     break;
        case(FormatMDL):      ptr = "mdl";      break;
        case(FormatXYZ):      ptr = "xyz";      break;
    }
    fprintf(OutFile,"load %s \"%s\"\n",ptr,InfoFileName);

    /* Colour Details */
    fprintf(OutFile,"set ambient %d\n", (int)(100*Ambient) );
    fputs("set specular ",OutFile);
    if( FakeSpecular )
    {   fprintf(OutFile,"on\nset specpower %d\n",SpecPower);
    } else fputs("off\n",OutFile);
    putc('\n',OutFile);

    /* Transformation */
    fputs("reset\n",OutFile);
    if( UseSlabPlane )
    {   if( (temp = (int)(50.0*DialValue[7])) )
        {   fprintf(OutFile,"slab %d\n",temp+50);
        } else fputs("slab on\n",OutFile);

        fputs("set slabmode ",OutFile);
        switch( SlabMode )
        {   default:            
            case(SlabClose):    ptr = "solid";    break;
            case(SlabReject):   ptr = "reject";   break;
            case(SlabHalf):     ptr = "half";     break;
            case(SlabHollow):   ptr = "hollow";   break;
            case(SlabSection):  ptr = "section";
        }
        fputs(ptr,OutFile);
        putc('\n',OutFile);
    } else fputs("slab off\n",OutFile);

    phi = Round(Rad2Deg*asin(RotX[2]));
    if( phi == 90 )
    {   theta = -Round(Rad2Deg*atan2(RotY[0],RotY[1]));
        psi = 0;
    } else if( phi == -90 )
    {   theta = Round(Rad2Deg*atan2(RotY[0],RotY[1]));
        psi = 0;
    } else /* General Case! */
    {   theta = Round(Rad2Deg*atan2(RotY[2],RotZ[2]));
        psi =  Round(-Rad2Deg*atan2(RotX[1],RotX[0]));
    }

    if( psi )   fprintf(OutFile,"rotate z %d\n",InvertY(-psi));
    if( phi )   fprintf(OutFile,"rotate y %d\n",phi);
    if( theta ) fprintf(OutFile,"rotate x %d\n",InvertY(-theta));

    if( (temp = (int)(100.0*DialValue[4])) )
        fprintf(OutFile,"translate x %d\n",temp);
    if( (temp = (int)(100.0*DialValue[5])) )
        fprintf(OutFile,"translate y %d\n",InvertY(-temp));

    if( DialValue[3] != 0.0 )
    {   if( DialValue[3]<0.0 )
        {   temp = (int)(100*DialValue[3]);
        } else temp = (int)(100*MaxZoom*DialValue[3]);
        fprintf(OutFile,"zoom %d\n",temp+100);
    }
    putc('\n',OutFile);

    /* Rendering */
    if( DrawAxes || DrawBoundBox || DrawUnitCell )
        fprintf(OutFile,"colour axes [%d %d %d]\n",BoxR,BoxG,BoxB);
    fprintf(OutFile,"set axes %s\n", DrawAxes? "on":"off" );
    fprintf(OutFile,"set boundingbox %s\n", DrawBoundBox? "on":"off" );
    fprintf(OutFile,"set unitcell %s\n", DrawUnitCell? "on":"off" );

    if( Database->hlist )
    {   fputs("set hbond ",OutFile);
        fputs(HBondMode?"backbone":"sidechain",OutFile);
        fputc('\n',OutFile);
    }

    if( Database->slist )
    {   fputs("set ssbond ",OutFile);
        fputs(SSBondMode?"backbone":"sidechain",OutFile);
        fputc('\n',OutFile);
    }

    fputs("set bondmode and\ndots off\n\n",OutFile); 
    fputs("\n# Avoid Colour Problems!\nselect all\n",OutFile);
    fputs("colour bonds none\ncolour backbone none\n",OutFile);
    fputs("colour hbonds none\ncolour ssbonds none\n",OutFile);
    fputs("colour ribbons none\ncolour white\n",OutFile);
    SelectAll = True;

    WriteScriptAtoms();
    if( UseSlabPlane && (SlabMode==SlabSection) )
    {   /* Section Mode Slabbing! */
        fclose(OutFile);
#ifdef APPLEMAC
        SetFileInfo(name,'RSML','RSML',133);
#endif
        return(True);
    }

    WriteScriptBonds();
    WriteScriptRibbons();
    WriteScriptBackbone();
    WriteScriptLabels();
    fputc('\n',OutFile);
    
    WriteScriptHBonds("ssbonds",Database->slist);
    WriteScriptHBonds("hbonds",Database->hlist);
    WriteScriptAll();

    fclose(OutFile);
#ifdef APPLEMAC
    SetFileInfo(name,'RSML','RSML',133);
#endif
    return( True );
}



#ifdef FUNCPROTO
static void OutputKinemageVector(Atom __far*,Atom __far*,Chain __far*,int);
static void WriteKinemageBonds( Chain __far* );
static void WriteKinemageSpheres( Chain __far* );
static void WriteKinemageRibbons( Chain __far* );
static void WriteKinemageLabels( Chain __far* );
#endif


static char *FindKinemageCol( r, g, b )
    int r, g, b;
{
    register Long dist,best;
    register int dr,dg,db;
    register int i,res;

    res = 0;
    dr = KinemageCol[0].r - r;
    dg = KinemageCol[0].g - g;
    db = KinemageCol[0].b - b;
    best = (Long)dr*dr + (Long)dg*dg + (Long)db*db;

    for( i=1; ir,ptr->g,ptr->b) );
}




static void OutputKinemageVector( src, dst, chain, col )
    Atom __far *src, __far *dst;  
    Chain __far *chain;
    int col;
{
    register Group __far *group;
    register Group __far *sgrp;
    register Group __far *dgrp;
    register Atom __far *aptr;
    register Real x, y, z;
    register char *col1;
    register char *col2;


    /* Determine Chain and Groups */
    sgrp = dgrp = (Group __far*)0;

    if( chain )
    {   for( group=chain->glist; group; group=group->gnext )
        {   for( aptr=group->alist; aptr; aptr=aptr->anext )
            {   if( aptr == src ) sgrp = group;
                if( aptr == dst ) dgrp = group;
            }
            if( sgrp && dgrp ) break;
        }
    } else for( chain=Database->clist; chain; chain=chain->cnext )
    {   for( group=chain->glist; group; group=group->gnext )
        {   for( aptr=group->alist; aptr; aptr=aptr->anext )
            {   if( aptr == src ) sgrp = group;
                if( aptr == dst ) dgrp = group;
            }
            if( sgrp && dgrp ) break;
        }
        if( group ) break;
    }


    if( !sgrp || !dgrp ) 
        return;

    if( !col )
    {   col1 = GetKinemageCol(src->col);
        col2 = GetKinemageCol(dst->col);
    } else col1 = col2 = GetKinemageCol(col);

    if( (col1!=MageCol) && (col2==MageCol) )
    {   aptr = src;  src = dst;  dst = aptr;
        col2 = col1;  col1 = MageCol;
    }


    if( col1 != MageCol )
    {   fprintf(OutFile,"@vectorlist {} color= %s\n",col1);
        MagePrev = (Atom __far*)0;
    }

    if( src != MagePrev )
    {   if( MainGroupCount>1 )
        {   fprintf(OutFile,"{%.4s %.3s %d}", ElemDesc[src->refno], 
                    Residue[sgrp->refno], sgrp->serno );
        } else fprintf(OutFile,"{%.4s %d}",ElemDesc[src->refno],src->serno);
        fprintf(OutFile," P %g %g %g\n", src->xorg/250.0, 
                InvertY(src->yorg)/250.0, src->zorg/250.0 );
    }

    if( col1 != col2 )
    {   x = (src->xorg+dst->xorg)/500.0;
        y = (src->yorg+dst->yorg)/500.0;
        z = (src->zorg+dst->zorg)/500.0;

        fprintf(OutFile,"{} L %g %g %g\n", x, InvertY(y), z );
        fprintf(OutFile,"@vectorlist {} color= %s\n",col2);
        fprintf(OutFile,"{} P %g %g %g\n", x, InvertY(y), z );
    }

    if( MainGroupCount>1 )
    {   fprintf(OutFile,"{%.4s %.3s %d}", ElemDesc[dst->refno],
                Residue[dgrp->refno], dgrp->serno );
    } else fprintf(OutFile,"{%.4s %d}",ElemDesc[dst->refno],dst->serno);
    fprintf(OutFile," L %g %g %g\n", dst->xorg/250.0,
            InvertY(dst->yorg)/250.0, dst->zorg/250.0 );

    MagePrev = dst;
    MageCol = col2;
}


static void WriteKinemageBonds( chain )
    Chain __far *chain;
{
    register Bond __far *bptr;
    register Bond __far *flag;

    MagePrev = (Atom __far*)0;  
    MageCol = (char*)0;

    ForEachBond
        if( KinemageFlag || (bptr->flag&DrawBondFlag) )
        {   if( !MagePrev ) 
                fputs("@subgroup {wireframe} dominant\n",OutFile);
            OutputKinemageVector(bptr->srcatom, bptr->dstatom, 
                                 chain, bptr->col);
        }

    if( !chain->blist ) 
        return;

    /* Test for displayed backbone */
    for( flag=chain->blist; flag; flag=flag->bnext )
        if( flag->flag & DrawBondFlag ) break;
    if( !KinemageFlag && !flag ) return;

    MagePrev = (Atom __far*)0;  
    MageCol = (char*)0;

    for( bptr=chain->blist; bptr; bptr=bptr->bnext )
        if( KinemageFlag || (bptr->flag&DrawBondFlag) )
        {   if( !MagePrev )
            {   fputs("@subgroup {alpha trace} dominant",OutFile);
                fputs( (KinemageFlag && !flag)? " off\n":"\n",OutFile);
            }
            OutputKinemageVector(bptr->srcatom,bptr->dstatom,
                                 chain,bptr->col);
        }
}


static void WriteKinemageSpheres( chain )
    Chain __far *chain;
{
    register Group __far *group;
    register Atom __far *aptr;
    register char *col;
    register int radius;

    MageCol = (char*)0;
    for( group=chain->glist; group; group=group->gnext )
        for( aptr=group->alist; aptr; aptr=aptr->anext )
            if( aptr->flag & SphereFlag )
            {   if( !MageCol )
                    fputs("@subgroup {CPK spheres} dominant\n",OutFile);

                col = GetKinemageCol(aptr->col);
                if( (col!=MageCol) || (aptr->radius!=radius) )
                {   fprintf(OutFile,"@balllist {} color= %s radius= %g\n",
                                    col, aptr->radius/250.0);
                    radius = aptr->radius;
                    MageCol = col;
                }

                if( MainGroupCount>1 )
                {   fprintf(OutFile,"{%.4s %.3s %d}", ElemDesc[aptr->refno],
                                    Residue[group->refno], group->serno );
                } else fprintf(OutFile,"{%.4s %d}",ElemDesc[aptr->refno],
                                    aptr->serno);
                fprintf(OutFile," %g %g %g\n", aptr->xorg/250.0,
                       InvertY(aptr->yorg)/250.0, aptr->zorg/250.0 );
            }
}


static void WriteKinemageRibbons( chain )
    Chain __far *chain;
{
}



static void WriteKinemageLabels( chain )
    Chain __far *chain;
{
    register Group __far *group;
    register Atom __far *aptr;
    register Label *label;
    register char *col;

    auto char buffer[256];

    MageCol = (char*)0;
    for( group=chain->glist; group; group=group->gnext )
        for( aptr=group->alist; aptr; aptr=aptr->anext )
            if( aptr->label )
            {   if( !MageCol )
                    fputs("@subgroup {labels} dominant\n",OutFile);
                if( UseLabelCol )
                {   col = FindKinemageCol(LabR,LabG,LabB);
                } else col = GetKinemageCol(aptr->col);

                if( col != MageCol )
                    fprintf(OutFile,"@labellist {} color= %s\n",col);
                label = (Label*)aptr->label;
                FormatLabel(chain,group,aptr,label->label,buffer);
                fprintf(OutFile,"{%s} %g %g %g\n", buffer, aptr->xorg/250.0, 
                        InvertY(aptr->yorg)/250.0, aptr->zorg/250.0);
                MageCol = col;
            }
}


static void OutputKinemageUnitCell()
{
}


static void WriteKinemageData()
{
    register DotStruct __far *ptr;
    register HBond __far *hptr;
    register Real dx, dy, dz;
    register char *col;
    register int i;

    /* Hydrogen Bonds */
    for( hptr=Database->hlist; hptr; hptr=hptr->hnext )
        if( hptr->flag & DrawBondFlag ) break;

    if( KinemageFlag && Database->hlist )
    {   fputs("@group {h-bonds}",OutFile);
        fputs( hptr? "\n" : "off", OutFile );

        fputs("@subgroup {sidechain} dominant",OutFile);
        fputs( HBondMode? " off\n" : "\n", OutFile);
        for( hptr=Database->hlist; hptr; hptr=hptr->hnext )
            OutputKinemageVector(hptr->src,hptr->dst,
                                 (Chain __far*)0, hptr->col);

        fputs("@subgroup {mainchain} dominant",OutFile);
        fputs( HBondMode? "\n" : " off\n", OutFile);
        for( hptr=Database->hlist; hptr; hptr=hptr->hnext )
            OutputKinemageVector(hptr->srcCA,hptr->dstCA,
                                 (Chain __far*)0, hptr->col);
    } else if( hptr )
    {   fputs("@group {h-bonds} dominant\n",OutFile);
        for( hptr=Database->hlist; hptr; hptr=hptr->hnext )
            if( hptr->flag&DrawBondFlag )
                OutputKinemageVector( HBondMode?hptr->srcCA:hptr->src,
                                      HBondMode?hptr->dstCA:hptr->dst,
                                     (Chain __far*)0, hptr->col);
    }


    /* Disulphide Bridges */
    for( hptr=Database->slist; hptr; hptr=hptr->hnext )
        if( hptr->flag & DrawBondFlag ) break;

    if( KinemageFlag && Database->slist )
    {   fputs("@group {S-S bridges}",OutFile);
        fputs( hptr? "\n" : "off", OutFile );

        fputs("@subgroup {sidechain} dominant",OutFile);
        fputs( SSBondMode? " off\n" : "\n", OutFile);
        for( hptr=Database->slist; hptr; hptr=hptr->hnext )
            OutputKinemageVector(hptr->src,hptr->dst,
                                 (Chain __far*)0, hptr->col);

        fputs("@subgroup {mainchain} dominant",OutFile);
        fputs( SSBondMode? "\n" : " off\n", OutFile);
        for( hptr=Database->slist; hptr; hptr=hptr->hnext )
            OutputKinemageVector(hptr->srcCA,hptr->dstCA,
                                 (Chain __far*)0, hptr->col);
    } else if( hptr )
    {   fputs("@group {S-S bridges} dominant\n",OutFile);
        for( hptr=Database->slist; hptr; hptr=hptr->hnext )
            if( hptr->flag&DrawBondFlag )
                OutputKinemageVector( SSBondMode?hptr->srcCA:hptr->src,
                                      SSBondMode?hptr->dstCA:hptr->dst,
                                     (Chain __far*)0, hptr->col);
    }


    /* Dot Surfaces */
    if( DrawDots )
    {   fputs("@group {dot surface} dominant\n",OutFile);
        MageCol = (char*)0;

        for( ptr=DotPtr; ptr; ptr=ptr->next )
            for( i=0; icount; i++ )
            {   col = GetKinemageCol(ptr->col[i]);
                if( col != MageCol )
                {   fprintf(OutFile,"@dotlist {} color= %s\n",col);
                    MageCol = col;
                }
                fprintf(OutFile, "{} %g %g %g\n", ptr->xpos[i]/250.0,
                        InvertY(ptr->ypos[i])/250.0, ptr->zpos[i]/250.0 );
            }
    }

    /* Draw `Background' Objects */
    if( !KinemageFlag && !DrawAxes && 
        !DrawBoundBox && !DrawUnitCell )
        return;

    dx = MaxX/250.0;  dy = MaxY/250.0;  dz = MaxZ/250.0;
    MageCol = FindKinemageCol( BoxR, BoxG, BoxB );

    if( DrawAxes || KinemageFlag )
    {   fputs("@group {coord axes} dominant",OutFile);
        fputs( (DrawAxes?"\n":" off\n"), OutFile );
        fprintf(OutFile,"@vectorlist {} color= %s\n",MageCol);

        fprintf(OutFile,"{} P %g 0 0\n{} L %g 0 0\n",-dx,dx);
        fprintf(OutFile,"{} P 0 %g 0\n{} L 0 %g 0\n",-dy,dy);
        fprintf(OutFile,"{} P 0 0 %g\n{} L 0 0 %g\n",-dz,dz);
    }

    if( DrawBoundBox || KinemageFlag )
    {   fputs("@group {bound box} dominant",OutFile);
        fputs( (DrawAxes?"\n":" off\n"), OutFile );
        fprintf(OutFile,"@vectorlist {} color= %s\n",MageCol);

        fprintf(OutFile,"{} P %g %g %g\n",-dx,-dy,-dz);
        fprintf(OutFile,"{} L %g %g %g\n", dx,-dy,-dz);
        fprintf(OutFile,"{} L %g %g %g\n", dx, dy,-dz);
        fprintf(OutFile,"{} L %g %g %g\n",-dx, dy,-dz);
        fprintf(OutFile,"{} L %g %g %g\n",-dx,-dy,-dz);
        fprintf(OutFile,"{} L %g %g %g\n",-dx,-dy, dz);
        fprintf(OutFile,"{} L %g %g %g\n", dx,-dy, dz);
        fprintf(OutFile,"{} L %g %g %g\n", dx, dy, dz);
        fprintf(OutFile,"{} L %g %g %g\n",-dx, dy, dz);
        fprintf(OutFile,"{} L %g %g %g\n",-dx,-dy, dz);

        fprintf(OutFile,"{} P %g %g %g\n", dx,-dy,-dz);
        fprintf(OutFile,"{} L %g %g %g\n", dx,-dy, dz);
        fprintf(OutFile,"{} P %g %g %g\n", dx, dy,-dz);
        fprintf(OutFile,"{} L %g %g %g\n", dx, dy, dz);
        fprintf(OutFile,"{} P %g %g %g\n",-dx, dy,-dz);
        fprintf(OutFile,"{} L %g %g %g\n",-dx, dy, dz);
    }

    if( DrawUnitCell || KinemageFlag )
    {   fputs("@group {unit cell} dominant",OutFile);
        fputs( (DrawAxes?"\n":" off\n"), OutFile );
        fprintf(OutFile,"@vectorlist {} color= %s\n",MageCol);
        OutputKinemageUnitCell();
    }
}


int WriteKinemageFile( name )
    char *name;
{
    register Chain __far *chain;
    register Real zoom;

    if( !Database )
        return(True);

    OutFile = fopen(name,"w");
    if( !OutFile )
    {   FatalScriptError(name);
        return(False);
    }

    fputs("@text\nRasMol v2.5 generated Kinemage\n \n",OutFile);
    if( *InfoMoleculeName )
        fprintf(OutFile,"Molecule name ....... %s\n",InfoMoleculeName);
    if( *InfoClassification )
        fprintf(OutFile,"Classification ...... %s\n",InfoClassification);
    if( *InfoIdentCode )
        fprintf(OutFile,"Brookhaven Code ..... %s\n",InfoIdentCode);

    fputs("@kinemage 1\n@caption RasMol v2.5 generated Kinemage\n",OutFile);
    fputs("@onewidth\n",OutFile);

    if( DialValue[3] != 0.0 )
    {   if( DialValue[3]<0.0 )
        {   zoom = DialValue[3];
        } else zoom = MaxZoom*DialValue[3];
        fprintf(OutFile,"zoom %g\n",zoom+1.0);
    }

    if( InfoChainCount>1 )
    {   for( chain=Database->clist; chain; chain=chain->cnext )
        {   fprintf(OutFile,"@group {chain %c}\n",chain->ident);
            WriteKinemageSpheres( chain );
            WriteKinemageBonds( chain );
            WriteKinemageRibbons( chain );
            WriteKinemageLabels( chain );
        }
    } else
    {   fputs("@group {molecule}\n",OutFile);
        chain = Database->clist;
        WriteKinemageSpheres( chain );
        WriteKinemageBonds( chain );
        WriteKinemageRibbons( chain );
        WriteKinemageLabels( chain );
    }

    WriteKinemageData();
    fclose(OutFile);
#ifdef APPLEMAC
    SetFileInfo(name,'MAGE','TEXT',135);
#endif
    return( True );
}

 int WritePOVRayFile( name )
    char *name;
{
    return( True );
}

Modified: Tue Oct 25 16:00:00 1994 GMT
Page accessed 1222 times since Sat Apr 17 21:38:35 1999 GMT