/* 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<