This is transfor.c in view mode; [Download] [Up]
/* transfor.c * RasMol2 Molecular Graphics * Roger Sayle, August 1995 * Version 2.6 */ #include "rasmol.h" #ifdef IBMPC #include <windows.h> #endif #ifdef APPLEMAC #include <Types.h> #include <Errors.h> #ifdef __CONDITIONALMACROS__ #include <Printing.h> #else #include <PrintTraps.h> #endif #endif #include <stdio.h> #include <math.h> #define TRANSFORM #include "molecule.h" #include "abstree.h" #include "transfor.h" #include "command.h" #include "render.h" #include "repres.h" #include "graphics.h" typedef struct { short col; short shade; unsigned char r; unsigned char g; unsigned char b; } ShadeRef; #define CPKMAX 16 static ShadeRef CPKShade[] = { { 0, 0, 200, 200, 200 }, /* 0 Light Grey */ { 0, 0, 143, 143, 255 }, /* 1 Sky Blue */ { 0, 0, 240, 0, 0 }, /* 2 Red */ { 0, 0, 255, 200, 50 }, /* 3 Yellow */ { 0, 0, 255, 255, 255 }, /* 4 White */ { 0, 0, 255, 192, 203 }, /* 5 Pink */ { 0, 0, 218, 165, 32 }, /* 6 Golden Rod */ { 0, 0, 0, 0, 255 }, /* 7 Blue */ { 0, 0, 255, 165, 0 }, /* 8 Orange */ { 0, 0, 128, 128, 144 }, /* 9 Dark Grey */ { 0, 0, 165, 42, 42 }, /* 10 Brown */ { 0, 0, 160, 32, 240 }, /* 11 Purple */ { 0, 0, 255, 20, 147 }, /* 12 Deep Pink */ { 0, 0, 0, 255, 0 }, /* 13 Green */ { 0, 0, 178, 34, 34 }, /* 14 Fire Brick */ { 0, 0, 34, 139, 34 } }; /* 15 Forest Green */ static ShadeRef Shapely[] = { { 0, 0, 140, 255, 140 }, /* ALA */ { 0, 0, 255, 255, 255 }, /* GLY */ { 0, 0, 69, 94, 69 }, /* LEU */ { 0, 0, 255, 112, 66 }, /* SER */ { 0, 0, 255, 140, 255 }, /* VAL */ { 0, 0, 184, 76, 0 }, /* THR */ { 0, 0, 71, 71, 184 }, /* LYS */ { 0, 0, 160, 0, 66 }, /* ASP */ { 0, 0, 0, 76, 0 }, /* ILE */ { 0, 0, 255, 124, 112 }, /* ASN */ { 0, 0, 102, 0, 0 }, /* GLU */ { 0, 0, 82, 82, 82 }, /* PRO */ { 0, 0, 0, 0, 124 }, /* ARG */ { 0, 0, 83, 76, 66 }, /* PHE */ { 0, 0, 255, 76, 76 }, /* GLN */ { 0, 0, 140, 112, 76 }, /* TYR */ { 0, 0, 112, 112, 255 }, /* HIS */ { 0, 0, 255, 255, 112 }, /* CYS */ { 0, 0, 184, 160, 66 }, /* MET */ { 0, 0, 79, 70, 0 }, /* TRP */ { 0, 0, 255, 0, 255 }, /* ASX */ { 0, 0, 255, 0, 255 }, /* GLX */ { 0, 0, 255, 0, 255 }, /* PCA */ { 0, 0, 255, 0, 255 }, /* HYP */ { 0, 0, 160, 160, 255 }, /* A */ { 0, 0, 255, 140, 75 }, /* C */ { 0, 0, 255, 112, 112 }, /* G */ { 0, 0, 160, 255, 160 }, /* T */ { 0, 0, 184, 184, 184 }, /* 28 -> BackBone */ { 0, 0, 94, 0, 94 }, /* 29 -> Special */ { 0, 0, 255, 0, 255 } }; /* 30 -> Default */ static ShadeRef AminoShade[] = { { 0, 0, 230, 10, 10 }, /* 0 ASP, GLU */ { 0, 0, 20, 90, 255 }, /* 1 LYS, ARG */ { 0, 0, 130, 130, 210 }, /* 2 HIS */ { 0, 0, 250, 150, 0 }, /* 3 SER, THR */ { 0, 0, 0, 220, 220 }, /* 4 ASN, GLN */ { 0, 0, 230, 230, 0 }, /* 5 CYS, MET */ { 0, 0, 200, 200, 200 }, /* 6 ALA */ { 0, 0, 235, 235, 235 }, /* 7 GLY */ { 0, 0, 15, 130, 15 }, /* 8 LEU, VAL, ILE */ { 0, 0, 50, 50, 170 }, /* 9 PHE, TYR */ { 0, 0, 180, 90, 180 }, /* 10 TRP */ { 0, 0, 220, 150, 130 }, /* 11 PRO, PCA, HYP */ { 0, 0, 190, 160, 110 } }; /* 12 Others */ static int AminoIndex[] = { 6, /*ALA*/ 7, /*GLY*/ 8, /*LEU*/ 3, /*SER*/ 8, /*VAL*/ 3, /*THR*/ 1, /*LYS*/ 0, /*ASP*/ 8, /*ILE*/ 4, /*ASN*/ 0, /*GLU*/ 11, /*PRO*/ 1, /*ARG*/ 9, /*PHE*/ 4, /*GLN*/ 9, /*TYR*/ 2, /*HIS*/ 5, /*CYS*/ 5, /*MET*/ 10, /*TRP*/ 4, /*ASX*/ 4, /*GLX*/ 11, /*PCA*/ 11 /*HYP*/ }; static ShadeRef HBondShade[] = { { 0, 0, 255, 255, 255 }, /* 0 Offset = 2 */ { 0, 0, 255, 0, 255 }, /* 1 Offset = 3 */ { 0, 0, 255, 0, 0 }, /* 2 Offset = 4 */ { 0, 0, 255, 165, 0 }, /* 3 Offset = 5 */ { 0, 0, 0, 255, 255 }, /* 4 Offset = -3 */ { 0, 0, 0, 255, 0 }, /* 5 Offset = -4 */ { 0, 0, 255, 255, 0 } }; /* 6 Others */ static ShadeRef StructShade[] = { { 0, 0, 255, 255, 255 }, /* 0 Default */ { 0, 0, 255, 0, 128 }, /* 1 Alpha Helix */ { 0, 0, 255, 200, 0 }, /* 2 Beta Sheet */ { 0, 0, 96, 128, 255 } }; /* 3 Turn */ static ShadeRef PotentialShade[] = { { 0, 0, 255, 0, 0 }, /* 0 Red 25 < V */ { 0, 0, 255, 165, 0 }, /* 1 Orange 10 < V < 25 */ { 0, 0, 255, 255, 0 }, /* 2 Yellow 3 < V < 10 */ { 0, 0, 0, 255, 0 }, /* 3 Green 0 < V < 3 */ { 0, 0, 0, 255, 255 }, /* 4 Cyan -3 < V < 0 */ { 0, 0, 0, 0, 255 }, /* 5 Blue -10 < V < -3 */ { 0, 0, 160, 32, 240 }, /* 6 Purple -25 < V < -10 */ { 0, 0, 255, 255, 255 } }; /* 7 White V < -25 */ /* Macros for commonly used loops */ #define ForEachAtom for(chain=Database->clist;chain;chain=chain->cnext) \ for(group=chain->glist;group;group=group->gnext) \ for(ptr=group->alist;ptr;ptr=ptr->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) #define MatchChar(a,b) (((a)=='#')||((a)==(b))) #define RootSix 2.44948974278 static ShadeRef ScaleRef[MAXSHADE]; static int MaskColour[MAXMASK]; static int MaskShade[MAXMASK]; static int ScaleCount; static int LastShade; static Real LastRX,LastRY,LastRZ; static Real Zoom; void DetermineClipping() { register int temp; register int max; max = 0; if( DrawAtoms && (MaxAtomRadius>max) ) max = MaxAtomRadius; if( DrawBonds && (MaxBondRadius>max) ) max = MaxBondRadius; temp = ImageRadius + max; if( (YOffset>=temp) && (XOffset>=temp) && (YOffset+temp<YRange) ) { if( UseStereo ) { UseScreenClip = (XOffset+temp) >= (XRange>>1); } else UseScreenClip = (XOffset+temp) >= XRange; } else UseScreenClip = True; } void SetRadiusValue( rad ) int rad; { register int irad,change; register Chain __far *chain; register Group __far *group; register Atom __far *ptr; if( !Database ) return; irad = (int)(Scale*rad); MaxAtomRadius = 0; DrawAtoms = False; change = False; ForEachAtom if( ptr->flag & SelectFlag ) { if( irad>MaxAtomRadius ) MaxAtomRadius = irad; ptr->flag |= SphereFlag; ptr->radius = rad; ptr->irad = irad; change = True; } else if( ptr->flag & SphereFlag ) { DrawAtoms = True; if( ptr->irad>MaxAtomRadius ) MaxAtomRadius = ptr->irad; } if( change ) { DrawAtoms = True; DetermineClipping(); VoxelsClean = False; BucketFlag = False; } } void SetRadiusTemperature() { register int rad,irad,change; register Chain __far *chain; register Group __far *group; register Atom __far *ptr; if( !Database ) return; MaxAtomRadius = 0; DrawAtoms = False; change = False; ForEachAtom if( (ptr->flag&SelectFlag) && (ptr->temp>0) ) { rad = (5*ptr->temp)>>1; if( rad>500 ) rad = 500; irad = (int)(Scale*rad); if( irad>MaxAtomRadius ) MaxAtomRadius = irad; ptr->flag |= SphereFlag; ptr->radius = rad; ptr->irad = irad; change = True; } else if( ptr->flag & SphereFlag ) { DrawAtoms = True; if( ptr->irad>MaxAtomRadius ) MaxAtomRadius = ptr->irad; } if( change ) { DrawAtoms = True; DetermineClipping(); VoxelsClean = False; BucketFlag = False; } } void SetVanWaalRadius() { register int rad,change; register Chain __far *chain; register Group __far *group; register Atom __far *ptr; if( !Database ) return; MaxAtomRadius = 0; DrawAtoms = False; change = False; ForEachAtom if( ptr->flag&SelectFlag ) { rad = ElemVDWRadius(ptr->elemno); ptr->irad = (int)(Scale*rad); ptr->radius = rad; change = True; ptr->flag |=SphereFlag; if( ptr->irad>MaxAtomRadius ) MaxAtomRadius = ptr->irad; } else if( ptr->flag&SphereFlag ) { DrawAtoms = True; if( ptr->irad>MaxAtomRadius ) MaxAtomRadius = ptr->irad; } if( change ) { DrawAtoms = True; DetermineClipping(); VoxelsClean = False; BucketFlag = False; } } void DisableSpacefill() { register Chain __far *chain; register Group __far *group; register Atom __far *ptr; if( !Database || !DrawAtoms ) return; MaxAtomRadius = 0; DrawAtoms = False; ForEachAtom if( !(ptr->flag&SelectFlag) ) { if( ptr->flag&SphereFlag ) { if( ptr->irad>MaxAtomRadius ) MaxAtomRadius = ptr->irad; DrawAtoms = True; } } else if( ptr->flag&SphereFlag ) ptr->flag &= ~SphereFlag; DetermineClipping(); VoxelsClean = False; BucketFlag = False; } void EnableWireframe( mask, rad ) int mask, rad; { register Bond __far *bptr; register int flag, irad; if( !Database ) return; DrawBonds = False; MaxBondRadius = 0; irad = (int)(Scale*rad); ForEachBond { flag = ZoneBoth? bptr->dstatom->flag & bptr->srcatom->flag : bptr->dstatom->flag | bptr->srcatom->flag; if( flag&SelectFlag ) { DrawBonds = True; bptr->flag &= ~DrawBondFlag; bptr->flag |= mask; if( mask == CylinderFlag ) { if( irad>MaxBondRadius ) MaxBondRadius = irad; bptr->radius = rad; bptr->irad = irad; } } else if( bptr->flag&DrawBondFlag ) { DrawBonds = True; if( bptr->flag&CylinderFlag ) if( bptr->irad>MaxBondRadius ) MaxBondRadius = bptr->irad; } } DetermineClipping(); } void DisableWireframe() { register Bond __far *bptr; register int flag; if( !Database || !DrawBonds ) return; DrawBonds = False; MaxBondRadius = 0; ForEachBond { flag = ZoneBoth? bptr->dstatom->flag & bptr->srcatom->flag : bptr->dstatom->flag | bptr->srcatom->flag; if( flag&SelectFlag ) { bptr->flag &= ~DrawBondFlag; } else if( bptr->flag&DrawBondFlag ) { DrawBonds = True; if( bptr->flag&CylinderFlag ) if( bptr->irad>MaxBondRadius ) MaxBondRadius = bptr->irad; } } DetermineClipping(); } void EnableBackbone( mask, rad ) int mask, rad; { register Chain __far *chain; register Bond __far *bptr; register int flag,irad; if( !Database ) return; irad = (int)(Scale*rad); ForEachBack { flag = ZoneBoth? bptr->dstatom->flag & bptr->srcatom->flag : bptr->dstatom->flag | bptr->srcatom->flag; if( flag&SelectFlag ) { bptr->flag &= ~DrawBondFlag; bptr->flag |= mask; if( mask == CylinderFlag ) { bptr->radius = rad; bptr->irad = irad; } } } } void DisableBackbone() { register Chain __far *chain; register Bond __far *bptr; if( !Database ) return; if( ZoneBoth ) { ForEachBack if( (bptr->dstatom->flag&bptr->srcatom->flag) & SelectFlag ) bptr->flag &= ~DrawBondFlag; } else ForEachBack if( (bptr->dstatom->flag|bptr->srcatom->flag) & SelectFlag ) bptr->flag &= ~DrawBondFlag; } void SetHBondStatus( hbonds, enable, rad ) int hbonds, enable, rad; { register HBond __far *list; register HBond __far *ptr; register Atom __far *src; register Atom __far *dst; register int flag, irad; if( !Database ) return; if( hbonds ) { if( enable && (InfoHBondCount<0) ) CalcHydrogenBonds(); list = Database->hlist; } else { if( enable && (InfoSSBondCount<0) ) FindDisulphideBridges(); list = Database->slist; } irad = (int)(Scale*rad); for( ptr=list; ptr; ptr=ptr->hnext ) { src = ptr->src; dst = ptr->dst; flag = ZoneBoth? src->flag&dst->flag : src->flag|dst->flag; if( flag & SelectFlag ) { ptr->flag &= ~DrawBondFlag; if( enable ) { if( rad ) { ptr->flag |= CylinderFlag; ptr->radius = rad; ptr->irad = irad; } else ptr->flag |= WireFlag; } } } } void SetRibbonStatus( enable, flag, width ) int enable, flag, width; { register Chain __far *chain; register Group __far *group; register Atom __far *ptr; if( !Database ) return; /* Ribbons already disabled! */ if( !enable && !DrawRibbon ) return; if( InfoHelixCount<0 ) DetermineStructure(False); DrawRibbon = False; for( chain=Database->clist; chain; chain=chain->cnext ) for( group=chain->glist; group; group=group->gnext ) if( enable ) { if( group->flag & DrawKnotFlag ) DrawRibbon = True; for( ptr=group->alist; ptr; ptr=ptr->anext ) if( IsAlphaCarbon(ptr->refno) ) { if( ptr->flag&SelectFlag ) { group->flag &= ~DrawKnotFlag; group->flag |= flag; if( !width ) { if( group->struc & (HelixFlag|SheetFlag) ) { group->width = 380; } else group->width = 100; } else group->width = width; DrawRibbon = True; } break; } else if( IsSugarPhosphate(ptr->refno) ) { if( ptr->flag&SelectFlag ) { group->width = width? width : 720; group->flag &= ~DrawKnotFlag; group->flag |= flag; DrawRibbon = True; } break; } } else /* Disable Ribbon */ if( group->flag & DrawKnotFlag ) { for( ptr=group->alist; ptr; ptr=ptr->anext ) if( IsAlphaCarbon(ptr->refno) || IsSugarPhosphate(ptr->refno) ) { if( ptr->flag&SelectFlag ) group->flag &= ~DrawKnotFlag; break; } if( group->flag & DrawKnotFlag ) DrawRibbon = True; } } void SetRibbonCartoons() { register Chain __far *chain; register Group __far *group; register Atom __far *ptr; if( !Database ) return; if( InfoHelixCount<0 ) DetermineStructure(False); /* DrawBetaArrows = True; */ /* CartoonHeight = 120; */ DrawRibbon = False; for( chain=Database->clist; chain; chain=chain->cnext ) for( group=chain->glist; group; group=group->gnext ) { if( group->flag & DrawKnotFlag ) DrawRibbon = True; for( ptr=group->alist; ptr; ptr=ptr->anext ) if( IsAlphaCarbon(ptr->refno) ) { if( ptr->flag&SelectFlag ) { group->flag &= ~DrawKnotFlag; if( group->struc & (HelixFlag|SheetFlag) ) { group->flag |= CartoonFlag; group->width = 380; } else { group->flag |= TraceFlag; group->width = 100; } DrawRibbon = True; } break; } else if( IsSugarPhosphate(ptr->refno) ) { if( ptr->flag&SelectFlag ) { group->flag &= ~DrawKnotFlag; group->flag |= RibbonFlag; group->width = 720; DrawRibbon = True; } break; } } } /*===========================*/ /* Atom Selection Functions! */ /*===========================*/ static void DisplaySelectCount() { char buffer[40]; if( FileDepth == -1 ) { if( CommandActive ) WriteChar('\n'); CommandActive=False; if( SelectCount==0 ) { WriteString("No atoms selected!\n"); } else if( SelectCount>1 ) { sprintf(buffer,"%ld atoms selected!\n",(long)SelectCount); WriteString(buffer); } else WriteString("1 atom selected!\n"); } if( DisplayMode ) ReDrawFlag |= RFRefresh; AdviseUpdate(AdvSelectCount); } void SelectZone( mask ) int mask; { register Bond __far *bptr; register Chain __far *chain; register Group __far *group; register Atom __far *ptr; if( !Database ) return; SelectCount = 0; ForEachAtom if( ptr->flag & mask ) { ptr->flag |= SelectFlag; SelectCount++; } else ptr->flag &= ~SelectFlag; DisplaySelectCount(); if( ZoneBoth ) { ForEachBond if( (bptr->srcatom->flag&bptr->dstatom->flag) & SelectFlag ) { bptr->flag |= SelectFlag; } else bptr->flag &= ~SelectFlag; } else ForEachBond if( (bptr->srcatom->flag|bptr->dstatom->flag) & SelectFlag ) { bptr->flag |= SelectFlag; } else bptr->flag &= ~SelectFlag; } void RestrictZone( mask ) int mask; { register Bond __far *bptr; register Chain __far *chain; register Group __far *group; register Atom __far *ptr; register int flag; if( !Database ) return; DrawAtoms = False; MaxAtomRadius = 0; DrawBonds = False; MaxBondRadius = 0; DrawLabels = False; SelectCount = 0; ForEachAtom if( ptr->flag & mask ) { ptr->flag |= SelectFlag; SelectCount++; if( ptr->flag & SphereFlag ) { DrawAtoms = True; if( ptr->irad>MaxAtomRadius ) MaxAtomRadius = ptr->irad; } if( ptr->label ) DrawLabels = True; } else { ptr->flag &= ~(SelectFlag|SphereFlag); if( ptr->label ) { DeleteLabel( (Label*)ptr->label ); ptr->label = (void*)0; } } DisplaySelectCount(); ForEachBond { /* Ignore ZoneBoth setting! */ flag = bptr->dstatom->flag & bptr->srcatom->flag; if( flag & SelectFlag ) { bptr->flag |= SelectFlag; if( bptr->flag&DrawBondFlag ) { DrawBonds = True; if( bptr->flag & CylinderFlag ) if( bptr->irad>MaxBondRadius ) MaxBondRadius = bptr->irad; } } else bptr->flag &= ~(SelectFlag|DrawBondFlag); } ForEachBack { /* Ignore ZoneBoth setting! */ flag = bptr->dstatom->flag & bptr->srcatom->flag; if( !(flag&SelectFlag) ) bptr->flag &= ~(SelectFlag|DrawBondFlag); } if( DrawRibbon ) { DrawRibbon = False; for( chain=Database->clist; chain; chain=chain->cnext ) for( group=chain->glist; group; group=group->gnext ) if( group->flag & DrawKnotFlag ) { for( ptr=group->alist; ptr; ptr=ptr->anext ) if( IsAlphaCarbon(ptr->refno) || IsSugarPhosphate(ptr->refno) ) { if( !(ptr->flag&SelectFlag) ) group->flag &= ~DrawKnotFlag; break; } if( group->flag & DrawKnotFlag ) DrawRibbon = True; } } DetermineClipping(); VoxelsClean = False; BucketFlag = False; } void SelectZoneExpr( expr ) Expr *expr; { register Bond __far *bptr; if( !Database ) return; SelectCount = 0; for( QChain=Database->clist; QChain; QChain=QChain->cnext ) for( QGroup=QChain->glist; QGroup; QGroup=QGroup->gnext ) for( QAtom=QGroup->alist; QAtom; QAtom=QAtom->anext ) if( EvaluateExpr(expr) ) { QAtom->flag |= SelectFlag; SelectCount++; } else QAtom->flag &= ~SelectFlag; DisplaySelectCount(); if( ZoneBoth ) { ForEachBond if( (bptr->srcatom->flag&bptr->dstatom->flag) & SelectFlag ) { bptr->flag |= SelectFlag; } else bptr->flag &= ~SelectFlag; } else ForEachBond if( (bptr->srcatom->flag|bptr->dstatom->flag) & SelectFlag ) { bptr->flag |= SelectFlag; } else bptr->flag &= ~SelectFlag; } void RestrictZoneExpr( expr ) Expr *expr; { register Bond __far *bptr; register Chain __far *chain; register Group __far *group; register Atom __far *ptr; register int flag; if( !Database ) return; DrawAtoms = False; MaxAtomRadius = 0; DrawBonds = False; MaxBondRadius = 0; DrawLabels = False; SelectCount = 0; for( QChain=Database->clist; QChain; QChain=QChain->cnext ) for( QGroup=QChain->glist; QGroup; QGroup=QGroup->gnext ) for( QAtom=QGroup->alist; QAtom; QAtom=QAtom->anext ) if( EvaluateExpr(expr) ) { QAtom->flag |= SelectFlag; SelectCount++; if( QAtom->flag & SphereFlag ) { DrawAtoms = True; if( QAtom->irad>MaxAtomRadius ) MaxAtomRadius = QAtom->irad; } if( QAtom->label ) DrawLabels = True; } else { QAtom->flag &= ~(SelectFlag|SphereFlag); if( QAtom->label ) { DeleteLabel( (Label*)QAtom->label ); QAtom->label = (void*)0; } } DisplaySelectCount(); ForEachBond { /* Ignore ZoneBoth setting! */ flag = bptr->dstatom->flag & bptr->srcatom->flag; if( flag & SelectFlag ) { bptr->flag |= SelectFlag; if( bptr->flag & CylinderFlag ) { DrawBonds = True; if( bptr->irad>MaxBondRadius ) MaxBondRadius = bptr->irad; } else if( bptr->flag&WireFlag ) DrawBonds = True; } else bptr->flag &= ~(SelectFlag|DrawBondFlag); } ForEachBack { /* Ignore ZoneBoth setting! */ flag = bptr->dstatom->flag & bptr->srcatom->flag; if( !(flag&SelectFlag) ) bptr->flag &= ~(SelectFlag|DrawBondFlag); } if( DrawRibbon ) { DrawRibbon = False; for( chain=Database->clist; chain; chain=chain->cnext ) for( group=chain->glist; group; group=group->gnext ) if( group->flag & DrawKnotFlag ) { for( ptr=group->alist; ptr; ptr=ptr->anext ) if( IsAlphaCarbon(ptr->refno) || IsSugarPhosphate(ptr->refno) ) { if( !(ptr->flag&SelectFlag) ) group->flag &= ~DrawKnotFlag; break; } if( group->flag & DrawKnotFlag ) DrawRibbon = True; } } DetermineClipping(); VoxelsClean = False; BucketFlag = False; } int DefineShade( r, g, b ) unsigned char r, g, b; { register int d,dr,dg,db; register int dist,best; register int i; /* Already defined! */ for( i=0; i<LastShade; i++ ) if( Shade[i].refcount ) if( (Shade[i].r==r)&&(Shade[i].g==g)&&(Shade[i].b==b) ) return(i); /* Allocate request */ for( i=0; i<LastShade; i++ ) if( !Shade[i].refcount ) { Shade[i].r = r; Shade[i].g = g; Shade[i].b = b; Shade[i].refcount = 0; return(i); } if( CommandActive ) WriteChar('\n'); WriteString("Warning: Unable to allocate shade!\n"); CommandActive = False; /* To avoid lint warning! */ best = dist = 0; /* Nearest match */ for( i=0; i<LastShade; i++ ) { dr = Shade[i].r - r; dg = Shade[i].g - g; db = Shade[i].b - b; d = dr*dr + dg*dg + db*db; if( !i || (d<dist) ) { dist = d; best = i; } } return( best ); } void ScaleColourMap( count ) int count; { register Real hue; register int fract, sextant; register int i, r, g, b; ScaleCount=0; for( i=0; i<LastShade; i++ ) if( !Shade[i].refcount ) ScaleCount++; /* If there are no shades free! */ if( !ScaleCount ) ScaleCount = LastShade; if( count && (count<ScaleCount) ) ScaleCount = count; for( i=0; i<ScaleCount; i++ ) { sextant = (int)(hue = (4.0*i)/(ScaleCount-1)); fract = (int)(255.0*(hue-sextant)); switch( sextant ) { case(0): r = 0; g = fract; b = 255; break; case(1): r = 0; g = 255; b = 255-fract; break; case(2): r = fract; g = 255; b = 0; break; case(3): r = 255; g = 255-fract; b = 0; break; default: r = 255; g = 0; b = 0; } ScaleRef[i].r = r; ScaleRef[i].g = g; ScaleRef[i].b = b; ScaleRef[i].shade = 0; ScaleRef[i].col = 0; } } static void SetLutEntry( i, r, g, b ) int i, r, g, b; { ULut[i] = True; RLut[i] = r; GLut[i] = g; BLut[i] = b; #ifdef EIGHTBIT #ifdef NEXT Lut[i] = (r + (g<<1) + b)>>2; #else Lut[i] = i; #endif #else #ifdef SIXTEENBIT { int s; /* adjust brightness at expense of color */ s = ((r + g + b)>>4) - (r>>4) - (g>>4) - (b>>4); while (s>0) { if (b<255) { b++; if (!(b&15) && !(--s)) break; } if (g<255) { g++; if (!(g&15) && !(--s)) break; } if (r<255) { r++; if (!(r&15) && !(--s)) break; } if (r==255 && g==255 && b==255) break; } /* Use cast to make byte order (endian) independent */ i<<=1; ((Byte *)Lut)[i] = (r&240) | (g>>4); ((Byte *)Lut)[i+1] = (b&240); } #else /* Use cast to make byte order (endian) independent */ i<<=2; ((Byte *)Lut)[i] = r; ((Byte *)Lut)[i+1] = g; ((Byte *)Lut)[i+2] = b; #endif #endif } static Real Power( x, y ) Real x; int y; { register Real result; result = x; while( y>1 ) { if( y&1 ) { result *= x; y--; } else { result *= result; y>>=1; } } return( result ); } void DefineColourMap() { register Real diffuse; register Real temp, inten; register int col, r, g, b; register int i, j, k; for( i=0; i<LutSize; i++ ) ULut[i] = False; if( !DisplayMode ) { SetLutEntry(BackCol,BackR,BackG,BackB); SetLutEntry(LabelCol,LabR,LabG,LabB); SetLutEntry(BoxCol,BoxR,BoxG,BoxB); } else SetLutEntry(BackCol,80,80,80); diffuse = 1.0 - Ambient; for( i=0; i<ColourDepth; i++ ) { temp = (Real)i/ColourMask; inten = diffuse*temp + Ambient; if( DisplayMode ) { /* Unselected [40,40,255] */ /* Selected [255,160,0] */ r = (int)(255*inten); g = (int)(160*inten); b = (int)(40*inten); /* Avoid Borland Compiler Warning! */ /* Shade2Colour(0) == FirstCol */ SetLutEntry( FirstCol+i, b, b, r ); SetLutEntry( Shade2Colour(1)+i, r, g, 0 ); } else { if( FakeSpecular ) { temp = Power(temp,SpecPower); inten *= 1.0 - temp; k = (int)(255*temp); } for( j=0; j<LastShade; j++ ) if( Shade[j].refcount ) { col = Shade2Colour(j); r = (int)(Shade[j].r*inten); g = (int)(Shade[j].g*inten); b = (int)(Shade[j].b*inten); if( FakeSpecular ) { r += k; g += k; b += k; } SetLutEntry( col+i, r, g, b ); } } } if( Interactive ) AllocateColourMap(); } void ResetColourMap() { register int i; #ifdef EIGHTBIT for( i=0; i<256; i++ ) ULut[i] = False; #endif SpecPower = 8; FakeSpecular = False; Ambient = DefaultAmbient; BackR = BackG = BackB = 0; BoxR = BoxG = BoxB = 255; LabR = LabG = LabB = 255; for( i=0; i<LastShade; i++ ) Shade[i].refcount = 0; ScaleCount = 0; } void ColourBondNone() { register Bond __far *bptr; if( Database ) ForEachBond if( (bptr->flag&SelectFlag) && bptr->col ) { Shade[Colour2Shade(bptr->col)].refcount--; bptr->col = 0; } } void ColourBondAttrib( r, g, b ) int r, g, b; { register Bond __far *bptr; register int shade,col; if( Database ) { ForEachBond if( (bptr->flag&SelectFlag) && bptr->col ) Shade[Colour2Shade(bptr->col)].refcount--; shade = DefineShade((Byte)r,(Byte)g,(Byte)b); col = Shade2Colour(shade); ForEachBond if( bptr->flag&SelectFlag ) { Shade[shade].refcount++; bptr->col = col; } } } void ColourBackNone() { register Chain __far *chain; register Bond __far *bptr; register int flag; if( Database ) ForEachBack { flag = ZoneBoth? bptr->dstatom->flag & bptr->srcatom->flag : bptr->dstatom->flag | bptr->srcatom->flag; if( flag&SelectFlag ) { bptr->flag |= SelectFlag; if( bptr->col ) { Shade[Colour2Shade(bptr->col)].refcount--; bptr->col = 0; } } else bptr->flag &= ~SelectFlag; } } void ColourBackAttrib( r, g, b ) int r, g, b; { register int shade,col; register Chain __far *chain; register Bond __far *bptr; if( Database ) { ColourBackNone(); shade = DefineShade((Byte)r,(Byte)g,(Byte)b); col = Shade2Colour(shade); ForEachBack if( bptr->flag&SelectFlag ) { Shade[shade].refcount++; bptr->col = col; } } } void ColourHBondNone( hbonds ) int hbonds; { register HBond __far *list; register HBond __far *ptr; register Atom __far *src; register Atom __far *dst; if( !Database ) return; list = hbonds? Database->hlist : Database->slist; if( ZoneBoth ) { for( ptr=list; ptr; ptr=ptr->hnext ) { src = ptr->src; dst = ptr->dst; if( (src->flag&dst->flag) & SelectFlag ) { ptr->flag |= SelectFlag; if( ptr->col ) { Shade[Colour2Shade(ptr->col)].refcount--; ptr->col = 0; } } else ptr->flag &= ~SelectFlag; } } else for( ptr=list; ptr; ptr=ptr->hnext ) { src = ptr->src; dst = ptr->dst; if( (src->flag|dst->flag) & SelectFlag ) { ptr->flag |= SelectFlag; if( ptr->col ) { Shade[Colour2Shade(ptr->col)].refcount--; ptr->col = 0; } } else ptr->flag &= ~SelectFlag; } } void ColourHBondType() { register HBond __far *ptr; register ShadeRef *ref; register int i; if( !Database ) return; for( i=0; i<7; i++ ) HBondShade[i].col = 0; if( InfoHBondCount<0 ) { CalcHydrogenBonds(); } else ColourHBondNone( True ); for( ptr=Database->hlist; ptr; ptr=ptr->hnext ) if( ptr->flag & SelectFlag ) { switch( ptr->offset ) { case( 2 ): ref = HBondShade; break; case( 3 ): ref = HBondShade+1; break; case( 4 ): ref = HBondShade+2; break; case( 5 ): ref = HBondShade+3; break; case( -3 ): ref = HBondShade+4; break; case( -4 ): ref = HBondShade+5; break; default: ref = HBondShade+6; break; } if( !ref->col ) { ref->shade = DefineShade( ref->r, ref->g, ref->b ); ref->col = Shade2Colour(ref->shade); } Shade[ref->shade].refcount++; ptr->col = (Byte)ref->col; } } void ColourHBondAttrib( hbonds, r, g, b ) int hbonds, r, g, b; { register HBond __far *list; register HBond __far *ptr; register int col,shade; if( !Database ) return; if( hbonds ) { if( InfoHBondCount<0 ) { CalcHydrogenBonds(); } else ColourHBondNone(True); } else if( InfoSSBondCount<0 ) { FindDisulphideBridges(); } else ColourHBondNone(False); shade = DefineShade((Byte)r,(Byte)g,(Byte)b); col = Shade2Colour(shade); list = hbonds? Database->hlist : Database->slist; for( ptr=list; ptr; ptr=ptr->hnext ) if( ptr->flag & SelectFlag ) { Shade[shade].refcount++; ptr->col = col; } } void ColourRibbonNone( flag ) int flag; { register Chain __far *chain; register Group __far *group; register Atom __far *aptr; if( !Database ) return; if( InfoHelixCount<0 ) return; for( chain=Database->clist; chain; chain=chain->cnext ) for( group=chain->glist; group; group=group->gnext ) { aptr = FindGroupAtom(group,1); if( aptr && (aptr->flag&SelectFlag) ) { if( (flag&RibColInside) && group->col1 ) { Shade[Colour2Shade(group->col1)].refcount--; group->col1 = 0; } if( (flag&RibColOutside) && group->col2 ) { Shade[Colour2Shade(group->col2)].refcount--; group->col2 = 0; } } } } void ColourRibbonAttrib( flag, r, g, b ) int flag, r, g, b; { register int shade, col; register Chain __far *chain; register Group __far *group; register Atom __far *aptr; if( Database ) { if( InfoHelixCount >= 0 ) { ColourRibbonNone( flag ); } else DetermineStructure(False); shade = DefineShade((Byte)r,(Byte)g,(Byte)b); col = Shade2Colour(shade); for( chain=Database->clist; chain; chain=chain->cnext ) for( group=chain->glist; group; group=group->gnext ) { aptr = FindGroupAtom(group,1); if( aptr && (aptr->flag&SelectFlag) ) { if( flag & RibColInside ) { Shade[shade].refcount++; group->col1 = col; } if( flag & RibColOutside ) { Shade[shade].refcount++; group->col2 = col; } } } } } void ColourMonitNone() { register Monitor *ptr; register int flag; if( Database ) for( ptr=MonitList; ptr; ptr=ptr->next ) if( ptr->col ) { flag = ZoneBoth? ptr->src->flag & ptr->dst->flag : ptr->src->flag | ptr->dst->flag; if( flag & SelectFlag ) { Shade[Colour2Shade(ptr->col)].refcount--; ptr->col = 0; } } } void ColourMonitAttrib( r, g, b ) int r, g, b; { register Monitor *ptr; register int shade,col; register int flag; if( !Database ) return; ColourMonitNone(); shade = DefineShade((Byte)r,(Byte)g,(Byte)b); col = Shade2Colour(shade); for( ptr=MonitList; ptr; ptr=ptr->next ) { flag = ZoneBoth? ptr->src->flag & ptr->dst->flag : ptr->src->flag | ptr->dst->flag; if( flag & SelectFlag ) { Shade[shade].refcount++; ptr->col = col; } } } void ColourDotsAttrib( r, g, b ) int r, g, b; { register DotStruct __far *ptr; register int i,shade,col; if( Database ) { for( ptr=DotPtr; ptr; ptr=ptr->next ) for( i=0; i<ptr->count; i++ ) { shade = Colour2Shade(ptr->col[i]); Shade[shade].refcount--; } shade = DefineShade((Byte)r,(Byte)g,(Byte)b); col = Shade2Colour(shade); for( ptr=DotPtr; ptr; ptr=ptr->next ) for( i=0; i<ptr->count; i++ ) { Shade[shade].refcount++; ptr->col[i] = col; } } } /* Coulomb's Law */ #define CoulombScale ((Long)(1<<12)) int CalculatePotential( x, y, z ) Long x, y, z; { register Chain __far *chain; register Group __far *group; register Atom __far *ptr; register Long dx,dy,dz; register Long result; register Card dist; register Card max; /* Calculated charges have b-values < 0.0 */ /* if( MinFun(MinMainTemp,MinHetaTemp) >= 0 ) */ /* CalculateCharges(); */ /* 8.0 Angstrom Cut Off */ max = (Long)2000*2000; result = 0; ForEachAtom { dx = ptr->xorg-x; if( (dist=dx*dx) < max ) { dy = ptr->yorg - y; if( (dist+=dy*dy) < max ) { dz = ptr->zorg - z; if( (dist+=dz*dz) < max ) result += (CoulombScale*ptr->temp) / (int)isqrt(dist); } } } /* Dielectric Constant = 10.0 */ /* (332.0*250.0)/(10.0*100.0) */ result = (result*83)/CoulombScale; return( (int)result ); } void ColourDotsPotential() { register DotStruct __far *ptr; register int i,shade,result; register ShadeRef *ref; if( Database ) { for( i=0; i<8; i++ ) PotentialShade[i].col = 0; /* Colour Dots None! */ for( ptr=DotPtr; ptr; ptr=ptr->next ) for( i=0; i<ptr->count; i++ ) { shade = Colour2Shade(ptr->col[i]); Shade[shade].refcount--; } for( ptr=DotPtr; ptr; ptr=ptr->next ) for( i=0; i<ptr->count; i++ ) { result = CalculatePotential( ptr->xpos[i], ptr->ypos[i], ptr->zpos[i] ); /* Determine Colour Bucket */ if( result >= 0 ) { if( result > 10 ) { if( result > 24 ) { ref = PotentialShade + 0; } else ref = PotentialShade + 1; } else if( result > 3 ) { ref = PotentialShade + 2; } else ref = PotentialShade + 3; } else if( result > -10 ) { if( result > -3 ) { ref = PotentialShade + 4; } else ref = PotentialShade + 5; } else if( result > -24 ) { ref = PotentialShade + 6; } else ref = PotentialShade + 7; if( !ref->col ) { ref->shade = DefineShade( ref->r, ref->g, ref->b ); ref->col = Shade2Colour(ref->shade); } Shade[ref->shade].refcount++; ptr->col[i] = ref->col; } } } static void ResetColourAttrib() { register Chain __far *chain; register Group __far *group; register Atom __far *ptr; ForEachAtom if( (ptr->flag&SelectFlag) && ptr->col ) Shade[Colour2Shade(ptr->col)].refcount--; } void MonoColourAttrib( r, g, b ) int r, g, b; { register int shade,col; register Chain __far *chain; register Group __far *group; register Atom __far *ptr; if( Database ) { ResetColourAttrib(); shade = DefineShade((Byte)r,(Byte)g,(Byte)b); col = Shade2Colour(shade); ForEachAtom if( ptr->flag&SelectFlag ) { Shade[shade].refcount++; ptr->col = col; } } } void ScaleColourAttrib( attr ) int attr; { register ShadeRef *ref; register int count, attrno, factor; register Chain __far *chain; register Group __far *group; register Atom __far *ptr; register Long temp; register int i; if( !Database ) return; switch( attr ) { case(ChainAttr): attrno = InfoChainCount; factor = 1; break; case(GroupAttr): factor = MinMainRes; attrno = MaxMainRes; if( HetaGroups && HetaGroupCount ) { if( MinHetaRes < factor ) factor = MinHetaRes; if( MaxHetaRes > attrno ) attrno = MaxHetaRes; } attrno -= (factor-1); break; case(ChargeAttr): case(TempAttr): factor = MinMainTemp; attrno = MaxMainTemp; if( HetaGroups && HetaGroupCount ) { if( MinHetaTemp < factor ) factor = MinHetaTemp; if( MaxHetaTemp > attrno ) attrno = MaxHetaTemp; } attrno -= (factor-1); break; default: return; } if( attrno<2 ) { MonoColourAttrib(255,255,255); return; } ResetColourAttrib(); ScaleColourMap(attrno); switch( attr ) { case(ChainAttr): count = 0; for( chain=Database->clist; chain; chain=chain->cnext ) { ref = &(ScaleRef[(count*ScaleCount)/attrno]); if( !(ref->col && Shade[ref->shade].refcount) ) { ref->shade = DefineShade(ref->r,ref->g,ref->b); ref->col = Shade2Colour(ref->shade); } for( group=chain->glist; group; group=group->gnext ) for( ptr=group->alist; ptr; ptr=ptr->anext ) if( ptr->flag&SelectFlag ) { Shade[ref->shade].refcount++; ptr->col = ref->col; } count++; } break; case(GroupAttr): for( chain=Database->clist; chain; chain=chain->cnext ) for( group=chain->glist; group; group=group->gnext ) { temp = (Long)ScaleCount*(group->serno-factor); i = (int)(temp/attrno); if( i >= ScaleCount ) { ref = ScaleRef + (ScaleCount-1); } else if( i >= 0 ) { ref = ScaleRef + i; } else ref = ScaleRef; if( !(ref->col && Shade[ref->shade].refcount) ) { ref->shade = DefineShade(ref->r,ref->g,ref->b); ref->col = Shade2Colour(ref->shade); } for( ptr=group->alist; ptr; ptr=ptr->anext ) if( ptr->flag&SelectFlag ) { Shade[ref->shade].refcount++; ptr->col = ref->col; } } break; case(TempAttr): ForEachAtom if( ptr->flag&SelectFlag ) { i = (int)(((Long)ScaleCount*(ptr->temp-factor)) /attrno); if( i >= ScaleCount ) { ref = ScaleRef + (ScaleCount-1); } else if( i >= 0 ) { ref = ScaleRef + i; } else ref = ScaleRef; if( !(ref->col && Shade[ref->shade].refcount) ) { ref->shade = DefineShade(ref->r,ref->g,ref->b); ref->col = Shade2Colour(ref->shade); } Shade[ref->shade].refcount++; ptr->col = ref->col; } break; case(ChargeAttr): ForEachAtom if( ptr->flag&SelectFlag ) { i = (int)(((Long)ScaleCount*(ptr->temp-factor)) /attrno); if( i <= 0 ) { ref = ScaleRef + (ScaleCount-1); } else if( i < ScaleCount ) { ref = ScaleRef + ((ScaleCount-1)-i); } else ref = ScaleRef; if( !(ref->col && Shade[ref->shade].refcount) ) { ref->shade = DefineShade(ref->r,ref->g,ref->b); ref->col = Shade2Colour(ref->shade); } Shade[ref->shade].refcount++; ptr->col = ref->col; } break; } } static int MatchNumber( len, value, mask ) int len, value; char *mask; { register char digit, template; register int result; register int i; result = True; for( i=0; i<len; i++ ) { digit = (value%10) + '0'; template = mask[len-i]; if( template==' ' ) { if( value ) result = False; } else if( !MatchChar(template,digit) ) result = False; value/=10; } return( result ); } void UserMaskAttrib( fields ) int fields; { register MaskDesc *mptr; register char *temp, *name; register int shade, change; register int i, rad, match; register Chain __far *chain; register Group __far *group; register Atom __far *ptr; if( !Database ) return; if( !MaskCount ) { if( CommandActive ) WriteChar('\n'); WriteString("Warning: No user supplied colour records!\n"); CommandActive = False; return; } change = False; ResetColourAttrib(); if( fields&MaskColourFlag ) for( i=0; i<MaskCount; i++ ) MaskShade[i] = -1; if( fields&MaskRadiusFlag ) { MaxAtomRadius = 0; DrawAtoms = False; } ForEachAtom if( ptr->flag&SelectFlag ) { for( i=0; i<MaskCount; i++ ) { mptr = UserMask+i; temp = mptr->mask; match = True; if( !MatchChar(temp[13],chain->ident) ) match=False; if( !MatchChar(temp[9],ptr->altl) ) match=False; /* Atom Name */ if( match ) { name = ElemDesc[ptr->refno]; if( !MatchChar(temp[5],name[0]) ) match=False; if( !MatchChar(temp[6],name[1]) ) match=False; if( !MatchChar(temp[7],name[2]) ) match=False; if( !MatchChar(temp[8],name[3]) ) match=False; } /* Group Name */ if( match ) { name = Residue[group->refno]; if( !MatchChar(temp[10],name[0]) ) match=False; if( !MatchChar(temp[11],name[1]) ) match=False; if( !MatchChar(temp[12],name[2]) ) match=False; } if( match && (mptr->flags&SerNoFlag) ) match = MatchNumber(4,ptr->serno,&temp[0]); if( match && (mptr->flags&ResNoFlag) ) match = MatchNumber(3,group->serno,&temp[14]); if( match ) break; } if( fields&MaskColourFlag ) { if( match ) { if( MaskShade[i] == -1 ) { MaskShade[i] = DefineShade(mptr->r,mptr->g,mptr->b); MaskColour[i] = Shade2Colour(MaskShade[i]); } Shade[MaskShade[i]].refcount++; ptr->col = MaskColour[i]; } else { shade = DefineShade(255,255,255); ptr->col = Shade2Colour(shade); Shade[shade].refcount++; } } if( fields&MaskRadiusFlag ) { rad = match? mptr->radius : 375; ptr->irad = (int)(Scale*rad); ptr->flag |= SphereFlag; ptr->radius = rad; if( ptr->irad>MaxAtomRadius ) MaxAtomRadius = ptr->irad; change = True; } } else if( ptr->flag&SphereFlag ) { DrawAtoms = True; if( ptr->irad>MaxAtomRadius ) MaxAtomRadius = ptr->irad; } if( change ) { DrawAtoms = True; DetermineClipping(); VoxelsClean = False; BucketFlag = False; } } void CPKColourAttrib() { register ShadeRef *ref; register Chain __far *chain; register Group __far *group; register Atom __far *ptr; register int i; if( !Database ) return; for( i=0; i<CPKMAX; i++ ) CPKShade[i].col = 0; ResetColourAttrib(); ForEachAtom if( ptr->flag&SelectFlag ) { ref = CPKShade + Element[ptr->elemno].cpkcol; if( !ref->col ) { ref->shade = DefineShade( ref->r, ref->g, ref->b ); ref->col = Shade2Colour(ref->shade); } Shade[ref->shade].refcount++; ptr->col = ref->col; } } void AminoColourAttrib() { register ShadeRef *ref; register Chain __far *chain; register Group __far *group; register Atom __far *ptr; register int i; if( !Database ) return; for( i=0; i<13; i++ ) AminoShade[i].col = 0; ResetColourAttrib(); ForEachAtom if( ptr->flag&SelectFlag ) { if( IsAmino(group->refno) ) { ref = AminoShade + AminoIndex[group->refno]; } else ref = AminoShade+12; if( !ref->col ) { ref->shade = DefineShade( ref->r, ref->g, ref->b ); ref->col = Shade2Colour(ref->shade); } Shade[ref->shade].refcount++; ptr->col = ref->col; } } void ShapelyColourAttrib() { register ShadeRef *ref; register Chain __far *chain; register Group __far *group; register Atom __far *ptr; register int i; if( !Database ) return; for( i=0; i<30; i++ ) Shapely[i].col = 0; ResetColourAttrib(); ForEachAtom if( ptr->flag&SelectFlag ) { if( IsAminoNucleo(group->refno) ) { ref = Shapely + group->refno; } else ref = Shapely+30; /* Original Colour Scheme * * ref = &(Shapely[26]); * if( IsNucleo(group->refno) ) * { ref = Shapely + group->refno; * } else if( IsShapelyBackbone(ptr->refno) ) * { ref = &(Shapely[24]); * } else if( IsShapelySpecial(ptr->refno) ) * { ref = &(Shapely[25]); * } else if( IsAmino(group->refno) ) * ref = Shapely + group->refno; */ if( !ref->col ) { ref->shade = DefineShade( ref->r, ref->g, ref->b ); ref->col = Shade2Colour(ref->shade); } Shade[ref->shade].refcount++; ptr->col = ref->col; } } void StructColourAttrib() { register ShadeRef *ref; register Chain __far *chain; register Group __far *group; register Atom __far *ptr; register int i; if( !Database ) return; if( InfoHelixCount<0 ) DetermineStructure(False); for( i=0; i<4; i++ ) StructShade[i].col = 0; ResetColourAttrib(); ForEachAtom if( ptr->flag&SelectFlag ) { if( group->struc & HelixFlag ) { ref = StructShade+1; } else if( group->struc & SheetFlag ) { ref = StructShade+2; } else if( group->struc & TurnFlag ) { ref = StructShade+3; } else ref = StructShade; if( !ref->col ) { ref->shade = DefineShade( ref->r, ref->g, ref->b ); ref->col = Shade2Colour(ref->shade); } Shade[ref->shade].refcount++; ptr->col = ref->col; } } int IsCPKColour( ptr ) Atom __far *ptr; { register ShadeRef *cpk; register ShadeDesc *col; cpk = CPKShade + Element[ptr->elemno].cpkcol; col = Shade + Colour2Shade(ptr->col); return( (col->r==cpk->r) && (col->g==cpk->g) && (col->b==cpk->b) ); } int IsVDWRadius( ptr ) Atom __far *ptr; { register int rad; if( ptr->flag & SphereFlag ) { rad = ElemVDWRadius( ptr->elemno ); return( ptr->radius == rad ); } else return( False ); } void InitialTransform() { register Card dist,max; register double fdist,fmax; register Chain __far *chain; register Group __far *group; register Atom __far *ptr; register Card ax, ay, az; register Long dx, dy, dz; dx = MaxX-MinX; OrigCX = (dx>>1)+MinX; dy = MaxY-MinY; OrigCY = (dy>>1)+MinY; dz = MaxZ-MinZ; OrigCZ = (dz>>1)+MinZ; MaxX -= OrigCX; MinX -= OrigCX; MaxY -= OrigCY; MinY -= OrigCY; MaxZ -= OrigCZ; MinZ -= OrigCZ; SideLen = MaxFun(dx,dy); if( dz>SideLen ) SideLen = dz; SideLen += 1000; Offset = SideLen>>1; XOffset = WRange; YOffset = HRange; ZOffset = 10000; ForEachAtom { ptr->xorg -= OrigCX; ptr->yorg -= OrigCY; ptr->zorg -= OrigCZ; } if( Offset > 37836 ) { fmax = 0.0; ForEachAtom { ax = (Card)AbsFun(ptr->xorg); ay = (Card)AbsFun(ptr->yorg); az = (Card)AbsFun(ptr->zorg); fdist = (double)ax*ax + (double)ay*ay + (double)az*az; if( fdist > fmax ) fmax = fdist; } } else { max = 0; ForEachAtom { ax = (Card)AbsFun(ptr->xorg); ay = (Card)AbsFun(ptr->yorg); az = (Card)AbsFun(ptr->zorg); dist = ax*ax + ay*ay + az*az; if( dist > max ) max = dist; } fmax = (double)max; } WorldRadius = (Card)sqrt(fmax); WorldSize = WorldRadius<<1; DScale = 1.0/(WorldSize+1000); /* MaxZoom*DScale*Range*500 == 118 */ MaxZoom = 0.236*(WorldSize+1000)/Range; if( MaxZoom < 1.0 ) { DScale *= MaxZoom; MaxZoom = 1.0; } ZoomRange = Range; MaxZoom -= 1.0; } void ReviseInvMatrix() { /* The inverse of a rotation matrix * is its transpose, and the inverse * of Scale is 1.0/Scale [IScale]! */ InvX[0] = IScale*RotX[0]; InvX[1] = IScale*RotY[0]; InvX[2] = IScale*RotZ[0]; InvY[0] = IScale*RotX[1]; InvY[1] = IScale*RotY[1]; InvY[2] = IScale*RotZ[1]; InvZ[0] = IScale*RotX[2]; InvZ[1] = IScale*RotY[2]; InvZ[2] = IScale*RotZ[2]; ShadowTransform(); } void PrepareTransform() { register Real theta, temp; register Real cost, sint; register Real x, y, z; register Real ncost; if( (ReDrawFlag&RFRotateX) && (DialValue[0]!=LastRX) ) { theta = PI*(DialValue[0]-LastRX); cost = cos(theta); sint = sin(theta); LastRX = DialValue[0]; y=RotY[0]; z=RotZ[0]; RotY[0]=cost*y+sint*z; RotZ[0]=cost*z-sint*y; y=RotY[1]; z=RotZ[1]; RotY[1]=cost*y+sint*z; RotZ[1]=cost*z-sint*y; y=RotY[2]; z=RotZ[2]; RotY[2]=cost*y+sint*z; RotZ[2]=cost*z-sint*y; if( CenX || CenY || CenZ ) { ncost = 1.0-cost; temp = CenX*(ncost*RotY[0] + sint*RotZ[0]); temp += CenY*(ncost*RotY[1] + sint*RotZ[1]); temp += CenZ*(ncost*RotY[2] + sint*RotZ[2]); temp = DialValue[5] - (Scale*temp)/YRange; if( temp < -1.0 ) { DialValue[5] = -1.0; } else if( temp > 1.0 ) { DialValue[5] = 1.0; } else DialValue[5] = temp; } } if( (ReDrawFlag&RFRotateY) && (DialValue[1]!=LastRY) ) { theta = PI*(DialValue[1]-LastRY); cost = cos(theta); sint = sin(theta); LastRY = DialValue[1]; x=RotX[0]; z=RotZ[0]; RotX[0]=cost*x+sint*z; RotZ[0]=cost*z-sint*x; x=RotX[1]; z=RotZ[1]; RotX[1]=cost*x+sint*z; RotZ[1]=cost*z-sint*x; x=RotX[2]; z=RotZ[2]; RotX[2]=cost*x+sint*z; RotZ[2]=cost*z-sint*x; if( CenX || CenY || CenZ ) { ncost = 1.0-cost; temp = CenX*(ncost*RotX[0] + sint*RotZ[0]); temp += CenY*(ncost*RotX[1] + sint*RotZ[1]); temp += CenZ*(ncost*RotX[2] + sint*RotZ[2]); temp = DialValue[4] - (Scale*temp)/XRange; if( temp < -1.0 ) { DialValue[4] = -1.0; } else if( temp > 1.0 ) { DialValue[4] = 1.0; } else DialValue[4] = temp; } } if( (ReDrawFlag&RFRotateZ) && (DialValue[2]!=LastRZ) ) { theta = PI*(DialValue[2]-LastRZ); cost = cos(theta); sint = sin(theta); LastRZ = DialValue[2]; x=RotX[0]; y=RotY[0]; RotX[0]=cost*x-sint*y; RotY[0]=cost*y+sint*x; x=RotX[1]; y=RotY[1]; RotX[1]=cost*x-sint*y; RotY[1]=cost*y+sint*x; x=RotX[2]; y=RotY[2]; RotX[2]=cost*x-sint*y; RotY[2]=cost*y+sint*x; if( CenX || CenY || CenZ ) { ncost = 1.0-cost; temp = CenX*(ncost*RotX[0] - sint*RotY[0]); temp += CenY*(ncost*RotX[1] - sint*RotY[1]); temp += CenZ*(ncost*RotX[2] - sint*RotY[2]); temp = DialValue[4] - (Scale*temp)/XRange; if( temp < -1.0 ) { DialValue[4] = -1.0; } else if( temp > 1.0 ) { DialValue[4] = 1.0; } else DialValue[4] = temp; ncost = 1.0-cost; temp = CenX*(ncost*RotY[0] + sint*RotX[0]); temp += CenY*(ncost*RotY[1] + sint*RotX[1]); temp += CenZ*(ncost*RotY[2] + sint*RotX[2]); temp = DialValue[5] - (Scale*temp)/YRange; if( temp < -1.0 ) { DialValue[5] = -1.0; } else if( temp > 1.0 ) { DialValue[5] = 1.0; } else DialValue[5] = temp; } } } void ApplyTransform() { register int temp; register Real x, y, z; register int oldx,oldy; register Chain __far *chain; register Group __far *group; register HBond __far *hptr; register Bond __far *bptr; register Atom __far *ptr; if( ReDrawFlag & RFMagnify ) { if( DialValue[3] <= 0.0 ) { Zoom = DialValue[3]+1.0; if( Zoom<0.1 ) Zoom=0.1; } else Zoom = (DialValue[3]*MaxZoom) + 1.0; Scale = Zoom*DScale*Range; ImageSize = (int)(Scale*WorldSize); ImageRadius = ImageSize>>1; IScale = 1.0/Scale; MaxAtomRadius = 0; MaxBondRadius = 0; } if( ReDrawFlag & RFRotate ) { PrepareTransform(); if( UseShadow ) ShadowTransform(); } if( ReDrawFlag & (RFRotate|RFMagnify) ) { MatX[0] = Scale*RotX[0]; MatX[1] = Scale*RotX[1]; MatX[2] = Scale*RotX[2]; MatY[0] = Scale*RotY[0]; MatY[1] = Scale*RotY[1]; MatY[2] = Scale*RotY[2]; MatZ[0] = Scale*RotZ[0]; MatZ[1] = Scale*RotZ[1]; MatZ[2] = Scale*RotZ[2]; if( UseShadow ) { InvX[0] = IScale*RotX[0]; InvX[1] = IScale*RotY[0]; InvX[2] = IScale*RotZ[0]; InvY[0] = IScale*RotX[1]; InvY[1] = IScale*RotY[1]; InvY[2] = IScale*RotZ[1]; InvZ[0] = IScale*RotX[2]; InvZ[1] = IScale*RotY[2]; InvZ[2] = IScale*RotZ[2]; } } oldx = XOffset; oldy = YOffset; XOffset = WRange + (int)(DialValue[4]*XRange); YOffset = HRange + (int)(DialValue[5]*YRange); /* Zoom dependent Translation! */ /* XOffset = WRange + (int)(DialValue[4]*ImageSize); */ /* YOffset = HRange + (int)(DialValue[5]*ImageSize); */ switch( ReDrawFlag ) { case(RFTransX): if( XOffset != oldx ) { temp = XOffset - oldx; ForEachAtom ptr->x += temp; } break; case(RFTransY): if( YOffset != oldy ) { temp = YOffset - oldy; ForEachAtom ptr->y += temp; } break; case(RFRotateX): ForEachAtom { x = ptr->xorg; y = ptr->yorg; z = ptr->zorg; ptr->y = (int)(x*MatY[0]+y*MatY[1]+z*MatY[2])+YOffset; ptr->z = (int)(x*MatZ[0]+y*MatZ[1]+z*MatZ[2])+ZOffset; } break; case(RFRotateY): ForEachAtom { x = ptr->xorg; y = ptr->yorg; z = ptr->zorg; ptr->x = (int)(x*MatX[0]+y*MatX[1]+z*MatX[2])+XOffset; ptr->z = (int)(x*MatZ[0]+y*MatZ[1]+z*MatZ[2])+ZOffset; } break; case(RFRotateZ): ForEachAtom { x = ptr->xorg; y = ptr->yorg; z = ptr->zorg; ptr->x = (int)(x*MatX[0]+y*MatX[1]+z*MatX[2])+XOffset; ptr->y = (int)(x*MatY[0]+y*MatY[1]+z*MatY[2])+YOffset; } break; default: if( DrawAtoms && (ReDrawFlag&RFMagnify) ) { ForEachAtom { x = ptr->xorg; y = ptr->yorg; z = ptr->zorg; ptr->x = (int)(x*MatX[0]+y*MatX[1]+z*MatX[2])+XOffset; ptr->y = (int)(x*MatY[0]+y*MatY[1]+z*MatY[2])+YOffset; ptr->z = (int)(x*MatZ[0]+y*MatZ[1]+z*MatZ[2])+ZOffset; if( ptr->flag&SphereFlag ) { ptr->irad = (int)(Scale*ptr->radius); if( ptr->irad>MaxAtomRadius ) MaxAtomRadius = ptr->irad; } } } else ForEachAtom { x = ptr->xorg; y = ptr->yorg; z = ptr->zorg; ptr->x = (int)(x*MatX[0]+y*MatX[1]+z*MatX[2])+XOffset; ptr->y = (int)(x*MatY[0]+y*MatY[1]+z*MatY[2])+YOffset; ptr->z = (int)(x*MatZ[0]+y*MatZ[1]+z*MatZ[2])+ZOffset; } if( ReDrawFlag & RFMagnify ) { if( DrawBonds ) ForEachBond if( bptr->flag&CylinderFlag ) { bptr->irad = (int)(Scale*bptr->radius); if( bptr->irad>MaxBondRadius ) MaxBondRadius = bptr->irad; } for( hptr=Database->hlist; hptr; hptr=hptr->hnext ) if( hptr->flag&CylinderFlag ) hptr->irad = (int)(Scale*hptr->radius); for( hptr=Database->slist; hptr; hptr=hptr->hnext ) if( hptr->flag&CylinderFlag ) hptr->irad = (int)(Scale*hptr->radius); ForEachBack if( bptr->flag&CylinderFlag ) bptr->irad = (int)(Scale*bptr->radius); } } DetermineClipping(); if( UseScreenClip || ReDrawFlag!=RFRotateY ) BucketFlag = False; } void ResetTransform() { RotX[0] = 1.0; RotX[1] = 0.0; RotX[2] = 0.0; RotY[0] = 0.0; RotY[1] = 1.0; RotY[2] = 0.0; RotZ[0] = 0.0; RotZ[1] = 0.0; RotZ[2] = 1.0; LastRX = LastRY = LastRZ = 0.0; CenX = CenY = CenZ = 0; } void InitialiseTransform() { ColourDepth = DefaultColDepth; ColourMask = ColourDepth-1; #ifdef APPLEMAC LastShade = Colour2Shade(LutSize-1); #else LastShade = Colour2Shade(LutSize); #endif ResetColourMap(); ResetTransform(); ZoneBoth = True; HetaGroups = True; Hydrogens = True; }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.