/* -*- mode: c++; c-basic-offset: 4; indent-tabs-mode: nil -*- */ /* * Copyright (C) 2011, Purdue Research Foundation * * Author: Leif Delgass */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "RpContour2D.h" #include "Trace.h" using namespace Rappture::VtkVis; Contour2D::Contour2D(int numContours) : VtkGraphicsObject(), _numContours(numContours) { _edgeColor[0] = _color[0]; _edgeColor[1] = _color[0]; _edgeColor[2] = _color[0]; _lighting = false; } Contour2D::Contour2D(const std::vector& contours) : VtkGraphicsObject(), _numContours(contours.size()), _contours(contours) { _edgeColor[0] = _color[0]; _edgeColor[1] = _color[0]; _edgeColor[2] = _color[0]; _lighting = false; } Contour2D::~Contour2D() { #ifdef WANT_TRACE if (_dataSet != NULL) TRACE("Deleting Contour2D for %s", _dataSet->getName().c_str()); else TRACE("Deleting Contour2D with NULL DataSet"); #endif } /** * \brief Internal method to re-compute contours after a state change */ void Contour2D::update() { if (_dataSet == NULL) { return; } vtkDataSet *ds = _dataSet->getVtkDataSet(); initProp(); // Contour filter to generate isolines if (_contourFilter == NULL) { _contourFilter = vtkSmartPointer::New(); } vtkSmartPointer cellToPtData; if (ds->GetPointData() == NULL || ds->GetPointData()->GetScalars() == NULL) { WARN("No scalar point data in dataset %s", _dataSet->getName().c_str()); if (ds->GetCellData() != NULL && ds->GetCellData()->GetScalars() != NULL) { cellToPtData = vtkSmartPointer::New(); cellToPtData->SetInput(ds); //cellToPtData->PassCellDataOn(); cellToPtData->Update(); ds = cellToPtData->GetOutput(); } else { ERROR("No scalar cell data in dataset %s", _dataSet->getName().c_str()); } } vtkPolyData *pd = vtkPolyData::SafeDownCast(ds); if (pd) { // DataSet is a vtkPolyData if (pd->GetNumberOfLines() == 0 && pd->GetNumberOfPolys() == 0 && pd->GetNumberOfStrips() == 0) { // DataSet is a point cloud PrincipalPlane plane; double offset; if (_dataSet->is2D(&plane, &offset)) { vtkSmartPointer mesher = vtkSmartPointer::New(); if (plane == PLANE_ZY) { vtkSmartPointer trans = vtkSmartPointer::New(); trans->RotateWXYZ(90, 0, 1, 0); if (offset != 0.0) { trans->Translate(-offset, 0, 0); } mesher->SetTransform(trans); } else if (plane == PLANE_XZ) { vtkSmartPointer trans = vtkSmartPointer::New(); trans->RotateWXYZ(-90, 1, 0, 0); if (offset != 0.0) { trans->Translate(0, -offset, 0); } mesher->SetTransform(trans); } else if (offset != 0.0) { // XY with Z offset vtkSmartPointer trans = vtkSmartPointer::New(); trans->Translate(0, 0, -offset); mesher->SetTransform(trans); } mesher->SetInput(pd); _contourFilter->SetInputConnection(mesher->GetOutputPort()); } else { vtkSmartPointer mesher = vtkSmartPointer::New(); mesher->SetInput(pd); vtkSmartPointer gf = vtkSmartPointer::New(); gf->SetInputConnection(mesher->GetOutputPort()); _contourFilter->SetInputConnection(gf->GetOutputPort()); } } else { // DataSet is a vtkPolyData with lines and/or polygons _contourFilter->SetInput(ds); } } else { TRACE("Generating surface for data set"); // DataSet is NOT a vtkPolyData vtkSmartPointer gf = vtkSmartPointer::New(); gf->SetInput(ds); _contourFilter->SetInputConnection(gf->GetOutputPort()); } _contourFilter->ComputeNormalsOff(); _contourFilter->ComputeGradientsOff(); // Speed up multiple contour computation at cost of extra memory use if (_numContours > 1) { _contourFilter->UseScalarTreeOn(); } else { _contourFilter->UseScalarTreeOff(); } _contourFilter->SetNumberOfContours(_numContours); if (_contours.empty()) { // Evenly spaced isovalues _contourFilter->GenerateValues(_numContours, _dataRange[0], _dataRange[1]); } else { // User-supplied isovalues for (int i = 0; i < _numContours; i++) { _contourFilter->SetValue(i, _contours[i]); } } if (_contourMapper == NULL) { _contourMapper = vtkSmartPointer::New(); _contourMapper->SetResolveCoincidentTopologyToPolygonOffset(); _contourMapper->ScalarVisibilityOff(); vtkSmartPointer stripper = vtkSmartPointer::New(); stripper->SetInputConnection(_contourFilter->GetOutputPort()); _contourMapper->SetInputConnection(stripper->GetOutputPort()); getActor()->SetMapper(_contourMapper); } _contourMapper->Update(); } void Contour2D::updateRanges(Renderer *renderer) { VtkGraphicsObject::updateRanges(renderer); if (_contours.empty() && _numContours > 0) { // Contour isovalues need to be recomputed update(); } } /** * \brief Specify number of evenly spaced contour lines to render * * Will override any existing contours */ void Contour2D::setContours(int numContours) { _contours.clear(); _numContours = numContours; update(); } /** * \brief Specify an explicit list of contour isovalues * * Will override any existing contours */ void Contour2D::setContourList(const std::vector& contours) { _contours = contours; _numContours = (int)_contours.size(); update(); } /** * \brief Get the number of contours */ int Contour2D::getNumContours() const { return _numContours; } /** * \brief Get the contour list (may be empty if number of contours * was specified in place of a list) */ const std::vector& Contour2D::getContourList() const { return _contours; } /** * \brief Set a group of world coordinate planes to clip rendering * * Passing NULL for planes will remove all cliping planes */ void Contour2D::setClippingPlanes(vtkPlaneCollection *planes) { if (_contourMapper != NULL) { _contourMapper->SetClippingPlanes(planes); } }