NorMIT-nav  16.5
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  if (mVtkPolyData)
107  {
108  int num;
109  for(int k=0; k < mVtkPolyData->GetPointData()->GetNumberOfArrays(); k++)
110  {
111  num=mVtkPolyData->GetPointData()->GetArray(k)->GetNumberOfComponents();
112  if(num==3)
113  {
114  if(strlen(mOrientationArray.c_str())==0)
115  {
116  mOrientationArray=mVtkPolyData->GetPointData()->GetArrayName(k);
117  mHasGlyph=true;
118  }
119  mOrientationArrayList << mVtkPolyData->GetPointData()->GetArrayName(k);
120  }
121  }
122  mColorArrayList << "";
123  mColorArray="";
124  for(int k=0; k < mVtkPolyData->GetPointData()->GetNumberOfArrays(); k++)
125  {
126  num=mVtkPolyData->GetPointData()->GetArray(k)->GetNumberOfComponents();
127  if(num==1)
128  {
129  mColorArrayList << mVtkPolyData->GetPointData()->GetArrayName(k);
130  }
131  }
132  }
133  mShowGlyph = shouldGlyphBeEnableByDefault();
134 
135  emit meshChanged();
136 }
138 {
139  return mVtkPolyData;
140 }
141 void Mesh::addXml(QDomNode& dataNode)
142 {
143  Data::addXml(dataNode);
144  QDomDocument doc = dataNode.ownerDocument();
145 
146  QDomNode meshNode = dataNode;
147 
148  QDomElement colorNode = doc.createElement("color");
149  QDomElement subNode = doc.createElement("red");
150  subNode.appendChild(doc.createTextNode(string_cast(mColor.red()).c_str()));
151  colorNode.appendChild(subNode);
152  subNode = doc.createElement("green");
153  subNode.appendChild(doc.createTextNode(string_cast(mColor.green()).c_str()));
154  colorNode.appendChild(subNode);
155  subNode = doc.createElement("blue");
156  subNode.appendChild(doc.createTextNode(string_cast(mColor.blue()).c_str()));
157  colorNode.appendChild(subNode);
158  subNode = doc.createElement("alpha");
159  subNode.appendChild(doc.createTextNode(string_cast(mColor.alpha()).c_str()));
160  colorNode.appendChild(subNode);
161  meshNode.appendChild(colorNode);
162 
163  QDomElement cullingNode = doc.createElement("culling");
164  QDomElement elem = cullingNode.toElement();
165  elem.setAttribute("backfaceCulling", mBackfaceCulling);
166  elem.setAttribute("frontfaceCulling", mFrontfaceCulling);
167  meshNode.appendChild(cullingNode);
168 
169  QDomElement glyphNode = doc.createElement("glyph");
170  QDomElement elemGlyph = glyphNode.toElement();
171  elemGlyph.setAttribute("showGlyph", mShowGlyph);
172  elemGlyph.setAttribute("orientationArray", mOrientationArray.c_str());
173  elemGlyph.setAttribute("colorArray", mColorArray.c_str());
174  elemGlyph.setAttribute("glyphLUT", mGlyphLUT.c_str());
175  elemGlyph.setAttribute("glyphVisSize", mVisSize);
176  meshNode.appendChild(elemGlyph);
177 
178 }
179 
180 void Mesh::parseXml(QDomNode& dataNode)
181 {
182  Data::parseXml(dataNode);
183 
184  // image node must be parsed in the data manager to create this Image object
185  // Only subnodes are parsed here
186 
187  if (dataNode.isNull())
188  return;
189 
190  // QDomNode registrationHistory = dataNode.namedItem("registrationHistory");
191  // m_rMd_History->parseXml(registrationHistory);
192 
193  QDomNode colorNode = dataNode.namedItem("color");
194  if (!colorNode.isNull())
195  {
196  int red = 255;
197  int green = 255;
198  int blue = 255;
199  int alpha = 255;
200 
201  QDomNode node = colorNode.namedItem("red");
202  if (!node.isNull())
203  red = node.toElement().text().toInt();
204 
205  node = colorNode.namedItem("green");
206  if (!node.isNull())
207  green = node.toElement().text().toInt();
208 
209  node = colorNode.namedItem("blue");
210  if (!node.isNull())
211  blue = node.toElement().text().toInt();
212 
213  node = colorNode.namedItem("alpha");
214  if (!node.isNull())
215  alpha = node.toElement().text().toInt();
216 
217  mColor = QColor(red, green, blue, alpha);
218  }
219 
220  QDomNode cullingNode = dataNode.namedItem("culling");
221  if (!cullingNode.isNull())
222  {
223  mBackfaceCulling = cullingNode.toElement().attribute("backfaceCulling").toInt();
224  mFrontfaceCulling = cullingNode.toElement().attribute("frontfaceCulling").toInt();
225  }
226 
227  QDomNode glyphNode = dataNode.namedItem("glyph");
228  if (!glyphNode.isNull())
229  {
230  mShowGlyph = glyphNode.toElement().attribute("showGlyph").toInt();
231  mOrientationArray = glyphNode.toElement().attribute("orientationArray").toStdString();
232  mColorArray = glyphNode.toElement().attribute("colorArray").toStdString();
233  mGlyphLUT = glyphNode.toElement().attribute("glyphLUT").toStdString();
234  mVisSize = glyphNode.toElement().attribute("glyphVisSize").toDouble();
235  }
236 
237  emit meshChanged();
238 }
239 
240 void Mesh::setColor(const QColor& color)
241 {
242  mColor = color;
243  emit meshChanged();
244 }
245 
247 {
248  return mColor;
249 }
250 
251 void Mesh::setBackfaceCullingSlot(bool backfaceCulling)
252 {
253  mBackfaceCulling = backfaceCulling;
254  emit meshChanged();
255 }
256 
258 {
259  return mBackfaceCulling;
260 }
261 
262 void Mesh::setFrontfaceCullingSlot(bool frontfaceCulling)
263 {
264  mFrontfaceCulling = frontfaceCulling;
265  emit meshChanged();
266 }
267 
269 {
270  return mFrontfaceCulling;
271 }
272 
273 void Mesh::setShowGlyph(bool val)
274 {
275  mShowGlyph = val;
276  emit meshChanged();
277 }
278 
280 {
281  return mHasGlyph;
282 }
283 
285 {
286  return mShowGlyph;
287 }
288 
289 bool Mesh::shouldGlyphBeEnableByDefault()
290 {
291  if(! mHasGlyph) return false;
292  if(!mVtkPolyData) return false;
293  if(mVtkPolyData->GetNumberOfVerts() > 0) return false;
294  if(mVtkPolyData->GetNumberOfLines() > 0) return false;
295  if(mVtkPolyData->GetNumberOfPolys() > 0) return false;
296  if(mVtkPolyData->GetNumberOfStrips() > 0) return false;
297 
298  return true;
299 }
300 
301 
303 {
304  return mOrientationArray.c_str();
305 }
306 
307 void Mesh::setOrientationArray(const char * orientationArray)
308 {
309  mOrientationArray = orientationArray;
310  emit meshChanged();
311 }
312 
314 {
315  return mVisSize;
316 }
317 
318 void Mesh::setVisSize(double size)
319 {
320  if(mVisSize==size) return;
321 
322  mVisSize=size;
323  emit meshChanged();
324 }
325 
326 const char * Mesh::getColorArray()
327 {
328  return mColorArray.c_str();
329 }
330 
331 void Mesh::setColorArray(const char * colorArray)
332 {
333  mColorArray = colorArray;
334  emit meshChanged();
335 }
336 
337 const char * Mesh::getGlyphLUT()
338 {
339  return mGlyphLUT.c_str();
340 }
341 
342 void Mesh::setGlyphLUT(const char * glyphLUT)
343 {
344  mGlyphLUT = glyphLUT;
345  emit meshChanged();
346 }
347 
348 
350 {
351  return mOrientationArrayList;
352 }
353 
355 {
356  return mColorArrayList;
357 }
358 
359 
360 
362 {
363 // getVtkPolyData()->Update();
364  DoubleBoundingBox3D bounds(getVtkPolyData()->GetBounds());
365  return bounds;
366 }
367 
369 {
370  // if transform elements exists, create a copy with entire position inside the polydata:
371  if (similar(transform, Transform3D::Identity()))
372  return getVtkPolyData();
373 
374 // getVtkPolyData()->Update();
375  vtkPolyDataPtr poly = vtkPolyDataPtr::New();
376  poly->DeepCopy(getVtkPolyData());
377  vtkPointsPtr points = poly->GetPoints();
378 
379  vtkPointsPtr floatPoints = vtkPointsPtr::New();
380  floatPoints->DeepCopy(points);
381  floatPoints->SetDataTypeToFloat();
382  for (int i = 0; i < poly->GetNumberOfPoints(); ++i)
383  {
384  Vector3D p(points->GetPoint(i));
385  p = transform.coord(p);
386  floatPoints->SetPoint(i, p.begin());
387  }
388  poly->SetPoints(floatPoints.GetPointer());
389  poly->Modified();
390 // poly->Update();
391 
392  return poly;
393 }
394 
396 {
398  return poly->GetLines()->GetNumberOfCells() > 0 && poly->GetPolys()->GetNumberOfCells() == 0 && poly->GetStrips()->GetNumberOfCells() == 0;
399 }
400 
401 void Mesh::save(const QString& basePath)
402 {
403  vtkPolyDataWriterPtr writer = vtkPolyDataWriterPtr::New();
404  writer->SetInputData(this->getVtkPolyData());
405  QString filename = basePath + "/Images/" + this->getUid() + ".vtk";
406  this->setFilename(QDir(basePath).relativeFilePath(filename));
407  writer->SetFileName(cstring_cast(filename));
408 
409  writer->Update();
410  writer->Write();
411 }
412 
413 } // namespace cx
virtual DoubleBoundingBox3D boundingBox() const
Definition: cxMesh.cpp:361
bool hasGlyph()
Definition: cxMesh.cpp:279
DoubleBoundingBox3D transform(const Transform3D &m, const DoubleBoundingBox3D &bb)
vtkPolyDataPtr getTransformedPolyData(Transform3D tranform)
Create a new transformed polydata.
Definition: cxMesh.cpp:368
const char * getOrientationArray()
Definition: cxMesh.cpp:302
bool isFiberBundle() const
Definition: cxMesh.cpp:395
Transform3D Transform3D
Transform3D is a representation of an affine 3D transform.
void setVisSize(double size)
Definition: cxMesh.cpp:318
void setName(const QString &name)
Definition: cxData.cpp:78
virtual vtkPolyDataPtr getVtkPolyData() const
Definition: cxMesh.cpp:137
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:262
QStringList getColorArrayList()
Definition: cxMesh.cpp:354
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:284
void setBackfaceCullingSlot(bool backfaceCulling)
Set backface culling on/off in mesh visualization.
Definition: cxMesh.cpp:251
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:257
void setOrientationArray(const char *orientationArray)
Definition: cxMesh.cpp:307
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:342
const char * getGlyphLUT()
Definition: cxMesh.cpp:337
virtual void save(const QString &basePath)
Definition: cxMesh.cpp:401
virtual void parseXml(QDomNode &dataNode)
Use a XML node to load data.
Definition: cxMesh.cpp:180
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:141
virtual ~Mesh()
Definition: cxMesh.cpp:73
void setShowGlyph(bool val)
Definition: cxMesh.cpp:273
Mesh(const QString &uid, const QString &name="")
Definition: cxMesh.cpp:57
bool getFrontfaceCulling()
Get frontface culling.
Definition: cxMesh.cpp:268
void setColorArray(const char *colorArray)
Definition: cxMesh.cpp:331
boost::shared_ptr< class Mesh > MeshPtr
QStringList getOrientationArrayList()
Definition: cxMesh.cpp:349
double getVisSize()
Definition: cxMesh.cpp:313
const char * getColorArray()
Definition: cxMesh.cpp:326
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:240
QColor getColor()
Get the color of the mesh (Values are range 0 - 255)
Definition: cxMesh.cpp:246