Subversion Repositories public iLand

Rev

Rev 1221 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
15 Werner 1
 
2
#include "hemigrid.h"
3
 
4
//#include <algorithm>
25 Werner 5
#include <QtCore>
6
// needed for drawing: image & color
7
#include <QImage>
8
#include <QColor>
15 Werner 9
 
10
//////////////////////////////////////////////////////
11
// Setup memory for the Grid.
12
// @param size of a single pixel in degree
13
//////////////////////////////////////////////////////
14
void HemiGrid::setup(double cellsize_degree)
15
{
16
      // setup grid...
17
      mMatrixCountAzimuth = int(360 / cellsize_degree);
18
      mMatrixCountElevation = int(90 / cellsize_degree);
25 Werner 19
      mCellSizeDegree = cellsize_degree;
15 Werner 20
      // size occupied by one pixel in rad
21
      mMatrixCellSize = cellsize_degree * M_PI / 180.;
22
      if (mMatrix)
23
        delete[] mMatrix;
24
      mMatrix = new double[mMatrixCountAzimuth*mMatrixCountElevation];
25
 
26
      clear();
27
 
28
}
29
 
30
 
31
//////////////////////////////////////////////////////
32
// Clear the Grid.
33
// @param SetWith value used to fill (default 0.)
34
//////////////////////////////////////////////////////
35
void HemiGrid::clear(double SetWith)
36
{
37
    if (mMatrix) {
38
      // blank matrix...
39
      for (int i=0;i<mMatrixCountAzimuth*mMatrixCountElevation;i++)
40
         mMatrix[i]=SetWith;
41
    }
42
}
43
 
25 Werner 44
void HemiGrid::matrixMinMax(double &rMatrixMin, double &rMatrixMax) const
15 Werner 45
{
46
    rMatrixMin = 100000000.;
47
    rMatrixMax = -1000000000;
48
    if (mMatrix) {
49
      // blank matrix...
50
      for (int i=0;i<mMatrixCountAzimuth*mMatrixCountElevation;i++) {
51
         rMatrixMin = std::min(mMatrix[i], rMatrixMin);
52
         rMatrixMax = std::max(mMatrix[i], rMatrixMax);
53
      }
54
    }
55
}
772 werner 56
double HemiGrid::sum(const double elevation) const
29 Werner 57
{
58
    int ie=indexElevation(elevation);
59
    int emax=matrixCountElevation();
60
    int amax=matrixCountAzimuth();
61
    double value = 0;
62
    for (int e=ie;e<emax;e++)
63
        for (int a=0;a<amax;a++)
64
            value+=rGetByIndex(a,e);
65
    return value;
66
}
15 Werner 67
 
68
//////////////////////////////////////////////////////
69
// Dump the grid into a TStringList
70
//////////////////////////////////////////////////////
71
//void HemiGrid::DumpGrid(TStrings* List)
72
//{
73
//    AnsiString Line;
74
//    for (int i=0;i<mMatrixCountAzimuth;i++)  {
75
//       Line=AnsiString(i);
76
//       for (int j=0;j<mMatrixCountElevation;j++)  {
77
//           Line+=";"+AnsiString(rGetByIndex(i,j));
78
//       }
79
//       List->Add(Line);
80
//    }
81
//
82
//}
83
 
84
//////////////////////////////////////////////////////
85
// Get Gridvalue by integer internal grid indices
86
// @param iAzimuth index of azimuth (0..count(pixels)-1
87
// @param iElevation index of elevatin (0..count-1)
88
// @return ref. to grid-value
89
//////////////////////////////////////////////////////
25 Werner 90
double& HemiGrid::rGetByIndex(const int iAzimuth, const int iElevation) const
15 Werner 91
{
92
if (iAzimuth < mMatrixCountAzimuth && iElevation < mMatrixCountElevation
93
        && iAzimuth>=0 && iElevation>=0)
94
       return mMatrix[iAzimuth*mMatrixCountElevation + iElevation];
95
    else
96
       throw QString("TSolar::Rad::Get() - invalid indices");
97
}
98
 
