Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members   Related Pages  

py_graphics.C

Go to the documentation of this file.
00001 /***************************************************************************
00002  *cr
00003  *cr            (C) Copyright 1995-2011 The Board of Trustees of the
00004  *cr                        University of Illinois
00005  *cr                         All Rights Reserved
00006  *cr
00007  ***************************************************************************/
00008 
00009 /***************************************************************************
00010  * RCS INFORMATION:
00011  *
00012  *      $RCSfile: py_graphics.C,v $
00013  *      $Author: johns $        $Locker:  $             $State: Exp $
00014  *      $Revision: 1.24 $       $Date: 2011/02/01 16:46:37 $
00015  *
00016  ***************************************************************************
00017  * DESCRIPTION:
00018  *  Python interface to user-provided graphics objects
00019  ***************************************************************************/
00020 
00021 #include "py_commands.h"
00022 #include "Molecule.h"
00023 #include "MoleculeList.h"
00024 #include "MaterialList.h"
00025 #include "VMDApp.h"
00026 #include "Scene.h"
00027 #include "MoleculeGraphics.h"
00028 
00029 // helper function to get a molecule.  Raises a ValueError exception on error
00030 static MoleculeGraphics *mol_from_id(int id) {
00031   VMDApp *app = get_vmdapp();
00032   MoleculeList *mlist = app->moleculeList;
00033   Molecule *mol = mlist->mol_from_id(id);
00034   if (!mol) {
00035     PyErr_SetString(PyExc_ValueError, (char *)"Invalid graphics molecule");
00036     return NULL;
00037   }
00038   return mol->moleculeGraphics();
00039 }
00040  
00041 // 
00042 // the rest of the commands define graphics primitives.  They all take an
00043 // id as the first argument, and optional keyword arguments to define the
00044 // the properties of the primitive
00045 //  
00046 
00047 // triangle: three vertices as tuples
00048 static PyObject *graphics_triangle(PyObject *self, PyObject *args) {
00049   int id;
00050   PyObject *v1, *v2, *v3;
00051   float arr1[3], arr2[3], arr3[3];
00052  
00053   if (!PyArg_ParseTuple(args, (char *)"iOOO:graphics.triangle", &id, &v1, &v2, &v3))
00054     return NULL;
00055  
00056   MoleculeGraphics *mol = mol_from_id(id);
00057   if (!mol)
00058     return NULL;
00059  
00060   if (!py_array_from_obj(v1, arr1) ||
00061       !py_array_from_obj(v2, arr2) ||
00062       !py_array_from_obj(v3, arr3)) 
00063      return NULL;
00064 
00065   
00066   int result = mol->add_triangle(arr1, arr2, arr3);
00067   return PyInt_FromLong(result);
00068 }
00069 
00070 // trinorm: three vertices, followed by three normals
00071 static PyObject *graphics_trinorm(PyObject *self, PyObject *args) {
00072   int id;
00073   PyObject *v1, *v2, *v3, *n1, *n2, *n3;
00074   float vert1[3], vert2[3], vert3[3], norm1[3], norm2[3], norm3[3];
00075 
00076   if (!PyArg_ParseTuple(args, (char *)"iOOOOOO:graphics.trinorm", &id, &v1, &v2, &v3, &n1, &n2, &n3))
00077     return NULL;
00078   
00079   MoleculeGraphics *mol = mol_from_id(id);
00080   if (!mol)
00081     return NULL;
00082 
00083   if (!py_array_from_obj(v1, vert1) ||
00084       !py_array_from_obj(v2, vert2) ||
00085       !py_array_from_obj(v3, vert3) ||
00086       !py_array_from_obj(n1, norm1) ||
00087       !py_array_from_obj(n2, norm2) ||
00088       !py_array_from_obj(n2, norm3)) 
00089     return NULL;
00090 
00091   int result = mol->add_trinorm(vert1,vert2,vert3,norm1,norm2,norm3);
00092   return PyInt_FromLong(result);
00093 }
00094 
00095 // cylinder: require two vertices
00096 // optional keywords, radius, resolution, filled
00097 static PyObject *graphics_cylinder(PyObject *self, PyObject *args, PyObject *keywds) {
00098   int id;
00099   PyObject *v1, *v2;
00100   float radius = 1.0;
00101   int resolution = 6;
00102   int filled = 0;
00103   float vert1[3], vert2[3];
00104 
00105   static char *kwlist[] = {
00106     (char *)"id", (char *)"v1", (char *)"v2", (char *)"radius",
00107     (char *)"resolution", (char *)"filled", NULL
00108   };
00109 
00110   if (!PyArg_ParseTupleAndKeywords(args, keywds, (char *)"iOO|fii:graphics.cylinder", kwlist,
00111     &id, &v1, &v2, &radius, &resolution, &filled))
00112     return NULL;
00113 
00114   MoleculeGraphics *mol = mol_from_id(id);
00115   if (!mol) 
00116     return NULL;
00117    
00118   if (!py_array_from_obj(v1, vert1) ||
00119       !py_array_from_obj(v2, vert2))
00120     return NULL;
00121 
00122   int result = mol->add_cylinder(vert1, vert2, (float)radius, resolution, 
00123                                  filled);
00124   return PyInt_FromLong(result);
00125 }
00126 
00127 // point: one vertex
00128 static PyObject *graphics_point(PyObject *self, PyObject *args) {
00129   int id;
00130   PyObject *v;
00131   float vert[3];
00132   
00133   if (!PyArg_ParseTuple(args, (char *)"iO:graphics.point", &id, &v))
00134     return NULL;
00135 
00136   MoleculeGraphics *mol = mol_from_id(id);
00137   if (!mol) 
00138     return NULL;
00139   
00140   if (!py_array_from_obj(v, vert))
00141     return NULL;
00142 
00143   int result = mol->add_point(vert);
00144   return PyInt_FromLong(result);
00145 }
00146 
00147 // line: two vertices
00148 // optional: style = "solid" | "dashed"
00149 //           width is an integer
00150 static PyObject *graphics_line(PyObject *self, PyObject *args, PyObject *keywds) {
00151   int id;
00152   PyObject *v1, *v2;
00153   float vert1[3], vert2[3];
00154   int width = 1;
00155   char *style = NULL;
00156   int line_style = ::SOLIDLINE;
00157 
00158   static char *kwlist[] = {
00159     (char *)"id", (char *)"v1", (char *)"v2", (char *)"style", (char *)"width",
00160     NULL
00161   };
00162 
00163   if (!PyArg_ParseTupleAndKeywords(args, keywds, (char *)"iOO|si:graphics.line", kwlist,
00164     &id, &v1, &v2, &style, &width))
00165     return NULL; 
00166 
00167   MoleculeGraphics *mol = mol_from_id(id);
00168   if (!mol) 
00169     return NULL;
00170  
00171   if (!py_array_from_obj(v1, vert1) ||
00172       !py_array_from_obj(v2, vert2))
00173     return NULL;
00174 
00175   if (style) {
00176     if (!strcmp(style, "solid"))
00177       line_style = ::SOLIDLINE;
00178     else if (!strcmp(style, "dashed"))
00179       line_style = ::DASHEDLINE;
00180     else {
00181       PyErr_SetString(PyExc_ValueError, (char *)"invalid line style");
00182       return NULL;
00183     }
00184   }
00185   
00186   // don't check the line width; I don't know what values different display 
00187   // devices will accept
00188   int result = mol->add_line(vert1, vert2, line_style, width);
00189   return PyInt_FromLong(result);
00190 }
00191 
00192 // materials: this just turns materials on or off.  Takes an integer
00193 static PyObject *graphics_materials(PyObject *self, PyObject *args) {
00194   int id;
00195   int onoff;
00196   
00197   if (!PyArg_ParseTuple(args, (char *)"ii:graphics.materials", &id, &onoff))
00198     return NULL;
00199 
00200   MoleculeGraphics *mol = mol_from_id(id);
00201   if (!mol) 
00202     return NULL;
00203  
00204   int result = mol->use_materials(onoff);
00205   return PyInt_FromLong(result);
00206 }
00207 
00208 // material(name)
00209 static PyObject *graphics_material(PyObject *self, PyObject *args) {
00210   int id;
00211   char *name;
00212   if (!PyArg_ParseTuple(args, (char *)"is:graphics.material", &id, &name))
00213      return NULL;
00214 
00215   MoleculeGraphics *mol = mol_from_id(id);
00216   if (!mol)
00217     return NULL;
00218 
00219   MaterialList *mlist = get_vmdapp()->materialList;
00220   int matindex = mlist->material_index(name);
00221   if (matindex < 0) {
00222     PyErr_SetString(PyExc_ValueError, (char *)"Invalid material name");
00223     return NULL;
00224   }
00225   int result = mol->use_material(mlist->material(matindex));
00226   return PyInt_FromLong(result);
00227 }
00228    
00229 // colors: Takes one argument, either a tuple of three floats, a string 
00230 // color name, or an integer color index 
00231 static PyObject *graphics_color(PyObject *self, PyObject *args) {
00232   int id;
00233   PyObject *obj;
00234   int result = -1;
00235   
00236   if (!PyArg_ParseTuple(args, (char *)"iO:graphics.color", &id, &obj))
00237     return NULL;
00238 
00239   MoleculeGraphics *mol = mol_from_id(id);
00240   if (!mol) 
00241     return NULL;
00242   
00243   if (PyInt_Check(obj)) {
00244     int index = PyInt_AsLong(obj);
00245     if (index >= 0 && index < MAXCOLORS) 
00246       result = mol->use_color(index);
00247 
00248   } else if (PyString_Check(obj)) { 
00249     char *name = PyString_AsString(obj);
00250     VMDApp *app = get_vmdapp();
00251     int index = app->color_index(name);
00252     if (index >= 0) 
00253       result = mol->use_color(index);
00254   }
00255 
00256   if (result >= 0)
00257     return PyInt_FromLong(result);
00258 
00259   PyErr_SetString(PyExc_ValueError, (char *)"Invalid color");
00260   return NULL;
00261 }  
00262 
00263 // cone: just like cylinder, except that it's always filled
00264 static PyObject *graphics_cone(PyObject *self, PyObject *args, PyObject *keywds) {
00265   int id;
00266   PyObject *v1, *v2;
00267   float radius = 1.0;
00268   float radius2 = 0.0;
00269   int resolution = 6;
00270   float vert1[3], vert2[3];
00271 
00272   static char *kwlist[] = {
00273     (char *)"id", (char *)"v1", (char *)"v2", (char *)"radius",
00274     (char *)"resolution", NULL
00275   };
00276 
00277   if (!PyArg_ParseTupleAndKeywords(args, keywds, (char *)"iOO|fi:graphics.cone", kwlist,
00278     &id, &v1, &v2, &radius, &resolution))
00279     return NULL;
00280 
00281   MoleculeGraphics *mol = mol_from_id(id);
00282   if (!mol)
00283     return NULL;
00284   
00285   if (!py_array_from_obj(v1, vert1) ||
00286       !py_array_from_obj(v2, vert2))
00287     return NULL;
00288 
00289   int result = mol->add_cone(vert1, vert2, (float)radius, (float)radius2, resolution);
00290   return PyInt_FromLong(result);
00291 }
00292 
00293 // sphere: center (tuple), radius (float), resolution (integer)
00294 static PyObject *graphics_sphere(PyObject *self, PyObject *args, PyObject *keywds) {
00295   
00296   int id;
00297   PyObject *center = NULL;
00298   float radius = 1;    // default value
00299   int resolution = 6;  // default value
00300   float arr[3];        // default will be 0,0,0
00301 
00302   static char *kwlist[] = {
00303     (char *)"id",(char *)"center", (char *)"radius", (char *)"resolution", NULL
00304   };
00305 
00306   if (!PyArg_ParseTupleAndKeywords(args, keywds, (char *)"i|Ofi:graphics.sphere", kwlist,
00307     &id, &center, &radius, &resolution))
00308     return NULL;
00309       
00310   MoleculeGraphics *mol = mol_from_id(id);
00311   if (!mol) 
00312     return NULL;
00313 
00314   if (center == NULL) {
00315     // no center set, so use 0,0,0
00316     arr[0] = arr[1] = arr[2] = 0.0f;
00317   } else {
00318     // try to get center from the passed in object
00319     if (!py_array_from_obj(center, arr))   
00320       return NULL;
00321   }
00322   int result = mol->add_sphere(arr, radius, resolution);
00323   return PyInt_FromLong(result);
00324 }
00325 
00326 // text: requires position and string arguments
00327 // optional: keyword argument size = float
00328 static PyObject *graphics_text(PyObject *self, PyObject *args, PyObject *keywds) {
00329   int id;
00330   PyObject *v;
00331   float arr[3];
00332   char *text;
00333   float size = 1.0f;
00334 
00335   static char *kwlist[] = {
00336     (char *)"id", (char *)"pos", (char *)"text", (char *)"size", NULL
00337   };
00338 
00339   if (!PyArg_ParseTupleAndKeywords(args, keywds, (char *)"iOs|f:graphics.text", kwlist,
00340     &id, &v, &text, &size))
00341     return NULL;
00342 
00343   MoleculeGraphics *mol = mol_from_id(id);
00344   if (!mol) 
00345     return NULL;
00346   
00347   if (!py_array_from_obj(v, arr))
00348     return NULL;
00349 
00350   int result = mol->add_text(arr, text, size, 1.0f);
00351   return PyInt_FromLong(result);
00352 }
00353 
00354 // delete: takes either an integer argument, which is the index to delete,
00355 // or a string argument "all", which deletes everything
00356 // returns nothing
00357 static PyObject *graphics_delete(PyObject *self, PyObject *args) {
00358   int id;
00359   PyObject *obj;
00360   
00361   if (!PyArg_ParseTuple(args, (char *)"iO:graphics.delete", &id, &obj))
00362     return NULL;
00363 
00364   MoleculeGraphics *mol = mol_from_id(id);
00365   if (!mol) 
00366     return NULL;
00367 
00368   if (PyInt_Check(obj)) {
00369     int index = PyInt_AsLong(obj);
00370     mol->delete_id(index);
00371   } else if (PyString_Check(obj)) {
00372     char *s = PyString_AsString(obj);
00373     if (!strcmp(s, "all")) 
00374       mol->delete_all();
00375     else {
00376       PyErr_SetString(PyExc_ValueError, (char *)"delete: invalid value");
00377       return NULL;
00378     }
00379   }
00380 
00381   Py_INCREF(Py_None);
00382   return Py_None;
00383 }
00384 
00385 // replace: delete the given id and have the next element replace this one
00386 static PyObject *graphics_replace(PyObject *self, PyObject *args) {
00387   int id;
00388   int index;
00389 
00390   if (!PyArg_ParseTuple(args, (char *)"ii:graphics.replace", &id, &index))
00391     return NULL;
00392 
00393   MoleculeGraphics *mol = mol_from_id(id);
00394   if (!mol) 
00395     return NULL;
00396    
00397   mol->replace_id(index);
00398 
00399   Py_INCREF(Py_None);
00400   return Py_None;
00401 }
00402 
00403 // info: return a string describing the graphics object with the given index
00404 // if out of range, or the object no longer exists, raise IndexError 
00405 static PyObject *graphics_info(PyObject *self, PyObject *args) {
00406   int id;
00407   int index;
00408 
00409   if (!PyArg_ParseTuple(args, (char *)"ii:graphics.info", &id, &index))
00410     return NULL;
00411 
00412   MoleculeGraphics *mol = mol_from_id(id);
00413   if (!mol) 
00414     return NULL;
00415 
00416   if (mol->index_id(index) == -1) {
00417     PyErr_SetString(PyExc_IndexError, "Invalid graphics object");
00418     return NULL;
00419   } 
00420   const char *info = mol->info_id(index);
00421   return PyString_FromString(info);
00422 }
00423  
00424 // list: return a list of the valid graphics objects
00425 static PyObject *graphics_listall(PyObject *self, PyObject *args) {
00426   int id;
00427   
00428   if (!PyArg_ParseTuple(args, (char *)"i:graphics.listall", &id))
00429     return NULL;
00430 
00431   MoleculeGraphics *mol = mol_from_id(id);
00432   if (!mol) 
00433     return NULL;
00434 
00435   PyObject *newlist = PyList_New(0);
00436   int num = mol->num_elements();
00437   for (int i=0; i<num; i++) {
00438     int index = mol->element_id(i);
00439     if (index >= 0) {
00440       if (PyList_Append(newlist, PyInt_FromLong(index)) < 0)  
00441         return NULL;
00442     }
00443   }
00444   return newlist;
00445 }
00446 
00447 static PyMethodDef GraphicsMethods[] = {
00448   {(char *)"sphere", (PyCFunction)graphics_sphere,METH_VARARGS | METH_KEYWORDS},
00449   {(char *)"triangle",(vmdPyMethod)graphics_triangle,METH_VARARGS},
00450   {(char *)"trinorm",(vmdPyMethod)graphics_trinorm,METH_VARARGS},
00451   {(char *)"cylinder", (PyCFunction)graphics_cylinder,METH_VARARGS | METH_KEYWORDS},
00452   {(char *)"point",(vmdPyMethod)graphics_point,METH_VARARGS},
00453   {(char *)"line", (PyCFunction)graphics_line,METH_VARARGS | METH_KEYWORDS},
00454   {(char *)"materials",(vmdPyMethod)graphics_materials,METH_VARARGS},
00455   {(char *)"material",(vmdPyMethod)graphics_material,METH_VARARGS},
00456   {(char *)"color",(vmdPyMethod)graphics_color,METH_VARARGS},
00457   {(char *)"cone", (PyCFunction)graphics_cone,METH_VARARGS | METH_KEYWORDS},
00458   {(char *)"sphere", (PyCFunction)graphics_sphere,METH_VARARGS | METH_KEYWORDS},
00459   {(char *)"text", (PyCFunction)graphics_text,METH_VARARGS | METH_KEYWORDS},
00460   {(char *)"delete",(vmdPyMethod)graphics_delete,METH_VARARGS},
00461   {(char *)"replace",(vmdPyMethod)graphics_replace,METH_VARARGS},
00462   {(char *)"info",(vmdPyMethod)graphics_info,METH_VARARGS},
00463   {(char *)"listall",(vmdPyMethod)graphics_listall,METH_VARARGS},
00464   {NULL, NULL}
00465 };
00466 
00467 void initgraphics() {
00468   (void) Py_InitModule((char *)"graphics", GraphicsMethods);
00469 }
00470  

Generated on Sun May 27 01:59:00 2012 for VMD (current) by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002