1 // Copyright (C) 2021 CEA/DEN, EDF R&D
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 // Lesser General Public License for more details.
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
20 #include "vtkContactReader.h"
22 #include <vtkArrowSource.h>
23 #include <vtkCellArray.h>
24 #include <vtkCellData.h>
25 #include <vtkDelimitedTextReader.h>
26 #include <vtkDoubleArray.h>
27 #include <vtkErrorCode.h>
28 #include <vtkInformation.h>
29 #include <vtkInformationVector.h>
30 #include <vtkIntArray.h>
32 #include <vtkObjectFactory.h>
33 #include <vtkPointData.h>
34 #include <vtkPolyData.h>
35 #include <vtkPVGlyphFilter.h>
36 #include <vtkStreamingDemandDrivenPipeline.h>
38 #include <vtkVariant.h>
39 #include <vtkVariantArray.h>
48 constexpr char INST_TAG[] = "INST";
50 class MyException : public std::exception
53 MyException(const char *what) : _what(what) {}
54 MyException(const std::string &what) : _what(what) {}
55 ~MyException() throw() {}
56 const char *what() const throw() { return _what.c_str(); }
66 AutoPtr(T *ptr = 0) : _ptr(ptr) {}
67 ~AutoPtr() { destroyPtr(); }
68 bool isNull() const { return _ptr == 0; }
69 bool isNotNull() const { return !isNull(); }
70 AutoPtr &operator=(T *ptr)
79 T *operator->() { return _ptr; }
80 const T *operator->() const { return _ptr; }
81 T &operator*() { return *_ptr; }
82 const T &operator*() const { return *_ptr; }
83 operator T *() { return _ptr; }
84 operator const T *() const { return _ptr; }
87 void destroyPtr() { delete[] _ptr; }
93 bool PresenceOf(const std::vector<std::string> &arr, const std::string &what)
95 auto pos = std::find(arr.begin(), arr.end(), what);
96 return pos!=arr.end();
99 vtkIdType PosOf(const std::vector<std::string> &arr, const std::string &what)
101 auto pos = std::find(arr.begin(), arr.end(), what);
102 if (pos == arr.end())
104 std::ostringstream oss;
105 oss << "vtkContactReader::PosOf : Fail to locate \"" << what << "\" in array !";
106 throw MyException(oss.str());
108 return std::distance(arr.begin(), pos);
111 double InstValueOf(vtkTable *table, vtkIdType iRow, vtkIdType iCol)
113 vtkVariantArray *row(table->GetRow(iRow));
114 vtkVariant *elt(row->GetPointer(iCol));
115 return elt->ToDouble();
118 vtkSmartPointer<vtkTable> LoadDataFromFile(const char *FileName)
120 vtkNew<vtkDelimitedTextReader> reader;
121 reader->SetFileName(FileName);
122 reader->SetDetectNumericColumns(true);
123 reader->SetUseStringDelimiter(true);
124 reader->SetHaveHeaders(true);
125 reader->SetFieldDelimiterCharacters(" ");
126 reader->SetAddTabFieldDelimiter(true);
127 reader->SetMergeConsecutiveDelimiters(true);
129 vtkTable *table(reader->GetOutput());
130 vtkSmartPointer<vtkTable> ret(table);
134 std::vector<std::string> GetColumnNames(vtkTable *table)
136 vtkIdType nbCols(table->GetNumberOfColumns());
137 std::vector<std::string> colNames(nbCols);
138 for (vtkIdType iCol = 0; iCol < nbCols; iCol++)
140 colNames[iCol] = table->GetColumnName(iCol);
145 void FillValue(vtkVariantArray *row, double *ptToFeed, std::size_t ipos, vtkIdType pos)
148 vtkVariant *elt(row->GetPointer(pos));
149 ptToFeed[ipos] = elt->ToDouble(&isOK);
152 std::ostringstream oss;
153 oss << "vtkContactReader::FillValue : Error during analyze content of file ! Float64 expected !";
154 throw MyException(oss.str());
158 vtkStandardNewMacro(vtkContactReader);
160 vtkContactReader::vtkContactReader() : FileName(NULL), ScaleFactor(0.02),IsTimed(false)
162 this->SetNumberOfInputPorts(0);
165 vtkContactReader::~vtkContactReader()
169 int vtkContactReader::RequestInformation(vtkInformation *vtkNotUsed(request),
170 vtkInformationVector **vtkNotUsed(inputVector),
171 vtkInformationVector *outputVector)
173 vtkInformation *outInfo(outputVector->GetInformationObject(0));
175 vtkSmartPointer<vtkTable> table(LoadDataFromFile(this->FileName));
176 std::vector<std::string> colNames(GetColumnNames(table));
177 this->IsTimed = PresenceOf(colNames,INST_TAG);
178 vtkIdType nbRows(table->GetNumberOfRows());
181 vtkIdType InstPos = PosOf(colNames, INST_TAG);
182 std::set<double> allInsts;
183 for (vtkIdType iRow = 0; iRow < nbRows; iRow++)
185 vtkVariantArray *row(table->GetRow(iRow));
186 vtkVariant *elt(row->GetPointer(InstPos));
187 allInsts.insert(elt->ToDouble());
189 std::vector<double> allInstsV(allInsts.begin(),allInsts.end());
191 timeRange[0]=allInstsV.front();
192 timeRange[1]=allInstsV.back();
193 outInfo->Set(vtkStreamingDemandDrivenPipeline::TIME_STEPS(),allInstsV.data(),(int)allInstsV.size());
194 outInfo->Set(vtkStreamingDemandDrivenPipeline::TIME_RANGE(),timeRange,2);
195 std::for_each(colNames.begin(),colNames.end(),[](const std::string& elt) { std::cerr << elt << " ";});
200 int vtkContactReader::RequestData(vtkInformation *vtkNotUsed(request),
201 vtkInformationVector **vtkNotUsed(inputVector),
202 vtkInformationVector *outputVector)
204 vtkInformation *outInfo(outputVector->GetInformationObject(0));
205 vtkPolyData *output(vtkPolyData::SafeDownCast(outInfo->Get(vtkDataObject::DATA_OBJECT())));
209 vtkSmartPointer<vtkTable> table(LoadDataFromFile(this->FileName));
210 vtkIdType nbRows(table->GetNumberOfRows()), nbCols(table->GetNumberOfColumns());
211 std::vector<std::string> colNames(GetColumnNames(table));
212 vtkIdType XPos(PosOf(colNames, "X")), YPos(PosOf(colNames, "Y")), ZPos(PosOf(colNames, "Z")), DXPos(PosOf(colNames, "DX")), DYPos(PosOf(colNames, "DY")), DZPos(PosOf(colNames, "DZ"));
213 // check of presence of INST. If yes -> it means that input file is on different time steps.
214 vtkIdType InstPos(std::numeric_limits<vtkIdType>::max());
216 vtkSmartPointer<vtkDoubleArray> coords(vtkSmartPointer<vtkDoubleArray>::New()), vectArr(vtkSmartPointer<vtkDoubleArray>::New());
218 vtkIdType nbTuples(nbRows),startRow(0);
222 InstPos = PosOf(colNames, INST_TAG);
223 if(outInfo->Has(vtkStreamingDemandDrivenPipeline::UPDATE_TIME_STEP()))
224 reqTS=outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_TIME_STEP());
226 for (; iRow < nbRows && InstValueOf(table,iRow,InstPos)!=reqTS; iRow++);
228 for (; iRow < nbRows && InstValueOf(table,iRow,InstPos)==reqTS; iRow++);
229 nbTuples = iRow-startRow;
232 vectArr->SetNumberOfComponents(3);
233 coords->SetNumberOfComponents(3);
234 coords->SetNumberOfTuples(nbTuples);
235 vectArr->SetNumberOfTuples(nbTuples);
236 double *ptToFeed1(coords->Begin()), *ptToFeed2(vectArr->Begin());
237 const vtkIdType POS[3] = {XPos, YPos, ZPos}, DX[3] = {DXPos, DYPos, DZPos};
238 for (vtkIdType iRow = startRow; iRow < startRow+nbTuples; iRow++, ptToFeed1 += 3, ptToFeed2 += 3)
240 vtkVariantArray *row(table->GetRow(iRow));
241 for (std::size_t ipos = 0; ipos < 3; ipos++)
243 FillValue(row, ptToFeed1, ipos, POS[ipos]);
244 FillValue(row, ptToFeed2, ipos, DX[ipos]);
246 std::for_each(ptToFeed2, ptToFeed2 + 3, [](double &v) { v = -v; });
248 vectArr->SetName("Resultante");
249 vtkNew<vtkPolyData> ret;
250 vtkSmartPointer<vtkPoints> pts(vtkSmartPointer<vtkPoints>::New());
251 pts->SetData(coords);
253 ret->GetPointData()->AddArray(vectArr);
255 vtkNew<vtkPVGlyphFilter> glyph;
256 glyph->SetInputData(ret);
257 glyph->SetGlyphMode(0); //vtkPVGlyphFilter::ALL_POINTS
258 glyph->SetVectorScaleMode(0); //vtkPVGlyphFilter::SCALE_BY_MAGNITUDE
260 vtkNew<vtkArrowSource> arrow;
261 arrow->SetTipResolution(6);
262 arrow->SetTipRadius(0.1);
263 arrow->SetTipLength(0.35);
264 arrow->SetShaftResolution(6);
265 arrow->SetShaftRadius(0.03);
266 glyph->SetSourceConnection(arrow->GetOutputPort());
267 //idx,port,connection,fieldAssociation,name
268 glyph->SetInputArrayToProcess(0, 0, 0, vtkDataObject::FIELD_ASSOCIATION_POINTS, "Resultante"); //idx==0 -> scaleArray
269 glyph->SetInputArrayToProcess(1, 0, 0, vtkDataObject::FIELD_ASSOCIATION_POINTS, "Resultante"); //idx==1 -> orientationArray
270 glyph->SetScaleFactor(this->ScaleFactor);
272 output->ShallowCopy(glyph->GetOutput());
274 output->GetInformation()->Set(vtkDataObject::DATA_TIME_STEP(),reqTS);
275 output->GetPointData()->SetActiveAttribute(0, vtkDataSetAttributes::SCALARS);
276 //output->ShallowCopy(ret);
278 catch (MyException &e)
280 vtkErrorMacro(<< "vtkContactReader::RequestData : during read of " << this->FileName << " : " << e.what());
286 void vtkContactReader::SetScaleFactor(double newScaleFactor)
288 if (this->ScaleFactor != newScaleFactor)
290 this->ScaleFactor = newScaleFactor;
295 void vtkContactReader::PrintSelf(ostream &os, vtkIndent indent)
297 this->Superclass::PrintSelf(os, indent);