Logo Search packages:      
Sourcecode: pymol version File versions  Download package

ObjectGadgetRamp.c

/* 
A* -------------------------------------------------------------------
B* This file contains source code for the PyMOL computer program
C* copyright 1998-2000 by Warren Lyford Delano of DeLano Scientific. 
D* -------------------------------------------------------------------
E* It is unlawful to modify or remove this copyright notice.
F* -------------------------------------------------------------------
G* Please see the accompanying LICENSE file for further information. 
H* -------------------------------------------------------------------
I* Additional authors of this source file include:
-* 
-* 
-*
Z* -------------------------------------------------------------------
*/

#include"os_predef.h"
#include"os_std.h"
#include"os_gl.h"

#include"OOMac.h"
#include"ObjectGadgetRamp.h"
#include"GadgetSet.h"
#include"Base.h"
#include"MemoryDebug.h"
#include"CGO.h"
#include"Scene.h"
#include"Setting.h"
#include"PConv.h"
#include"main.h"
#include"Color.h"
#include"VFont.h"
#include"ObjectMolecule.h"
#include"Executive.h"
#include"Util.h"

#include"P.h"

void ObjectGadgetRampFree(ObjectGadgetRamp *I) {
  ColorForgetExt(I->Gadget.Obj.G,I->Gadget.Obj.Name);
  VLAFreeP(I->Level);
  VLAFreeP(I->Color);
  VLAFreeP(I->Special);
  VLAFreeP(I->Extreme);
  ObjectGadgetPurge(&I->Gadget);
  OOFreeP(I);
}

#define ShapeVertex(cgo,a,b) CGOVertex(cgo,(float)a,(float)b,0.0F)
#define ShapeFVertex(cgo,a,b) CGOFontVertex(cgo,(float)a,(float)b,0.0F)
#define ABS 0.0F
#define REL 1.0F
#define OFF 2.0F

#define ShapeNormal(cgo,a,b) CGONormal(cgo,(float)a,(float)b,0.0F)
#define ShapeColor(cgo,a,b) CGONormal(cgo,(float)a,(float)b,0.0F)
#define LKP 2.0F

#ifdef _PYMOL_INLINE 
__inline__
#endif
static void ObjectGadgetRampCalculate(ObjectGadgetRamp *I, float v,float *result)
{
  int i;
  const float _1 = 1.0F;
  const float _0 = 0.0F;
  /* from Filipe Maia */
  
  /* All of this functions are taken right of the gnuplot manual  */
  if(v>_1)
    v=_1;
  else if(v<_0)
    v=_0;

  switch(I->CalcMode){
  case cRAMP_TRADITIONAL:
    result[0] = (float)sqrt(v);
    result[1] = v*v*v;
    result[2] = (float)sin(v*2*cPI);
    break;
  case cRAMP_SLUDGE:
    result[0] = v;
    result[1] = (float)fabs(v-0.5F);
    result[2] = v*v*v*v;
    break;
  case cRAMP_OCEAN:
    result[0] = 3*v-2;
    result[1] = (float)fabs((3*v-1)/2);
    result[2] = v;
    break;
  case cRAMP_HOT:
    result[0] = 3*v;
    result[1] = 3*v-1;
    result[2] = 3*v-2;
    break;
  case cRAMP_GRAYABLE:
    result[0] = v/0.32F-0.78125F; 
    result[1] = 2*v-0.84F;
    result[2] = v/0.08F-11.5F; /* I'm not so sure about this one */
    break;
  case cRAMP_RAINBOW:
    result[0] = (float)fabs(2*v - 0.5F);
    result[1] = (float)sin(v*cPI);
    result[2] = (float)cos(v*cPI/2.0F);
    break;
  case cRAMP_AFMHOT:
    result[0] = 2*v;
    result[1] = 2*v-0.5F;
    result[2] = 2*v-1.0F;
    break;
  case cRAMP_GRAYSCALE:
    result[0] = v;
    result[1] = v;
    result[2] = v;
    break;
  default: /* default is simply white */
    result[0] = 1.0F;
    result[1] = 1.0F;
    result[2] = 1.0F;
    break;
  }  
  for(i = 0;i<3;i++) {
    if(result[i] > 1.0F){
      result[i] = 1.0F;
    } else if(result[i]<0.0F){
      result[i] = 0.0F;
    }
  }
}

