Subversion Repositories public iLand

Rev

Rev 753 | Rev 779 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

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