CustusX  16.12
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 #include <vtkCellArray.h>
36 #include <vtkColorSeries.h>
37 #include <vtkPolyData.h>
38 #include <vtkPolyDataWriter.h>
39 #include <vtkPointData.h>
40 #include <QDomDocument>
41 #include <QColor>
42 #include <QDir>
43 #include <vtkTransformTextureCoords.h>
44 #include <vtkTexture.h>
45 #include <vtkTextureMapToCylinder.h>
46 #include <vtkTextureMapToPlane.h>
47 #include <vtkTextureMapToSphere.h>
48 #include "cxTypeConversions.h"
50 #include "cxBoundingBox3D.h"
51 #include "cxDataReaderWriter.h"
52 #include "vtkProperty.h"
53 #include "vtkImageData.h"
54 
55 
56 namespace cx
57 {
58 
59 
60 //---------------------------------------------------------
61 //---------------------------------------------------------
62 //---------------------------------------------------------
63 
64 MeshPtr Mesh::create(const QString& uid, const QString& name, PatientModelServicePtr patientModelService, SpaceProviderPtr spaceProvider)
65 {
66  return MeshPtr(new Mesh(uid, name, vtkPolyDataPtr(), patientModelService, spaceProvider));
67 }
68 
69 Mesh::Mesh(const QString& uid, const QString& name, vtkPolyDataPtr polyData, PatientModelServicePtr patientModelService, SpaceProviderPtr spaceProvider) :
70  Data(uid, name), mVtkPolyData(polyData), mHasGlyph(false), mOrientationArray(""), mColorArray(""), mPatientModelService(patientModelService),
71  mSpaceProvider(spaceProvider), mTextureData(patientModelService)
72 {
73  if (!mVtkPolyData)
74  mVtkPolyData = vtkPolyDataPtr::New();
75  connect(&mProperties, &MeshPropertyData::changed, this, &Mesh::meshChanged);
76  connect(&mTextureData, &MeshTextureData::changed, this, &Mesh::meshChanged);
77  mShowGlyph = shouldGlyphBeEnableByDefault();
78  mGlyphLUT ="Citrus";
79  this->setAcquisitionTime(QDateTime::currentDateTime());
80 }
81 
83 {
84 }
85 
86 void Mesh::setIsWireframe(bool on)
87 {
88  if (on)
89  mProperties.mRepresentation->setValue(QString::number(VTK_WIREFRAME));
90  else
91  mProperties.mRepresentation->setValue(QString::number(VTK_SURFACE));
92 }
93 
95 {
96  return mProperties.mRepresentation->getValue().toInt() == VTK_WIREFRAME;
97 }
98 
99 bool Mesh::load(QString path)
100 {
101  vtkPolyDataPtr raw;
102  raw = DataReaderWriter().loadVtkPolyData(path);
103  if(raw)
104  {
105  this->setVtkPolyData(raw);
106  this->setName(QFileInfo(path).baseName());
107  this->setFilename(path); // need path even when not set explicitly: nice for testing
108  }
109  return raw!=0;
110 }
111 
113 {
114  mVtkPolyData = polyData;
115  mOrientationArrayList.clear();
116  mColorArrayList.clear();
117 
118  if (mVtkPolyData)
119  {
120  int num;
121  for(int k=0; k < mVtkPolyData->GetPointData()->GetNumberOfArrays(); k++)
122  {
123  num=mVtkPolyData->GetPointData()->GetArray(k)->GetNumberOfComponents();
124  if(num==3)
125  {
126  if(strlen(mOrientationArray.c_str())==0)
127  {
128  mOrientationArray=mVtkPolyData->GetPointData()->GetArrayName(k);
129  mHasGlyph=true;
130  }
131  mOrientationArrayList << mVtkPolyData->GetPointData()->GetArrayName(k);
132  }
133  }
134  mColorArrayList << "";
135  mColorArray="";
136  for(int k=0; k < mVtkPolyData->GetPointData()->GetNumberOfArrays(); k++)
137  {
138  num=mVtkPolyData->GetPointData()->GetArray(k)->GetNumberOfComponents();
139  if(num==1)
140  {
141  mColorArrayList << mVtkPolyData->GetPointData()->GetArrayName(k);
142  }
143  }
144  }
145  mShowGlyph = shouldGlyphBeEnableByDefault();
146 
147  emit meshChanged();
148 }
150 {
151  return mVtkPolyData;
152 }
153 
155 {
156  return mVtkTexture;
157 }
158 
159 void Mesh::addXml(QDomNode& dataNode)
160 {
161  Data::addXml(dataNode);
162  QDomDocument doc = dataNode.ownerDocument();
163 
164  QDomNode meshNode = dataNode;
165 
166  mProperties.addXml(dataNode);
167  mTextureData.addXml(dataNode);
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  meshNode.appendChild(elemGlyph);
176 
177 }
178 
179 void Mesh::parseXml(QDomNode& dataNode)
180 {
181  Data::parseXml(dataNode);
182 
183  // image node must be parsed in the data manager to create this Image object
184  // Only subnodes are parsed here
185 
186  if (dataNode.isNull())
187  return;
188 
189  mProperties.parseXml(dataNode);
190  mTextureData.parseXml(dataNode);
191 
192  QDomNode glyphNode = dataNode.namedItem("glyph");
193  if (!glyphNode.isNull())
194  {
195  mShowGlyph = glyphNode.toElement().attribute("showGlyph").toInt();
196  mOrientationArray = glyphNode.toElement().attribute("orientationArray").toStdString();
197  mColorArray = glyphNode.toElement().attribute("colorArray").toStdString();
198  mGlyphLUT = glyphNode.toElement().attribute("glyphLUT").toStdString();
199  }
200 
201  emit meshChanged();
202 }
203 
204 void Mesh::setColor(const QColor& color)
205 {
206  mProperties.mColor->setValue(color);
207 }
208 
210 {
211  return mProperties.mColor->getValue();
212 }
213 
214 void Mesh::setBackfaceCullingSlot(bool backfaceCulling)
215 {
216  mProperties.mBackfaceCulling->setValue(backfaceCulling);
217 }
218 
220 {
221  return mProperties.mBackfaceCulling->getValue();
222 }
223 
224 void Mesh::setFrontfaceCullingSlot(bool frontfaceCulling)
225 {
226  mProperties.mFrontfaceCulling->setValue(frontfaceCulling);
227  emit meshChanged();
228 }
229 
231 {
232  return mProperties.mFrontfaceCulling->getValue();
233 }
234 
235 void Mesh::setShowGlyph(bool val)
236 {
237  mShowGlyph = val;
238  emit meshChanged();
239 }
240 
242 {
243  return mHasGlyph;
244 }
245 
247 {
248  return mShowGlyph;
249 }
250 
251 bool Mesh::shouldGlyphBeEnableByDefault()
252 {
253  if(! mHasGlyph) return false;
254  if(!mVtkPolyData) return false;
255  if(mVtkPolyData->GetNumberOfVerts() > 0) return false;
256  if(mVtkPolyData->GetNumberOfLines() > 0) return false;
257  if(mVtkPolyData->GetNumberOfPolys() > 0) return false;
258  if(mVtkPolyData->GetNumberOfStrips() > 0) return false;
259 
260  return true;
261 }
262 
263 
265 {
266  return mOrientationArray.c_str();
267 }
268 
269 void Mesh::setOrientationArray(const char * orientationArray)
270 {
271  mOrientationArray = orientationArray;
272  emit meshChanged();
273 }
274 
276 {
277  return mProperties.mVisSize->getValue();
278 }
279 
280 void Mesh::setVisSize(double size)
281 {
282  mProperties.mVisSize->setValue(size);
283 }
284 
285 const char * Mesh::getColorArray()
286 {
287  return mColorArray.c_str();
288 }
289 
290 void Mesh::setColorArray(const char * colorArray)
291 {
292  mColorArray = colorArray;
293  emit meshChanged();
294 }
295 
296 const char * Mesh::getGlyphLUT()
297 {
298  return mGlyphLUT.c_str();
299 }
300 
302 {
303  return mTextureData.getTextureShape()->getValue();
304 }
305 
306 void Mesh::setGlyphLUT(const char * glyphLUT)
307 {
308  mGlyphLUT = glyphLUT;
309  emit meshChanged();
310 }
311 
312 bool Mesh::hasTexture() const
313 {
314  if(mTextureData.getTextureImage()->getValue().isEmpty() || mTextureData.getTextureImage()->getImage() == NULL)
315  return false;
316  else
317  return true;
318 }
319 
321 {
322  QString textureShape = this->getTextureShape();
323  if (!this->hasTexture())
324  {
325  mVtkTexture = vtkTexturePtr::New();
326  return;
327  }
328 
329  //create the texture mapper
330  vtkDataSetAlgorithmPtr tMapper;
331  if(!this->createTextureMapper(tMapper))
332  return;
333 
334  //Get the image data
335  ImagePtr textureImage = mTextureData.getTextureImage()->getImage();
336  vtkImageDataPtr vtkImageData = textureImage->getBaseVtkImageData();
337 
338  //Create the texture
339  mVtkTexture = vtkTexturePtr::New();
340  mVtkTexture->SetRepeat(mTextureData.getRepeat()->getValue());
341  mVtkTexture->SetInputData(vtkImageData);
342 
343  //transform texture coordinates
344  //VTK uses r, s and t coordinates. t is only used for 3D texturing which is not supported by VTK yet.
345  //We map r and s to match the CustusX X and Y directions.
346  vtkTransformTextureCoordsPtr transformTexture = vtkTransformTextureCoordsPtr::New();
347  transformTexture->SetInputConnection(tMapper->GetOutputPort());
348  double posR = this->getTextureData().getPositionX()->getValue();
349  double posS = this->getTextureData().getPositionY()->getValue();
350  transformTexture->SetPosition(-posR, -posS, 0);
351  double scaleR = this->getTextureData().getScaleX()->getValue();
352  double scaleS = this->getTextureData().getScaleY()->getValue();
353  transformTexture->SetScale(scaleR, scaleS, 1);
354  transformTexture->Update();
355 
356  //Update the poly data
357  mVtkPolyData = transformTexture->GetPolyDataOutput();
358 }
359 
360 bool Mesh::createTextureMapper(vtkDataSetAlgorithmPtr &tMapper)
361 {
362  QString textureShape = this->getTextureShape();
363 
364  if (textureShape == mTextureData.getCylinderText())
365  {
366  tMapper = vtkTextureMapToCylinderPtr::New();
367  dynamic_cast<vtkTextureMapToCylinder*>(tMapper.Get())->PreventSeamOn();
368  }
369  else if (textureShape == mTextureData.getPlaneText())
370  {
371  vtkTextureMapToPlanePtr mapper = vtkTextureMapToPlanePtr::New();
372  DoubleBoundingBox3D bb = this->boundingBox();
373  // Explicitly state the plane as the upper xy-plane of the bounding box
374  // The automatic plane generation is not deterministic for square cases.
375  mapper->SetOrigin(bb.corner(0,0,1).data());
376  mapper->SetPoint1(bb.corner(1,0,1).data());
377  mapper->SetPoint2(bb.corner(0,1,1).data());
378 
379  tMapper = mapper;
380  }
381  else if (textureShape == mTextureData.getSphereText())
382  {
383  tMapper = vtkTextureMapToSpherePtr::New();
384  }
385  else
386  {
387  return false;
388  }
389 
390  tMapper->SetInputData(mVtkPolyData);
391  return true;
392 }
393 
395 {
396  return mOrientationArrayList;
397 }
398 
400 {
401  return mColorArrayList;
402 }
403 
405 {
406  return mProperties;
407 }
408 
410 {
411  return mTextureData;
412 }
413 
415 {
416  // getVtkPolyData()->Update();
417  DoubleBoundingBox3D bounds(getVtkPolyData()->GetBounds());
418  return bounds;
419 }
420 
422 {
423  // if transform elements exists, create a copy with entire position inside the polydata:
424  if (similar(transform, Transform3D::Identity()))
425  return getVtkPolyData();
426 
427  // getVtkPolyData()->Update();
428  vtkPolyDataPtr poly = vtkPolyDataPtr::New();
429  poly->DeepCopy(getVtkPolyData());
430  vtkPointsPtr points = poly->GetPoints();
431 
432  vtkPointsPtr floatPoints = vtkPointsPtr::New();
433  floatPoints->DeepCopy(points);
434  floatPoints->SetDataTypeToFloat();
435  for (int i = 0; i < poly->GetNumberOfPoints(); ++i)
436  {
437  Vector3D p(points->GetPoint(i));
438  p = transform.coord(p);
439  floatPoints->SetPoint(i, p.begin());
440  }
441  poly->SetPoints(floatPoints.GetPointer());
442  poly->Modified();
443  // poly->Update();
444 
445  return poly;
446 }
447 
449 {
451  return poly->GetLines()->GetNumberOfCells() > 0 && poly->GetPolys()->GetNumberOfCells() == 0 && poly->GetStrips()->GetNumberOfCells() == 0;
452 }
453 
454 void Mesh::save(const QString& basePath)
455 {
456  vtkPolyDataWriterPtr writer = vtkPolyDataWriterPtr::New();
457  writer->SetInputData(this->getVtkPolyData());
458  QString filename = basePath + "/Images/" + this->getUid() + ".vtk";
459  this->setFilename(QDir(basePath).relativeFilePath(filename));
460  writer->SetFileName(cstring_cast(filename));
461 
462  writer->Update();
463  writer->Write();
464 }
465 
466 } // namespace cx
virtual DoubleBoundingBox3D boundingBox() const
Definition: cxMesh.cpp:414
boost::shared_ptr< class SpaceProvider > SpaceProviderPtr
bool hasGlyph()
Definition: cxMesh.cpp:241
vtkSmartPointer< class vtkTexture > vtkTexturePtr
DoubleBoundingBox3D transform(const Transform3D &m, const DoubleBoundingBox3D &bb)
DoublePropertyPtr mVisSize
vtkPolyDataPtr getTransformedPolyData(Transform3D tranform)
Create a new transformed polydata.
Definition: cxMesh.cpp:421
const char * getOrientationArray()
Definition: cxMesh.cpp:264
Mesh(const QString &uid, const QString &name="", vtkPolyDataPtr polyData=vtkPolyDataPtr(), PatientModelServicePtr patientModelService=PatientModelService::getNullObject(), SpaceProviderPtr spaceProvider=SpaceProvider::getNullObject())
Definition: cxMesh.cpp:69
bool isFiberBundle() const
Definition: cxMesh.cpp:448
void parseXml(QDomNode dataNode)
Transform3D Transform3D
Transform3D is a representation of an affine 3D transform.
vtkSmartPointer< class vtkDataSetAlgorithm > vtkDataSetAlgorithmPtr
void parseXml(QDomNode &dataNode)
BoolPropertyPtr mFrontfaceCulling
void setVisSize(double size)
Definition: cxMesh.cpp:280
boost::shared_ptr< class Image > ImagePtr
Definition: cxDicomWidget.h:48
void setName(const QString &name)
Definition: cxData.cpp:79
virtual vtkPolyDataPtr getVtkPolyData() const
Definition: cxMesh.cpp:149
virtual bool load(QString path)
Definition: cxMesh.cpp:99
cstring_cast_Placeholder cstring_cast(const T &val)
void updateVtkPolyDataWithTexture()
Definition: cxMesh.cpp:320
void setFrontfaceCullingSlot(bool backfaceCulling)
Set frontface culling on/off in mesh visualization.
Definition: cxMesh.cpp:224
QStringList getColorArrayList()
Definition: cxMesh.cpp:399
virtual void addXml(QDomNode &dataNode)
adds xml information about the data and its variabels
Definition: cxData.cpp:144
vtkSmartPointer< class vtkTransformTextureCoords > vtkTransformTextureCoordsPtr
vtkSmartPointer< class vtkTextureMapToPlane > vtkTextureMapToPlanePtr
QString getTextureShape()
Definition: cxMesh.cpp:301
DoublePropertyPtr getPositionY() const
QString getPlaneText() const
virtual QString getUid() const
Definition: cxData.cpp:85
DoublePropertyPtr getScaleX() const
vtkPolyDataPtr loadVtkPolyData(QString filename)
bool hasTexture() const
Definition: cxMesh.cpp:312
StringPropertySelectImagePtr getTextureImage() const
bool getIsWireframe() const
true=wireframe, false=surface
Definition: cxMesh.cpp:94
DoublePropertyPtr getPositionX() const
StringPropertyPtr mRepresentation
static MeshPtr create(const QString &uid, const QString &name="", PatientModelServicePtr patientModelService=PatientModelService::getNullObject(), SpaceProviderPtr spaceProvider=SpaceProvider::getNullObject())
Definition: cxMesh.cpp:64
vtkSmartPointer< class vtkPolyData > vtkPolyDataPtr
QString getSphereText() const
bool showGlyph()
Definition: cxMesh.cpp:246
void setBackfaceCullingSlot(bool backfaceCulling)
Set backface culling on/off in mesh visualization.
Definition: cxMesh.cpp:214
BoolPropertyPtr getRepeat() const
void setVtkPolyData(const vtkPolyDataPtr &polyData)
Definition: cxMesh.cpp:112
virtual void parseXml(QDomNode &dataNode)
Use a XML node to load data.
Definition: cxData.cpp:170
bool getBackfaceCulling()
Get backface culling.
Definition: cxMesh.cpp:219
void setOrientationArray(const char *orientationArray)
Definition: cxMesh.cpp:269
boost::shared_ptr< class PatientModelService > PatientModelServicePtr
void setAcquisitionTime(QDateTime time)
Definition: cxData.cpp:210
void meshChanged()
BoolPropertyPtr mBackfaceCulling
void addXml(QDomNode &dataNode)
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:86
void setGlyphLUT(const char *glyphLUT)
Definition: cxMesh.cpp:306
cxLogicManager_EXPORT SpaceProviderPtr spaceProvider()
const MeshTextureData & getTextureData() const
Definition: cxMesh.cpp:409
const char * getGlyphLUT()
Definition: cxMesh.cpp:296
virtual void save(const QString &basePath)
Definition: cxMesh.cpp:454
virtual void parseXml(QDomNode &dataNode)
Use a XML node to load data.
Definition: cxMesh.cpp:179
Eigen::Vector3d Vector3D
Vector3D is a representation of a point or vector in 3D.
Definition: cxVector3D.h:63
DoublePropertyPtr getScaleY() const
Superclass for all data objects.
Definition: cxData.h:109
QString getCylinderText() const
void addXml(QDomNode &dataNode)
adds xml information about the image and its variabels
Definition: cxMesh.cpp:159
virtual ~Mesh()
Definition: cxMesh.cpp:82
bool similar(const CameraInfo &lhs, const CameraInfo &rhs, double tol)
void addXml(QDomNode &dataNode)
void setShowGlyph(bool val)
Definition: cxMesh.cpp:235
bool getFrontfaceCulling()
Get frontface culling.
Definition: cxMesh.cpp:230
const MeshPropertyData & getProperties() const
Definition: cxMesh.cpp:404
void setColorArray(const char *colorArray)
Definition: cxMesh.cpp:290
boost::shared_ptr< class Mesh > MeshPtr
vtkSmartPointer< class vtkImageData > vtkImageDataPtr
QStringList getOrientationArrayList()
Definition: cxMesh.cpp:394
virtual vtkTexturePtr getVtkTexture() const
Definition: cxMesh.cpp:154
double getVisSize()
Definition: cxMesh.cpp:275
StringPropertyPtr getTextureShape() const
const char * getColorArray()
Definition: cxMesh.cpp:285
virtual void setFilename(QString val)
Definition: cxData.cpp:99
ColorPropertyPtr mColor
vtkSmartPointer< class vtkPoints > vtkPointsPtr
void setColor(const QColor &color)
Set the color of the mesh.
Definition: cxMesh.cpp:204
QColor getColor()
Get the color of the mesh (Values are range 0 - 255)
Definition: cxMesh.cpp:209