Ignore:
Timestamp:
Apr 1, 2011 12:28:21 AM (13 years ago)
Author:
ldelgass
Message:

Fix pan/zoom for VTK contours, add command to control data range mapping for
multiple datasets. Still need to fix 3D panning, allow absolute rotation/
orientation of the camera.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/packages/vizservers/vtkvis/RpVtkRenderer.cpp

    r2146 r2194  
    77
    88#include <cfloat>
     9#include <cstring>
     10#include <cassert>
    911
    1012#include <vtkCamera.h>
     
    3941    _windowWidth(320),
    4042    _windowHeight(320),
    41     _useCumulativeRanges(true)
     43    _cameraZoomRatio(1),
     44    _useCumulativeRange(true),
     45    _cumulativeRangeOnlyVisible(false)
    4246{
    4347    _bgColor[0] = 0;
    4448    _bgColor[1] = 0;
    4549    _bgColor[2] = 0;
     50    _cameraPan[0] = 0;
     51    _cameraPan[1] = 0;
    4652    _cumulativeDataRange[0] = 0.0;
    4753    _cumulativeDataRange[1] = 1.0;
     
    268274        TRACE("After deleting graphics objects");
    269275
    270         // Update cumulative data range
    271         collectDataRanges(_cumulativeDataRange);
    272 
    273276        delete itr->second;
    274277        _dataSets.erase(itr);
    275278    } while (doAll && ++itr != _dataSets.end());
     279
     280    // Update cumulative data range
     281    collectDataRanges(_cumulativeDataRange, _cumulativeRangeOnlyVisible);
     282    updateRanges(_useCumulativeRange);
    276283
    277284    _needsRedraw = true;
     
    301308    if (ds) {
    302309        bool ret = ds->setDataFile(filename);
    303         collectDataRanges(_cumulativeDataRange);
    304         updateRanges(_useCumulativeRanges);
     310        collectDataRanges(_cumulativeDataRange, _cumulativeRangeOnlyVisible);
     311        updateRanges(_useCumulativeRange);
    305312        _needsRedraw = true;
    306313        return ret;
     
    317324    if (ds) {
    318325        bool ret = ds->setData(data, nbytes);
    319         collectDataRanges(_cumulativeDataRange);
    320         updateRanges(_useCumulativeRanges);
     326        collectDataRanges(_cumulativeDataRange, _cumulativeRangeOnlyVisible);
     327        updateRanges(_useCumulativeRange);
    321328        _needsRedraw = true;
    322329        return ret;
    323330    } else
    324331        return false;
     332}
     333
     334/**
     335 * \brief Control whether the cumulative data range of datasets is used for
     336 * colormapping and contours
     337 */
     338void Renderer::setUseCumulativeDataRange(bool state, bool onlyVisible)
     339{
     340    if (state != _useCumulativeRange) {
     341        _useCumulativeRange = state;
     342        _cumulativeRangeOnlyVisible = onlyVisible;
     343        collectDataRanges(_cumulativeDataRange, _cumulativeRangeOnlyVisible);
     344        updateRanges(_useCumulativeRange);
     345        _needsRedraw = true;
     346    }
    325347}
    326348
     
    384406    _cubeAxesActor2D->ScalingOff();
    385407    //_cubeAxesActor2D->SetShowActualBounds(0);
    386     _cubeAxesActor2D->SetFontFactor(2);
     408    _cubeAxesActor2D->SetFontFactor(1.25);
    387409    // Use "nice" range and number of ticks/labels
    388410    _cubeAxesActor2D->GetXAxisActor2D()->AdjustLabelsOn();
     
    744766        pc->setDataSet(ds);
    745767
     768        // Use the default color map
     769        vtkSmartPointer<vtkLookupTable> lut = vtkSmartPointer<vtkLookupTable>::New();
     770        ColorMap *cmap = getColorMap("default");
     771        lut->DeepCopy(cmap->getLookupTable());
     772        if (_useCumulativeRange) {
     773            lut->SetRange(_cumulativeDataRange);
     774        } else {
     775            double range[2];
     776            ds->getDataRange(range);
     777            lut->SetRange(range);
     778        }
     779
     780        pc->setLookupTable(lut);
     781
    746782        _renderer->AddActor(pc->getActor());
    747783    } while (doAll && ++itr != _dataSets.end());
     
    802838        lut->DeepCopy(cmap->getLookupTable());
    803839
     840        if (_useCumulativeRange) {
     841            lut->SetRange(_cumulativeDataRange);
     842        } else {
     843            if (itr->second->getDataSet() != NULL) {
     844                double range[2];
     845                itr->second->getDataSet()->getDataRange(range);
     846                lut->SetRange(range);
     847            }
     848        }
     849
    804850        itr->second->setLookupTable(lut);
    805851    } while (doAll && ++itr != _pseudoColors.end());
     
    10681114
    10691115    do {
    1070         itr->second->setContours(numContours);
     1116        if (_useCumulativeRange) {
     1117            itr->second->setContours(numContours, _cumulativeDataRange);
     1118        } else {
     1119            itr->second->setContours(numContours);
     1120        }
    10711121    } while (doAll && ++itr != _contours.end());
    10721122
     
    15201570    _windowHeight = height;
    15211571    _renderWindow->SetSize(_windowWidth, _windowHeight);
    1522 #ifdef notdef
    1523     setCameraZoomRegion(_imgWorldOrigin[0], _imgWorldOrigin[1],
    1524                         _imgWorldDims[0], _imgWorldDims[1]);
    1525 #endif
     1572    if (_cameraMode == IMAGE) {
     1573        setCameraZoomRegion(_imgWorldOrigin[0], _imgWorldOrigin[1],
     1574                            _imgWorldDims[0], _imgWorldDims[1]);
     1575    }
    15261576    _needsRedraw = true;
    15271577}
     
    15771627}
    15781628
     1629/**
     1630 * \brief Get the current camera mode
     1631 */
     1632Renderer::CameraMode Renderer::getCameraMode() const
     1633{
     1634    return _cameraMode;
     1635}
     1636
    15791637void Renderer::storeCameraOrientation()
    15801638{
     
    16141672        _renderer->ResetCamera();
    16151673        _renderer->ResetCameraClippingRange();
    1616     }
     1674        computeScreenWorldCoords();
     1675    }
     1676    _cameraZoomRatio = 1;
     1677    _cameraPan[0] = 0;
     1678    _cameraPan[1] = 0;
    16171679    _needsRedraw = true;
    16181680}
     
    16351697    _renderer->ResetCameraClippingRange();
    16361698    storeCameraOrientation();
    1637     _needsRedraw = true;
    1638 }
    1639 
    1640 /**
    1641  * \brief Perform a relative 2D translation of the camera
    1642  *
    1643  * \param[in] x World coordinate horizontal panning
    1644  * \param[in] y World coordinate vertical panning
    1645  */
    1646 void Renderer::panCamera(double x, double y)
    1647 {
     1699    computeScreenWorldCoords();
     1700    _needsRedraw = true;
     1701}
     1702
     1703/**
     1704 * \brief Perform a 2D translation of the camera
     1705 *
     1706 * \param[in] x [0,1] Viewport coordinate horizontal panning
     1707 * \param[in] y [0,1] Viewport coordinate vertical panning (with origin at top)
     1708 * \param[in] absolute Control if pan amount is relative to current or absolute
     1709 */
     1710void Renderer::panCamera(double x, double y, bool absolute)
     1711{
     1712    // Reverse x rather than y, since we are panning the camera, and client
     1713    // expects to be panning/moving the object
     1714    x = -x * _screenWorldCoords[2];
     1715    y = y * _screenWorldCoords[3];
     1716
     1717    if (absolute) {
     1718        double panAbs[2];
     1719        panAbs[0] = x;
     1720        panAbs[1] = y;
     1721        x -= _cameraPan[0];
     1722        y -= _cameraPan[1];
     1723        _cameraPan[0] = panAbs[0];
     1724        _cameraPan[1] = panAbs[1];
     1725    } else {
     1726        _cameraPan[0] += x;
     1727        _cameraPan[1] += y;
     1728    }
    16481729    if (_cameraMode == IMAGE) {
    16491730        _imgWorldOrigin[0] += x;
     
    16511732        setCameraZoomRegion(_imgWorldOrigin[0], _imgWorldOrigin[1],
    16521733                            _imgWorldDims[0], _imgWorldDims[1]);
    1653         _needsRedraw = true;
    1654         return;
    1655     }
    1656     vtkSmartPointer<vtkCamera> camera = _renderer->GetActiveCamera();
    1657     vtkSmartPointer<vtkTransform> trans = vtkSmartPointer<vtkTransform>::New();
    1658     trans->Translate(x, y, 0);
    1659     camera->ApplyTransform(trans);
    1660     _renderer->ResetCameraClippingRange();
    1661     storeCameraOrientation();
     1734    } else {
     1735        vtkSmartPointer<vtkCamera> camera = _renderer->GetActiveCamera();
     1736        vtkSmartPointer<vtkTransform> trans = vtkSmartPointer<vtkTransform>::New();
     1737        trans->Translate(x, y, 0);
     1738        camera->ApplyTransform(trans);
     1739        _renderer->ResetCameraClippingRange();
     1740        storeCameraOrientation();
     1741        computeScreenWorldCoords();
     1742    }
    16621743    _needsRedraw = true;
    16631744}
     
    16671748 *
    16681749 * \param[in] z Ratio to change zoom (greater than 1 is zoom in, less than 1 is zoom out)
    1669  */
    1670 void Renderer::zoomCamera(double z)
    1671 {
     1750 * \param[in] absolute Control if zoom factor is relative to current setting or absolute
     1751 */
     1752void Renderer::zoomCamera(double z, bool absolute)
     1753{
     1754    if (absolute) {
     1755        assert(_cameraZoomRatio > 0.0);
     1756        double zAbs = z;
     1757        z *= 1.0/_cameraZoomRatio;
     1758        _cameraZoomRatio = zAbs;
     1759    } else {
     1760        _cameraZoomRatio *= z;
     1761    }
    16721762    if (_cameraMode == IMAGE) {
    16731763        double dx = _imgWorldDims[0];
     
    16811771        setCameraZoomRegion(_imgWorldOrigin[0], _imgWorldOrigin[1],
    16821772                            _imgWorldDims[0], _imgWorldDims[1]);
    1683         _needsRedraw = true;
    1684         return;
    1685     }
    1686     vtkSmartPointer<vtkCamera> camera = _renderer->GetActiveCamera();
    1687     camera->Zoom(z); // Change perspective FOV angle or ortho parallel scale
    1688     //camera->Dolly(z); // Move camera forward/back
    1689     _renderer->ResetCameraClippingRange();
    1690     storeCameraOrientation();
     1773    } else {
     1774        vtkSmartPointer<vtkCamera> camera = _renderer->GetActiveCamera();
     1775        camera->Zoom(z); // Change perspective FOV angle or ortho parallel scale
     1776        //camera->Dolly(z); // Move camera forward/back
     1777        _renderer->ResetCameraClippingRange();
     1778        storeCameraOrientation();
     1779    }
    16911780    _needsRedraw = true;
    16921781}
     
    17041793    double camPos[2];
    17051794
    1706     int pxOffsetX = 75;
     1795    int pxOffsetX = 85;
    17071796    int pxOffsetY = 75;
    17081797    int outerGutter = 15;
    17091798
    17101799    int imgHeightPx = _windowHeight - pxOffsetY - outerGutter;
    1711     double pxToWorld = height / imgHeightPx;
     1800    int imgWidthPx = _windowWidth - pxOffsetX - outerGutter;
     1801    double pxToWorld;
     1802    if (height > width)
     1803        pxToWorld = height / imgHeightPx;
     1804    else
     1805        pxToWorld = width / imgWidthPx;
    17121806    double offsetX = pxOffsetX * pxToWorld;
    17131807    double offsetY = pxOffsetY * pxToWorld;
     
    17491843                                _imgWorldOrigin[1], _imgWorldOrigin[1] + _imgWorldDims[1], 0, 0);
    17501844
     1845    // Compute screen world coordinates
     1846    computeScreenWorldCoords();
     1847
    17511848#ifdef DEBUG
    17521849    printCameraInfo(camera);
     
    17561853}
    17571854
     1855void Renderer::computeScreenWorldCoords()
     1856{
     1857    // Start with viewport coords [-1,1]
     1858    double x0 = -1;
     1859    double y0 = -1;
     1860    double z0 = 0;
     1861    double x1 = 1;
     1862    double y1 = 1;
     1863    double z1 = 0;
     1864
     1865    vtkMatrix4x4 *mat = vtkMatrix4x4::New();
     1866    double result[4];
     1867
     1868    // get the perspective transformation from the active camera
     1869    mat->DeepCopy(_renderer->GetActiveCamera()->
     1870                  GetCompositeProjectionTransformMatrix(_renderer->GetTiledAspectRatio(),0,1));
     1871
     1872    // use the inverse matrix
     1873    mat->Invert();
     1874
     1875    // Transform point to world coordinates
     1876    result[0] = x0;
     1877    result[1] = y0;
     1878    result[2] = z0;
     1879    result[3] = 1.0;
     1880
     1881    mat->MultiplyPoint(result, result);
     1882
     1883    // Get the transformed vector & set WorldPoint
     1884    // while we are at it try to keep w at one
     1885    if (result[3]) {
     1886        x0 = result[0] / result[3];
     1887        y0 = result[1] / result[3];
     1888        z0 = result[2] / result[3];
     1889    }
     1890
     1891    result[0] = x1;
     1892    result[1] = y1;
     1893    result[2] = z1;
     1894    result[3] = 1.0;
     1895
     1896    mat->MultiplyPoint(result, result);
     1897
     1898    if (result[3]) {
     1899        x1 = result[0] / result[3];
     1900        y1 = result[1] / result[3];
     1901        z1 = result[2] / result[3];
     1902    }
     1903
     1904    mat->Delete();
     1905
     1906    _screenWorldCoords[0] = x0;
     1907    _screenWorldCoords[1] = y0;
     1908    _screenWorldCoords[2] = x1 - x0;
     1909    _screenWorldCoords[3] = y1 - y0;
     1910}
     1911
     1912/**
     1913 * \brief Get the world coordinates of the image camera plot area
     1914 *
     1915 * \param[out] xywh Array to hold x,y,width,height world coordinates
     1916 */
     1917void Renderer::getCameraZoomRegion(double xywh[4]) const
     1918{
     1919    xywh[0] = _imgWorldOrigin[0];
     1920    xywh[1] = _imgWorldOrigin[1];
     1921    xywh[2] = _imgWorldDims[0];
     1922    xywh[3] = _imgWorldDims[1];
     1923}
     1924
     1925/**
     1926 * \brief Get the world origin and dimensions of the screen
     1927 *
     1928 * \param[out] xywh Array to hold x,y,width,height world coordinates
     1929 */
     1930void Renderer::getScreenWorldCoords(double xywh[4]) const
     1931{
     1932    memcpy(xywh, _screenWorldCoords, sizeof(double)*4);
     1933}
     1934
     1935/**
     1936 * \brief Compute bounding box containing the two input bounding boxes
     1937 *
     1938 * \param[out] boundsDest Union of the two input bounding boxes
     1939 * \param[in] bounds1 Input bounding box
     1940 * \param[in] bounds2 Input bounding box
     1941 */
    17581942void Renderer::mergeBounds(double *boundsDest,
    17591943                           const double *bounds1, const double *bounds2)
     
    18091993
    18101994/**
    1811  * \brief Update data ranges for color-mapping
     1995 * \brief Update data ranges for color-mapping and contours
    18121996 *
    18131997 * \param[in] useCumulative Use cumulative range of all DataSets
     
    18302014        }
    18312015    }
     2016    for (Contour2DHashmap::iterator itr = _contours.begin();
     2017         itr != _contours.end(); ++itr) {
     2018        // Only need to update range if using evenly spaced contours
     2019        if (itr->second->getContourList().empty()) {
     2020            if (useCumulative) {
     2021                itr->second->setContours(itr->second->getNumContours(), _cumulativeDataRange);
     2022            } else {
     2023                itr->second->setContours(itr->second->getNumContours());
     2024            }
     2025        }
     2026    }
    18322027}
    18332028
     
    18362031 *
    18372032 * \param[inout] range Data range of all DataSets
    1838  */
    1839 void Renderer::collectDataRanges(double *range)
     2033 * \param[in] onlyVisible Only collect range of visible DataSets
     2034 */
     2035void Renderer::collectDataRanges(double *range, bool onlyVisible)
    18402036{
    18412037    range[0] = DBL_MAX;
     
    18442040    for (DataSetHashmap::iterator itr = _dataSets.begin();
    18452041         itr != _dataSets.end(); ++itr) {
    1846         double r[2];
    1847         itr->second->getDataRange(r);
    1848         range[0] = min2(range[0], r[0]);
    1849         range[1] = max2(range[1], r[1]);
     2042        if (!onlyVisible || itr->second->getVisibility()) {
     2043            double r[2];
     2044            itr->second->getDataRange(r);
     2045            range[0] = min2(range[0], r[0]);
     2046            range[1] = max2(range[1], r[1]);
     2047        }
    18502048    }
    18512049    if (range[0] == DBL_MAX)
     
    18752073    _imgWorldDims[0] = bounds[1] - bounds[0];
    18762074    _imgWorldDims[1] = bounds[3] - bounds[2];
     2075    _cameraPan[0] = 0;
     2076    _cameraPan[1] = 0;
     2077    _cameraZoomRatio = 1;
    18772078
    18782079    if (_cameraMode == IMAGE) {
     
    18852086        resetAxes();
    18862087        _renderer->ResetCamera();
     2088        computeScreenWorldCoords();
    18872089    } else if (_cameraMode == PERSPECTIVE) {
    18882090        _renderer->GetActiveCamera()->ParallelProjectionOff();
    18892091        resetAxes();
    18902092        _renderer->ResetCamera();
     2093        computeScreenWorldCoords();
    18912094    }
    18922095}
     
    19332136void Renderer::setVisibility(const DataSetId& id, bool state)
    19342137{
     2138    DataSetHashmap::iterator itr;
     2139
     2140    bool doAll = false;
     2141
     2142    if (id.compare("all") == 0) {
     2143        itr = _dataSets.begin();
     2144        doAll = true;
     2145    } else {
     2146        itr = _dataSets.find(id);
     2147    }
     2148    if (itr == _dataSets.end()) {
     2149        ERROR("Unknown dataset %s", id.c_str());
     2150        return;
     2151    }
     2152
     2153    do {
     2154        itr->second->setVisibility(state);
     2155    } while (doAll && ++itr != _dataSets.end());
     2156
    19352157    setPseudoColorVisibility(id, state);
    19362158    setContourVisibility(id, state);
     
    20142236    double *worldCoords = coord->GetComputedWorldValue(_renderer);
    20152237
    2016 #ifdef DEBUG
    20172238    TRACE("Pixel coords: %d, %d\nWorld coords: %.12e, %.12e, %12e", x, y,
    20182239          worldCoords[0],
    20192240          worldCoords[1],
    20202241          worldCoords[2]);
    2021 #endif
    20222242
    20232243    return getDataValue(id, worldCoords[0], worldCoords[1], worldCoords[2]);
Note: See TracChangeset for help on using the changeset viewer.