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);
199 int vtkContactReader::RequestData(vtkInformation *vtkNotUsed(request),
200 vtkInformationVector **vtkNotUsed(inputVector),
201 vtkInformationVector *outputVector)
203 vtkInformation *outInfo(outputVector->GetInformationObject(0));
204 vtkPolyData *output(vtkPolyData::SafeDownCast(outInfo->Get(vtkDataObject::DATA_OBJECT())));
208 vtkSmartPointer<vtkTable> table(LoadDataFromFile(this->FileName));
209 vtkIdType nbRows(table->GetNumberOfRows()), nbCols(table->GetNumberOfColumns());
210 std::vector<std::string> colNames(GetColumnNames(table));
211 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"));
212 // check of presence of INST. If yes -> it means that input file is on different time steps.
213 vtkIdType InstPos(std::numeric_limits<vtkIdType>::max());
215 vtkSmartPointer<vtkDoubleArray> coords(vtkSmartPointer<vtkDoubleArray>::New()), vectArr(vtkSmartPointer<vtkDoubleArray>::New());
217 vtkIdType nbTuples(nbRows),startRow(0);
221 InstPos = PosOf(colNames, INST_TAG);
222 if(outInfo->Has(vtkStreamingDemandDrivenPipeline::UPDATE_TIME_STEP()))
223 reqTS=outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_TIME_STEP());
225 for (; iRow < nbRows && InstValueOf(table,iRow,InstPos)!=reqTS; iRow++);
227 for (; iRow < nbRows && InstValueOf(table,iRow,InstPos)==reqTS; iRow++);
228 nbTuples = iRow-startRow;
231 vectArr->SetNumberOfComponents(3);
232 coords->SetNumberOfComponents(3);
233 coords->SetNumberOfTuples(nbTuples);
234 vectArr->SetNumberOfTuples(nbTuples);
235 double *ptToFeed1(coords->Begin()), *ptToFeed2(vectArr->Begin());
236 const vtkIdType POS[3] = {XPos, YPos, ZPos}, DX[3] = {DXPos, DYPos, DZPos};
237 for (vtkIdType iRow = startRow; iRow < startRow+nbTuples; iRow++, ptToFeed1 += 3, ptToFeed2 += 3)
239 vtkVariantArray *row(table->GetRow(iRow));
240 for (std::size_t ipos = 0; ipos < 3; ipos++)
242 FillValue(row, ptToFeed1, ipos, POS[ipos]);
243 FillValue(row, ptToFeed2, ipos, DX[ipos]);
245 std::for_each(ptToFeed2, ptToFeed2 + 3, [](double &v) { v = -v; });
247 vectArr->SetName("Resultante");
248 vtkNew<vtkPolyData> ret;
249 vtkSmartPointer<vtkPoints> pts(vtkSmartPointer<vtkPoints>::New());
250 pts->SetData(coords);
252 ret->GetPointData()->AddArray(vectArr);
254 vtkNew<vtkPVGlyphFilter> glyph;
255 glyph->SetInputData(ret);
256 glyph->SetGlyphMode(0); //vtkPVGlyphFilter::ALL_POINTS
257 glyph->SetVectorScaleMode(0); //vtkPVGlyphFilter::SCALE_BY_MAGNITUDE
259 vtkNew<vtkArrowSource> arrow;
260 arrow->SetTipResolution(6);
261 arrow->SetTipRadius(0.1);
262 arrow->SetTipLength(0.35);
263 arrow->SetShaftResolution(6);
264 arrow->SetShaftRadius(0.03);
265 glyph->SetSourceConnection(arrow->GetOutputPort());
266 //idx,port,connection,fieldAssociation,name
267 glyph->SetInputArrayToProcess(0, 0, 0, vtkDataObject::FIELD_ASSOCIATION_POINTS, "Resultante"); //idx==0 -> scaleArray
268 glyph->SetInputArrayToProcess(1, 0, 0, vtkDataObject::FIELD_ASSOCIATION_POINTS, "Resultante"); //idx==1 -> orientationArray
269 glyph->SetScaleFactor(this->ScaleFactor);
271 output->ShallowCopy(glyph->GetOutput());
273 output->GetInformation()->Set(vtkDataObject::DATA_TIME_STEP(),reqTS);
274 output->GetPointData()->SetActiveAttribute(0, vtkDataSetAttributes::SCALARS);
275 //output->ShallowCopy(ret);
277 catch (MyException &e)
279 vtkErrorMacro(<< "vtkContactReader::RequestData : during read of " << this->FileName << " : " << e.what());
285 void vtkContactReader::SetScaleFactor(double newScaleFactor)
287 if (this->ScaleFactor != newScaleFactor)
289 this->ScaleFactor = newScaleFactor;
294 void vtkContactReader::PrintSelf(ostream &os, vtkIndent indent)
296 this->Superclass::PrintSelf(os, indent);