#ifdef _PYMOL_INLINE 
__inline__
#endif
static int _ObjectGadgetRampInterpolate(ObjectGadgetRamp *I,float level,float *color,
                                        float *table,float *extreme)
{
  register float *i_level = I->Level;
  register int n_level = I->NLevel;
  const float _0 = 0.0F;
  const float _1 = 1.0F;
  int ok=true;
  if(i_level&&table) {
    register int level_is_ge = -1;
    register int level_is_le = n_level; 
    register int i=0;
    i = n_level-1;
    while(i>=0) { 
      register float f = i_level[i];
      if(level>=f) {
        level_is_ge = i;
        break;
      }
      i--;
    }
    i = 0;
    while(i<n_level) {
      register float f = i_level[i];
      if(level<=f) {
        level_is_le = i;
        break;
      } else 
        i++;
    }
#if 0
    printf("%9.2f %2i %9.2f %2i %9.2f\n",
           level, 
           level_is_ge,
           ((level_is_ge>=0) && (level_is_ge<n_level)) ? i_level[level_is_ge] : 1000.0F,  
           level_is_le, 
           ((level_is_le>=0) && (level_is_le<n_level)) ? i_level[level_is_le] : -1000.0F);
#endif
      
    if(level_is_ge!=level_is_le) {
      if(level_is_le==0) { /* lower extreme */
        register float *v;
        if(extreme) {
          v = extreme;
        } else {
          v = table;
        }
        copy3f(v,color);
      } else if(level_is_ge==(n_level-1)) { /* upper extreme */
        register float *v;
        if(extreme) {
          v = extreme + 3;
        } else {
          v = table + 3*(n_level-1);
        }
        copy3f(v,color);
      } else {
        register float d,x0,x1;

        d = i_level[level_is_ge] - i_level[level_is_le];
        if(fabs(d)>R_SMALL8) {
          x0=(level-i_level[level_is_le])/d;
          x1=1.0F-x0;
          for(i=0;i<3;i++) {
            color[i]= x0*table[3*level_is_ge+i] + x1*table[3*level_is_le+i];
          }
          clamp3f(color);
        } else {
          register float *v = table+3*level_is_ge;
          copy3f(v,color);
        }
      }
    } else { /* dead on the specified level */
      copy3f(table+3*level_is_ge,color);
      clamp3f(color);
    }
  } else {
    float base,range;
    if(n_level&&i_level) {
      base=i_level[0];
      range=i_level[n_level-1]-base;
      if(fabs(range)<R_SMALL8)
        range=_1;
    } else {
      base = _0;
      range = _1;
    }
    level = (level-base)/range;
    ObjectGadgetRampCalculate(I,level,color);
  }
  return(ok);
}


#ifdef _PYMOL_INLINE 
__inline__
#endif
static int _ObjectGadgetRampBlend(ObjectGadgetRamp *I,float *color,
                                  float *table,float *extreme,int mode)
{
  /* this capability needs to be re-thought */

  register float *i_level = I->Level;
  register int n_level = I->NLevel;
  const float _1 = 1.0F;
  float avg[3];
  int ok=true;
  zero3f(avg);

  {
    int cnt = 0;
    switch(mode) {
    case 1:
    case 2:
      break;
    default:
      if(i_level&&table) {
        int i;
        for(i=0;i<n_level;i++) {
          add3f(table+3*i,avg,avg);
          cnt++;
        }
        if(extreme) {
          add3f(extreme,avg,avg);
          add3f(extreme+3,avg,avg);
          cnt+=2;
        }
        if(cnt) {
          float fact = _1/cnt;
          scale3f(avg,fact,avg);
        }
        clamp3f(avg);
      }
      copy3f(avg,color);
    }
  }

  switch(mode) {
  case 1: /* min components */
  case 3:
    ones3f(color);
    if(i_level&&table) {
      int i,j;
      for(i=0;i<n_level;i++) {
        for(j=0;j<3;j++) {
          color[j] = (color[j] < table[3*i+j]) ? color[j] : table[3*i+j];
        }
      }
      if(extreme) {
        for(j=0;j<3;j++) {
          color[j] = (color[j] < extreme[j  ]) ? color[j] : extreme[j  ];
          color[j] = (color[j] < extreme[j+3]) ? color[j] : extreme[j+3];
        }
      }
      clamp3f(color);
    }
    if(mode==3) { /* average serves as a minimum */
      int j;
      for(j=0;j<3;j++) {
        color[j] = (color[j] > avg[j]) ? color[j] : avg[j];
      }
    }
    break;
  case 2: /* max components */
    zero3f(color);
    if(i_level&&table) {
      int i,j;
      for(i=0;i<n_level;i++) {
        for(j=0;j<3;j++) {
          color[j] = (color[j] > table[3*i+j]) ? color[j] : table[3*i+j];
        }
      }
      if(extreme) {
        for(j=0;j<3;j++) {
          color[j] = (color[j] > extreme[j  ]) ? color[j] : extreme[j  ];
          color[j] = (color[j] > extreme[j+3]) ? color[j] : extreme[j+3];
        }
      }
      clamp3f(color);
    }
    break;
  default: /* simple average of all colors */
    copy3f(avg,color);
    break;
  }
  return(ok);
}

#define MAX_COLORS 64