99
//////////////////////////////////////////////////////
100
// Get Gridvalue
101
// @param Azimuth azimuth angle (-pi .. +pi, 0=south)
102
// @param Elevation elevation angle (0=horizon, pi/2: zenith)
103
// @return ref. to grid-value
104
//////////////////////////////////////////////////////
25 Werner 105
double& HemiGrid::rGet(const double Azimuth, const double Elevation) const
15 Werner 106
{
107
    // Azimuth goes from -pi .. +pi -> move to 0..2pi, scale to 0..1 and convert to integer indices
24 Werner 108
    int iAzimuth = indexAzimuth(Azimuth);
15 Werner 109
    // Elevation goes from 0..90° = 0..pi/2
24 Werner 110
    int iElevation = indexElevation(Elevation);
15 Werner 111
 
112
    return rGetByIndex(iAzimuth, iElevation);
113
}
114
 
115
void HemiGrid::modify(const HemiGrid &Source, const ModifyMode mode)
116
{
117
        for (int i=0; i<mMatrixCountAzimuth*mMatrixCountElevation; i++) {
118
            switch (mode) {
119
                case Add: mMatrix[i]+=Source.mMatrix[i]; break;
120
                case Multiply: mMatrix[i] *= Source.mMatrix[i]; break;
121
                case SetTo: mMatrix[i] = Source.mMatrix[i]; break;
122
            }
123
        }
124
 
125
}
126
 
127
/** retrieve total sum of the hemigrid.
128
  @param Weighter if available (non null) each cell value of this grid is multiplied with the weighter grid (note: no additional calculations are performed) */
129
double HemiGrid::getSum(const HemiGrid *Weighter) const
130
{
131
    double Sum=0.;
132
    if (Weighter) {
24 Werner 133
        if (Weighter->matrixCountAzimuth()!=this->matrixCountAzimuth()
134
            || Weighter->matrixCountElevation() != this->matrixCountElevation())
15 Werner 135
                throw QString("HemiGrid::getSum: invalid weighing object!");
136
 
137
        for (int i=0; i<mMatrixCountAzimuth*mMatrixCountElevation; i++) {
138
            Sum += mMatrix[i]*Weighter->mMatrix[i];
139
        }
140
        return Sum;
141
    }
142
    for (int i=0; i<mMatrixCountAzimuth*mMatrixCountElevation; i++) {
143
        Sum += mMatrix[i];
144
    }
145
    return Sum;
146
}
147
 
148
void HemiGrid::projectLine(const double &x, const double &y, const double &deltah, const double &r, double &elevation, double &azimuth1, double &azimuth2)
149
{
150
   // transform coordinates....
151
   // distance to footing point (x/y)
152
   double distance = sqrt(x*x + y*y);
153
   elevation = atan2(deltah, distance);
154
   double azimuth = atan2(x,y);
155
   // distance to point (x/y/z)
156
   double dist3 = sqrt(x*x+y*y+deltah*deltah);
157
   double azimuth_delta = atan2(r, dist3);
158
   azimuth1 = azimuth - azimuth_delta;
159
   azimuth2 = azimuth + azimuth_delta;
160
}
161
 
162
//////////////////////////////////////////////////////
163
// Modify a rect defined by coordinates, a mode and a value
164
// @param  elow, ehigh: elevation angles
165
// @param alow1, alow2: azimuth angles at base, alow1 must be < alow2
166
// @param ahigh1, ahigh2: azimuth angles at the top, ahigh1 must be < ahigh2
167
// @param ModifyMode multiply or add to the matrix
168
// @param Value value used for multiply/add,...
169
//////////////////////////////////////////////////////
170
void HemiGrid::modifyAngleRect( const double &elow, const double &alow1, const double &alow2,
171
                    const double &ehigh, const double &ahigh1, const double &ahigh2,
172
                    const ModifyMode mode, const double &value)
