RasMol2
|
Announce,
ChangeLog,
ChangeLog.1,
ChangeLog.2,
ChangeLog.3,
ChangeLog.4,
INSTALL,
Imakefile,
Makefile,
Makefile.bak,
Makefile.in,
Makefile.nt,
Makefile.pc,
PROJECTS,
README,
TODO,
abstree.c,
abstree.h,
applemac.c,
bitmaps.h,
command.c,
command.h,
data,
doc,
font.h,
graphics.h,
molecule.c,
molecule.h,
mswin,
mswin31.c,
outfile.c,
outfile.h,
pixutils.c,
pixutils.h,
rasmac.c,
rasmol.c,
rasmol.h,
rasmol.hlp,
rasmol.sh,
raswin.c,
render.c,
render.h,
script.c,
script.h,
tokens.h,
transfor.c,
transfor.h,
vms,
x11win.c,
|
|
|
/* render.c
* RasMol2 Molecular Graphics
* Roger Sayle, October 1994
* Version 2.5
*/
#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
#define RENDER
#include "graphics.h"
#include "render.h"
#include "molecule.h"
#include "transfor.h"
#include "command.h"
#include "abstree.h"
#include "pixutils.h"
/* Avoid PowerPC Errors! */
#ifdef INFINITY
#undef INFINITY
#endif
#define PoolSize 16
#define RootSix 2.4494897427831780
#define OneOverRootSix 0.4082482904638630
#define TwoOverRootSix 0.8164965809277260
#define ApproxZero 1.0E-3
#define INFINITY 200000
#define FUDGEFACTOR 1000
typedef struct { int dx, dy, dz; } DotVector;
typedef struct {
DotVector __far *probe;
DotVector __far *dots;
int count;
} ElemDotStruct;
typedef struct _Item {
struct _Item __far *list;
Atom __far *data;
} Item;
typedef struct { Real h,l; } Interval;
static ElemDotStruct __far *ElemDots;
static Label *FreeLabel, *LabelList;
static Atom __far * __far *YBucket;
static Atom __far * __far *IBuffer;
static int BuckY,ItemX;
static int FBufX,FBufY;
static int DBClear;
static Atom __far *SBuffer;
static Atom __far *Exclude;
static Real ShadowI, ShadowJ, ShadowK;
static int ShadowX, ShadowY, ShadowZ;
static int deltax, deltay, deltaz;
static int xcord, ycord, zcord;
static int xflag, yflag, zflag;
static int xhash, yhash, zhash;
static int RayCount;
static Item __far *FreeItem;
static Real VoxRatio,IVoxRatio;
static int VoxelCount,InVoxCount;
static int ProbeCount;
static int VoxelsDone;
/* Identified Atom Info */
static Long IdentDist;
static int IdentFound;
static int IdentDepth;
/* 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 FatalRenderError(ptr)
char *ptr;
{
char buffer[80];
sprintf(buffer,"Renderer Error: Unable to allocate %s!",ptr);
RasMolFatalExit(buffer);
}
int isqrt( val )
Card val;
{
#ifndef sun386
register int i,result;
register Card side, left;
register Card temp;
result = 0;
side = left = 0;
for( i=0; i>30);
result <<= 1; side <<= 1;
temp = side | 1;
val <<= 2;
if( left >= temp )
{ side = temp+1;
left -= temp;
result |= 1;
}
}
return( (int)result );
#else
return( (int)sqrt((double)val) );
#endif
}
#ifdef IBMPC
void ClearBuffers()
{
register char __huge *ptr;
register Long count;
if( !FBClear )
{ FBClear = True;
ptr = (Pixel __huge*)GlobalLock(FBufHandle);
count = (Long)XRange*YRange;
while( count > 65534 )
{ _fmemset(ptr,0,(size_t)65534);
count -= 65534;
ptr += 65534;
}
if( count )
_fmemset(ptr,0,(size_t)count);
GlobalUnlock(FBufHandle);
}
if( !DBClear )
{ DBClear = True;
ptr = (char __huge*)GlobalLock(DBufHandle);
count = (Long)XRange*YRange*sizeof(short);
while( count > 65534 )
{ _fmemset(ptr,0,(size_t)65534);
count -= 65534;
ptr += 65534;
}
if( count )
_fmemset(ptr,0,(size_t)count);
GlobalUnlock(DBufHandle);
}
}
#else /* !IBMPC */
void ClearBuffers()
{
register Long __huge *ptr;
register Long __huge *end;
register Long fill;
if( !FBClear )
{ FBClear = True;
fill = Lut[BackCol];
#ifdef EIGHTBIT
fill |= fill<<8;
fill |= fill<<16;
#endif
ptr = (Long __huge*)FBuffer;
end = (Long __huge*)(FBuffer+(Long)XRange*YRange);
do { *ptr++=fill; *ptr++=fill;
*ptr++=fill; *ptr++=fill;
} while( ptr>2; iptr = IBuffer;
for( index=0; index<=len; index++ )
{ *iptr++ = (void __far*)0; *iptr++ = (void __far*)0;
*iptr++ = (void __far*)0; *iptr++ = (void __far*)0;
}
ItemX = XRange;
}
}
void ReSizeScreen()
{
register Real orig;
if( Range != ZoomRange )
{ orig = MaxZoom;
MaxZoom = 0.236*(WorldSize+1000)/Range;
ZoomRange = Range; MaxZoom -= 1.0;
/* Handle Change in MaxZoom */
if( DialValue[3]>0.0 )
{ DialValue[3] *= orig/MaxZoom;
if( DialValue[3]>1.0 )
DialValue[3] = 1.0;
}
}
#ifdef IBMPC
if( !FBufHandle || (FBufX!=XRange) || (FBufY!=YRange) )
#else /* UNIX */
if( !FBuffer || (FBufX!=XRange) || (FBufY!=YRange) )
#endif
{ if( !CreateImage() )
FatalRenderError("frame buffer");
BucketFlag = False;
FBufX=XRange; FBufY=YRange; FBClear = False;
ReAllocBuffers();
ClearBuffers();
}
}
static void PrepareYBucket()
{
register Atom __far * __far *temp;
register Chain __far *chain;
register Group __far *group;
register Atom __far *aptr;
register int scan;
register int rad;
temp = YBucket;
for( scan=0; scanflag&SphereFlag )
{ rad = aptr->irad;
if( (aptr->x-rad>=XRange) ||
(aptr->x+rad<0) || (aptr->y+rad<0) )
continue;
if( (scan=aptr->y-rad) > BuckY ) continue;
if( scan>0 )
{ aptr->bucket = YBucket[scan];
YBucket[scan] = aptr;
} else
{ aptr->bucket = *YBucket;
*YBucket = aptr;
}
}
} else
ForEachAtom
if( aptr->flag&SphereFlag )
{ scan = aptr->y-aptr->irad;
aptr->bucket = YBucket[scan];
YBucket[scan] = aptr;
}
BucketFlag = True;
}
#ifdef FUNCPROTO
/* Function Prototypes */
static void SqrInterval( Interval __far* );
static void VoxelInsert( Atom __far*, int );
static int AtomInter( Atom __far* );
#endif
static void SqrInterval( ival )
Interval __far *ival;
{ register Real l,h;
l = ival->l;
h = ival->h;
if( l>=0.0 )
{ ival->l = l*l;
ival->h = h*h;
} else if( h<0.0 )
{ ival->l = h*h;
ival->h = l*l;
} else
{ ival->h = (-l>h)? l*l : h*h;
ival->l = 0.0;
}
}
static void VoxelInsert( ptr, ref )
Atom __far *ptr;
int ref;
{
register Item __far *datum;
register int i;
if( !FreeItem )
{ datum = (Item __far*)_fmalloc( PoolSize*sizeof(Item) );
if( !datum ) FatalRenderError("voxel item");
for( i=1; ilist = FreeItem;
FreeItem = datum++;
}
} else
{ datum = FreeItem;
FreeItem = datum->list;
}
datum->data = ptr;
InVoxCount++;
if( !HashTable[ref] ) VoxelCount++;
datum->list = (Item __far*)HashTable[ref];
HashTable[ref] = (void __far*)datum;
}
void ResetVoxelData()
{
register Item __far *datum;
register int i;
if( VoxelsDone )
{ for( i=0; ilist ) datum = datum->list;
datum->list = FreeItem;
FreeItem = (Item __far*)HashTable[i];
HashTable[i] = (void __far*)0;
}
VoxelsDone = False;
} else for( i=0; iflag & flag )
{ mx = aptr->xorg+Offset;
my = aptr->yorg+Offset;
mz = aptr->zorg+Offset;
if( flag != SphereFlag )
{ if( SolventDots || !ProbeRadius )
{ rad = ElemVDWRadius(GetElemNumber(aptr));
} else rad = ProbeRadius;
} else rad = aptr->radius;
radius2 = (Long)rad*rad;
lvx = (int)((mx-rad)*IVoxRatio); hvx = (int)((mx+rad)*IVoxRatio);
lvy = (int)((my-rad)*IVoxRatio); hvy = (int)((my+rad)*IVoxRatio);
lvz = (int)((mz-rad)*IVoxRatio); hvz = (int)((mz+rad)*IVoxRatio);
for( px=lvx; px<=hvx; px++ )
{ ix.l=px*VoxRatio-mx;
ix.h=ix.l+VoxRatio;
SqrInterval(&ix);
i = VOXORDER2*px + VOXORDER*lvy;
for( py=lvy; py<=hvy; py++ )
{ iy.l=py*VoxRatio-my;
iy.h=iy.l+VoxRatio;
SqrInterval(&iy);
for( pz=lvz; pz<=hvz; pz++ )
{ iz.l=pz*VoxRatio-mz;
iz.h=iz.l+VoxRatio;
SqrInterval(&iz);
if( ((ix.h+iy.h+iz.h)>radius2) &&
((ix.l+iy.l+iz.l)ApproxZero )
{ deltax = (int)(FUDGEFACTOR/ShadowI); xhash = VOXORDER2; xflag = 1;
} else if( ShadowI<-ApproxZero )
{ deltax = -(int)(FUDGEFACTOR/ShadowI); xhash = -VOXORDER2; xflag = -1;
} else xflag = 0;
if( ShadowJ>ApproxZero )
{ deltay = (int)(FUDGEFACTOR/ShadowJ); yhash = VOXORDER; yflag = 1;
} else if( ShadowJ<-ApproxZero )
{ deltay = -(int)(FUDGEFACTOR/ShadowJ); yhash = -VOXORDER; yflag = -1;
} else yflag = 0;
if( ShadowK>ApproxZero )
{ deltaz = (int)(FUDGEFACTOR/ShadowK); zhash = zflag = 1;
} else if( ShadowK<-ApproxZero )
{ deltaz = -(int)(FUDGEFACTOR/ShadowK); zhash = zflag = -1;
} else zflag = 0;
}
static int AtomInter( ptr )
Atom __far *ptr;
{
register Long modv,radius2;
register int vx, vy, vz;
register Real tca;
if( ptr->mbox == RayCount )
return( False );
ptr->mbox = RayCount;
vx = (int)ptr->xorg-ShadowX;
vy = (int)ptr->yorg-ShadowY;
vz = (int)ptr->zorg-ShadowZ;
tca = vx*ShadowI + vy*ShadowJ + vz*ShadowK;
if( tca<0.0 ) return( False );
radius2 = ptr->radius+10; radius2 = radius2*radius2;
modv = (Long)vx*vx + (Long)vy*vy + (Long)vz*vz - radius2;
return( modvlist )
if( (ptr->data!=Exclude) && AtomInter(ptr->data) )
{ SBuffer = ptr->data;
return( True );
}
if( (dx<=dy) && (dx<=dz) )
{ xcord += xflag;
if( (xcord<0) || (xcord>=VOXORDER) ) return( False );
ident += xhash; dx += deltax;
} else if( dy<=dz ) /*(dy<=dx)*/
{ ycord += yflag;
if( (ycord<0) || (ycord>=VOXORDER) ) return( False );
ident += yhash; dy += deltay;
} else /* (dz<=dx) && (dz<=dy) */
{ zcord += zflag;
if( (zcord<0) || (zcord>=VOXORDER) ) return( False );
ident += zhash; dz += deltaz;
}
}
}
#define UpdateScanAcross \
if( depth>*dptr ) \
{ *dptr = depth; \
iptr[dx] = ptr; \
} dptr++; dx++;
/* ScanLine for Shadows! */
static void ScanLine()
{
static Atom __far *list;
register Atom __far *ptr;
register Atom __far * __far *iptr;
register Atom __far * __far *prev;
register short __huge *dbase;
register short __huge *dptr;
register Pixel __huge *fptr;
register Byte __far *tptr;
register int pos,depth,inten;
register int lastx,wide,scan;
register int dx,dy,dz;
fptr = FBuffer;
dbase = DBuffer;
list = (void __far*)0;
wide = XRange>>2; iptr = IBuffer;
for( pos=0; pos<=wide; pos++ )
{ *iptr++ = (void __far*)0; *iptr++ = (void __far*)0;
*iptr++ = (void __far*)0; *iptr++ = (void __far*)0;
}
for( scan=0; scanbucket )
{ ptr->next = list; list = ptr; }
prev = &list;
for( ptr=list; ptr; ptr=ptr->next )
{ dy = scan - ptr->y;
wide = LookUp[ptr->irad][AbsFun(dy)];
lastx = (XRange-1)-ptr->x;
if( widex);
iptr = IBuffer+ptr->x;
tptr = LookUp[wide];
dptr = dbase+ptr->x+dx;
while( dx<=lastx )
{ depth = tptr[AbsFun(dx)]+ptr->z;
UpdateScanAcross;
}
/* Remove completed atoms */
if( dy == ptr->irad )
{ *prev = ptr->next;
} else prev = &ptr->next;
} /*ptr*/
/* Process visible scanline */
prev = (Atom __far* __far*)IBuffer;
SBuffer = (void __far*)0;
dptr = dbase;
for( pos=0; posz;
#ifdef INVERT
inten = (dz<<1)+(pos-ptr->x)+(scan-ptr->y);
#else
inten = (dz<<1)+(pos-ptr->x)-(scan-ptr->y);
#endif
if( inten>0 )
{ inten = (int)( (inten*ColConst[ptr->irad])>>ColBits);
dz = *dptr-ZOffset;
dx = pos-XOffset;
dy = scan-YOffset;
ShadowX = (int)(dx*InvX[0]+dy*InvX[1]+dz*InvX[2]);
ShadowY = (int)(dx*InvY[0]+dy*InvY[1]+dz*InvY[2]);
ShadowZ = (int)(dx*InvZ[0]+dy*InvZ[1]+dz*InvZ[2]);
Exclude = ptr;
if( ShadowRay() )
{ *fptr = Lut[ptr->col+(inten>>2)];
} else *fptr = Lut[ptr->col+inten];
} else *fptr = Lut[ptr->col];
*prev = (void __far*)0;
}
dptr++; fptr++; prev++;
}
dbase = dptr;
} /*scan*/
}
#ifdef FUNCPROTO
/* Function Prototype */
static void DisplayHBonds( HBond __far *, int );
static void DisplayRibbon( Chain __far * );
#endif
static void DisplaySpaceFill()
{
register Chain __far *chain;
register Group __far *group;
register Atom __far *aptr;
if( UseShadow )
{ if( !BucketFlag )
PrepareYBucket();
ScanLine();
} else if( UseClipping )
{ ForEachAtom
if( aptr->flag&SphereFlag )
ClipSphere(aptr->x,aptr->y,aptr->z,aptr->irad,aptr->col);
} else
ForEachAtom
if( aptr->flag&SphereFlag )
DrawSphere(aptr->x,aptr->y,aptr->z,aptr->irad,aptr->col);
}
static void DisplayWireFrame()
{
register Bond __far *bptr;
register Atom __far *s;
register Atom __far *d;
register int sc,dc;
if( UseClipping )
{ ForEachBond
if( bptr->flag&WireFlag )
{ s = bptr->srcatom; d = bptr->dstatom;
if( !bptr->col )
{ sc = s->col; dc = d->col;
} else sc = dc = bptr->col;
ClipTwinVector(s->x,s->y,s->z,d->x,d->y,d->z,sc,dc);
} else if( bptr->flag&CylinderFlag )
{ s = bptr->srcatom; d = bptr->dstatom;
if( !bptr->col )
{ sc = s->col; dc = d->col;
} else sc = dc = bptr->col;
if( bptr->irad>0 )
{ ClipCylinder(s->x,s->y,s->z,sc,d->x,d->y,d->z,dc,bptr->irad);
} else ClipTwinLine(s->x,s->y,s->z,d->x,d->y,d->z,
sc+ColourMask,dc+ColourMask);
}
} else
ForEachBond
if( bptr->flag&WireFlag )
{ s = bptr->srcatom; d = bptr->dstatom;
if( !bptr->col )
{ sc = s->col; dc = d->col;
} else sc = dc = bptr->col;
DrawTwinVector(s->x,s->y,s->z,d->x,d->y,d->z,sc,dc);
} else if( bptr->flag&CylinderFlag )
{ s = bptr->srcatom; d = bptr->dstatom;
if( !bptr->col )
{ sc = s->col; dc = d->col;
} else sc = dc = bptr->col;
if( bptr->irad>0 )
{ DrawCylinder(s->x,s->y,s->z,sc,d->x,d->y,d->z,dc,bptr->irad);
} else DrawTwinLine(s->x,s->y,s->z,d->x,d->y,d->z,
sc+ColourMask,dc+ColourMask);
}
}
static void DisplayBackBone()
{
register Chain __far *chain;
register Bond __far *bptr;
register Atom __far *s;
register Atom __far *d;
register int sc,dc;
ForEachBack
if( bptr->flag&DrawBondFlag )
{ s = bptr->srcatom; d = bptr->dstatom;
if( !bptr->col )
{ sc = s->col; dc = d->col;
} else sc = dc = bptr->col;
if( bptr->flag&CylinderFlag )
{ if( bptr->irad>0 )
{ ClipCylinder(s->x,s->y,s->z,sc,d->x,d->y,d->z,dc,bptr->irad);
} else ClipTwinLine(s->x,s->y,s->z,d->x,d->y,d->z,
sc+ColourMask,dc+ColourMask);
} else ClipTwinVector(s->x,s->y,s->z,d->x,d->y,d->z,sc,dc);
}
}
static void DisplayHBonds( list, mode )
HBond __far *list;
int mode;
{
register HBond __far *ptr;
register Atom __far *s;
register Atom __far *d;
register int sc,dc;
for( ptr=list; ptr; ptr=ptr->hnext )
if( ptr->flag & DrawBondFlag )
{ if( mode )
{ s = ptr->srcCA; d = ptr->dstCA;
if( !s || !d ) continue;
} else
{ d = ptr->src;
s = ptr->dst;
}
if( !ptr->col )
{ sc = s->col; dc = d->col;
} else sc = dc = ptr->col;
if( ptr->flag & CylinderFlag )
{ if( ptr->irad>0 )
{ ClipCylinder(s->x,s->y,s->z,sc,
d->x,d->y,d->z,dc,ptr->irad);
} else ClipTwinLine(s->x,s->y,s->z,d->x,d->y,d->z,
sc+ColourMask,dc+ColourMask);
} else ClipDashVector(s->x,s->y,s->z,d->x,d->y,d->z,sc,dc);
}
}
static void CalculateInten( ptr )
Knot *ptr;
{
register Real inten;
register int size;
size = isqrt( (Long)ptr->cx*ptr->cx +
(Long)ptr->cy*ptr->cy +
(Long)ptr->cz*ptr->cz );
if( size )
{
#ifdef INVERT
inten = ptr->cx + ptr->cy + ptr->cz + ptr->cz;
#else
inten = ptr->cx - ptr->cy + ptr->cz + ptr->cz;
#endif
inten /= size*RootSix;
if( ptr->cz < 0 ) inten = -inten;
ptr->inten = (int)(ColourMask*inten);
if( ptr->inten<0 ) ptr->inten = 0;
} else ptr->inten = ColourMask;
}
static void DisplayRibbon( chain )
Chain __far *chain;
{
register Group __far *group;
register Atom __far *captr;
register Atom __far *o1ptr;
register Atom __far *o2ptr;
register Atom __far *next;
register int prev,wide;
register int col1,col2;
register int bx,by,bz;
register int dx,dy,dz;
register int size;
static Knot mid1, mid2, mid3;
static Knot knot1, knot2;
prev = False;
group = chain->glist;
if( IsAmino(group->refno) )
{ captr = FindGroupAtom(group,1);
} else captr = FindGroupAtom(group,7);
while( group->gnext )
{ if( IsAmino(group->gnext->refno) )
{ next = FindGroupAtom(group->gnext,1);
o1ptr = FindGroupAtom(group,3);
} else /* Nucleic Acid */
{ next = FindGroupAtom(group->gnext,7);
o1ptr = FindGroupAtom(group->gnext,10);
}
/* When not to have a control point! */
if( !next || !captr || !o1ptr || (next->flag&BreakFlag) ||
!((group->flag|group->gnext->flag)&(RibbonFlag|StrandFlag)) )
{ group = group->gnext;
captr = next;
prev = False;
continue;
}
knot2.tx = next->x - captr->x;
knot2.ty = next->y - captr->y;
knot2.tz = next->z - captr->z;
if( IsAmino(group->refno) )
{ bx = o1ptr->x - captr->x;
by = o1ptr->y - captr->y;
bz = o1ptr->z - captr->z;
} else if( !FindGroupAtom(group,17) &&
(o2ptr=FindGroupAtom(group,8)) )
{ /* Deoxyribonucleic Acid */
o2ptr = FindGroupAtom(group,8);
bx = (o1ptr->x + o2ptr->x)/2 - captr->x;
by = (o1ptr->y + o2ptr->y)/2 - captr->y;
bz = (o1ptr->z + o2ptr->z)/2 - captr->z;
} else /* Ribonucleic Acid */
{ bx = o1ptr->x - captr->x;
by = o1ptr->y - captr->y;
bz = o1ptr->z - captr->z;
}
/* c := a x b */
knot2.cx = knot2.ty*bz - knot2.tz*by;
knot2.cy = knot2.tz*bx - knot2.tx*bz;
knot2.cz = knot2.tx*by - knot2.ty*bx;
knot2.px = (captr->x + next->x)/2;
knot2.py = (captr->y + next->y)/2;
knot2.pz = (captr->z + next->z)/2;
if( (group->struc&group->gnext->struc) & HelixFlag )
{ size = isqrt((Long)knot2.cx*knot2.cx +
(Long)knot2.cy*knot2.cy +
(Long)knot2.cz*knot2.cz);
if( size )
{ wide = (int)(375*Scale);
#ifdef INVERT
knot2.px += (int)(((Long)wide*knot2.cx)/size);
knot2.py += (int)(((Long)wide*knot2.cy)/size);
knot2.pz += (int)(((Long)wide*knot2.cz)/size);
#else
knot2.px -= (int)(((Long)wide*knot2.cx)/size);
knot2.py -= (int)(((Long)wide*knot2.cy)/size);
knot2.pz -= (int)(((Long)wide*knot2.cz)/size);
#endif
}
}
/* d := c x a */
dx = (int)(((Long)knot2.cy*knot2.tz -
(Long)knot2.cz*knot2.ty)/96);
dy = (int)(((Long)knot2.cz*knot2.tx -
(Long)knot2.cx*knot2.tz)/96);
dz = (int)(((Long)knot2.cx*knot2.ty -
(Long)knot2.cy*knot2.tx)/96);
/* Average Ribbon Width */
if( group->flag & (RibbonFlag|StrandFlag) )
{ if( group->gnext->flag & (RibbonFlag|StrandFlag) )
{ wide = (group->width+group->gnext->width)>>1;
} else wide = group->width;
} else wide = group->gnext->width;
wide = (int)(wide*Scale);
size = isqrt((Long)dx*dx + (Long)dy*dy + (Long)dz*dz);
if( size )
{ dx = (int)(((Long)wide*dx)/size);
dy = (int)(((Long)wide*dy)/size);
dz = (int)(((Long)wide*dz)/size);
/* Handle Carbonyl Oxygen Flip */
if( prev && ((knot1.wx*dx + knot1.wy*dy + knot1.wz*dz) < 0) )
{ knot2.wx = -dx;
knot2.wy = -dy;
knot2.wz = -dz;
} else
{ knot2.wx = dx;
knot2.wy = dy;
knot2.wz = dz;
}
} else
{ knot2.wx = 0;
knot2.wy = 0;
knot2.wz = 0;
}
if( (group->flag|group->gnext->flag)&RibbonFlag )
CalculateInten( &knot2 );
if( !(col1 = group->col1) )
col1 = captr->col;
if( !(col2 = group->col2) )
col2 = captr->col;
if( prev )
{ /* Approximate spline segment with straight line! */
/* StrandRibbon( &knot1, &knot2, col1, col2 ); */
/* Calculate Hermite Spline Points */
mid1.px = (int)(((Long)54*knot1.px + (Long)9*knot1.tx +
(Long)10*knot2.px - (Long)3*knot2.tx)>>6);
mid1.py = (int)(((Long)54*knot1.py + (Long)9*knot1.ty +
(Long)10*knot2.py - (Long)3*knot2.ty)>>6);
mid1.pz = (int)(((Long)54*knot1.pz + (Long)9*knot1.tz +
(Long)10*knot2.pz - (Long)3*knot2.tz)>>6);
mid2.px = (int)(((Long)4*knot1.px + knot1.tx +
(Long)4*knot2.px - knot2.tx)>>3);
mid2.py = (int)(((Long)4*knot1.py + knot1.ty +
(Long)4*knot2.py - knot2.ty)>>3);
mid2.pz = (int)(((Long)4*knot1.pz + knot1.tz +
(Long)4*knot2.pz - knot2.tz)>>3);
mid3.px = (int)(((Long)10*knot1.px + (Long)3*knot1.tx +
(Long)54*knot2.px - (Long)9*knot2.tx)>>6);
mid3.py = (int)(((Long)10*knot1.py + (Long)3*knot1.ty +
(Long)54*knot2.py - (Long)9*knot2.ty)>>6);
mid3.pz = (int)(((Long)10*knot1.pz + (Long)3*knot1.tz +
(Long)54*knot2.pz - (Long)9*knot2.tz)>>6);
/* Calculate Hermite Spline Widths */
mid1.wx = (27*knot1.wx + 5*knot2.wx)>>5;
mid1.wy = (27*knot1.wy + 5*knot2.wy)>>5;
mid1.wz = (27*knot1.wz + 5*knot2.wz)>>5;
mid2.wx = (knot1.wx + knot2.wx)>>1;
mid2.wy = (knot1.wy + knot2.wy)>>1;
mid2.wz = (knot1.wz + knot2.wz)>>1;
mid3.wx = (5*knot1.wx + 27*knot2.wx)>>5;
mid3.wy = (5*knot1.wy + 27*knot2.wy)>>5;
mid3.wz = (5*knot1.wz + 27*knot2.wz)>>5;
/* Draw the Spline Segments */
if( group->flag & RibbonFlag )
{ mid1.cx = (27*knot1.cx + 5*knot2.cx)>>5;
mid1.cy = (27*knot1.cy + 5*knot2.cy)>>5;
mid1.cz = (27*knot1.cz + 5*knot2.cz)>>5;
CalculateInten(&mid1);
mid2.cx = (knot1.cx + knot2.cx)>>1;
mid2.cy = (knot1.cy + knot2.cy)>>1;
mid2.cz = (knot1.cz + knot2.cz)>>1;
CalculateInten(&mid2);
mid3.cx = (5*knot1.cx + 27*knot2.cx)>>5;
mid3.cy = (5*knot1.cy + 27*knot2.cy)>>5;
mid3.cz = (5*knot1.cz + 27*knot2.cz)>>5;
CalculateInten(&mid3);
SolidRibbon( &knot1, &mid1, col1 );
SolidRibbon( &mid1, &mid2, col1 );
SolidRibbon( &mid2, &mid3, col1 );
SolidRibbon( &mid3, &knot2, col1 );
} else if( group->flag & StrandFlag )
{ StrandRibbon( &knot1, &mid1, col1, col2 );
StrandRibbon( &mid1, &mid2, col1, col2 );
StrandRibbon( &mid2, &mid3, col1, col2 );
StrandRibbon( &mid3, &knot2, col1, col2 );
}
} else prev = True;
group = group->gnext;
captr = next;
knot1 = knot2;
}
}
static void ResetLabels()
{
register Label *ptr;
while( LabelList )
{ ptr = LabelList;
LabelList = ptr->next;
ptr->next = FreeLabel;
free(ptr->label);
FreeLabel = ptr;
}
}
int DeleteLabels()
{
register Chain __far *chain;
register Group __far *group;
register Atom __far *aptr;
register Label *label;
register Label **ptr;
register int result;
if( !Database )
return( True );
result = True;
DrawLabels = False;
ForEachAtom
if( aptr->flag & SelectFlag )
{ result = False;
if( aptr->label )
{ label = (Label*)aptr->label;
aptr->label = (void*)0;
label->refcount--;
result = False;
if( !label->refcount )
{ ptr = &LabelList;
while( *ptr != label )
ptr = &(*ptr)->next;
*ptr = label->next;
label->next = FreeLabel;
free(label->label);
FreeLabel = label;
}
}
} else if( aptr->label )
DrawLabels = True;
return( result );
}
void DefineLabels( label )
char *label;
{
register Chain __far *chain;
register Group __far *group;
register Atom __far *aptr;
register Label *ptr;
register char *cptr;
register int len;
if( !Database ) return;
if( DeleteLabels() )
return;
len = 0;
for( cptr=label; *cptr; cptr++ )
len++;
/* Strip trailing spaces */
while( len && cptr[-1]==' ' )
{ cptr--; len--;
*cptr = '\0';
}
if( !len ) return;
/* Test for existing label */
for( ptr=LabelList; ptr; ptr=ptr->next )
if( !strcmp(ptr->label,label) )
break;
if( !ptr )
{ if( FreeLabel )
{ ptr = FreeLabel; FreeLabel = ptr->next;
} else if( !(ptr=(Label*)malloc(sizeof(Label))) )
FatalRenderError("label");
ptr->label = (char*)malloc(len+1);
if( !ptr->label ) FatalRenderError("label");
cptr = ptr->label;
while( *cptr++ = *label++ );
ptr->next = LabelList;
ptr->refcount = 0;
LabelList = ptr;
}
ForEachAtom
if( aptr->flag & SelectFlag )
{ aptr->label = ptr;
DrawLabels = True;
ptr->refcount++;
}
}
static void DisplayLabels()
{
register Chain __far *chain;
register Group __far *group;
register Atom __far *aptr;
register Label *label;
register int col,z;
auto char buffer[256];
if( !Database )
return;
if( !UseSlabPlane )
{ z = ImageRadius + ZOffset;
} else z = SlabValue - 1;
ForEachAtom
if( aptr->label )
{ /* Peform Label Slabbing! */
if( !ZValid(aptr->z) )
continue;
label = (Label*)aptr->label;
FormatLabel(chain,group,aptr,label->label,buffer);
if( !UseLabelCol )
{ /* Depth-cue atom labels */
/* col = aptr->col + (ColorDepth* */
/* (aptr->z+ImageRadius-ZOffset))/ImageSize; */
col = aptr->col + ColourMask;
} else col = LabelCol;
/* (aptr->z+2) + ((aptr->flag & SphereFlag)?aptr->irad:0); */
DisplayString(aptr->x+4,aptr->y,z,buffer,col);
}
}
#ifdef FUNCPROTO
/* Function Prototype */
static void AddDot( Long, Long, Long, int );
static void CheckVDWDot( Long, Long, Long, int );
static int TestSolventDot( Long, Long, Long );
#endif
void DeleteSurface()
{
register DotStruct __far *ptr;
register int shade;
register int i;
while( DotPtr )
{ for( i=0; icount; i++ )
{ shade = Colour2Shade(DotPtr->col[i]);
Shade[shade].refcount--;
}
ptr = DotPtr->next;
_ffree( DotPtr );
DotPtr = ptr;
}
DrawDots = False;
}
static void AddDot( x, y, z, col )
Long x, y, z; int col;
{
register DotStruct __far *ptr;
register int i, shade;
if( !DotPtr || (DotPtr->count==DotMax) )
{ ptr = (DotStruct __far*)_fmalloc(sizeof(DotStruct));
if( !ptr ) FatalRenderError("dot surface");
ptr->next = DotPtr;
ptr->count = 0;
DotPtr = ptr;
} else ptr = DotPtr;
shade = Colour2Shade(col);
Shade[shade].refcount++;
i = ptr->count++;
ptr->col[i] = col;
ptr->xpos[i] = x;
ptr->ypos[i] = y;
ptr->zpos[i] = z;
DrawDots = True;
}
static void CheckVDWDot( x, y, z, col )
Long x, y, z; int col;
{
register Item __far *item;
register Atom __far *aptr;
register int ix,iy,iz;
register int dx,dy,dz;
register Long dist;
register Long rad;
register int i;
ix = (int)((x+Offset)*IVoxRatio);
iy = (int)((y+Offset)*IVoxRatio);
iz = (int)((z+Offset)*IVoxRatio);
i = VOXORDER2*ix + VOXORDER*iy + iz;
for( item=HashTable[i]; item; item=item->list )
if( item->data != Exclude )
{ aptr = item->data;
if( !ProbeRadius )
{ rad = ElemVDWRadius(GetElemNumber(aptr));
} else rad = ProbeRadius;
rad = rad*rad;
/* Optimized Test! */
dx = (int)(aptr->xorg - x);
if( (dist=(Long)dx*dx) < rad )
{ dy = (int)(aptr->yorg - y);
if( (dist+=(Long)dy*dy) < rad )
{ dz = (int)(aptr->zorg - z);
if( (dist+=(Long)dz*dz) < rad )
return;
}
}
}
AddDot( x, y, z, col );
}
static int TestSolventDot( x, y, z )
Long x, y, z;
{
register Item __far *item;
register Atom __far *aptr;
register int lx,ly,lz;
register int hx,hy,hz;
register int dx,dy,dz;
register int ix,iy,iz;
register Long dist;
register Long rad;
register int i;
dist = Offset-ProbeRadius;
lx = (int)((x+dist)*IVoxRatio);
if( lx >= VOXORDER ) return( True );
ly = (int)((y+dist)*IVoxRatio);
if( ly >= VOXORDER ) return( True );
lz = (int)((z+dist)*IVoxRatio);
if( lz >= VOXORDER ) return( True );
dist = Offset+ProbeRadius;
hx = (int)((x+dist)*IVoxRatio);
if( hx < 0 ) return( True );
hy = (int)((y+dist)*IVoxRatio);
if( hy < 0 ) return( True );
hz = (int)((z+dist)*IVoxRatio);
if( hz < 0 ) return( True );
if( lx < 0 ) lx = 0; if( hx >= VOXORDER ) hx = VOXORDER-1;
if( ly < 0 ) ly = 0; if( hy >= VOXORDER ) hy = VOXORDER-1;
if( lz < 0 ) lz = 0; if( hz >= VOXORDER ) hz = VOXORDER-1;
for( ix=lx; ix<=hx; ix++ )
for( iy=ly; iy<=hy; iy++ )
for( iz=lz; iz<=hz; iz++ )
{ i = VOXORDER2*ix + VOXORDER*iy + iz;
for( item=HashTable[i]; item; item=item->list )
if( item->data != Exclude )
{ aptr = item->data;
rad = ElemVDWRadius(GetElemNumber(aptr));
rad = (rad+ProbeRadius)*(rad+ProbeRadius);
/* Optimized Test! */
dx = (int)(aptr->xorg - x);
if( (dist=(Long)dx*dx) < rad )
{ dy = (int)(aptr->yorg - y);
if( (dist+=(Long)dy*dy) < rad )
{ dz = (int)(aptr->zorg - z);
if( (dist+=(Long)dz*dz) < rad )
return( False );
}
}
}
}
return( True );
}
static void InitElemDots()
{
register int i,size;
size = MAXELEMNO*sizeof(ElemDotStruct);
ElemDots = (ElemDotStruct __far*)_fmalloc(size);
if( !ElemDots ) FatalRenderError("dot vector table");
for( i=0; i>1) )
vert = 1;
i = 0;
for( j=0; (iflag & SelectFlag )
{ elem = GetElemNumber(aptr);
if( !ElemDots[elem].count )
AddElemDots(elem,density);
Exclude = aptr;
ptr = ElemDots[elem].dots;
probe = ElemDots[elem].probe;
count = ElemDots[elem].count;
if( SolventDots )
{ for( i=0; ixorg + probe[i].dx,
aptr->yorg + probe[i].dy,
aptr->zorg + probe[i].dz ) )
AddDot( aptr->xorg + ptr[i].dx,
aptr->yorg + ptr[i].dy,
aptr->zorg + ptr[i].dz,
aptr->col );
} else
for( i=0; ixorg + ptr[i].dx,
aptr->yorg + ptr[i].dy,
aptr->zorg + ptr[i].dz,
aptr->col);
}
FreeElemDots();
}
static void DisplaySurface()
{
register DotStruct __far *ptr;
register int xi,yi,zi;
register Real x,y,z;
register int i;
for( ptr=DotPtr; ptr; ptr=ptr->next )
for( i=0; icount; i++ )
{ x = ptr->xpos[i];
y = ptr->ypos[i];
z = ptr->zpos[i];
xi = (int)(x*MatX[0]+y*MatX[1]+z*MatX[2])+XOffset;
if( XValid(xi) )
{ yi = (int)(x*MatY[0]+y*MatY[1]+z*MatY[2])+YOffset;
if( YValid(yi) )
{ zi = (int)(x*MatZ[0]+y*MatZ[1]+z*MatZ[2])+ZOffset;
if( ZValid(zi) )
PlotDeepPoint(xi,yi,zi,ptr->col[i]);
}
}
}
}
static void DisplayBoxes()
{
register Real cosa, cosb, cosg;
register Real sina, sinb, sing;
register Real lena, lenb, lenc;
register Real tmpx, tmpy, tmpz;
register Real temp;
register int xorg, yorg, zorg;
register int dxx,dxy,dxz;
register int dyx,dyy,dyz;
register int dzx,dzy,dzz;
register int x, y, z;
if( DrawAxes || DrawBoundBox )
{ dxx = (int)(MaxX*MatX[0]);
dxy = (int)(MaxX*MatY[0]);
dxz = (int)(MaxX*MatZ[0]);
dyx = (int)(MaxY*MatX[1]);
dyy = (int)(MaxY*MatY[1]);
dyz = (int)(MaxY*MatZ[1]);
dzx = (int)(MaxZ*MatX[2]);
dzy = (int)(MaxZ*MatY[2]);
dzz = (int)(MaxZ*MatZ[2]);
if( DrawAxes )
{ /* Line (MinX,0,0) to (MaxX,0,0) */
ClipTwinLine(XOffset-dxx,YOffset-dxy,ZOffset-dxz,
XOffset+dxx,YOffset+dxy,ZOffset+dxz,BoxCol,BoxCol);
/* Line (0,MinY,0) to (0,MaxY,0) */
ClipTwinLine(XOffset-dyx,YOffset-dyy,ZOffset-dyz,
XOffset+dyx,YOffset+dyy,ZOffset+dyz,BoxCol,BoxCol);
/* Line (0,0,MinZ) to (0,0,MaxZ) */
ClipTwinLine(XOffset-dzx,YOffset-dzy,ZOffset-dzz,
XOffset+dzx,YOffset+dzy,ZOffset+dzz,BoxCol,BoxCol);
}
if( DrawBoundBox )
{ /* Line (MinX,MinY,MinZ) to (MaxX,MinY,MinZ) */
x=XOffset-dyx-dzx; y=YOffset-dyy-dzy; z=ZOffset-dyz-dzz;
ClipTwinLine(x-dxx,y-dxy,z-dxz,x+dxx,y+dxy,z+dxz,BoxCol,BoxCol);
/* Line (MaxX,MinY,MinZ) to (MaxX,MaxY,MinZ) */
x=XOffset+dxx-dzx; y=YOffset+dxy-dzy; z=ZOffset+dxz-dzz;
ClipTwinLine(x-dyx,y-dyy,z-dyz,x+dyx,y+dyy,z+dyz,BoxCol,BoxCol);
/* Line (MaxX,MaxY,MinZ) to (MinX,MaxY,MinZ) */
x=XOffset+dyx-dzx; y=YOffset+dyy-dzy; z=ZOffset+dyz-dzz;
ClipTwinLine(x+dxx,y+dxy,z+dxz,x-dxx,y-dxy,z-dxz,BoxCol,BoxCol);
/* Line (MinX,MaxY,MinZ) to (MinX,MinY,MinZ) */
x=XOffset-dxx-dzx; y=YOffset-dxy-dzy; z=ZOffset-dxz-dzz;
ClipTwinLine(x+dyx,y+dyy,z+dyz,x-dyx,y-dyy,z-dyz,BoxCol,BoxCol);
/* Line (MinX,MinY,MinZ) to (MinX,MinY,MaxZ) */
x=XOffset-dxx-dyx; y=YOffset-dxy-dyy; z=ZOffset-dxz-dyz;
ClipTwinLine(x-dzx,y-dzy,z-dzz,x+dzx,y+dzy,z+dzz,BoxCol,BoxCol);
/* Line (MaxX,MinY,MinZ) to (MaxX,MinY,MaxZ) */
x=XOffset+dxx-dyx; y=YOffset+dxy-dyy; z=ZOffset+dxz-dyz;
ClipTwinLine(x-dzx,y-dzy,z-dzz,x+dzx,y+dzy,z+dzz,BoxCol,BoxCol);
/* Line (MaxX,MaxY,MinZ) to (MaxX,MaxY,MaxZ) */
x=XOffset+dxx+dyx; y=YOffset+dxy+dyy; z=ZOffset+dxz+dyz;
ClipTwinLine(x-dzx,y-dzy,z-dzz,x+dzx,y+dzy,z+dzz,BoxCol,BoxCol);
/* Line (MinX,MaxY,MinZ) to (MinX,MaxY,MaxZ) */
x=XOffset-dxx+dyx; y=YOffset-dxy+dyy; z=ZOffset-dxz+dyz;
ClipTwinLine(x-dzx,y-dzy,z-dzz,x+dzx,y+dzy,z+dzz,BoxCol,BoxCol);
/* Line (MinX,MinY,MaxZ) to (MaxX,MinY,MaxZ) */
x=XOffset-dyx+dzx; y=YOffset-dyy+dzy; z=ZOffset-dyz+dzz;
ClipTwinLine(x-dxx,y-dxy,z-dxz,x+dxx,y+dxy,z+dxz,BoxCol,BoxCol);
/* Line (MaxX,MinY,MaxZ) to (MaxX,MaxY,MaxZ) */
x=XOffset+dxx+dzx; y=YOffset+dxy+dzy; z=ZOffset+dxz+dzz;
ClipTwinLine(x-dyx,y-dyy,z-dyz,x+dyx,y+dyy,z+dyz,BoxCol,BoxCol);
/* Line (MaxX,MaxY,MaxZ) to (MinX,MaxY,MaxZ) */
x=XOffset+dyx+dzx; y=YOffset+dyy+dzy; z=ZOffset+dyz+dzz;
ClipTwinLine(x+dxx,y+dxy,z+dxz,x-dxx,y-dxy,z-dxz,BoxCol,BoxCol);
/* Line (MinX,MaxY,MaxZ) to (MinX,MinY,MaxZ) */
x=XOffset-dxx+dzx; y=YOffset-dxy+dzy; z=ZOffset-dxz+dzz;
ClipTwinLine(x+dyx,y+dyy,z+dyz,x-dyx,y-dyy,z-dyz,BoxCol,BoxCol);
}
}
if( DrawUnitCell )
{ /* Calculate Unit Cell! */
lena = 250.0*InfoCellA;
lenb = 250.0*InfoCellB;
lenc = -250.0*InfoCellC;
cosa = cos(InfoCellAlpha); sina = sin(InfoCellAlpha);
cosb = cos(InfoCellBeta); sinb = sin(InfoCellBeta);
cosg = cos(InfoCellGamma); sing = sin(InfoCellGamma);
temp = cosa*cosa + cosb*cosb + cosg*cosg - 2.0*cosa*cosb*cosg;
tmpx = cosb;
tmpy = (cosa - cosb*cosg)/sing;
tmpz = sqrt(1.0-temp)/sing;
dxx = (int)(lena*MatX[0]);
dxy = (int)(lena*MatY[0]);
dxz = (int)(lena*MatZ[0]);
dyx = (int)(lenb*(cosg*MatX[0] + sing*MatX[1]));
dyy = (int)(lenb*(cosg*MatY[0] + sing*MatY[1]));
dyz = (int)(lenb*(cosg*MatZ[0] + sing*MatZ[1]));
dzx = (int)(lenc*(tmpx*MatX[0] + tmpy*MatX[1] + tmpz*MatX[2]));
dzy = (int)(lenc*(tmpx*MatY[0] + tmpy*MatY[1] + tmpz*MatY[2]));
dzz = (int)(lenc*(tmpx*MatZ[0] + tmpy*MatZ[1] + tmpz*MatZ[2]));
xorg = XOffset - (int)(OrigCX*MatX[0]+OrigCY*MatX[1]+OrigCZ*MatX[2]);
yorg = YOffset - (int)(OrigCX*MatY[0]+OrigCY*MatY[1]+OrigCZ*MatY[2]);
zorg = ZOffset + (int)(OrigCX*MatZ[0]+OrigCY*MatZ[1]+OrigCZ*MatZ[2]);
/* Draw Unit Cell! */
x = xorg;
y = yorg;
z = zorg;
ClipTwinLine(x,y,z,x+dxx,y+dxy,z+dxz,BoxCol,BoxCol);
ClipTwinLine(x,y,z,x+dyx,y+dyy,z+dyz,BoxCol,BoxCol);
ClipTwinLine(x,y,z,x+dzx,y+dzy,z+dzz,BoxCol,BoxCol);
x = xorg + dxx + dyx;
y = yorg + dxy + dyy;
z = zorg + dxz + dyz;
ClipTwinLine(x,y,z,x-dxx,y-dxy,z-dxz,BoxCol,BoxCol);
ClipTwinLine(x,y,z,x-dyx,y-dyy,z-dyz,BoxCol,BoxCol);
ClipTwinLine(x,y,z,x+dzx,y+dzy,z+dzz,BoxCol,BoxCol);
x = xorg + dxx + dzx;
y = yorg + dxy + dzy;
z = zorg + dxz + dyz;
ClipTwinLine(x,y,z,x-dxx,y-dxy,z-dxz,BoxCol,BoxCol);
ClipTwinLine(x,y,z,x+dyx,y+dyy,z+dyz,BoxCol,BoxCol);
ClipTwinLine(x,y,z,x-dzx,y-dzy,z-dzz,BoxCol,BoxCol);
x = xorg + dyx + dzx;
y = yorg + dyy + dzy;
z = zorg + dyz + dzz;
ClipTwinLine(x,y,z,x+dxx,y+dxy,z+dxz,BoxCol,BoxCol);
ClipTwinLine(x,y,z,x-dyx,y-dyy,z-dyz,BoxCol,BoxCol);
ClipTwinLine(x,y,z,x-dzx,y-dzy,z-dzz,BoxCol,BoxCol);
}
}
static void DisplaySelected()
{
register Atom __far *s, __far *d;
register Chain __far *chain;
register Group __far *group;
register Bond __far *bptr;
register Atom __far *aptr;
register int irad,sc,dc;
register int col;
irad = (int)(Scale*20);
if( irad>0 )
{ ForEachBond
{ s = bptr->srcatom;
col = (s->flag&SelectFlag)? 1 : 0;
sc = Shade2Colour(col);
d = bptr->dstatom;
col = (d->flag&SelectFlag)? 1 : 0;
dc = Shade2Colour(col);
ClipCylinder(s->x,s->y,s->z,sc,d->x,d->y,d->z,dc,irad);
}
} else ForEachBond
{ s = bptr->srcatom;
col = (s->flag&SelectFlag)? 1 : 0;
sc = Shade2Colour(col);
d = bptr->dstatom;
col = (d->flag&SelectFlag)? 1 : 0;
dc = Shade2Colour(col);
ClipTwinLine(s->x,s->y,s->z,d->x,d->y,d->z,
sc+ColourMask,dc+ColourMask);
}
irad = (int)(Scale*50);
ForEachAtom
if( aptr->flag&NonBondFlag )
{ col = Shade2Colour( (aptr->flag&SelectFlag)? 1 : 0 );
ClipSphere(aptr->x,aptr->y,aptr->z,irad,col);
}
}
void DrawFrame()
{
register Chain __far *chain;
if( !Database )
return;
ClearBuffers();
if( UseSlabPlane )
{ SlabValue = (int)(DialValue[7]*ImageRadius)+ZOffset;
SlabInten = (int)(ColourMask*TwoOverRootSix);
SliceValue = SlabValue+16;
UseClipping = True;
} else UseClipping = UseScreenClip;
#ifdef IBMPC
/* Lock Buffers into Memory */
FBuffer = (Pixel __huge*)GlobalLock(FBufHandle);
DBuffer = (short __huge*)GlobalLock(DBufHandle);
#endif
if( !DisplayMode )
{ if( UseShadow && DrawAtoms )
if( !VoxelsClean )
CreateVoxelData( SphereFlag );
if( DrawAtoms )
DisplaySpaceFill();
if( !UseSlabPlane || (SlabMode != SlabSection) )
{ if( DrawBonds )
DisplayWireFrame();
if( DrawRibbon )
for( chain=Database->clist; chain; chain=chain->cnext )
if( chain->glist )
DisplayRibbon( chain );
if( DrawDots ) DisplaySurface();
if( DrawLabels ) DisplayLabels();
DisplayHBonds( Database->slist, SSBondMode );
DisplayHBonds( Database->hlist, HBondMode );
DisplayBackBone();
}
} else DisplaySelected();
DisplayBoxes();
#ifdef IBMPC
/* Unlock Buffers */
GlobalUnlock(FBufHandle);
GlobalUnlock(DBufHandle);
#endif
DBClear = False;
FBClear = False;
}
#ifdef FUNCPROTO
/* Function Prototype */
static void TestAtomProximity( Atom __far *, int, int );
#endif
static void TestAtomProximity( ptr, xpos, ypos )
Atom __far *ptr;
int xpos, ypos;
{
register Long dist;
register int dx,dy;
if( UseSlabPlane && (ptr->z>SlabValue) )
return;
dx = ptr->x - xpos;
dy = ptr->y - ypos;
dist = (Long)dx*dx + (Long)dy*dy;
if( IdentFound )
{ if( dist==IdentDist )
{ if( ptr->zIdentDist )
return;
}
IdentDepth = ptr->z;
IdentFound = True;
IdentDist = dist;
QAtom = ptr;
}
void IdentifyAtom( xpos, ypos )
int xpos, ypos;
{
register int rad, wide, dpth;
register int new, dx, dy, dz;
register Chain __far *chain;
register Group __far *group;
register HBond __far *hptr;
register Atom __far *aptr;
register Bond __far *bptr;
register char *str;
char buffer[40];
/* Reset Search */
QChain = (void __far*)0;
QGroup = (void __far*)0;
QAtom = (void __far*)0;
IdentFound = False;
if( !DisplayMode )
{ if( !UseSlabPlane || (SlabMode != SlabSection) )
{ if( DrawBonds )
ForEachBond
if( bptr->flag&DrawBondFlag )
{ TestAtomProximity(bptr->srcatom,xpos,ypos);
TestAtomProximity(bptr->dstatom,xpos,ypos);
}
ForEachBack
if( bptr->flag&DrawBondFlag )
{ TestAtomProximity(bptr->srcatom,xpos,ypos);
TestAtomProximity(bptr->dstatom,xpos,ypos);
}
for( hptr=Database->hlist; hptr; hptr=hptr->hnext )
if( hptr->flag )
{ if( HBondMode )
{ TestAtomProximity(hptr->srcCA,xpos,ypos);
TestAtomProximity(hptr->dstCA,xpos,ypos);
} else
{ TestAtomProximity(hptr->src,xpos,ypos);
TestAtomProximity(hptr->dst,xpos,ypos);
}
}
for( hptr=Database->slist; hptr; hptr=hptr->hnext )
if( hptr->flag )
{ if( HBondMode )
{ TestAtomProximity(hptr->srcCA,xpos,ypos);
TestAtomProximity(hptr->dstCA,xpos,ypos);
} else
{ TestAtomProximity(hptr->src,xpos,ypos);
TestAtomProximity(hptr->dst,xpos,ypos);
}
}
}
ForEachAtom
{ /* Identify bond! */
if( aptr == QAtom )
{ QChain = chain;
QGroup = group;
}
if( aptr->flag & SphereFlag )
{ dy = AbsFun(aptr->y-ypos);
if( dy>aptr->irad ) continue;
rad = LookUp[aptr->irad][dy];
dx = AbsFun(aptr->x-xpos);
if( dx>rad ) continue;
new = False;
dpth = aptr->z+LookUp[rad][dx];
if( UseSlabPlane && (aptr->z+rad>=SlabValue) )
{ dz = SlabValue-aptr->z;
if( SlabMode && (dz >= -rad) )
{ wide = LookUp[aptr->irad][AbsFun(dz)];
if( (dy<=wide) && (dx<=(int)(LookUp[wide][dy])) )
{ if( SlabMode == SlabFinal )
{ dpth = SliceValue;
new = True;
} else if( SlabMode == SlabHollow )
{ dpth = aptr->z-LookUp[rad][dx];
new = !IdentFound || (dpth>IdentDepth);
} else if( SlabMode != SlabHalf )
{ /* SlabClose, SlabSection */
dpth = dx*dx+dy*dy+dz*dz+SliceValue;
if( IdentFound )
{ new = (IdentDepth0) && (SlabMode!=SlabSection) )
new = !IdentFound || (dpth>IdentDepth);
}
} else if( !UseSlabPlane || (SlabMode != SlabSection) )
new = !IdentFound || IdentDist || (dpth>IdentDepth);
if( new )
{ IdentFound = True;
IdentDepth = dpth;
IdentDist = 0;
QChain = chain;
QGroup = group;
QAtom = aptr;
}
}
}
} else /* Display Mode */
{ ForEachAtom
{ TestAtomProximity(aptr,xpos,ypos);
/* Identify bond! */
if( aptr == QAtom )
{ QChain = chain;
QGroup = group;
}
}
}
if( IdentFound && (IdentDist<50) )
{ if( CommandActive )
WriteChar('\n');
CommandActive = False;
WriteString("Atom: ");
str = ElemDesc[QAtom->refno];
if( str[0]!=' ' ) WriteChar(str[0]);
WriteChar(str[1]); WriteChar(str[2]);
if( str[3]!=' ' ) WriteChar(str[3]);
sprintf(buffer," %d ",QAtom->serno);
WriteString(buffer);
str = Residue[QGroup->refno];
if( QAtom->flag&HeteroFlag )
{ WriteString("Hetero: ");
} else WriteString("Group: ");
if( str[0]!=' ' ) WriteChar(str[0]);
WriteChar(str[1]); WriteChar(str[2]);
sprintf(buffer," %d",QGroup->serno);
WriteString(buffer);
if( QChain->ident!=' ' )
{ WriteString(" Chain: ");
WriteChar(QChain->ident);
}
WriteChar('\n');
} else /* Reset Pick Atom! */
{ QChain = (void __far*)0;
QGroup = (void __far*)0;
QAtom = (void __far*)0;
}
}
void SetStereoMode( enable )
int enable;
{
StereoView = ViewLeft;
UseStereo = enable;
}
void ResetRenderer()
{
DeleteSurface();
SolventDots = False;
ProbeRadius = 0;
DrawAtoms = False; MaxAtomRadius = 0;
DrawBonds = False; MaxBondRadius = 0;
DrawRibbon = False; DrawDots = False;
DrawLabels = False;
ResetLabels();
SlabMode = SlabClose;
UseSlabPlane = False;
UseLabelCol = False;
UseShadow = False;
SSBondMode = False;
HBondMode = False;
DisplayMode = 0;
DrawBoundBox = False;
DrawUnitCell = False;
DrawAxes = False;
SetStereoMode(False);
}
void InitialiseRenderer()
{
register Real radius2;
register Byte __far *ptr;
register int index,rad;
register int maxval;
FBuffer = (void __huge*)0;
DBuffer = (void __huge*)0;
IBuffer = (void __far*)0;
YBucket = (void __far*)0;
#if defined(IBMPC) || defined(APPLEMAC)
FBufHandle = NULL;
DBufHandle = NULL;
#endif
#if defined(IBMPC) || defined(APPLEMAC)
/* Allocate tables on FAR heaps */
Array = (Byte __far*)_fmalloc(7261*sizeof(Byte));
LookUp = (Byte __far* __far*)_fmalloc(120*sizeof(Byte __far*));
HashTable = (void __far* __far*)_fmalloc(VOXSIZE*sizeof(void __far*));
ColConst = (Card __far*)_fmalloc(120*sizeof(Card));
if( !Array || !LookUp || !HashTable || !ColConst )
FatalRenderError("tables");
#endif
ptr = Array;
for( rad=0; rad<120; rad++ )
{ radius2 = rad*rad;
LookUp[rad] = ptr;
for( index=0; index<=rad; index++ )
*ptr++ = isqrt( (Card)(radius2-index*index) );
maxval = (int)(RootSix*rad)+2;
ColConst[rad] = ((Card)ColourDepth<
|