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 GRID_H
00030 #define GRID_H
00031
00032 #include <math.h>
00033
00034 #include "QGpCoreToolsDLLExport.h"
00035 #include "Point2D.h"
00036 #include "Translations.h"
00037 #include "CoreApplication.h"
00038 #include "XMLClass.h"
00039
00040 namespace QGpCoreTools {
00041
00042 template <class ValueType>
00043 class QGPCORETOOLS_EXPORT Grid2D : public XMLClass
00044 {
00045 TRANSLATIONS( "Grid2D" )
00046 public:
00047 Grid2D();
00048 Grid2D(int nx, int ny);
00049 Grid2D(const Grid2D& m);
00050 virtual ~Grid2D();
00051
00052 virtual const QString& xml_tagName() const {return xmlGrid2DTag;}
00053 static const QString xmlGrid2DTag;
00054
00055 int nx() const {return _nx;}
00056 int ny() const {return _ny;}
00057 void clear();
00058 void init(int nx, int ny);
00059 void init(ValueType value);
00060 inline void init(int nx, int ny, ValueType value);
00061
00062 ValueType value(int ix, int iy) const {return _values[ix+_nx*iy];}
00063 void setValue(int ix, int iy, double val) {_values[ix+_nx*iy]=val;}
00064 ValueType * valuePointer(int ix, int iy) {return _values+ix+_nx*iy;}
00065 const ValueType * valuePointer(int ix, int iy) const {return _values+ix+_nx*iy;}
00066
00067 void setOrigin(const Point2D& p) {_origin=p;}
00068 const Point2D& origin() const {return _origin;}
00069 void setDeltaX(double dx) {_delta.setX(dx); _invDelta.setX(1.0/dx);}
00070 void setDeltaY(double dy) {_delta.setY(dy); _invDelta.setY(1.0/dy);}
00071 double deltaX() const {return _delta.x();}
00072 double deltaY() const {return _delta.y();}
00073 double x(int ix) const {return _origin.x()+ix*_delta.x();}
00074 double y(int iy) const {return _origin.y()+iy*_delta.y();}
00075 double west(int ix) const {return x(ix)-_delta.x()*0.5;}
00076 double east(int ix) const {return x(ix)+_delta.x()*0.5;}
00077 double south(int iy) const {return y(iy)-_delta.y()*0.5;}
00078 double north(int iy) const {return y(iy)+_delta.y()*0.5;}
00079 Point2D coordinates(int ix, int iy) const;
00080 int indexOfX(double x) const {return (int) round((x - _origin.x()) * _invDelta.x());}
00081 int indexOfY(double y) const {return (int) round((y - _origin.y()) * _invDelta.y());}
00082
00083 ValueType minimumValue() const;
00084 ValueType maximumValue() const;
00085 protected:
00086 virtual void xml_writeProperties(XML_WRITEPROPERTIES_ARGS) const;
00087 virtual bool xml_setProperty(XML_SETPROPERTY_ARGS);
00088 virtual XMLMember xml_member(XML_MEMBER_ARGS);
00089 virtual void xml_writeBinaryData(XML_WRITEBINARYDATA_ARGS) const;
00090 virtual bool xml_setBinaryData(XML_SETBINARYDATA_ARGS);
00091 private:
00092 int _nx, _ny;
00093 Point2D _origin, _delta, _invDelta;
00094 ValueType *_values;
00095 };
00096
00097
00098 template <class ValueType>
00099 QGPCORETOOLS_EXPORT QTextStream& operator<<(QTextStream& s, Grid2D<ValueType>& grd);
00100 template <class ValueType>
00101 QGPCORETOOLS_EXPORT QTextStream& operator>>(QTextStream& s, Grid2D<ValueType>& grd);
00102
00103 template <class ValueType>
00104 const QString Grid2D<ValueType>::xmlGrid2DTag="Grid2D";
00105
00106 template <class ValueType>
00107 Grid2D<ValueType>::Grid2D()
00108 {
00109 TRACE;
00110 _nx=_ny=0;
00111 _delta=Point2D(1., 1. );
00112 _invDelta=Point2D(1., 1. );
00113 _origin=Point2D(0., 0. );
00114 _values=0;
00115 }
00116
00117 template <class ValueType>
00118 Grid2D<ValueType>::Grid2D(int nx, int ny)
00119 {
00120 TRACE;
00121 _values=0;
00122 _delta=Point2D(1., 1. );
00123 _invDelta=Point2D(1., 1. );
00124 _origin=Point2D(0., 0. );
00125 init(nx, ny);
00126 }
00127
00128 template <class ValueType>
00129 Grid2D<ValueType>::Grid2D(const Grid2D& m) : XMLClass()
00130 {
00131 TRACE;
00132 _values=0;
00133 _delta=m._delta;
00134 _invDelta=m._invDelta;
00135 _origin=m._origin;
00136 init(m._nx, m._ny);
00137 int n=_ny * _nx;
00138 for(int i=0; i < n; i++ )
00139 _values[ i ]=m._values[ i ];
00140 }
00141
00142 template <class ValueType>
00143 Grid2D<ValueType>::~Grid2D()
00144 {
00145 TRACE;
00146 if(_values) delete [] _values;
00147 }
00148
00149 template <class ValueType>
00150 void Grid2D<ValueType>::init(int nx, int ny)
00151 {
00152 TRACE;
00153 if(_values) delete [] _values;
00154 _nx=nx;
00155 _ny=ny;
00156 _values=new ValueType[ _ny * _nx ];
00157 }
00158
00159 template <class ValueType>
00160 void Grid2D<ValueType>::init(ValueType value)
00161 {
00162 TRACE;
00163 int n=_ny * _nx;
00164 for(int i=0; i < n; i++ ) _values[ i ]=value;
00165 }
00166
00167 template <class ValueType>
00168 inline void Grid2D<ValueType>::init(int nx, int ny, ValueType value)
00169 {
00170 init(nx, ny);
00171 init(value);
00172 }
00173
00174 template <class ValueType>
00175 ValueType Grid2D<ValueType>::minimumValue() const
00176 {
00177 TRACE;
00178 int n=_nx*_ny;
00179 if(n<1) return 0;
00180 ValueType val=_values[0];
00181 for(int i=1; i<n; i++) {
00182 if(_values[i]<val) val=_values[i];
00183 }
00184 return val;
00185 }
00186
00187 template <class ValueType>
00188 ValueType Grid2D<ValueType>::maximumValue() const
00189 {
00190 TRACE;
00191 int n=_nx*_ny;
00192 if(n<1) return 0;
00193 ValueType val=_values[0];
00194 for(int i=1; i<n; i++) {
00195 if(_values[i]>val) val=_values[i];
00196 }
00197 return val;
00198 }
00199
00200 template <class ValueType>
00201 Point2D Grid2D<ValueType>::coordinates(int ix, int iy) const
00202 {
00203 TRACE;
00204 double x=_origin.x() + (double) ix * _delta.x();
00205 double y=_origin.y() + (double) iy * _delta.y();
00206 return (Point2D(x, y));
00207 }
00208
00209 template <class ValueType>
00210 void Grid2D<ValueType>::xml_writeProperties(XML_WRITEPROPERTIES_ARGS) const
00211 {
00212 TRACE;
00213 writeProperty(s, "nx", _nx);
00214 writeProperty(s, "ny", _ny);
00215 writeProperty(s, "origin", _origin.toString());
00216 writeProperty(s, "delta", _delta.toString());
00217 writeBinaryData(s, context);
00218 }
00219
00220 template <class ValueType>
00221 void Grid2D<ValueType>::xml_writeBinaryData(XML_WRITEBINARYDATA_ARGS) const
00222 {
00223 TRACE;
00224 Q_UNUSED(context);
00225 s << _nx;
00226 s << _ny;
00227 s.writeRawData((const char *)_values, sizeof(double)*_nx * _ny);
00228 }
00229
00230 template <class ValueType>
00231 bool Grid2D<ValueType>::xml_setBinaryData(XML_SETBINARYDATA_ARGS)
00232 {
00233 TRACE;
00234 Q_UNUSED(context);
00235 int nx, ny;
00236 s >> nx;
00237 s >> ny;
00238 if(nx!=_nx || ny!=ny) {
00239 App::stream() << tr( "Grid2D size in binary file: %1x%2\n"
00240 " in XML data : %3x%4" )
00241 .arg(nx).arg(ny).arg(_nx).arg(_ny) << endl;
00242 _nx=nx;
00243 _ny=ny;
00244 }
00245 init(_nx, _ny);
00246 s.readRawData((char *)_values, sizeof(double)*_nx * _ny);
00247 return true;
00248 }
00249
00250 template <class ValueType>
00251 XMLMember Grid2D<ValueType>::xml_member(XML_MEMBER_ARGS)
00252 {
00253 TRACE;
00254 Q_UNUSED(attributes);
00255 Q_UNUSED(context);
00256 if(tag=="origin" ) return XMLMember(0);
00257 else if(tag=="delta" ) return XMLMember(1);
00258 else if(tag=="nx" ) return XMLMember(2);
00259 else if(tag=="ny" ) return XMLMember(3);
00260 return XMLMember(XMLMember::Unknown);
00261 }
00262
00263 template <class ValueType>
00264 bool Grid2D<ValueType>::xml_setProperty(XML_SETPROPERTY_ARGS)
00265 {
00266 TRACE;
00267 Q_UNUSED(tag);
00268 Q_UNUSED(attributes);
00269 Q_UNUSED(context);
00270 switch (memberID) {
00271 case 0: _origin.fromString(content); return true;
00272 case 1:
00273 _delta.fromString(content);
00274 _invDelta.setX(1.0/_delta.x());
00275 _invDelta.setY(1.0/_delta.y());
00276 return true;
00277 case 2: _nx=content.toInt(); return true;
00278 case 3: _ny=content.toInt(); return true;
00279 }
00280 return false;
00281 }
00282
00283 template <class ValueType>
00284 QTextStream& operator<<(QTextStream& s, const Grid2D<double>& grd)
00285 {
00286 TRACE;
00287 s << "x y val" << ::endl;
00288 const double * ptr=grd.valuePointer(0, 0);
00289 for(int iy=0;iy < grd.ny();iy++ ) {
00290 for(int ix=0;ix < grd.nx();ix++ )
00291 s << grd.x(ix) << " " << grd.y(iy) << " " << *(ptr++ ) << ::endl;
00292 }
00293 return s;
00294 }
00295
00296 template <class ValueType>
00297 QTextStream& operator>>(QTextStream& s, Grid2D<ValueType>& grd)
00298 {
00299 TRACE;
00300 QString str;
00301 bool ok;
00302 int i;
00303 int line=0;
00304 str=s.readLine().trimmed(); line++;
00305 while(str.isEmpty() || str[0]=='#') {
00306 str=s.readLine().trimmed(); line++;
00307 }
00308 if(str=="x y val" ) {
00309 QVector<Point2D> points;
00310 QVector<ValueType> values;
00311 Point2D p;
00312 ValueType val;
00313 const QChar * ptr;
00314 StringSection f;
00315 bool ok=true;
00316 while( !s.atEnd()) {
00317 str=s.readLine().trimmed(); line++;
00318 if(str.isEmpty() || str[0]=='#') break;
00319 StringSection pStr(str);
00320 ptr=0;
00321 f=pStr.nextField(ptr);
00322 if(f.isValid()) p.setX(f.toDouble()); else ok=false;
00323 f=pStr.nextField(ptr);
00324 if(f.isValid()) p.setY(f.toDouble()); else ok=false;
00325 f=pStr.nextField(ptr);
00326 if(f.isValid()) val=f.toDouble(); else ok=false;
00327 if( !ok) {
00328 App::stream() << QCoreApplication::translate( "Grid2D", "Wrong format at line %1, expected: float value" ).arg(line) << endl;
00329 return s;
00330 }
00331 points.append(p);
00332 values.append(val);
00333 }
00334
00335 QMap<double,int> xMap, yMap;
00336 QMap<double,int>::iterator itMap;
00337 for(QVector<Point2D>::iterator it=values.begin();it!=values.end(); it++) {
00338 itMap=xMap.find(it->x());
00339 if(itMap==xMap.end()) {
00340 xMap.insert(it->x(),0);
00341 }
00342 itMap=yMap.find(it->y());
00343 if(itMap==yMap.end()) {
00344 yMap.insert(it->y(),0);
00345 }
00346 }
00347 if(xMap.isEmpty() || yMap.isEmpty()) {
00348 return s;
00349 }
00350 grd.setOrigin(Point2D(xMap.begin().value(), yMap.begin().value()));
00351 grd.setDeltaX(((--xMap.end()).value() - xMap.begin().value())/xMap.count());
00352 grd.setDeltaY(((--yMap.end()).value() - yMap.begin().value())/yMap.count());
00353 grd.init(xMap.count(), yMap.count(), 0.0);
00354
00355 int i;
00356 i=0;
00357 for(QMap<double,int>::iterator it=xMap.begin();it!=xMap.end(); it++, i++) {
00358 grd.setX(i, it.key());
00359 it.value()=i;
00360
00361 }
00362 i=0;
00363 for(QMap<double,int>::iterator it=yMap.begin();it!=yMap.end(); it++, i++) {
00364 grd.setY(i, it.key());
00365 it.value()=i;
00366
00367 }
00368
00369 for(int i=points.count()-1; i>=0; i--) {
00370 Point2D& p=points.at(i);
00371 grd.setValue(xMap[p.x()], yMap[p.y()], values.at(i));
00372 }
00373 } else {
00374 App::stream() << QCoreApplication::translate( "Grid2D", "Wrong format at line %1, expected: values" ).arg(line) << endl;
00375 }
00376 return s;
00377 }
00378
00379 }
00380
00381 #endif // GRID2D.H