173
{
24 Werner 174
    int i_e_low = indexElevation(elow);
175
    int i_e_high = indexElevation(ehigh);
176
    int i_a_low1 = indexAzimuth(alow1);
177
    int i_a_low2 = indexAzimuth(alow2);
178
    int i_a_high1 = indexAzimuth(ahigh1);
179
    int i_a_high2 = indexAzimuth(ahigh2);
15 Werner 180
    int i_a_min = std::min(i_a_low1, i_a_high1);
181
    int i_a_max = std::max(i_a_low2, i_a_high2);
182
 
183
    for (int e = i_e_low; e<=i_e_high; e++) {
184
       for (int a = i_a_min; a<=i_a_max; a++) {
185
          double &ref = rGetByIndex((a+mMatrixCountAzimuth)%mMatrixCountAzimuth, e);
186
          switch (mode) {
187
            case Multiply: ref*=value; break;
188
            case Add: ref+=value; break;
189
            case SetTo: ref=value; break;
190
          }
191
       }
192
    }
193
 
194
}
195
 
196
 
197
//////////////////////////////////////////////////////
198
// Project a cylinder onto the grid.
199
// @param deltax, deltay: relative position
200
// @param offsetz: relative height of lower edge
201
// @param height, r: height and radius of cylinder
202
// @param mode, value: mode and value of change
203
// @param  elow, ehigh: elevation angles
204
//////////////////////////////////////////////////////
205
void HemiGrid::projectCylinder(const double &deltax, const double &deltay,
206
                     const double &offsetz, const double &height, const double &r,
207
                     const ModifyMode mode, const double &value)
208
{
209
    double elow, ehigh; // elevations...
210
    double al1, al2, ah1, ah2;
211
    projectLine(deltax, deltay, std::max(offsetz+height, 0.), r, ehigh, ah1, ah2);
212
    // ignore if top is t
213
    if (ehigh < 5.*M_PI/180.)
214
       return;
215
    projectLine(deltax, deltay, std::max(offsetz, 0.), r, elow, al1, al2);
216
    modifyAngleRect(elow, al1, al2, ehigh, ah1, ah2, mode, value);
217
}
218
 
219
 
25 Werner 220
void HemiGrid::paintGrid(QImage &image) const
221
{
222
    int dx = image.width();
223
    int dy = image.height();
224
    int ix,iy;
225
    double x,y;
226
    int maxsize = std::min(dx,dy);
753 werner 227
    double mmin=0, mmax=0; // min and max values of matrix
228
    //if (mmax==0) mmax=1;
25 Werner 229
    matrixMinMax(mmin, mmax);
230
    QColor col;
231
    double phi, r, elevation, value;
232
    for (ix=0;ix<maxsize;ix++){
233
        for (iy=0;iy<maxsize;iy++){
234
            // to -1..1
235
            x = 2*(ix-maxsize/2.) / maxsize;
236
            y = 2*(iy-maxsize/2.) / maxsize;
237
            // get phi,r (polar coords)
238
            if (x==0 && y==0)
239
                continue;
15 Werner 240
 
25 Werner 241
            r = sqrt(x*x + y*y);
242
            if (r>=1)
243
                continue;
402 werner 244
            phi = atan2(y,x);
25 Werner 245
            elevation = M_PI_2 - (r * M_PI_2);
246
            value = rGet(phi, elevation);
247
            value /= mmax;
248
            col = QColor::fromHsvF((1.-value)*0.666666 ,0.9, 0.9); // hue from 0..240 = red to blue
40 Werner 249
            image.setPixel(ix,maxsize-iy,col.rgb());
25 Werner 250
        }
251
    }
252
}
253
 
254
QString HemiGrid::dumpGrid() const
255
{
256
    QString text;
257
    text="rows: azimuth steps, cols: elevation. (first value in row: index of azimuth)\n";
258
    for (int i=0;i<mMatrixCountAzimuth;i++)  {
259
       text+=QString::number(i);
260
       for (int j=0;j<mMatrixCountElevation;j++)  {
261
           text+=";"+QString::number(rGetByIndex(i,j));
262
       }
263
       text+="\n";
264
    }
265
    return text;
266
}
267
 
268