/*========================================================================= Program: Visualization Toolkit Module: vtkHeatmapItem.h Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ /** * @class vtkHeatmapItem * @brief A 2D graphics item for rendering a heatmap * * * This item draws a heatmap as a part of a vtkContextScene. * * .SEE ALSO * vtkTable */ #ifndef vtkHeatmapItem_h #define vtkHeatmapItem_h #include "vtkContextItem.h" #include "vtkViewsInfovisModule.h" // For export macro #include "vtkNew.h" // For vtkNew ivars #include "vtkSmartPointer.h" // For vtkSmartPointer ivars #include "vtkStdString.h" // For get/set ivars #include "vtkVector.h" // For vtkVector2f ivar #include // For column ranges #include // For blank row support #include // For row mapping class vtkBitArray; class vtkCategoryLegend; class vtkColorLegend; class vtkLookupTable; class vtkStringArray; class vtkTable; class vtkTooltipItem; class vtkVariantArray; class VTKVIEWSINFOVIS_EXPORT vtkHeatmapItem : public vtkContextItem { public: static vtkHeatmapItem* New(); vtkTypeMacro(vtkHeatmapItem, vtkContextItem); void PrintSelf(ostream& os, vtkIndent indent) override; /** * Set the table that this item draws. The first column of the table * must contain the names of the rows. */ virtual void SetTable(vtkTable* table); /** * Get the table that this item draws. */ vtkTable* GetTable(); /** * Get the table that this item draws. */ vtkStringArray* GetRowNames(); //@{ /** * Get/Set the name of the column that specifies the name * of this table's rows. By default, we assume this * column will be named "name". If no such column can be * found, we then assume that the 1st column in the table * names the rows. */ vtkGetMacro(NameColumn, vtkStdString); vtkSetMacro(NameColumn, vtkStdString); //@} /** * Set which way the table should face within the visualization. */ void SetOrientation(int orientation); /** * Get the current heatmap orientation. */ int GetOrientation(); /** * Get the angle that row labels should be rotated for the corresponding * heatmap orientation. For the default orientation (LEFT_TO_RIGHT), this * is 0 degrees. */ double GetTextAngleForOrientation(int orientation); //@{ /** * Set the position of the heatmap. */ vtkSetVector2Macro(Position, float); void SetPosition(const vtkVector2f& pos); //@} //@{ /** * Get position of the heatmap. */ vtkGetVector2Macro(Position, float); vtkVector2f GetPositionVector(); //@} //@{ /** * Get/Set the height of the cells in our heatmap. * Default is 18 pixels. */ vtkGetMacro(CellHeight, double); vtkSetMacro(CellHeight, double); //@} //@{ /** * Get/Set the width of the cells in our heatmap. * Default is 36 pixels. */ vtkGetMacro(CellWidth, double); vtkSetMacro(CellWidth, double); //@} /** * Get the bounds for this item as (Xmin,Xmax,Ymin,Ymax). */ virtual void GetBounds(double bounds[4]); /** * Mark a row as blank, meaning that no cells will be drawn for it. * Used by vtkTreeHeatmapItem to represent missing data. */ void MarkRowAsBlank(const std::string& rowName); /** * Paints the table as a heatmap. */ bool Paint(vtkContext2D* painter) override; //@{ /** * Get the width of the largest row or column label drawn by this * heatmap. */ vtkGetMacro(RowLabelWidth, float); vtkGetMacro(ColumnLabelWidth, float); //@} /** * Enum for Orientation. */ enum { LEFT_TO_RIGHT, UP_TO_DOWN, RIGHT_TO_LEFT, DOWN_TO_UP }; /** * Returns true if the transform is interactive, false otherwise. */ bool Hit(const vtkContextMouseEvent& mouse) override; /** * Display a tooltip when the user mouses over a cell in the heatmap. */ bool MouseMoveEvent(const vtkContextMouseEvent& event) override; /** * Display a legend for a column of data. */ bool MouseDoubleClickEvent(const vtkContextMouseEvent& event) override; protected: vtkHeatmapItem(); ~vtkHeatmapItem() override; vtkVector2f PositionVector; float* Position; /** * Generate some data needed for painting. We cache this information as * it only needs to be generated when the input data changes. */ virtual void RebuildBuffers(); /** * This function does the bulk of the actual work in rendering our heatmap. */ virtual void PaintBuffers(vtkContext2D* painter); /** * This function returns a bool indicating whether or not we need to rebuild * our cached data before painting. */ virtual bool IsDirty(); /** * Generate a separate vtkLookupTable for each column in the table. */ void InitializeLookupTables(); /** * Helper function. Find the prominent, distinct values in the specified * column of strings and add it to our "master list" of categorical values. * This list is then used to generate a vtkLookupTable for all categorical * data within the heatmap. */ void AccumulateProminentCategoricalDataValues(vtkIdType column); /** * Setup the default lookup table to use for continuous (not categorical) * data. */ void GenerateContinuousDataLookupTable(); /** * Setup the default lookup table to use for categorical (not continuous) * data. */ void GenerateCategoricalDataLookupTable(); /** * Get the value for the cell of the heatmap located at scene position (x, y) * This function assumes the caller has already determined that (x, y) falls * within the heatmap. */ std::string GetTooltipText(float x, float y); /** * Calculate the extent of the data that is visible within the window. * This information is used to ensure that we only draw details that * will be seen by the user. This improves rendering speed, particularly * for larger data. */ void UpdateVisibleSceneExtent(vtkContext2D* painter); /** * Returns true if any part of the line segment defined by endpoints * (x0, y0), (x1, y1) falls within the extent of the currently * visible scene. Returns false otherwise. */ bool LineIsVisible(double x0, double y0, double x1, double y1); /** * Compute the extent of the heatmap. This does not include * the text labels. */ void ComputeBounds(); /** * Compute the width of our longest row label and the width of our * longest column label. These values are used by GetBounds(). */ void ComputeLabelWidth(vtkContext2D* painter); // Setup the position, size, and orientation of this heatmap's color // legend based on the heatmap's current orientation. void PositionColorLegend(int orientation); // Setup the position, size, and orientation of this heatmap's // legends based on the heatmap's current orientation. void PositionLegends(int orientation); vtkSmartPointer Table; vtkStringArray* RowNames; vtkStdString NameColumn; private: vtkHeatmapItem(const vtkHeatmapItem&) = delete; void operator=(const vtkHeatmapItem&) = delete; unsigned long HeatmapBuildTime; vtkNew CategoryLegend; vtkNew ColorLegend; vtkNew Tooltip; vtkNew ContinuousDataLookupTable; vtkNew CategoricalDataLookupTable; vtkNew ColorLegendLookupTable; vtkNew CategoricalDataValues; vtkNew CategoryLegendValues; double CellWidth; double CellHeight; std::map > ColumnRanges; std::vector SceneRowToTableRowMap; std::vector SceneColumnToTableColumnMap; std::set BlankRows; double MinX; double MinY; double MaxX; double MaxY; double SceneBottomLeft[3]; double SceneTopRight[3]; float RowLabelWidth; float ColumnLabelWidth; vtkBitArray* CollapsedRowsArray; vtkBitArray* CollapsedColumnsArray; bool LegendPositionSet; }; #endif