Back to index

salome-gui  6.5.0
Plot2d_AnalyticalParser.cxx
Go to the documentation of this file.
00001 // Copyright (C) 2007-2012  CEA/DEN, EDF R&D, OPEN CASCADE
00002 //
00003 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
00004 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
00005 //
00006 // This library is free software; you can redistribute it and/or
00007 // modify it under the terms of the GNU Lesser General Public
00008 // License as published by the Free Software Foundation; either
00009 // version 2.1 of the License.
00010 //
00011 // This library is distributed in the hope that it will be useful,
00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014 // Lesser General Public License for more details.
00015 //
00016 // You should have received a copy of the GNU Lesser General Public
00017 // License along with this library; if not, write to the Free Software
00018 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
00019 //
00020 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
00021 //
00022 //  File   : Plot2d_AnalyticalParser.cxx
00023 //  Author : Roman NIKOLAEV, Open CASCADE S.A.S. (roman.nikolaev@opencascade.com)
00024 #include "Plot2d_AnalyticalParser.h"
00025 #include <structmember.h>
00026 
00027 
00028 /* ==================================
00029  * ===========  PYTHON ==============
00030  * ==================================*/
00031 
00032 typedef struct {
00033   PyObject_HEAD
00034   int softspace;
00035   std::string *out;
00036   } PyStdOut;
00037 
00038 static void
00039 PyStdOut_dealloc(PyStdOut *self)
00040 {
00041   PyObject_Del(self);
00042 }
00043 
00044 static PyObject *
00045 PyStdOut_write(PyStdOut *self, PyObject *args)
00046 {
00047   char *c;
00048   int l;
00049   if (!PyArg_ParseTuple(args, "t#:write",&c, &l))
00050     return NULL;
00051 
00052   //std::cerr << c ;
00053   *(self->out)=*(self->out)+c;
00054 
00055   Py_INCREF(Py_None);
00056   return Py_None;
00057 }
00058 
00059 static PyMethodDef PyStdOut_methods[] = {
00060   {"write",  (PyCFunction)PyStdOut_write,  METH_VARARGS,
00061     PyDoc_STR("write(string) -> None")},
00062   {NULL,    NULL}   /* sentinel */
00063 };
00064 
00065 static PyMemberDef PyStdOut_memberlist[] = {
00066   {(char*)"softspace", T_INT,  offsetof(PyStdOut, softspace), 0,
00067    (char*)"flag indicating that a space needs to be printed; used by print"},
00068   {NULL} /* Sentinel */
00069 };
00070 
00071 static PyTypeObject PyStdOut_Type = {
00072   /* The ob_type field must be initialized in the module init function
00073    * to be portable to Windows without using C++. */
00074   PyObject_HEAD_INIT(NULL)
00075   0,                            /*ob_size*/
00076   "PyOut",                      /*tp_name*/
00077   sizeof(PyStdOut),             /*tp_basicsize*/
00078   0,                            /*tp_itemsize*/
00079   /* methods */
00080   (destructor)PyStdOut_dealloc, /*tp_dealloc*/
00081   0,                            /*tp_print*/
00082   0,                            /*tp_getattr*/
00083   0,                            /*tp_setattr*/
00084   0,                            /*tp_compare*/
00085   0,                            /*tp_repr*/
00086   0,                            /*tp_as_number*/
00087   0,                            /*tp_as_sequence*/
00088   0,                            /*tp_as_mapping*/
00089   0,                            /*tp_hash*/
00090   0,                            /*tp_call*/
00091   0,                            /*tp_str*/
00092   PyObject_GenericGetAttr,      /*tp_getattro*/
00093   /* softspace is writable:  we must supply tp_setattro */
00094   PyObject_GenericSetAttr,      /* tp_setattro */
00095   0,                            /*tp_as_buffer*/
00096   Py_TPFLAGS_DEFAULT,           /*tp_flags*/
00097   0,                            /*tp_doc*/
00098   0,                            /*tp_traverse*/
00099   0,                            /*tp_clear*/
00100   0,                            /*tp_richcompare*/
00101   0,                            /*tp_weaklistoffset*/
00102   0,                            /*tp_iter*/
00103   0,                            /*tp_iternext*/
00104   PyStdOut_methods,             /*tp_methods*/
00105   PyStdOut_memberlist,          /*tp_members*/
00106   0,                            /*tp_getset*/
00107   0,                            /*tp_base*/
00108   0,                            /*tp_dict*/
00109   0,                            /*tp_descr_get*/
00110   0,                            /*tp_descr_set*/
00111   0,                            /*tp_dictoffset*/
00112   0,                            /*tp_init*/
00113   0,                            /*tp_alloc*/
00114   0,                            /*tp_new*/
00115   0,                            /*tp_free*/
00116   0,                            /*tp_is_gc*/
00117 };
00118 
00119 PyObject * newPyStdOut( std::string& out )
00120 {
00121   PyStdOut *self;
00122   self = PyObject_New(PyStdOut, &PyStdOut_Type);
00123   if (self == NULL)
00124     return NULL;
00125   self->softspace = 0;
00126   self->out=&out;
00127   return (PyObject*)self;
00128 }
00129 
00130 
00132 
00133 
00135 Plot2d_AnalyticalParser* Plot2d_AnalyticalParser::myParser = 0;
00136 
00137 //Define the script
00138 QString Plot2d_AnalyticalParser::myScript = QString("");
00139 
00144 Plot2d_AnalyticalParser* Plot2d_AnalyticalParser::parser()
00145 {
00146   if ( !myParser )
00147     myParser = new Plot2d_AnalyticalParser();
00148   return myParser;
00149 }
00150 
00156 Plot2d_AnalyticalParser::Plot2d_AnalyticalParser() 
00157 {
00158   /* Initialize the Python interpreter */
00159   if (Py_IsInitialized()) {
00160     PyGILState_STATE gstate = PyGILState_Ensure();
00161     myMainMod = PyImport_AddModule("__main__");
00162     myMainDict = PyModule_GetDict(myMainMod);
00163     PyGILState_Release(gstate);
00164     initScript();
00165   }
00166 }
00167 
00168 int Plot2d_AnalyticalParser::calculate( const QString& theExpr,
00169                                   const double theMin,
00170                                   const double theMax,
00171                                   const int theNbStep,
00172                                   double** theX,
00173                                   double** theY) {
00174   
00175   QString aPyScript = myScript;
00176   aPyScript = aPyScript.arg(theExpr);
00177   int result = -1;
00178   PyGILState_STATE gstate = PyGILState_Ensure();
00179   PyObject* obj = PyRun_String(qPrintable(aPyScript), Py_file_input, myMainDict, NULL);
00180 
00181   if(obj == NULL) {
00182     PyErr_Print();
00183     PyGILState_Release(gstate);        
00184     return result;
00185     
00186   } else {
00187     Py_DECREF(obj);
00188   }
00189   
00190   PyObject* func = NULL;
00191   PyObject* f_y = NULL;
00192   
00193   if(PyObject_HasAttrString(myMainMod, "Y")) {
00194     f_y = PyObject_GetAttrString(myMainMod, "Y");
00195   }
00196 
00197   if(PyObject_HasAttrString(myMainMod, "coordCalculator")) {
00198     func = PyObject_GetAttrString(myMainMod, "coordCalculator");
00199   }
00200 
00201   PyObject* new_stderr = NULL;
00202   
00203   if( f_y == NULL || func == NULL )  {
00204     fflush(stderr);
00205     std::string err_description="";
00206     new_stderr = newPyStdOut(err_description);
00207     PySys_SetObject((char*)"stderr", new_stderr);
00208     PyErr_Print();
00209     PySys_SetObject((char*)"stderr", PySys_GetObject((char*)"__stderr__"));
00210     Py_DECREF(new_stderr);
00211     PyGILState_Release(gstate);
00212     return result;
00213   }
00214     
00215   PyObject* coords;
00216   coords = PyObject_CallFunction(func,(char*)"(d, d, i)", theMin, theMax, theNbStep );
00217 
00218   new_stderr = NULL;
00219   
00220   if (coords == NULL){
00221     fflush(stderr);
00222     std::string err_description="";
00223     new_stderr = newPyStdOut(err_description);
00224     PySys_SetObject((char*)"stderr", new_stderr);
00225     PyErr_Print();
00226     PySys_SetObject((char*)"stderr", PySys_GetObject((char*)"__stderr__"));
00227     Py_DECREF(new_stderr);
00228     PyGILState_Release(gstate);
00229     return result;
00230   }
00231 
00232   Py_ssize_t size = PyList_Size( coords );
00233   if( size <= 0 ) {
00234     Py_DECREF(coords);
00235     return result;
00236   }
00237 
00238   result = size;
00239 
00240   *theX = new double[size];
00241   *theY = new double[size];
00242   
00243   for ( Py_ssize_t i = 0; i< size; ++i ) {
00244     PyObject* coord = PyList_GetItem( coords, i );
00245     (*theX)[i] =  PyFloat_AsDouble(PyList_GetItem(coord, 0));
00246     (*theY)[i] =  PyFloat_AsDouble(PyList_GetItem(coord, 1));
00247   }
00248 
00249   PyGILState_Release(gstate);
00250   return result;
00251 }
00252 
00256 void Plot2d_AnalyticalParser::initScript() {
00257   myScript.clear();
00258   myScript += "from math import *                      \n";
00259   myScript += "def Y(x):                               \n";
00260   myScript += "    return ";
00261   myScript += "%1\n";
00262 
00263   myScript += "def coordCalculator(xmin, xmax, nstep):     \n";
00264   myScript += "   coords = []                              \n";
00265   myScript += "   xstep  = (xmax - xmin) / nstep           \n";
00266   myScript += "   n = 0                                    \n";
00267   myScript += "   while n <= nstep :                       \n";
00268   myScript += "      x = xmin + n*xstep                    \n";
00269   myScript += "      try:                                  \n";
00270   myScript += "                    y = Y(x)                           \n";
00271   myScript += "                    coords.append([x,y])               \n";
00272   myScript += "      except ValueError, ZeroDivisionError: \n";
00273   myScript += "                    pass                               \n";
00274   myScript += "      n = n+1                               \n";
00275   myScript += "   return coords                            \n";
00276 }