#ifdef _PYMOL_INLINE 
__inline__
#endif
static int ObjectGadgetRampInterpolateWithSpecial(ObjectGadgetRamp *I,
                                                  float level,
                                                  float *color,
                                                  float *atomic, 
                                                  float *object,
                                                  float *vertex, 
                                                  int state, 
                                                  int blend_all)
{
  /* now thread-safe...via stack copy of colors */

  float stack_color[MAX_COLORS*3];
  float stack_extreme[6];
  register float *i_level = I->Level;
  register float *i_color = I->Color;
  register int *i_special = I->Special;
  if(i_level && i_color && i_special) {
    register int i = 0;
    register int n_level = I->NLevel;
    register float *i_extreme = I->Extreme;
    register float *extreme = i_extreme;
    /* mix special coloring into the table */
    register float *src = i_color,*dst = stack_color;
    if((n_level+2)>MAX_COLORS)
      n_level = MAX_COLORS - 2;
    while(i<n_level) {
      register int index = i_special[i];
      switch(index) {
      case 0:
        *(dst++) = *(src++);
        *(dst++) = *(src++);
        *(dst++) = *(src++);
        break;
      case cColorDefault:
      case cColorAtomic: 
        copy3f(atomic,dst);
        src+=3;
        dst+=3;
        break;
      case cColorObject:
        copy3f(object,dst);
        dst+=3;
        src+=3;
        break;
      default: /* allow nested ramps */
        if(ColorCheckRamped(I->Gadget.Obj.G,index)) {
          ColorGetRamped(I->Gadget.Obj.G,index,vertex,dst,state);
        } else {
          copy3f(src,dst);
        }
        dst+=3;
        src+=3;
        break;
      }
      i++;
    }
    /* mix extreme colors in (if present) */
    if(i_extreme) {
      i = 0;
      extreme = stack_extreme;
      src = i_extreme;
      dst = stack_extreme;
      while(i<2) {
        register int index = i_special[i+n_level];
        switch(index) {
        case 0:
          *(dst++)=*(src++);
          *(dst++)=*(src++);
          *(dst++)=*(src++);
          break;
        case cColorDefault:
        case cColorAtomic: 
          copy3f(atomic,dst);
          dst+=3;
          src+=3;
          break;
        case cColorObject:
          copy3f(object,dst);          
          dst+=3;
          src+=3;
          break;
        default: /* allow nested ramps */
          if(ColorCheckRamped(I->Gadget.Obj.G,index)) {
            ColorGetRamped(I->Gadget.Obj.G,index,vertex,dst,state);
          } else {
            copy3f(src,dst);
          }
          dst+=3;
          src+=3;
          break;
        }
        i++;
      }
    }
    /* interpolate using stack tables */
    if(blend_all) 
      return _ObjectGadgetRampBlend(I,color,stack_color,extreme,I->SrcState);
    else
      return _ObjectGadgetRampInterpolate(I,level,color,stack_color,extreme);
  } else {
    /* interpolate using static tables */
    if(blend_all)
      return _ObjectGadgetRampBlend(I,color,i_color,I->Extreme,I->SrcState);
    else
      return _ObjectGadgetRampInterpolate(I,level,color,i_color,I->Extreme);
  }
}


int ObjectGadgetRampInterpolate(ObjectGadgetRamp *I,float level,float *color)
{
  int result = _ObjectGadgetRampInterpolate(I,level,color,I->Color,I->Extreme);
  return result;
}

PyObject *ObjectGadgetRampAsPyList(ObjectGadgetRamp *I)
{
#ifdef _PYMOL_NOPY
  return NULL;
#else

  PyObject *result = NULL;

  result = PyList_New(11);

  PyList_SetItem(result,0,ObjectGadgetPlainAsPyList(&I->Gadget));
  PyList_SetItem(result,1,PyInt_FromLong(I->RampType));
  PyList_SetItem(result,2,PyInt_FromLong(I->NLevel));
  if(I->Level&&I->NLevel) {
    PyList_SetItem(result,3,PConvFloatVLAToPyList(I->Level));
  } else {
    PyList_SetItem(result,3,PConvAutoNone(NULL));
  }
  if(I->Color&&I->NLevel) {
    PyList_SetItem(result,4,PConvFloatVLAToPyList(I->Color));
  } else {
    PyList_SetItem(result,4,PConvAutoNone(NULL));
  }
  PyList_SetItem(result,5,PyInt_FromLong(I->var_index));
  PyList_SetItem(result,6,PyString_FromString(I->SrcName));
  PyList_SetItem(result,7,PyInt_FromLong(I->SrcState));
  PyList_SetItem(result,8,PyInt_FromLong(I->CalcMode));
  if(I->Special&&I->NLevel) {
    PyList_SetItem(result,9,PConvIntVLAToPyList(I->Special));
  } else {
    PyList_SetItem(result,9,PConvAutoNone(NULL));
  }
  if(I->Extreme&&I->NLevel) {
    PyList_SetItem(result,10,PConvFloatVLAToPyList(I->Extreme));
  } else {
    PyList_SetItem(result,10,PConvAutoNone(NULL));
  }
  return(PConvAutoNone(result));  
#endif
}


