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 |