Fraxinus  16.5.0-fx-rc9
An IGT application
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
cxMesh.cpp
Go to the documentation of this file.
1 /*=========================================================================
2 This file is part of CustusX, an Image Guided Therapy Application.
3 
4 Copyright (c) 2008-2014, SINTEF Department of Medical Technology
5 All rights reserved.
6 
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions are met:
9 
10 1. Redistributions of source code must retain the above copyright notice,
11  this list of conditions and the following disclaimer.
12 
13 2. Redistributions in binary form must reproduce the above copyright notice,
14  this list of conditions and the following disclaimer in the documentation
15  and/or other materials provided with the distribution.
16 
17 3. Neither the name of the copyright holder nor the names of its contributors
18  may be used to endorse or promote products derived from this software
19  without specific prior written permission.
20 
21 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
25 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 =========================================================================*/
32 
33 
34 #include "cxMesh.h"
35 
36 #include <vtkCellArray.h>
37 #include <vtkColorSeries.h>
38 #include <vtkPolyData.h>
39 #include <vtkPolyDataWriter.h>
40 #include <vtkPointData.h>
41 #include <QDomDocument>
42 #include <QColor>
43 #include <QDir>
44 #include "cxTypeConversions.h"
46 #include "cxBoundingBox3D.h"
47 #include "cxDataReaderWriter.h"
48 
49 namespace cx
50 {
51 
52 MeshPtr Mesh::create(const QString& uid, const QString& name)
53 {
54  return MeshPtr(new Mesh(uid, name));
55 }
56 
57 Mesh::Mesh(const QString& uid, const QString& name) :
58  Data(uid, name), mVtkPolyData(vtkPolyDataPtr::New()), mWireframe(false), mBackfaceCulling(false), mFrontfaceCulling(false),mHasGlyph(false), mOrientationArray(""), mColorArray(""),mVisSize(2.0)
59 {
60  mColor = QColor(255, 0, 0, 255);
61  mShowGlyph = shouldGlyphBeEnableByDefault();
62  mGlyphLUT ="Citrus";
63  this->setAcquisitionTime(QDateTime::currentDateTime());
64 }
65 Mesh::Mesh(const QString& uid, const QString& name, const vtkPolyDataPtr& polyData) :
66  Data(uid, name), mVtkPolyData(polyData), mWireframe(false), mBackfaceCulling(false), mFrontfaceCulling(false),mHasGlyph(false), mOrientationArray(""), mColorArray(""),mVisSize(2.0)
67 {
68  mColor = QColor(255, 0, 0, 255);
69  mShowGlyph = shouldGlyphBeEnableByDefault();
70  mGlyphLUT ="Citrus";
71  this->setAcquisitionTime(QDateTime::currentDateTime());
72 }
74 {
75 }
76 
77 void Mesh::setIsWireframe(bool on)
78 {
79  mWireframe = on;
80  emit meshChanged();
81 }
83 {
84  return mWireframe;
85 }
86 
87 bool Mesh::load(QString path)
88 {
89  vtkPolyDataPtr raw;
90  raw = DataReaderWriter().loadVtkPolyData(path);
91  if(raw)
92  {
93  this->setVtkPolyData(raw);
94  this->setName(QFileInfo(path).baseName());
95  this->setFilename(path); // need path even when not set explicitly: nice for testing
96  }
97  return raw!=0;
98 }
99 
101 {
102  mVtkPolyData = polyData;
103  mOrientationArrayList.clear();
104  mColorArrayList.clear();
105 
106  int num;
107  for(int k=0; k < mVtkPolyData->GetPointData()->GetNumberOfArrays(); k++)
108  {
109  num=mVtkPolyData->GetPointData()->GetArray(k)->GetNumberOfComponents();
110  if(num==3)
111  {
112  if(strlen(mOrientationArray.c_str())==0)
113  {
114  mOrientationArray=mVtkPolyData->GetPointData()->GetArrayName(k);
115  mHasGlyph=true;
116  }
117  mOrientationArrayList << mVtkPolyData->GetPointData()->GetArrayName(k);
118  }
119  }
120  mColorArrayList << "";
121  mColorArray="";
122  for(int k=0; k < mVtkPolyData->GetPointData()->GetNumberOfArrays(); k++)
123  {
124  num=mVtkPolyData->GetPointData()->GetArray(k)->GetNumberOfComponents();
125  if(num==1)
126  {
127  mColorArrayList << mVtkPolyData->GetPointData()->GetArrayName(k);
128  }
129  }
130  mShowGlyph = shouldGlyphBeEnableByDefault();
131 
132  emit meshChanged();
133 }
135 {
136  return mVtkPolyData;
137 }
138 void Mesh::addXml(QDomNode& dataNode)
139 {
140  Data::addXml(dataNode);
141  QDomDocument doc = dataNode.ownerDocument();
142 
143  QDomNode meshNode = dataNode;
144 
145  QDomElement colorNode = doc.createElement("color");
146  QDomElement subNode = doc.createElement("red");
147  subNode.appendChild(doc.createTextNode(string_cast(mColor.red()).c_str()));
148  colorNode.appendChild(subNode);
149  subNode = doc.createElement("green");
150  subNode.appendChild(doc.createTextNode(string_cast(mColor.green()).c_str()));
151  colorNode.appendChild(subNode);
152  subNode = doc.createElement("blue");
153  subNode.appendChild(doc.createTextNode(string_cast(mColor.blue()).c_str()));
154  colorNode.appendChild(subNode);
155  subNode = doc.createElement("alpha");
156  subNode.appendChild(doc.createTextNode(string_cast(mColor.alpha()).c_str()));
157  colorNode.appendChild(subNode);
158  meshNode.appendChild(colorNode);
159 
160  QDomElement cullingNode = doc.createElement("culling");
161  QDomElement elem = cullingNode.toElement();
162  elem.setAttribute("backfaceCulling", mBackfaceCulling);
163  elem.setAttribute("frontfaceCulling", mFrontfaceCulling);
164  meshNode.appendChild(cullingNode);
165 
166  QDomElement glyphNode = doc.createElement("glyph");
167  QDomElement elemGlyph = glyphNode.toElement();
168  elemGlyph.setAttribute("showGlyph", mShowGlyph);
169  elemGlyph.setAttribute("orientationArray", mOrientationArray.c_str());
170  elemGlyph.setAttribute("colorArray", mColorArray.c_str());
171  elemGlyph.setAttribute("glyphLUT", mGlyphLUT.c_str());
172  elemGlyph.setAttribute("glyphVisSize", mVisSize);
173  meshNode.appendChild(elemGlyph);
174 
175 }
176 
177 void Mesh::parseXml(QDomNode& dataNode)
178 {
179  Data::parseXml(dataNode);
180 
181  // image node must be parsed in the data manager to create this Image object
182  // Only subnodes are parsed here
183 
184  if (dataNode.isNull())
185  return;
186 
187  // QDomNode registrationHistory = dataNode.namedItem("registrationHistory");
188  // m_rMd_History->parseXml(registrationHistory);
189 
190  QDomNode colorNode = dataNode.namedItem("color");
191  if (!colorNode.isNull())
192  {
193  int red = 255;
194  int green = 255;
195  int blue = 255;
196  int alpha = 255;
197 
198  QDomNode node = colorNode.namedItem("red");
199  if (!node.isNull())
200  red = node.toElement().text().toInt();
201 
202  node = colorNode.namedItem("green");
203  if (!node.isNull())
204  green = node.toElement().text().toInt();
205 
206  node = colorNode.namedItem("blue");
207  if (!node.isNull())
208  blue = node.toElement().text().toInt();
209 
210  node = colorNode.namedItem("alpha");
211  if (!node.isNull())
212  alpha = node.toElement().text().toInt();
213 
214  mColor = QColor(red, green, blue, alpha);
215  }
216 
217  QDomNode cullingNode = dataNode.namedItem("culling");
218  if (!cullingNode.isNull())
219  {
220  mBackfaceCulling = cullingNode.toElement().attribute("backfaceCulling").toInt();
221  mFrontfaceCulling = cullingNode.toElement().attribute("frontfaceCulling").toInt();
222  }
223 
224  QDomNode glyphNode = dataNode.namedItem("glyph");
225  if (!glyphNode.isNull())
226  {
227  mShowGlyph = glyphNode.toElement().attribute("showGlyph").toInt();
228  mOrientationArray = glyphNode.toElement().attribute("orientationArray").toStdString();
229  mColorArray = glyphNode.toElement().attribute("colorArray").toStdString();
230  mGlyphLUT = glyphNode.toElement().attribute("glyphLUT").toStdString();
231  mVisSize = glyphNode.toElement().attribute("glyphVisSize").toDouble();
232  }
233 
234  emit meshChanged();
235 }
236 
237 void Mesh::setColor(const QColor& color)
238 {
239  mColor = color;
240  emit meshChanged();
241 }
242 
244 {
245  return mColor;
246 }
247 
248 void Mesh::setBackfaceCullingSlot(bool backfaceCulling)
249 {
250  mBackfaceCulling = backfaceCulling;
251  emit meshChanged();
252 }
253 
255 {
256  return mBackfaceCulling;
257 }
258 
259 void Mesh::setFrontfaceCullingSlot(bool frontfaceCulling)
260 {
261  mFrontfaceCulling = frontfaceCulling;
262  emit meshChanged();
263 }
264 
266 {
267  return mFrontfaceCulling;
268 }
269 
270 void Mesh::setShowGlyph(bool val)
271 {
272  mShowGlyph = val;
273  emit meshChanged();
274 }
275 
277 {
278  return mHasGlyph;
279 }
280 
282 {
283  return mShowGlyph;
284 }
285 
286 bool Mesh::shouldGlyphBeEnableByDefault()
287 {
288  if(! mHasGlyph) return false;
289  if(mVtkPolyData->GetNumberOfVerts() > 0) return false;
290  if(mVtkPolyData->GetNumberOfLines() > 0) return false;
291  if(mVtkPolyData->GetNumberOfPolys() > 0) return false;
292  if(mVtkPolyData->GetNumberOfStrips() > 0) return false;
293 
294  return true;
295 }
296 
297 
299 {
300  return mOrientationArray.c_str();
301 }
302 
303 void Mesh::setOrientationArray(const char * orientationArray)
304 {
305  mOrientationArray = orientationArray;
306  emit meshChanged();
307 }
308 
310 {
311  return mVisSize;
312 }
313 
314 void Mesh::setVisSize(double size)
315 {
316  if(mVisSize==size) return;
317 
318  mVisSize=size;
319  emit meshChanged();
320 }
321 
322 const char * Mesh::getColorArray()
323 {
324  return mColorArray.c_str();
325 }
326 
327 void Mesh::setColorArray(const char * colorArray)
328 {
329  mColorArray = colorArray;
330  emit meshChanged();
331 }
332 
333 const char * Mesh::getGlyphLUT()
334 {
335  return mGlyphLUT.c_str();
336 }
337 
338 void Mesh::setGlyphLUT(const char * glyphLUT)
339 {
340  mGlyphLUT = glyphLUT;
341  emit meshChanged();
342 }
343 
344 
346 {
347  return mOrientationArrayList;
348 }
349 
351 {
352  return mColorArrayList;
353 }
354 
355 
356 
358 {
359 // getVtkPolyData()->Update();
360  DoubleBoundingBox3D bounds(getVtkPolyData()->GetBounds());
361  return bounds;
362 }
363 
365 {
366  // if transform elements exists, create a copy with entire position inside the polydata:
367  if (similar(transform, Transform3D::Identity()))
368  return getVtkPolyData();
369 
370 // getVtkPolyData()->Update();
371  vtkPolyDataPtr poly = vtkPolyDataPtr::New();
372  poly->DeepCopy(getVtkPolyData());
373  vtkPointsPtr points = poly->GetPoints();
374 
375  vtkPointsPtr floatPoints = vtkPointsPtr::New();
376  floatPoints->DeepCopy(points);
377  floatPoints->SetDataTypeToFloat();
378  for (int i = 0; i < poly->GetNumberOfPoints(); ++i)
379  {
380  Vector3D p(points->GetPoint(i));
381  p = transform.coord(p);
382  floatPoints->SetPoint(i, p.begin());
383  }
384  poly->SetPoints(floatPoints.GetPointer());
385  poly->Modified();
386 // poly->Update();
387 
388  return poly;
389 }
390 
392 {
394  return poly->GetLines()->GetNumberOfCells() > 0 && poly->GetPolys()->GetNumberOfCells() == 0 && poly->GetStrips()->GetNumberOfCells() == 0;
395 }
396 
397 void Mesh::save(const QString& basePath)
398 {
399  vtkPolyDataWriterPtr writer = vtkPolyDataWriterPtr::New();
400  writer->SetInputData(this->getVtkPolyData());
401  QString filename = basePath + "/Images/" + this->getUid() + ".vtk";
402  this->setFilename(QDir(basePath).relativeFilePath(filename));
403  writer->SetFileName(cstring_cast(filename));
404 
405  writer->Update();
406  writer->Write();
407 }
408 
409 } // namespace cx
virtual DoubleBoundingBox3D boundingBox() const
Definition: cxMesh.cpp:357
bool hasGlyph()
Definition: cxMesh.cpp:276
DoubleBoundingBox3D transform(const Transform3D &m, const DoubleBoundingBox3D &bb)
vtkPolyDataPtr getTransformedPolyData(Transform3D tranform)
Create a new transformed polydata.
Definition: cxMesh.cpp:364
const char * getOrientationArray()
Definition: cxMesh.cpp:298
bool isFiberBundle() const
Definition: cxMesh.cpp:391
Transform3D Transform3D
Transform3D is a representation of an affine 3D transform.
void setVisSize(double size)
Definition: cxMesh.cpp:314
void setName(const QString &name)
Definition: cxData.cpp:78
virtual vtkPolyDataPtr getVtkPolyData() const
Definition: cxMesh.cpp:134
virtual bool load(QString path)
Definition: cxMesh.cpp:87
cstring_cast_Placeholder cstring_cast(const T &val)
static MeshPtr create(const QString &uid, const QString &name="")
Definition: cxMesh.cpp:52
void setFrontfaceCullingSlot(bool backfaceCulling)
Set frontface culling on/off in mesh visualization.
Definition: cxMesh.cpp:259
QStringList getColorArrayList()
Definition: cxMesh.cpp:350
virtual void addXml(QDomNode &dataNode)
adds xml information about the data and its variabels
Definition: cxData.cpp:126
std::string string_cast(const T &val)
virtual QString getUid() const
Definition: cxData.cpp:84
bool similar(const DoubleBoundingBox3D &a, const DoubleBoundingBox3D &b, double tol)
vtkPolyDataPtr loadVtkPolyData(QString filename)
bool getIsWireframe() const
true=wireframe, false=surface
Definition: cxMesh.cpp:82
vtkSmartPointer< class vtkPolyData > vtkPolyDataPtr
bool showGlyph()
Definition: cxMesh.cpp:281
void setBackfaceCullingSlot(bool backfaceCulling)
Set backface culling on/off in mesh visualization.
Definition: cxMesh.cpp:248
void setVtkPolyData(const vtkPolyDataPtr &polyData)
Definition: cxMesh.cpp:100
virtual void parseXml(QDomNode &dataNode)
Use a XML node to load data.
Definition: cxData.cpp:152
bool getBackfaceCulling()
Get backface culling.
Definition: cxMesh.cpp:254
void setOrientationArray(const char *orientationArray)
Definition: cxMesh.cpp:303
void setAcquisitionTime(QDateTime time)
Definition: cxData.cpp:192
void meshChanged()
vtkSmartPointer< class vtkPolyDataWriter > vtkPolyDataWriterPtr
Representation of a floating-point bounding box in 3D. The data are stored as {xmin,xmax,ymin,ymax,zmin,zmax}, in order to simplify communication with vtk.
void setIsWireframe(bool on)
Set rep to wireframe, false means surface.
Definition: cxMesh.cpp:77
void setGlyphLUT(const char *glyphLUT)
Definition: cxMesh.cpp:338
const char * getGlyphLUT()
Definition: cxMesh.cpp:333
virtual void save(const QString &basePath)
Definition: cxMesh.cpp:397
virtual void parseXml(QDomNode &dataNode)
Use a XML node to load data.
Definition: cxMesh.cpp:177
Eigen::Vector3d Vector3D
Vector3D is a representation of a point or vector in 3D.
Definition: cxVector3D.h:63
Superclass for all data objects.
Definition: cxData.h:109
void addXml(QDomNode &dataNode)
adds xml information about the image and its variabels
Definition: cxMesh.cpp:138
virtual ~Mesh()
Definition: cxMesh.cpp:73
void setShowGlyph(bool val)
Definition: cxMesh.cpp:270
Mesh(const QString &uid, const QString &name="")
Definition: cxMesh.cpp:57
bool getFrontfaceCulling()
Get frontface culling.
Definition: cxMesh.cpp:265
void setColorArray(const char *colorArray)
Definition: cxMesh.cpp:327
boost::shared_ptr< class Mesh > MeshPtr
QStringList getOrientationArrayList()
Definition: cxMesh.cpp:345
double getVisSize()
Definition: cxMesh.cpp:309
const char * getColorArray()
Definition: cxMesh.cpp:322
virtual void setFilename(QString val)
Definition: cxData.cpp:98
vtkSmartPointer< class vtkPoints > vtkPointsPtr
void setColor(const QColor &color)
Set the color of the mesh.
Definition: cxMesh.cpp:237
QColor getColor()
Get the color of the mesh (Values are range 0 - 255)
Definition: cxMesh.cpp:243