int ObjectGadgetRampNewFromPyList(PyMOLGlobals *G,PyObject *list,ObjectGadgetRamp **result,int version)
{
#ifdef _PYMOL_NOPY
  return 0;
#else

  ObjectGadgetRamp *I = NULL;
  int ok = true;
  int ll = 0;

  if(ok) I=ObjectGadgetRampNew(G);
  if(ok) ok = (I!=NULL);
  if(ok) ok = (list!=NULL);
  if(ok) ok = PyList_Check(list);
  if(ok) ll = PyList_Size(list);
  /* TO SUPPORT BACKWARDS COMPATIBILITY...
   Always check ll when adding new PyList_GetItem's */

  if(ok) ok = ObjectGadgetInitFromPyList(G,PyList_GetItem(list,0),&I->Gadget,version);
  if(ok) ok = PConvPyIntToInt(PyList_GetItem(list,1),&I->RampType);
  if(ok) ok = PConvPyIntToInt(PyList_GetItem(list,2),&I->NLevel);
  if(ok&&I->NLevel) ok = PConvPyListToFloatVLA(PyList_GetItem(list,3),&I->Level);
  if(ok&&I->NLevel) {
    PyObject *item = PyList_GetItem(list,4);
    if(item!=Py_None) {
      ok = PConvPyListToFloatVLA(item,&I->Color);
    }
  }
  if(ok) ok = PConvPyIntToInt(PyList_GetItem(list,5),&I->var_index);
  if(ok) ok = PConvPyStrToStr(PyList_GetItem(list,6),I->SrcName,WordLength);
  if(ok) ok = PConvPyIntToInt(PyList_GetItem(list,7),&I->SrcState);
  if(ok&&(ll>8)) ok=PConvPyIntToInt(PyList_GetItem(list,8),&I->CalcMode);
  if(ok&&(ll>9)) {
    PyObject *item = PyList_GetItem(list,9);
    if(item!=Py_None) {
      ok = PConvPyListToIntVLA(item,&I->Special);
    }
  } else {
    I->Special = NULL;
  }
  if(ok&&I->NLevel&&(ll>10)) {
    PyObject *item = PyList_GetItem(list,10);
    if(item!=Py_None) {
      ok = PConvPyListToFloatVLA(item,&I->Extreme);
    }
  } else {
    I->Extreme = NULL;
  }
  /*  if(ok) ObjectGadgetRampBuild(I);
      if(ok) ObjectGadgetRampUpdate(I);*/
  if(ok) ObjectGadgetUpdateStates(&I->Gadget);
  if(ok) ObjectGadgetUpdateExtents(&I->Gadget);
  if(ok) (*result)=I;
  return(ok);
#endif
}

int ObjectGadgetRampInterVertex(ObjectGadgetRamp *I,float *pos,float *color,int state)
{
  float level;
  int ok=true;
  switch(I->RampType) {
  case cRampMap:
    if(!I->Map)
      I->Map = ExecutiveFindObjectMapByName(I->Gadget.Obj.G,I->SrcName);
    if(!ExecutiveValidateObjectPtr(I->Gadget.Obj.G,(CObject*)I->Map,cObjectMap))
      ok=false;
    else {
      int src_state;
      if(I->SrcState>=0)
        src_state = I->SrcState;
      else
        src_state = state;
      if(src_state<0)
        src_state = SceneGetState(I->Gadget.Obj.G);
      if(ok) ok = (I->Map!=NULL);
      if(ok) ok = ObjectMapInterpolate(I->Map,src_state,pos,&level,NULL,1);
      if(ok) ok = ObjectGadgetRampInterpolate(I,level,color);
    }
    break;
  case cRampMol:
    if(!I->Mol)
      I->Mol = ExecutiveFindObjectMoleculeByName(I->Gadget.Obj.G,I->SrcName);
    if(!ExecutiveValidateObjectPtr(I->Gadget.Obj.G,(CObject*)I->Mol,cObjectMolecule))
      ok=false;
    else  {
      float cutoff = 1.0F;
      float dist;
      int sub_vdw = false;
      if(state<0) state = SceneGetState(I->Gadget.Obj.G);
      if(I->Level&&I->NLevel) {
        cutoff = I->Level[I->NLevel-1];
        if(I->Level[0]<0.0F) {
          sub_vdw=true;
          cutoff+=MAX_VDW;
        }
      }
      if(ok) ok = (I->Mol!=NULL);      
      if(ok) {
        if(SettingGet_b(I->Gadget.Obj.G,I->Gadget.Obj.Setting,NULL,cSetting_ramp_blend_nearby_colors)) {
          float atomic[3];
          int index = ObjectMoleculeGetNearestBlendedColor(I->Mol, pos, cutoff, state, &dist, atomic, sub_vdw);
          if(index>=0) {
            float *object =  ColorGetRaw(I->Gadget.Obj.G,I->Mol->Obj.Color);
            
            if(!ObjectGadgetRampInterpolateWithSpecial(I,dist,color,atomic,
                                                       object,pos,state,false)) {
              copy3f(I->Color,color);
            }
          } else {
            float white[3] = {1.0F, 1.0F, 1.0F};
            if(!ObjectGadgetRampInterpolateWithSpecial(I,cutoff+1.0F,color,white,
                                                       white,pos,state,false)) {
              copy3f(I->Color,color);
            }
          }
        } else {
          int index = ObjectMoleculeGetNearestAtomIndex(I->Mol, pos, cutoff, state, &dist);
          if(index>=0) {
            float *atomic =  ColorGetRaw(I->Gadget.Obj.G,I->Mol->AtomInfo[index].color);
            float *object =  ColorGetRaw(I->Gadget.Obj.G,I->Mol->Obj.Color);
            
            if(sub_vdw) {
              dist-=I->Mol->AtomInfo[index].vdw;
              if(dist<0.0F)
                dist = 0.0F;
            }
            
            if(!ObjectGadgetRampInterpolateWithSpecial(I,dist,color,atomic,
                                                       object,pos,state,false)) {
              copy3f(I->Color,color);
            }
          } else {
            float white[3] = {1.0F, 1.0F, 1.0F};
            if(!ObjectGadgetRampInterpolateWithSpecial(I,cutoff+1.0F,color,white,
                                                       white,pos,state,false)) {
              copy3f(I->Color,color);
            }
          }
        }
      }
    }
    break;
  case cRampNone:
    {
      float white[3] = {1.0F, 1.0F, 1.0F};
      if(!ObjectGadgetRampInterpolateWithSpecial(I,0.0F,color,white,white,
                                                 pos,state,true)) { /* simple blend */
        copy3f(I->Color,color);
      }
    }
    break;
  default:
    ok=false;
    break;
  }
  return(ok);
}

