00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #ifndef GRIDPLOT_H
00030 #define GRIDPLOT_H
00031
00032 #include "GraphContentLayer.h"
00033 #include "LayerPainterRequest.h"
00034
00035 namespace SciFigs {
00036
00037 class PaletteEditor;
00038 class GridEditProperties;
00039 class IrregularGrid2DDraw;
00040
00041 class SCIFIGS_EXPORT GridPlot : public GraphContentLayer
00042 {
00043 Q_OBJECT
00044 Q_PROPERTY(bool smooth READ smooth WRITE setSmooth SCRIPTABLE true);
00045 Q_PROPERTY(bool showGrid READ showGrid WRITE setShowGrid SCRIPTABLE true);
00046 public:
00047 GridPlot(AxisWindow * parent);
00048 ~GridPlot();
00049
00050 virtual const QString& xml_tagName() const {return xmlGridPlotTag;}
00051 static const QString xmlGridPlotTag;
00052
00053 virtual bool hasProperties() {return true;}
00054 virtual void addProperties(PropertyProxy * pp);
00055 virtual void removeProperties(PropertyProxy * pp);
00056 virtual void properties(PropertyWidget * w) const;
00057 virtual void setProperty(uint wid, int pid, QVariant val);
00058
00059 const ColorPalette& palette() const {return _pal;}
00060 void setLinearPalette(double minVal, double maxVal);
00061
00062 bool showGrid() const {return _showGrid;}
00063 void setShowGrid(bool b) {_showGrid=b;}
00064
00065 bool smooth() const {return _smooth;}
00066 void setSmooth(bool b) {_smooth=b;}
00067
00068 Rect::Area fillType() const {return _fillType;}
00069 void setFillType(Rect::Area ft) {_fillType=ft;}
00070
00071 double fillValue() const {return _fillValue;}
00072 void setFillValue(double v) {_fillValue=v;}
00073 public slots:
00074 void setPalette(const ColorPalette& pal);
00075 signals:
00076 void paletteChanged(const ColorPalette& pal);
00077 protected:
00078 template <class ValueType>
00079 static void drawGrid2DYSmooth(const Grid2D<ValueType>& grid, ColorPalette pal,
00080 const LayerPainterRequest& lp, QPainter& p);
00081 template <class ValueType>
00082 static void drawGrid2DBlock(const Grid2D<ValueType>& grid, ColorPalette pal,
00083 const LayerPainterRequest& lp, QPainter& p);
00084 static void drawGrid2DSmooth(const IrregularGrid2D& grid, ColorPalette pal,
00085 const LayerPainterRequest& lp, QPainter& p, IrregularGrid2DDraw& d);
00086 static void drawGrid2DBlock(const IrregularGrid2D& grid, ColorPalette pal,
00087 const LayerPainterRequest& lp, QPainter& p, const IrregularGrid2DDraw& d);
00088 void drawGridLines(QPainter& p, const IrregularGrid2DDraw& d) const;
00089 template <class ValueType>
00090 void drawGridLines(const Grid2D<ValueType>& grid,
00091 const LayerPainterRequest& lp, QPainter& p) const;
00092
00093 virtual void xml_writeChildren(XML_WRITECHILDREN_ARGS) const;
00094 virtual XMLMember xml_member(XML_MEMBER_ARGS);
00095 virtual void xml_polishChild(XML_POLISHCHILD_ARGS);
00096
00097 Rect::Area _fillType;
00098 double _fillValue;
00099 ColorPalette _pal;
00100 private:
00101 bool _showGrid;
00102 bool _smooth;
00103
00104 static uint _tabPalette, _tabGrid;
00105 private:
00106 static inline bool notEnd(int i, int stopi, int di);
00107 };
00108
00109 template <class ValueType>
00110 void GridPlot::drawGrid2DYSmooth(const Grid2D<ValueType>& grid, ColorPalette pal,
00111 const LayerPainterRequest& lp, QPainter& p)
00112 {
00113 TRACE;
00114 const GraphContentOptions& gc=lp.options();
00115
00116 double startx, ddx, stopx, x;
00117 double starty, ddy, stopy, y;
00118 double coef;
00119 int startix, startiy, dmx, dmy;
00120 int y1, y2, x1, x2, dx, dy, dlim, limx, limxdy, yn1, yn2;
00121
00122 ddx=grid.deltaX();
00123 ddy=grid.deltaY();
00124 startx=grid.origin().x() - ddx * 0.5;
00125 starty=grid.origin().y();
00126 stopx=startx + (double) grid.nx() * ddx;
00127 stopy=starty + (double) (grid.ny() - 1) * ddy;
00128
00129
00130 if(startx > gc.xVisMin()) {
00131 if(startx > gc.xVisMax()) return ;
00132 startix=0;
00133 } else {
00134 if(stopx < gc.xVisMin()) return ;
00135 startix=(int) floor(( gc.xVisMin() - startx)/ddx);
00136 startx += (double) startix * ddx;
00137 }
00138 stopx -= 0.5 * ddx;
00139 if(stopx > gc.xVisMax()) stopx=gc.xVisMax();
00140
00141
00142 if(starty > gc.yVisMin()) {
00143 if(starty > gc.yVisMax()) return ;
00144 y=starty;
00145 startiy=0;
00146 } else {
00147 if(stopy < gc.yVisMin()) return ;
00148 startiy=(int) floor(( gc.yVisMin() - starty)/ddy);
00149 y=starty + (double) startiy * ddy;
00150 }
00151 stopy -= 0.5 * ddy;
00152 if(stopy > gc.yVisMax()) stopy=gc.yVisMax();
00153
00154
00155 if(fabs( gc.ax() * ddx) < 1.0) {
00156 dmx=(int) ceil(( double) 1.0/fabs(gc.ax() * ddx) );
00157 ddx *= (double) dmx;
00158 } else dmx=1;
00159
00160
00161 if(fabs( gc.ay() * ddy) < 1.0) {
00162 dmy=(int) ceil(( double) 1.0/fabs(gc.ay() * ddy) );
00163 ddy *= (double) dmy;
00164 dmy *= grid.nx();
00165 } else dmy=grid.nx();
00166
00167 const double * valx, * valy, * valxdy;
00168 valy=grid.valuePointer(startix, startiy);
00169 y2=gc.yr2s(y);
00170 for( ; y < stopy; ) {
00171 if(lp.terminated()) return;
00172 y1=y2;
00173 y += ddy;
00174 y2=gc.yr2s(y);
00175 dy=y1 - y2;
00176 valx=valy;
00177 valy += dmy;
00178 valxdy=valy;
00179 x2=gc.xr2s(startx);
00180 for(x=startx; x < stopx; valx += dmx, valxdy += dmx) {
00181 x1=x2;
00182 x += ddx;
00183 x2=gc.xr2s(x);
00184 dx=x2 - x1;
00185 limx=pal.index( *valx);
00186 limxdy=pal.index( *valxdy);
00187 dlim=limxdy - limx;
00188 if(dlim==0) p.fillRect (x1, y2, dx, dy, pal.color(limx) );
00189 else {
00190 coef=(( double) dy)/( *valx - *valxdy);
00191 yn2=y1;
00192 if(dlim > 0) {
00193 dlim=1;
00194 for(int lim=limx;lim < limxdy;lim += dlim) {
00195 yn1=yn2;
00196 yn2=(int) (coef * (pal.upperValue(lim) - *valx) ) + y1;
00197 if(yn1!=yn2)
00198 p.fillRect (x1, yn2, dx, yn1 - yn2, pal.color(lim) );
00199 else if(lim!=limx) dlim=dlim << 1;
00200 }
00201 } else {
00202 dlim=1;
00203 for(int lim=limx - 1;lim >= limxdy;lim -= dlim) {
00204 yn1=yn2;
00205 yn2=(int) (coef * (pal.upperValue(lim) - *valx) ) + y1;
00206 if(yn1!=yn2)
00207 p.fillRect (x1, yn2, dx, yn1 - yn2, pal.color(lim + 1) );
00208 else if(lim!=limx - 1) dlim=dlim << 1;
00209 }
00210 }
00211 if(yn2!=y2)
00212 p.fillRect (x1, y2, dx, yn2 - y2, pal.color(limxdy) );
00213 }
00214 }
00215 }
00216 }
00217
00218 template <class ValueType>
00219 void GridPlot::drawGrid2DBlock(const Grid2D<ValueType>& grid, ColorPalette pal,
00220 const LayerPainterRequest& lp, QPainter& p)
00221 {
00222 TRACE;
00223 const GraphContentOptions& gc=lp.options();
00224
00225 double startx, ddx, stopx, x;
00226 double starty, ddy, stopy, y;
00227 int startix, startiy;
00228 int y1, y2, x1, x2, dy, dmx, dmy;
00229
00230 ddx=grid.deltaX();
00231 ddy=grid.deltaY();
00232 startx=grid.origin().x() - ddx * 0.5;
00233 starty=grid.origin().y() - ddy * 0.5;
00234 stopx=startx + (double) grid.nx() * ddx;
00235 stopy=starty + (double) grid.ny() * ddy;
00236
00237
00238 if(startx > gc.xVisMin()) {
00239 if(startx > gc.xVisMax()) return ;
00240 startix=0;
00241 } else {
00242 if(stopx < gc.xVisMin()) return ;
00243 startix=(int) floor(( gc.xVisMin() - startx)/ddx);
00244 startx += (double) startix * ddx;
00245 }
00246 stopx -= 0.5 * ddx;
00247 if(stopx > gc.xVisMax()) stopx=gc.xVisMax();
00248
00249
00250 if(starty > gc.yVisMin()) {
00251 if(starty > gc.yVisMax()) return ;
00252 y=starty;
00253 startiy=0;
00254 } else {
00255 if(stopy < gc.yVisMin()) return ;
00256 startiy=(int) floor(( gc.yVisMin() - starty)/ddy);
00257 y=starty + (double) startiy * ddy;
00258 }
00259 stopy -= 0.5 * ddy;
00260 if(stopy > gc.yVisMax()) stopy=gc.yVisMax();
00261
00262
00263 if(fabs( gc.ax() * ddx) < 1.0) {
00264 dmx=(int) ceil(( double) 1.0/fabs(gc.ax() * ddx) );
00265 ddx *= (double) dmx;
00266 } else dmx=1;
00267
00268
00269 if(fabs( gc.ay() * ddy) < 1.0) {
00270 dmy=(int) ceil(( double) 1.0/fabs(gc.ay() * ddy) );
00271 ddy *= (double) dmy;
00272 dmy *= grid.nx();
00273 } else dmy=grid.nx();
00274
00275 const double * valx, *valy;
00276 valy=grid.valuePointer(startix, startiy);
00277 y2=gc.yr2s(y);
00278 for( ; y < stopy; ) {
00279 if(lp.terminated()) return;
00280 y1=y2;
00281 y += ddy;
00282 y2=gc.yr2s(y);
00283 dy=y2 - y1;
00284 valx=valy;
00285 valy += dmy;
00286 x2=gc.xr2s(startx);
00287 for(x=startx; x < stopx; valx += dmx) {
00288 x1=x2;
00289 x += ddx;
00290 x2=gc.xr2s(x);
00291 p.fillRect (x1, y1, x2 - x1, dy, pal.color( *valx) );
00292 }
00293 }
00294 }
00295
00296 template <class ValueType>
00297 void GridPlot::drawGridLines(const Grid2D<ValueType>& grid,
00298 const LayerPainterRequest& lp, QPainter& p) const
00299 {
00300 TRACE;
00301 const GraphContentOptions& gc=lp.options();
00302 int x, y;
00303 int x0=gc.xr2s(grid.west(0)), x1=gc.xr2s(grid.east(grid.nx()-1));
00304 for(int iy=grid.ny()-1; iy>=0; iy--) {
00305 y=gc.yr2s(grid.south(iy));
00306 p.drawLine(x0, y, x1, y);
00307 }
00308 y=gc.yr2s(grid.north(0));
00309 p.drawLine(x0, y, x1, y);
00310 int y0=gc.yr2s(grid.south(0)), y1=gc.yr2s(grid.north(grid.ny()-1));
00311 for(int ix=grid.nx()-1;ix >= 0;ix-- ) {
00312 x=gc.xr2s(grid.east(ix));
00313 p.drawLine(x, y0, x, y1);
00314 }
00315 x=gc.xr2s(grid.west(0));
00316 p.drawLine(x, y0, x, y1);
00317 }
00318
00319 }
00320
00321 #endif // GRIDPLOT_H