#ifdef LEMMAUSEVTK #include "matplot.h" #include "vtkActor.h" #include "vtkAxesActor.h" #include "vtkCamera.h" #include "vtkCaptionActor2D.h" #include "vtkContourFilter.h" #include "vtkDataSetMapper.h" #include "vtkGlyph3D.h" #include "vtkGlyphSource2D.h" #include "vtkOutlineFilter.h" #include "vtkPolyData.h" #include "vtkPolyDataMapper.h" #include "vtkPNGWriter.h" #include "vtkProperty.h" #include "vtkProperty2D.h" #include "vtkRectilinearGridGeometryFilter.h" #include "vtkRenderWindow.h" #include "vtkRenderWindowInteractor.h" #include "vtkStructuredGridGeometryFilter.h" #include "vtkScalarBarActor.h" #include "vtkTextProperty.h" #include "vtkTubeFilter.h" #include "vtkWarpScalar.h" #include "vtkWindowToImageFilter.h" #include "vtkRenderLargeImage.h" #include "vtkTextActor.h" #include "vtkVectorText.h" #include "vtkTransformPolyDataFilter.h" #include "vtkTransform.h" #include "vtkFollower.h" #include "vtkAxisActor2D.h" //#include "vtkCubeAxesActor.h" #include "vtkCubeAxesActor2D.h" using namespace matplot; /// Default constructor Plot2D_VTK::Plot2D_VTK(std::string x_label, std::string y_label, int xpix, int ypix, bool semilogX) { semilogx = semilogX; xPix = xpix; yPix = ypix; plot_no = 0; // set up the renderer rend = vtkRenderer::New(); rend->SetBackground(1., 1., 1.); // set up the xy plot xyplot = vtkXYPlotActor::New(); xyplot->GetProperty()->SetColor(0.0, 0.0, 0.0); xyplot->SetBorder(10); xyplot->GetPositionCoordinate()->SetValue(0.0, 0.0, 0); xyplot->GetPosition2Coordinate()->SetValue(1.0, 1.0, 0); xyplot->GetProperty()->SetLineWidth(1); xyplot->GetProperty()->SetPointSize(5); xyplot->PlotPointsOff(); xyplot->PlotLinesOff(); xyplot->PlotCurvePointsOn(); xyplot->PlotCurveLinesOn(); xyplot->SetXValuesToArcLength(); xyplot->SetLabelFormat("%2.1f"); xyplot->SetTitle(""); xyplot->SetXTitle(x_label.c_str()); xyplot->SetYTitle(y_label.c_str()); if (semilogx) { xyplot->LogxOn(); } vtkTextProperty* text_prop = xyplot->GetTitleTextProperty(); text_prop->SetColor(0.0, 0.0, 0.0); text_prop->SetFontFamilyToArial(); xyplot->SetAxisTitleTextProperty(text_prop); xyplot->SetAxisLabelTextProperty(text_prop); xyplot->SetTitleTextProperty(text_prop); } /// Destructor Plot2D_VTK::~Plot2D_VTK() { xyplot->Delete(); rend->Delete(); } /// Render current figure to screen void Plot2D_VTK::show() { rend->AddActor(xyplot); render_interactive(rend,xPix,yPix); } /// Render current figure to file void Plot2D_VTK::draw_to_png(std::string filename) { rend->AddActor(xyplot); render_to_png(rend,xPix,yPix,filename); } //============================================================================== Surf_VTK::Surf_VTK(int px, int py) { has_data = false; Lxy = -1; Lz = -1; xPix = px; yPix = py; gridfunc = vtkStructuredGrid::New(); rend = vtkRenderer::New(); } /// Destructor Surf_VTK::~Surf_VTK() { gridfunc->Delete(); rend->Delete(); } /// Clear plot data before reuse void Surf_VTK::purge() { assert(has_data); gridfunc->Delete(); rend->Delete(); gridfunc = vtkStructuredGrid::New(); rend = vtkRenderer::New(); has_data = false; Lxy = -1; Lz = -1; } void Surf_VTK::renderer(bool draw_axes, bool draw_colorbar, bool draw_box, bool do_warp) { assert(has_data); // filter to geometry primitive vtkStructuredGridGeometryFilter *geometry = vtkStructuredGridGeometryFilter::New(); geometry->SetInputData(gridfunc); // warp to fit in box vtkWarpScalar *warp = vtkWarpScalar::New(); if (do_warp) { double scale = Lxy/Lz; warp->SetInputConnection(geometry->GetOutputPort()); warp->XYPlaneOn(); warp->SetScaleFactor(scale); } // map gridfunction vtkPolyDataMapper *mapper = vtkPolyDataMapper::New(); if (do_warp) mapper->SetInputConnection(warp->GetOutputPort()); else mapper->SetInputConnection(geometry->GetOutputPort()); double tmp[2]; gridfunc->GetScalarRange(tmp); mapper->SetScalarRange(tmp[0], tmp[1]); // create plot surface actor vtkActor *surfplot = vtkActor::New(); surfplot->SetMapper(mapper); // create outline vtkOutlineFilter *outlinefilter = vtkOutlineFilter::New(); if (do_warp) outlinefilter->SetInputConnection(warp->GetOutputPort()); else outlinefilter->SetInputConnection(geometry->GetOutputPort()); vtkPolyDataMapper *outlineMapper = vtkPolyDataMapper::New(); outlineMapper->SetInputConnection(outlinefilter->GetOutputPort()); vtkActor *outline = vtkActor::New(); outline->SetMapper(outlineMapper); outline->GetProperty()->SetColor(0, 0, 0); // create axes vtkAxesActor* axes = vtkAxesActor::New(); axes->SetShaftTypeToCylinder(); axes->SetNormalizedShaftLength( 0.85, 0.85, 0.85); axes->SetNormalizedTipLength( 0.15, 0.15, 0.15); axes->SetCylinderRadius( 0.500 * axes->GetCylinderRadius() ); axes->SetConeRadius( 1.025 * axes->GetConeRadius() ); axes->SetSphereRadius( 1.500 * axes->GetSphereRadius() ); vtkTextProperty* text_prop_ax = axes->GetXAxisCaptionActor2D()-> GetCaptionTextProperty(); text_prop_ax->SetColor(0.0, 0.0, 0.0); text_prop_ax->SetFontFamilyToArial(); text_prop_ax->SetFontSize(8); axes->GetYAxisCaptionActor2D()->GetCaptionTextProperty()-> ShallowCopy(text_prop_ax); axes->GetZAxisCaptionActor2D()->GetCaptionTextProperty()-> ShallowCopy(text_prop_ax); // create colorbar vtkScalarBarActor *colorbar = vtkScalarBarActor::New(); colorbar->SetLookupTable(mapper->GetLookupTable()); colorbar->SetWidth(0.085); colorbar->SetHeight(0.9); colorbar->SetPosition(0.9, 0.1); vtkTextProperty* text_prop_cb = colorbar->GetLabelTextProperty(); text_prop_cb->SetColor(1.0, 1.0, 1.0); colorbar->SetLabelTextProperty(text_prop_cb); // renderer rend->AddActor(surfplot); if (draw_box) rend->AddActor(outline); if (draw_axes) rend->AddActor(axes); if (draw_colorbar) rend->AddActor(colorbar); rend->SetBackground(0.25, 0.25, 0.25); // renderer is now set up! // clean up colorbar->Delete(); warp->Delete(); axes->Delete(); outline->Delete(); outlinefilter->Delete(); outlineMapper->Delete(); surfplot->Delete(); mapper->Delete(); geometry->Delete(); } //============================================================================== /// Default constructor Contour_VTK::Contour_VTK(int px, int py) { XScale = LINEAR; YScale = LINEAR; has_data = false; xPix = px; yPix = py; gridfunc = vtkRectilinearGrid::New(); rend = vtkRenderer::New(); } /// Default constructor Contour_VTK::Contour_VTK(int px, int py, SCALE xsc, SCALE ysc) { XScale = xsc; YScale = ysc; xlabel = "x"; ylabel = "y"; has_data = false; xPix = px; yPix = py; gridfunc = vtkRectilinearGrid::New(); rend = vtkRenderer::New(); } /// Destructor Contour_VTK::~Contour_VTK() { gridfunc->Delete(); rend->Delete(); } /// Clear plot data before reuse void Contour_VTK::purge() { assert(has_data); gridfunc->Delete(); rend->Delete(); gridfunc = vtkRectilinearGrid::New(); rend = vtkRenderer::New(); has_data = false; } /// Set labels for contour plots void Contour_VTK::SetXLabel(const std::string &xlab) { xlabel = xlab; } void Contour_VTK::SetYLabel(const std::string &ylab ) { ylabel = ylab; } void Contour_VTK::renderer(bool draw_colorbar, bool draw_surf, int lines) { assert(has_data); // filter to geometry primitive vtkRectilinearGridGeometryFilter *geometry = vtkRectilinearGridGeometryFilter::New(); geometry->SetInputData(gridfunc); // map gridfunction vtkPolyDataMapper *mapper = vtkPolyDataMapper::New(); mapper->SetInputConnection(geometry->GetOutputPort()); double tmp[2]; gridfunc->GetScalarRange(tmp); mapper->SetScalarRange(tmp[0], tmp[1]); // create plot surface actor vtkActor *surfplot = vtkActor::New(); surfplot->SetMapper(mapper); // create contour lines (10 lines) vtkContourFilter *contlines = vtkContourFilter::New(); contlines->SetInputConnection(geometry->GetOutputPort()); double tempdiff = (tmp[1]-tmp[0])/(10*lines); contlines->GenerateValues(lines, tmp[0]+tempdiff, tmp[1]-tempdiff); vtkPolyDataMapper *contourMapper = vtkPolyDataMapper::New(); contourMapper->SetInputConnection(contlines->GetOutputPort()); if (draw_surf) contourMapper->ScalarVisibilityOff(); else contourMapper->SetScalarRange(tmp[0], tmp[1]); vtkActor *contours = vtkActor::New(); contours->SetMapper(contourMapper); contours->GetProperty()->SetOpacity(.25); contours->GetProperty()->SetColor(0.5,0.5,0.5); // create outline vtkOutlineFilter *outlinefilter = vtkOutlineFilter::New(); outlinefilter->SetInputConnection(geometry->GetOutputPort()); vtkPolyDataMapper *outlineMapper = vtkPolyDataMapper::New(); outlineMapper->SetInputConnection(outlinefilter->GetOutputPort()); vtkActor *outline = vtkActor::New(); outline->SetMapper(outlineMapper); outline->GetProperty()->SetColor(0, 0, 0); // create colorbar vtkScalarBarActor *colorbar = vtkScalarBarActor::New(); if (draw_surf) colorbar->SetLookupTable(mapper->GetLookupTable()); else colorbar->SetLookupTable(contourMapper->GetLookupTable()); // colorbar->SetWidth(0.085); colorbar->SetHeight(0.9); colorbar->SetPosition(0.9, 0.1); vtkTextProperty* text_prop_cb = colorbar->GetLabelTextProperty(); text_prop_cb->SetColor(1.0, 1.0, 1.0); colorbar->SetLabelTextProperty(text_prop_cb); double xrange[2]; double yrange[2]; gridfunc->GetXCoordinates()->GetRange(xrange); gridfunc->GetYCoordinates()->GetRange(yrange); vtkCubeAxesActor2D *caxis = vtkCubeAxesActor2D::New(); caxis->ZAxisVisibilityOff(); caxis->SetXLabel(xlabel.c_str()); caxis->SetYLabel(ylabel.c_str()); vtkCamera* mycam = rend->MakeCamera(); // vtkCamera::New(); //rend->SetActiveCamera(mycam); caxis->SetBounds( xrange[0], xrange[1], yrange[0], yrange[1], 0, 0); caxis->SetRanges( xrange[0], xrange[1], ymin, ymax, 0, 0); caxis->SetUseRanges(1); caxis->SetCamera( mycam ); caxis->SetNumberOfLabels(6); // doesn't work, rotate y label 90 degrees caxis->GetYAxisActor2D()->GetTitleTextProperty()->SetOrientation(90.); rend->AddActor(caxis); mycam->Delete(); caxis->Delete(); // handdrwan label // // X label // vtkVectorText *xlabel = vtkVectorText::New(); // vtkTransformPolyDataFilter *transxlabel = vtkTransformPolyDataFilter::New(); // vtkTransform *trans = vtkTransform::New(); // vtkPolyDataMapper *xlabmap = vtkPolyDataMapper::New(); // vtkFollower *xlabact = vtkFollower::New(); // locate and rotate as needed //double yranget = std::abs(yrange[1]-yrange[0]); //double xranget = std::abs(xrange[1]-xrange[0]); // trans->Identity(); // trans->Scale(5,5,5); // TODO, is 5 always OK??? // transxlabel->SetTransform(trans); // transxlabel->SetInputConnection(xlabel->GetOutputPort()); // // TODO input name // xlabel->SetText("Frequency [Hz]"); // transxlabel->SetInputConnection(xlabel->GetOutputPort()); // xlabmap->SetInputConnection(transxlabel->GetOutputPort()); // xlabact->SetMapper(xlabmap); // // centre between axis // xlabact->SetPosition( (xrange[0]+xrange[1])/2 - xlabact->GetCenter()[0], // yrange[0]-.2*yranget, 0 ); // //rend->AddActor(xlabact); // // Y label // vtkVectorText *ylabel = vtkVectorText::New(); // vtkTransformPolyDataFilter *transylabel = vtkTransformPolyDataFilter::New(); // vtkTransform *ytrans = vtkTransform::New(); // vtkPolyDataMapper *ylabmap = vtkPolyDataMapper::New(); // vtkFollower *ylabact = vtkFollower::New(); // // locate and rotate as needed // ytrans->Identity(); // ytrans->Scale(5,5,5); // TODO don't hard code, calc from window size maybe?? // ytrans->RotateZ(90); // transylabel->SetTransform(ytrans); // transylabel->SetInputConnection(ylabel->GetOutputPort()); // // ylabel->SetText("Pulse moment [A sec]"); // transylabel->SetInputConnection(ylabel->GetOutputPort()); // ylabmap->SetInputConnection(transylabel->GetOutputPort()); // ylabact->SetMapper(ylabmap); // ylabact->SetPosition( xrange[0]-.2*xranget, // (yrange[0]+yrange[1])/2 - ylabact->GetCenter()[1], // 0 ); // //rend->AddActor(ylabact); if (draw_surf) rend->AddActor(surfplot); rend->AddActor(contours); rend->AddActor(outline); if (draw_colorbar) { rend->AddActor(colorbar); } rend->SetBackground(0.25, 0.25, 0.25); // double xrange[2]; // double yrange[2]; // gridfunc->GetXCoordinates()->GetRange(xrange); // gridfunc->GetYCoordinates()->GetRange(yrange); // vtkCubeAxesActor *caxis = vtkCubeAxesActor::New(); // caxis->ZAxisVisibilityOff(); // caxis->SetCamera(rend->GetActiveCamera()); // caxis->SetBounds( xrange[0], xrange[1], yrange[0], yrange[1], 0, 1 ); // rend->AddActor(caxis); //rend->AddActor(yaxis); // // clean up // xlabel->Delete(); // transxlabel->Delete(); // trans->Delete(); // xlabmap->Delete(); // xlabact->Delete(); // // ylabel->Delete(); // transylabel->Delete(); // ytrans->Delete(); // ylabmap->Delete(); // ylabact->Delete(); // renderer is now set up! //caxis->Delete(); //yaxis->Delete(); contours->Delete(); contlines->Delete(); contourMapper->Delete(); outline->Delete(); outlinefilter->Delete(); outlineMapper->Delete(); colorbar->Delete(); surfplot->Delete(); mapper->Delete(); geometry->Delete(); } //============================================================================== /// Default constructor Quiver_VTK::Quiver_VTK(int px, int py) { has_data = false; xPix = px; yPix = py; gridfunc = vtkRectilinearGrid::New(); rend = vtkRenderer::New(); } /// Destructor Quiver_VTK::~Quiver_VTK() { gridfunc->Delete(); rend->Delete(); } /// Clear plot data before reuse void Quiver_VTK::purge() { assert(has_data); gridfunc->Delete(); rend->Delete(); gridfunc = vtkRectilinearGrid::New(); rend = vtkRenderer::New(); has_data = false; } void Quiver_VTK::renderer(double s) { assert(has_data); // filter to geometry primitive vtkRectilinearGridGeometryFilter *geometry = vtkRectilinearGridGeometryFilter::New(); geometry->SetInputData(gridfunc); // make a vector glyph vtkGlyphSource2D* vec = vtkGlyphSource2D::New(); vec->SetGlyphTypeToArrow(); vec->SetScale(s); vec->FilledOff(); vtkGlyph3D* glyph = vtkGlyph3D::New(); glyph->SetInputConnection(geometry->GetOutputPort()); glyph->SetSourceConnection(vec->GetOutputPort()); glyph->SetColorModeToColorByScalar(); // map gridfunction vtkPolyDataMapper *mapper = vtkPolyDataMapper::New(); mapper->SetInputConnection(glyph->GetOutputPort()); double tmp[2]; gridfunc->GetScalarRange(tmp); mapper->SetScalarRange(tmp[0], tmp[1]); // create plot quiver actor vtkActor *quiver_actor = vtkActor::New(); quiver_actor->SetMapper(mapper); // create colorbar vtkScalarBarActor *colorbar = vtkScalarBarActor::New(); colorbar->SetLookupTable(mapper->GetLookupTable()); colorbar->SetWidth(0.085); colorbar->SetHeight(0.9); colorbar->SetPosition(0.9, 0.1); vtkTextProperty* text_prop_cb = colorbar->GetLabelTextProperty(); text_prop_cb->SetColor(1.0, 1.0, 1.0); colorbar->SetLabelTextProperty(text_prop_cb); // create outline vtkOutlineFilter *outlinefilter = vtkOutlineFilter::New(); outlinefilter->SetInputConnection(geometry->GetOutputPort()); vtkPolyDataMapper *outlineMapper = vtkPolyDataMapper::New(); outlineMapper->SetInputConnection(outlinefilter->GetOutputPort()); vtkActor *outline = vtkActor::New(); outline->SetMapper(outlineMapper); outline->GetProperty()->SetColor(0, 0, 0); // add actors to renderer rend->AddActor(quiver_actor); rend->AddActor(colorbar); rend->AddActor(outline); rend->SetBackground(0.25, 0.25, 0.25); // renderer is now set up! // clean up outline->Delete(); outlinefilter->Delete(); outlineMapper->Delete(); vec->Delete(); glyph->Delete(); colorbar->Delete(); quiver_actor->Delete(); mapper->Delete(); } //============================================================================== /** Start interactive rendereing (default camera). * Sets resolution to (xPix,yPix) */ void matplot::render_interactive(vtkRenderer *rend, int xPix, int yPix) { vtkRenderWindow *renWin = vtkRenderWindow::New(); vtkRenderWindowInteractor *iren = vtkRenderWindowInteractor::New(); renWin->AddRenderer(rend); iren->SetRenderWindow(renWin); renWin->SetSize(xPix, yPix); // makes first frame look reasonable interactive renWin->Render(); renWin->Start(); // Start interactive rendering iren->Initialize(); iren->Start(); iren->Disable(); iren->Delete(); renWin->Delete(); } /** Start interactive rendereing (manual camera placement). * Sets resolution to (xPix,yPix) */ void matplot::render_interactive_cam(vtkRenderer *rend, int xPix, int yPix, double cam[3], double focal[3]) { rend->GetActiveCamera()->SetViewUp(0, 0, 1); rend->GetActiveCamera()->SetPosition(cam); rend->GetActiveCamera()->SetFocalPoint(focal); vtkRenderWindow *renWin = vtkRenderWindow::New(); vtkRenderWindowInteractor *iren = vtkRenderWindowInteractor::New(); renWin->AddRenderer(rend); iren->SetRenderWindow(renWin); renWin->SetSize(xPix, yPix); // Start interactive rendering iren->Initialize(); iren->Start(); iren->Delete(); renWin->Delete(); } /// Renders scene to PNG (default camera) void matplot::render_to_png(vtkRenderer *rend, int xPix, int yPix, std::string fname) { vtkRenderWindow *renWin = vtkRenderWindow::New(); renWin->AddRenderer(rend); renWin->SetSize(xPix, yPix); renWin->Render(); rend->Render(); vtkRenderLargeImage* renderLarge = vtkRenderLargeImage::New(); renderLarge->SetInput(rend); renderLarge->SetMagnification(1); vtkPNGWriter *pngfile = vtkPNGWriter::New(); pngfile->SetFileName(fname.c_str()); pngfile->SetInputConnection(renderLarge->GetOutputPort()); pngfile->Update(); pngfile->Update(); pngfile->Update(); pngfile->Write(); renderLarge->Delete(); pngfile->Delete(); renWin->Delete(); } /// Renders scene to PNG (manual camera placement) void matplot::render_to_png_cam(vtkRenderer *rend, int xPix, int yPix, std::string fname, double cam[3], double focal[3]) { rend->GetActiveCamera()->SetViewUp(0, 0, 1); rend->GetActiveCamera()->SetPosition(cam); rend->GetActiveCamera()->SetFocalPoint(focal); vtkRenderWindow *renWin = vtkRenderWindow::New(); renWin->AddRenderer(rend); renWin->SetSize(xPix, yPix); vtkRenderLargeImage* renderLarge = vtkRenderLargeImage::New(); renderLarge->SetInput(rend); renderLarge->SetMagnification(1); //vtkWindowToImageFilter *w2i = vtkWindowToImageFilter::New(); vtkPNGWriter *pngfile = vtkPNGWriter::New(); //pngfile->SetInputConnection(w2i->GetOutputPort()); pngfile->SetInputConnection(renderLarge->GetOutputPort()); pngfile->SetFileName(fname.c_str()); //w2i->SetInput(renWin); //w2i->Update(); renWin->Render(); pngfile->Write(); //w2i->Delete(); renderLarge->Delete(); pngfile->Delete(); renWin->Delete(); } #endif