static void ObjectGadgetRampUpdateCGO(ObjectGadgetRamp *I,GadgetSet *gs)
{
  CGO *cgo;
  int n_extra;
  int a,c=0;
  float *p;
  char buffer[255];
  float white[3] = {1.0F,1.0F,1.0F};

  cgo = CGONewSized(I->Gadget.Obj.G,100);

  /* behind text */

  CGOBegin(cgo,GL_TRIANGLE_STRIP);
  CGOColor(cgo,0.05F,0.05F,0.05F);
  ShapeNormal(cgo,LKP,2);
  ShapeVertex(cgo,REL,9);
  ShapeVertex(cgo,REL,10);
  ShapeVertex(cgo,REL,7);
  ShapeVertex(cgo,REL,8);
  CGOEnd(cgo);

  CGOColor(cgo,1.0F,1.0F,1.0F);

#ifndef _PYMOL_NOPY
  CGOFontScale(cgo,I->text_scale_h,I->text_scale_v);

  if(I->Level&&I->NLevel) {
    /*
    for(a=0;a<I->NLevel;a++) {
      sprintf(buffer,"%0.3f",I->Level[a]);
      ShapeFVertex(cgo,REL,11+a);
      CGOWriteIndent(cgo,buffer, -(I->NLevel-a)/(float)a);
    }
    */
    sprintf(buffer,"%0.3f",I->Level[0]);
    ShapeFVertex(cgo,REL,11);
    CGOWrite(cgo,buffer);
    sprintf(buffer,"%0.3f",I->Level[I->NLevel-1]);
    ShapeFVertex(cgo,REL,12);
    CGOWriteLeft(cgo,buffer);
  }
#endif

  CGOBegin(cgo,GL_TRIANGLE_STRIP);
  ShapeNormal(cgo,LKP,2);

  if(I->Color) {

    n_extra = 3*I->NLevel;
    if(n_extra<6)
      n_extra = 6;

    {
      VLACheck(gs->Coord,float,(I->var_index+n_extra)*3);      
      c = I->var_index;
      p=gs->Coord+3*c;
      if(I->NLevel>1) {
        for(a=0;a<I->NLevel;a++) {
          
          if(I->Special&&(I->Special[a]<0)) {
            CGOColorv(cgo,white);
          } else {
            float tmp[3],*src = I->Color+3*a;
            copy3f(src,tmp);
            ColorClampColor(I->Gadget.Obj.G,tmp);
            CGOColorv(cgo,tmp);
          }
          
          *(p++) = I->border + (I->width * a)/(I->NLevel-1);
          *(p++) = -I->border;
          *(p++) = I->border;
          ShapeVertex(cgo,REL,c);
          c++;
          
          *(p++) = I->border + (I->width * a)/(I->NLevel-1);
          *(p++) = -(I->border+I->bar_height);
          *(p++) = I->border;
          ShapeVertex(cgo,REL,c);
          c++;
          
          *(p++) = I->border + (I->width * a)/(I->NLevel-1);
          *(p++) = -(I->border+I->height+I->height);
          *(p++) = I->border;
          c++;
        }
      } else {
        for(a=0;a<2;a++) {
          if(I->Special&&(I->Special[0]<0)) {
            CGOColorv(cgo,white);
          } else {
            float tmp[3],*src = I->Color;
            copy3f(src,tmp);
            ColorClampColor(I->Gadget.Obj.G,tmp);
            CGOColorv(cgo,tmp);
          }
          
          *(p++) = I->border + (I->width * a);
          *(p++) = -I->border;
          *(p++) = I->border;
          ShapeVertex(cgo,REL,c);
          c++;
          
          *(p++) = I->border + (I->width * a);
          *(p++) = -(I->border+I->bar_height);
          *(p++) = I->border;
          ShapeVertex(cgo,REL,c);
          c++;
          
          *(p++) = I->border + (I->width * a);
          *(p++) = -(I->border+I->height+I->height);
          *(p++) = I->border;
          c++;
        }
        
      }
    }
  } else {
    int samples=20;
    float fxn;
    float color[3];
    n_extra = 3*samples;
    VLACheck(gs->Coord,float,(I->var_index+n_extra)*3);      
    c = I->var_index;
    p=gs->Coord+3*c;

    for(a=0;a<samples;a++) {
      fxn = a/(samples-1.0F);

      ObjectGadgetRampCalculate(I,fxn,color);
      CGOColorv(cgo,color);
      
      *(p++) = I->border + (I->width * fxn);
      *(p++) = -I->border;
      *(p++) = I->border;
      ShapeVertex(cgo,REL,c);
      c++;
        
      *(p++) = I->border + (I->width * fxn);
      *(p++) = -(I->border+I->bar_height);
      *(p++) = I->border;
      ShapeVertex(cgo,REL,c);
      c++;
        
      *(p++) = I->border + (I->width * fxn);
      *(p++) = -(I->border+I->height+I->height);
      *(p++) = I->border;
      c++;
      
    }
  }
  gs->NCoord = c;
  /* center */
  CGOEnd(cgo);


  CGOColor(cgo,0.5F,0.5F,0.5F);

  /* top */
  CGOBegin(cgo,GL_TRIANGLE_STRIP);
  ShapeNormal(cgo,LKP,2);
  ShapeVertex(cgo,REL,5);
  ShapeVertex(cgo,REL,6);
  ShapeNormal(cgo,LKP,1);
  ShapeVertex(cgo,REL,1);
  ShapeVertex(cgo,REL,2);
  CGOEnd(cgo);

  /* bottom */

  CGOBegin(cgo,GL_TRIANGLE_STRIP);
  ShapeNormal(cgo,LKP,4);
  ShapeVertex(cgo,REL,3);
  ShapeVertex(cgo,REL,4);
  ShapeNormal(cgo,LKP,2);
  ShapeVertex(cgo,REL,7);
  ShapeVertex(cgo,REL,8);
  CGOEnd(cgo);

  /* left */

  CGOBegin(cgo,GL_TRIANGLE_STRIP);
  ShapeNormal(cgo,LKP,3);
  ShapeVertex(cgo,REL,1);
  ShapeVertex(cgo,REL,3);
  ShapeNormal(cgo,LKP,2);
  ShapeVertex(cgo,REL,5);
  ShapeVertex(cgo,REL,7);
  CGOEnd(cgo);

  /* right */
  CGOBegin(cgo,GL_TRIANGLE_STRIP);
  ShapeNormal(cgo,LKP,2);
  ShapeVertex(cgo,REL,6);
  ShapeVertex(cgo,REL,8);
  ShapeNormal(cgo,LKP,0);
  ShapeVertex(cgo,REL,2);
  ShapeVertex(cgo,REL,4);
  CGOEnd(cgo);


  CGOStop(cgo);

  CGOFree(gs->ShapeCGO);
  gs->ShapeCGO = cgo;

#ifndef _PYMOL_NOPY
  CGOPreloadFonts(gs->ShapeCGO);
#endif

  cgo = CGONewSized(I->Gadget.Obj.G,100);
  CGODotwidth(cgo,5);
  CGOPickColor(cgo,0,cPickableGadget);

  /* top */
  CGOBegin(cgo,GL_TRIANGLE_STRIP);
  ShapeVertex(cgo,REL,1);
  ShapeVertex(cgo,REL,2);
  ShapeVertex(cgo,REL,5);
  ShapeVertex(cgo,REL,6);

  CGOEnd(cgo);

  /* bottom */

  CGOBegin(cgo,GL_TRIANGLE_STRIP);
  ShapeVertex(cgo,REL,3);
  ShapeVertex(cgo,REL,4);
  ShapeVertex(cgo,REL,7);
  ShapeVertex(cgo,REL,8);
  CGOEnd(cgo);

  /* left */

  CGOBegin(cgo,GL_TRIANGLE_STRIP);
  ShapeVertex(cgo,REL,1);
  ShapeVertex(cgo,REL,3);
  ShapeVertex(cgo,REL,5);
  ShapeVertex(cgo,REL,7);
  CGOEnd(cgo);

  /* right */
  CGOBegin(cgo,GL_TRIANGLE_STRIP);
  ShapeVertex(cgo,REL,6);
  ShapeVertex(cgo,REL,8);
  ShapeVertex(cgo,REL,2);
  ShapeVertex(cgo,REL,4);
  CGOEnd(cgo);

  /* band */

  CGOPickColor(cgo,13,cPickableGadget);
  CGOBegin(cgo,GL_TRIANGLE_STRIP);
  ShapeVertex(cgo,REL,5);
  ShapeVertex(cgo,REL,6);
  ShapeVertex(cgo,REL,7);
  ShapeVertex(cgo,REL,8);
  CGOEnd(cgo);
  
  CGOStop(cgo);

  CGOFree(gs->PickShapeCGO);
  gs->PickShapeCGO = cgo;
}

