Matthias Pospiech | 17 Apr 09:47

Re: Help with understanding QwtRasterData needed

Using you hint about the clone function made the whole thing work:
    virtual QwtRasterData *copy() const
    {
        SpectrogramData *clone = new SpectrogramData();
        clone->setRangeX(m_RangeX.min, m_RangeX.max);
        clone->setRangeY(m_RangeY.min, m_RangeY.max);
        clone->setData(m_Array, m_DataSize.x, m_DataSize.y);
        return clone;
    }
It however requires to set the Range of the Data bevor setting the data 
which is not nice in term of the implementation.

I however still have the problem that the axis do not match the Data 
size (goes from -0.6 to 0.6 instead of 0-1024) and therefore no data is 
displayed since the value of alwyas 0.

Uwe Rathmann schrieb:
> a) YourRasterData::range()
>
> If you have a color map from blue to red you also need to define which value 
> means blue and which means red. Values above or below are mapped to the 
> borders of the color map. Range is what we call "Wertebereich" in German.
>   
That has been implmented as
    virtual QwtDoubleInterval range() const
    {
        return QwtDoubleInterval(m_minValue, m_maxValue);
    }

> b) YourRasterData::value()
>
> Here you have to return the value at a specific position. Usually your 2D 
> array will have a different raster, so you have to do some resampling here ( 
> f.e. next neighbour ).
>   
That was a bit tricky, but works now. As you see there is some resampling:
    double value(double x, double y) const
    {
        int xpos = (int)((x - m_RangeX.min) * m_RealToArray.x);
        int ypos = (int)((y - m_RangeY.min) * m_RealToArray.y);
        return m_Array[ArrPos(xpos, ypos)];
    }

> The following methods are optional, but might speedup the process of rendering 
> a lot:
>
> c) YourRasterData::initRaster()
>   
> The item tells the data object in advance about the raster it is going to 
> render. F.e. if you have a huge number of samples in a file, you can resample 
> and load it into memory here.
>
>   
It is defined as
    void initRaster(const QwtDoubleRect &, const QSize &
but I have no idea what I should do. I could reply with the area of the 
data and the pixels in each direction, but the implementation is with const,
so I cannot do that. And what I should do to resampl and load my data 
into memory is not obvious to me.

> d) YourRasterData::discardRaster()
>
> The item tells the data object, that the rendering of the image is complete. 
> So you can do some cleanups here.
>   
How do I know when the image is complete?

> e) YourData::rasterHint
>
> Here you can return the resolution of your 2D matrix and limit the resolution 
> of the image, that is rendered. ( There is no need to render an image in a 
> higher resolution than the data has ). On screen this is not so important, 
> but for printing ( f.e 1200dpi on a A0 plotter ) it can be substantial.
>   
This step would really make sense for me.

It is defined as
QSize QwtRasterData::rasterHint (const QwtDoubleRect & ) const

I however do not know what the parameter QwtDoubleRect contains.
Is it the real position of the data (in the coordinates of the data) ?
The I could convert with the step I do within value() to the pixel:
        int xpos = (int)((x - m_RangeX.min) * m_RealToArray.x);
        int ypos = (int)((y - m_RangeY.min) * m_RealToArray.y);

-------------

Here the class in its current shape:

class SpectrogramData: public QwtRasterData
{
private:
    double * m_Array;
    double m_minValue;
    double m_maxValue;

    struct structMinMax{
        double min;
        double max;
    };
    structMinMax m_RangeX;
    structMinMax m_RangeY;
    struct structXY{
        double x;
        double y;
    };
    structXY m_DataSize;
    structXY m_RealToArray;

public:
    // Constructor giving back the QwtRasterData Constructor
    SpectrogramData(): QwtRasterData()
    {
        m_Array = NULL;
    }

    virtual QwtRasterData *copy() const
    {
        SpectrogramData *clone = new SpectrogramData();
        clone->setRangeX(m_RangeX.min, m_RangeX.max);
        clone->setRangeY(m_RangeY.min, m_RangeY.max);
        clone->setData(m_Array, m_DataSize.x, m_DataSize.y);
        return clone;
    }

    virtual QwtDoubleInterval range() const
    {
        return QwtDoubleInterval(m_minValue, m_maxValue);
    }

    double value(double x, double y) const
    {
        int xpos = (int)((x - m_RangeX.min) * m_RealToArray.x);
        int ypos = (int)((y - m_RangeY.min) * m_RealToArray.y);
        double dvalue = m_Array[ArrPos(xpos, ypos)];
        return dvalue;
    }

    void setData(double * Array, int sizex, int sizey)
    {
        m_DataSize.x = sizex;
        m_DataSize.y = sizey;
        int size = sizex * sizey;
        MinMaxArrayValue(Array, size, &m_minValue, &m_maxValue);
        if (m_Array != NULL)
            delete [] m_Array;
        m_Array = new double [size];
        memcpy(m_Array, Array, size * sizeof(double));

        m_RealToArray.x = (m_RangeX.max - m_RangeX.min) / m_DataSize.x;
        m_RealToArray.y = (m_RangeY.max - m_RangeY.min) / m_DataSize.y;
    }

    void setRangeX(const double min, const double max)
    {
        m_RangeX.min = min;
        m_RangeX.max = max;
    }

    void setRangeY(const double min, const double max)
    {
        m_RangeY.min = min;
        m_RangeY.max = max;       
    }

    int ArrPos(const int x, const int y) const
    {
        return y + m_DataSize.y * x;
    }

};

-------------------------------------------------------------------------
This SF.net email is sponsored by the 2008 JavaOne(SM) Conference 
Don't miss this year's exciting event. There's still time to save $100. 
Use priority code J8TL2D2. 
http://ad.doubleclick.net/clk;198757673;13503038;p?http://java.sun.com/javaone

Gmane