1 // Copyright (C) 2007-2008 CEA/DEN, EDF R&D, OPEN CASCADE
3 // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License.
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 // Lesser General Public License for more details.
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
22 // VISU OBJECT : interactive object for VISU entities implementation
27 #include "VISU_TableReader.hxx"
33 #include <QStringList>
39 #include <vtkPoints.h>
40 #include <vtkDoubleArray.h>
41 #include <vtkPointData.h>
42 #include <vtkCellData.h>
43 #include <vtkPolyData.h>
45 #include <vtkStructuredGrid.h>
46 #include <vtkStructuredGridGeometryFilter.h>
49 static int MYDEBUG = 0;
51 static int MYDEBUG = 0;
55 //---------------------------------------------------------------
63 int iEnd = myRows[0].myValues.size();
67 if ( myColumnTitles.size() != iEnd )
68 myColumnTitles.resize( iEnd );
70 if ( myColumnUnits.size() != iEnd )
71 myColumnUnits.resize( iEnd );
73 int jEnd = myRows.size();
74 for ( int j = 0; j < jEnd; j++ )
75 if ( myRows[j].myValues.size() != iEnd )
82 //---------------------------------------------------------------
85 ::getColumns(VISU::TTable2D& theTable2D) const
87 TRows& aRows = theTable2D.myRows;
92 int jEnd = myRows.size();
94 //Define Titles & Units
95 theTable2D.myColumnTitles.resize(jEnd);
96 theTable2D.myColumnUnits.resize(jEnd);
97 for ( int j = 0; j < jEnd; j++ ) {
98 theTable2D.myColumnTitles[j] = myRows[j].myTitle;
99 theTable2D.myColumnUnits[j] = myRows[j].myUnit;
103 int iEnd = myRows[0].myValues.size();
104 for ( int i = 0; i < iEnd; i++ ) {
106 aNewRow.myTitle = myColumnTitles[i];
107 aNewRow.myUnit = myColumnUnits[i];
108 aNewRow.myValues.resize(jEnd);
109 for ( int j = 0; j < jEnd; j++ ) {
110 aNewRow.myValues[j] = myRows[j].myValues[i];
112 aRows.push_back(aNewRow);
117 //---------------------------------------------------------------
120 int getLine( std::ifstream& theStmIn, QString& theString )
123 std::ostrstream aStrOut;
125 while ( theStmIn.get( tmp ) ) {
132 theString = aStrOut.str();
134 return !theStmIn.eof();
139 //---------------------------------------------------------------
141 VISU::ImportTables( const char* theFileName, TTableContainer& theContainer )
143 std::ifstream aStmIn;
144 QFileInfo aFileInfo( theFileName );
145 if( !aFileInfo.isFile() || !aFileInfo.isReadable() || !aFileInfo.size() )
148 aStmIn.open( theFileName );
151 // find beginning of table (tables are separated by empty lines)
152 while( ::getLine( aStmIn, aTmp ) && aTmp.trimmed() == "");
154 PTableIDMapper aTableIDMapper( new TTableIDMapper() );
155 TTable2D& aTable2D = *aTableIDMapper;
156 if(MYDEBUG) std::cout << "New table is found" << std::endl;
158 while( !aStmIn.eof() && aTmp.trimmed() != "" ){
159 QString data = aTmp.trimmed();
161 QString keyword = "";
162 // split string to data and comment (comment starts from '#' symbol)
163 int index = aTmp.indexOf( "#" );
165 data = aTmp.left( index ).trimmed();
166 cmt = aTmp.mid( index+1 ).trimmed();
168 // if comment is not empty, try to get keyword from it (separated by ':' symbol)
169 if ( !cmt.isEmpty() ) {
170 int index1 = cmt.indexOf( ":" );
172 QString tmpstr = cmt.left( index1 ).trimmed();
173 if ( tmpstr == QString( "TITLE" ) ||
174 tmpstr == QString( "COLUMN_TITLES" ) ||
175 tmpstr == QString( "COLUMN_UNITS" ) ||
176 tmpstr == QString( "COMMENT" ) ) {
178 cmt = cmt.mid( index1+1 ).trimmed();
182 // if data is empty, process only comment
183 if ( data.isEmpty() ) {
184 // if keyword is found, try to process it
185 // elsewise it is a simple comment, just ignore it
186 if ( !keyword.isEmpty() ) {
187 if ( keyword == QString( "TITLE" ) ) {
189 if ( aTable2D.myTitle != "" )
190 title = QString( aTable2D.myTitle.c_str() ) + QString( " " ) + title;
191 if(MYDEBUG) std::cout << "...Table TITLE is: " << title.toLatin1().constData() << std::endl;
192 aTable2D.myTitle = title.toLatin1().constData();
194 else if ( keyword == QString( "COLUMN_TITLES" ) ) {
195 // comment may contain column headers
196 QStringList aStrList = cmt.split( "|", QString::SkipEmptyParts );
197 if(MYDEBUG) std::cout << "...Column TITLES are: ";
198 for ( int i = 0; i < aStrList.count(); i++ ) {
199 QString tmpstr = aStrList[ i ].trimmed();
200 if(MYDEBUG) std::cout << tmpstr.toLatin1().constData() << " ";
201 aTable2D.myColumnTitles.push_back( tmpstr.toLatin1().constData() );
203 if(MYDEBUG) std::cout << std::endl;
205 else if ( keyword == QString( "COLUMN_UNITS" ) ) {
206 // comment may contain column units
207 QStringList aStrList = cmt.split( " ", QString::SkipEmptyParts );
208 if(MYDEBUG) std::cout << "...Column UNITS are: ";
209 for ( int i = 0; i < aStrList.count(); i++ ) {
210 QString tmpstr = aStrList[ i ].trimmed();
211 if(MYDEBUG) std::cout << tmpstr.toLatin1().constData() << " ";
212 aTable2D.myColumnUnits.push_back( tmpstr.toLatin1().constData() );
214 if(MYDEBUG) std::cout << std::endl;
216 else if ( keyword == QString( "COMMENT" ) ) {
217 // keyword 'COMMENT' processing can be here
218 // currently it is ignored
219 if(MYDEBUG) std::cout << "...COMMENT: " << cmt.toLatin1().constData() << std::endl;
223 if(MYDEBUG) std::cout << "...comment: " << cmt.toLatin1().constData() << std::endl;
224 // simple comment processing can be here
225 // currently it is ignored
228 // if data is not empty, try to process it
231 if(MYDEBUG) std::cout << "...New row is found: " << std::endl;
232 if ( !cmt.isEmpty() ) {
233 aRow.myTitle = cmt.toLatin1().constData();
234 if(MYDEBUG) std::cout << "......ROW TITLE is: " << cmt.toLatin1().constData() << std::endl;
236 QString datar1 = data.replace(QRegExp("\t"), " ");
237 QStringList aValList = datar1.split( " ", QString::SkipEmptyParts );
238 for ( int i = 0; i < aValList.count(); i++ ) {
239 if ( aValList[i].trimmed() != "" ) {
240 TTable2D::TValue aVal = aValList[i].trimmed().toLatin1().constData();
241 aRow.myValues.push_back( aVal );
244 if( aRow.myValues.size() > 0 )
245 aTable2D.myRows.push_back( aRow );
246 // ************** OLD CODE ******************
249 istrstream aStream( data );
250 aStream.precision( STRPRECISION );
251 while( aStream >> aVal ) {
252 aRow.myValues.push_back( aVal );
254 if( aRow.myValues.size() > 0 )
255 aTable2D.myRows.push_back( aRow );
257 // ************** OLD CODE ******************
259 ::getLine( aStmIn, aTmp );
261 if( aTable2D.Check() ) {
262 if(MYDEBUG) std::cout << "aTable2D is checked OK " << aTable2D.myTitle << std::endl;
263 theContainer.push_back( aTableIDMapper );
265 } while ( !aStmIn.eof() );
268 if(MYDEBUG) std::cout << "After close" << std::endl;
272 //---------------------------------------------------------------
275 myOutput( vtkPolyData::New() ),
276 myXAxisPosition( -1 )
287 ::GetPolyDataOutput()
289 if ( myXAxisPosition == -1 )
290 SetXAxisPosition( 0 );
299 return myOutput->GetActualMemorySize() * 1024;
304 ::SetXAxisPosition( vtkIdType theAxisPosition )
306 if ( myXAxisPosition == theAxisPosition || !Check() )
309 myOutput->Initialize();
315 getColumns( aTable2D );
317 vtkIdType aXSize = aTable2D.myRows[0].myValues.size();
319 // It is necessary to decrease the size at 1 take intoa account X axis
320 vtkIdType anYSize = aTable2D.myRows.size() - 1;
322 vtkIdType aNbPoints = aXSize * anYSize;
324 std::vector<double> anXAxis(aXSize);
325 const TTable2D::TValues& aValues = aTable2D.myRows[theAxisPosition].myValues;
326 for ( vtkIdType aX = 0; aX < aXSize; aX++ )
327 anXAxis[aX] = atof( aValues[aX].c_str() );
329 double aXRange = anXAxis[aXSize - 1] - anXAxis[0];
330 double anYDelta = aXRange / anYSize;
331 std::vector<double> anYAxis(anYSize);
332 for ( vtkIdType anY = 0; anY < anYSize; anY++ )
333 anYAxis[anY] = anY * anYDelta;
335 vtkPoints* aPoints = vtkPoints::New();
336 aPoints->SetNumberOfPoints( aNbPoints );
338 vtkIntArray *aPointsIDMapper = vtkIntArray::New();
339 aPointsIDMapper->SetName("VISU_POINTS_MAPPER");
340 aPointsIDMapper->SetNumberOfComponents(2);
341 aPointsIDMapper->SetNumberOfTuples(aNbPoints);
342 int *aPointsIDMapperPtr = aPointsIDMapper->GetPointer(0);
344 //vtkIntArray *aCellIDMapper = vtkIntArray::New();
345 //aCellIDMapper->SetName("VISU_POINTS_MAPPER");
346 //aCellIDMapper->SetNumberOfComponents(2);
347 //aCellIDMapper->SetNumberOfTuples(aNbPoints);
348 //int *aCellIDMapperPtr = aCellIDMapper->GetPointer(0);
350 for ( vtkIdType aY = 0, aPntId = 0; aY < anYSize; aY++ ) {
351 for ( vtkIdType aX = 0; aX < aXSize; aX++, aPntId++ ) {
352 aPoints->SetPoint( aPntId, anXAxis[aX], anYAxis[aY], 0.0 );
354 *aPointsIDMapperPtr++ = aPntId;
355 *aPointsIDMapperPtr++ = 0;
357 //*aCellIDMapperPtr++ = aPntId;
358 //*aCellIDMapperPtr++ = 0;
362 std::vector<TValues> anYData;
363 for ( vtkIdType anY = 0; anY < anYSize + 1; anY++ ) {
364 if ( anY == theAxisPosition )
366 anYData.push_back( aTable2D.myRows[anY].myValues );
369 vtkDoubleArray* aScalars = vtkDoubleArray::New();
370 aScalars->SetNumberOfComponents( 1 );
371 aScalars->SetNumberOfTuples( aNbPoints );
372 double *aScalarsPtr = aScalars->GetPointer(0);
373 for ( vtkIdType anY = 0; anY < anYSize; anY++ ) {
374 const TTable2D::TValues& aValues = anYData[anY];
375 for ( vtkIdType aX = 0; aX < aXSize; aX++ ) {
376 double aValue = atof( aValues[aX].c_str() );
377 *aScalarsPtr++ = aValue;
381 vtkStructuredGrid* aStructuredGrid = vtkStructuredGrid::New();
382 aStructuredGrid->SetPoints( aPoints );
385 aStructuredGrid->SetDimensions( aXSize, anYSize, 1 );
387 aStructuredGrid->GetPointData()->AddArray( aPointsIDMapper );
388 aPointsIDMapper->Delete();
390 //aStructuredGrid->GetCellData()->AddArray( aCellIDMapper );
391 //aCellIDMapper->Delete();
393 aStructuredGrid->GetPointData()->SetScalars( aScalars );
396 vtkStructuredGridGeometryFilter* aFilter = vtkStructuredGridGeometryFilter::New();
397 aFilter->SetInput( aStructuredGrid );
399 myOutput->ShallowCopy( aFilter->GetOutput() );