static void ObjectGadgetRampBuild(ObjectGadgetRamp *I)
{
  GadgetSet *gs = NULL;
  ObjectGadget *og;
  int a;

  float coord[100];
  int ix=0;

  float normal[] = {
    1.0, 0.0, 0.1,
    0.0, 1.0, 0.1,
    0.0, 0.0, 1.0,
   -1.0, 0.0, 0.1,
    0.0,-1.0, 0.1,
  };
#define VV(a,b,c) {coord[ix++]=a;coord[ix++]=b;coord[ix++]=c;};

VV(    I->x ,  I->y , 0.3F );

    /* outer points */

VV(    0.0 ,  0.0 , 0.0 );
    VV(I->width+I->border*2 ,  0.0 , 0.0 );
VV(    0.0 , -(I->height+I->border*2) , 0.0 );
VV(    I->width+I->border*2 , -(I->height+I->border*2) , 0.0 );

VV(    I->border, -I->border, I->border);
VV(    I->width+I->border,-I->border, I->border);
VV(    I->border,  -(I->height+I->border), I->border);
VV(    I->width+I->border, -(I->height+I->border), I->border);

VV(    I->border, -(I->border+I->bar_height), I->border);
VV(    I->width+I->border,-(I->border+I->bar_height), I->border);
    
VV(    I->border+I->text_border, I->text_border-(I->border+I->height), I->border+I->text_raise);
VV(    I->width+I->border,I->text_border-(I->border+I->height), I->border+I->text_raise);

 VV(   0.0,0.0,0.0);
#undef VV

  OrthoBusyPrime(I->Gadget.Obj.G);

  og = &I->Gadget;
  gs = GadgetSetNew(I->Gadget.Obj.G);

  gs->NCoord = 14;
  I->var_index = gs->NCoord;
  gs->Coord = VLAlloc(float,gs->NCoord*3);
  for(a=0;a<gs->NCoord*3;a++) {
    gs->Coord[a]=coord[a];
  }

  gs->NNormal = 5;
  gs->Normal = VLAlloc(float,gs->NNormal*3);
  for(a=0;a<gs->NNormal;a++) {
    copy3f(normal+3*a,gs->Normal+3*a);
    normalize3f(gs->Normal+3*a);
  }


  og->GSet[0] = gs;
  og->NGSet = 1;
  og->Obj.Context=1; /* unit window */
  gs->Obj = (ObjectGadget*)I;
  gs->State = 0;

  
  ObjectGadgetRampUpdateCGO(I,gs);
  gs->fUpdate(gs);

}

/*========================================================================*/
void ObjectGadgetRampUpdate(ObjectGadgetRamp *I)
{
  float scale;

  if(I->Gadget.Changed) {
    scale = (1.0F+5*I->Gadget.GSet[0]->Coord[13*3]);
    
    I->Gadget.GSet[0]->Coord[13*3] = 0.0;
    switch(I->RampType) {
    case cRampMol:
      {
        int a;
        for(a=0;a<I->NLevel;a++) {
          I->Level[a]=I->Level[a]*scale;
        }
        ExecutiveInvalidateRep(I->Gadget.Obj.G,cKeywordAll,cRepAll,cRepInvColor);
      }
      break;
    default:
      if(I->NLevel==2) {
        {
          float mean = (I->Level[0]+I->Level[1])/2.0F;
          I->Level[0]=(I->Level[0]-mean)*scale+mean;
          I->Level[2]=(I->Level[1]-mean)*scale+mean;
          ExecutiveInvalidateRep(I->Gadget.Obj.G,cKeywordAll,cRepAll,cRepInvColor);
        }
        break;
      } else if(I->NLevel==3) {
        I->Level[0]=(I->Level[0]-I->Level[1])*scale+I->Level[1];
        I->Level[2]=(I->Level[2]-I->Level[1])*scale+I->Level[1];
        ExecutiveInvalidateRep(I->Gadget.Obj.G,cKeywordAll,cRepAll,cRepInvColor);
      }
    }
    if(I->Gadget.NGSet)
      if(I->Gadget.GSet[0]) {
        ObjectGadgetRampUpdateCGO(I,I->Gadget.GSet[0]);
        ObjectGadgetUpdateStates(&I->Gadget);
      }
    ObjectGadgetUpdateExtents(&I->Gadget);
    I->Gadget.Changed=false;
    SceneChanged(I->Gadget.Obj.G);
  }
}

static int ObjectGadgetRampHandleInputColors(ObjectGadgetRamp *I)
{
  int ok=true;
  if(I->NLevel<1) {
    I->Level=VLASetSize(I->Level,1);
    I->NLevel = 1;
    I->Level[0] = 0.0F;
  }
  if(ok&&I->Color) { /* handle cases where number of colors doesn't make expectation */
    int n_color = VLAGetSize(I->Color)/3;

    if(!n_color) {
      I->Color = VLASetSize(I->Color,3);
      I->Color[0] = I->Color[1] = I->Color[2] = 1.0F;
      n_color++;
    }

    if(n_color<I->NLevel) {
      I->Color = VLASetSize(I->Color,3*I->NLevel);
      while(n_color<I->NLevel) {
        float *v0 = I->Color + 3*(n_color-1);
        float *v1 = v0+3;
        copy3f(v0,v1);
        n_color++;
      }
    } else if(n_color>I->NLevel) {
      I->Extreme = VLAlloc(float,6); /* above/below extreme values */
      if(I->Extreme) {
        if(n_color==I->NLevel+1) { /* upper extreme only */
          copy3f(I->Color,I->Extreme);
          copy3f(I->Color+3*I->NLevel,I->Extreme+3);
        } else { /* both extremes */
          copy3f(I->Color+(3*I->NLevel),I->Extreme);
          copy3f(I->Color+(3*I->NLevel)+3,I->Extreme+3);
        }
      }
      I->Color = VLASetSize(I->Color,3*I->NLevel);
    }
  }
  if(ok && I->Color && I->NLevel) { /* detect default coloring as negative R */
    I->Special = VLACalloc(int,I->NLevel+2);
    if(I->Special&&I->Color) {
      int a;
      for(a=0;a<I->NLevel;a++) {
        if(I->Color[a*3]<0.0F) {
          I->Special[a] = (int)I->Color[a*3];
        }
      }
      if(I->Extreme) { /* Extremes */
        for(a=0;a<2;a++) {
          if(I->Extreme[a*3]<0.0F) { /* is red negative? then color is special */ 
            I->Special[I->NLevel+a] = (int)I->Extreme[a*3];
          }
        }
      } 
    }
  }
  
  return ok;
}


/*========================================================================*/
ObjectGadgetRamp *ObjectGadgetRampMapNewAsDefined(PyMOLGlobals *G,
                                                  ObjectMap *map,
                                                  float *level_vla,
                                                  float *color_vla,int map_state,
                                                  float *vert_vla,float beyond,float within,
                                                  float sigma,int zero,int calc_mode)
{


  ObjectGadgetRamp *I;
  int ok = true;
  I = ObjectGadgetRampNew(G);
  I->RampType = cRampMap;

  if(ok) I->Color = color_vla;
  if(ok) I->CalcMode = calc_mode;

  if(ok) {     
    ObjectMapState *ms;
    float tmp_level[3];
    if(map_state<0)
      map_state = 0;
    if(vert_vla && 
       (ms = ObjectMapGetState(map,map_state))) {
      if(ObjectMapStateGetExcludedStats(G,ms,vert_vla,beyond,within,tmp_level)) {
        tmp_level[0]=tmp_level[1]+(tmp_level[0]-tmp_level[1])*sigma;
        tmp_level[2]=tmp_level[1]+(tmp_level[2]-tmp_level[1])*sigma;
        if(zero) {
          if(tmp_level[1]<0.0F) {
            tmp_level[1]=0.0F;
            tmp_level[2]=-tmp_level[0];
          } else if(tmp_level[1]>0.0F) {
            tmp_level[1]=0.0F;
            tmp_level[0]=-tmp_level[2];
          }
        }
      }
      I->Level = VLAlloc(float,3);
      copy3f(tmp_level,I->Level);
      VLAFreeP(level_vla);
    } else  {
      I->Level = level_vla;
    }
  }
  if(ok) I->NLevel=VLAGetSize(I->Level);
  if(ok) ok = ObjectGadgetRampHandleInputColors(I);
  ObjectGadgetRampBuild(I);
  UtilNCopy(I->SrcName,map->Obj.Name,WordLength);
  I->SrcState=map_state;
  
  /* test interpolate 
     { 
    float test[3];

    ObjectGadgetRampInterpolate(I,-2.0,test);
    dump3f(test,"test color");
    ObjectGadgetRampInterpolate(I,-1.0,test);
    dump3f(test,"test color");
    ObjectGadgetRampInterpolate(I,-0.9,test);
    dump3f(test,"test color");
    ObjectGadgetRampInterpolate(I,-0.5,test);
    dump3f(test,"test color");
    ObjectGadgetRampInterpolate(I,0.0,test);
    dump3f(test,"test color");
    ObjectGadgetRampInterpolate(I,0.5,test);
    dump3f(test,"test color");
    ObjectGadgetRampInterpolate(I,1.0,test);
    dump3f(test,"test color");
    ObjectGadgetRampInterpolate(I,2.0,test);
    dump3f(test,"test color");
  }
  */
  return(I);

}

/*========================================================================*/
ObjectGadgetRamp *ObjectGadgetRampMolNewAsDefined(PyMOLGlobals *G,ObjectMolecule *mol,
                                                  float *level_vla,
                                                  float *color_vla,
                                                  int mol_state, int calc_mode)
{

  ObjectGadgetRamp *I;
  int ok = true;

  I = ObjectGadgetRampNew(G);
  if(mol) 
    I->RampType = cRampMol;
  else
    I->RampType = cRampNone;
  if(ok) I->Color = color_vla;
  if(ok) I->CalcMode = calc_mode;
  if(ok) I->Level = level_vla;
  if(ok) I->NLevel=VLAGetSize(I->Level);
  if(ok) ok = ObjectGadgetRampHandleInputColors(I);
  
  if(ok && I->Level && I->NLevel) {
    int a;
    float last = I->Level[0];
    for(a=1;a<I->NLevel;a++) {
      if(I->Level[a]<last)
        I->Level[a] = last;
      last = I->Level[a];
    }
  }
  
  ObjectGadgetRampBuild(I);
  if(mol) {
    UtilNCopy(I->SrcName,mol->Obj.Name,WordLength);
  } else {
    UtilNCopy(I->SrcName,"none",WordLength);
  }
  I->SrcState=mol_state;
  return(I);
}


static void ObjectGadgetRampInvalidate(ObjectGadgetRamp *I,int rep,int level,int state)
{
  I->Gadget.Changed=true;
}

/*========================================================================*/
ObjectGadgetRamp *ObjectGadgetRampNew(PyMOLGlobals *G)
{
  OOAlloc(G,ObjectGadgetRamp);

  ObjectGadgetInit(G,&I->Gadget);
  I->Gadget.GadgetType = cGadgetRamp;
  I->RampType = 0;
  I->NLevel = 0;
  I->Level = NULL;
  I->Color = NULL;
  I->Special = NULL;
  I->Extreme = NULL;
  I->SrcName[0] = 0;

  I->Gadget.Obj.fUpdate =(void (*)(CObject *)) ObjectGadgetRampUpdate;
  I->Gadget.Obj.fFree =(void (*)(CObject *)) ObjectGadgetRampFree;
  I->Gadget.Obj.fInvalidate = (void (*)(CObject *,int,int,int)) ObjectGadgetRampInvalidate;

  I->Mol = NULL;
  I->Map = NULL;
  I->width = 0.9F;
  I->height = 0.06F;
  I->bar_height = 0.03F;
  I->text_raise = 0.003F;
  I->text_border = 0.004F;
  I->text_scale_h = 0.04F;
  I->text_scale_v = 0.02F;
  I->border = 0.018F;
  I->var_index = 0;
  I->x = (1.0F-(I->width+2*I->border))/2.0F;
  I->y = 0.12F;
  I->Map = NULL;
  I->CalcMode = 0;
  return(I);
}


Generated by  Doxygen 1.6.0   Back to index