Rev 39 | Rev 42 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
1 | |||
3 | Werner | 2 | |
3 | #include "tree.h" |
||
16 | Werner | 4 | #include "core/grid.h" |
30 | Werner | 5 | #include "imagestamp.h" |
3 | Werner | 6 | |
38 | Werner | 7 | #include "core/stamp.h" |
8 | #include "treespecies.h" |
||
9 | |||
13 | Werner | 10 | Expression Tree::rScale=Expression(); |
11 | Expression Tree::hScale=Expression(); |
||
39 | Werner | 12 | FloatGrid *Tree::m_grid = 0; |
40 | Werner | 13 | int Tree::m_statPrint=0; |
14 | int Tree::m_nextId=0; |
||
15 | |||
3 | Werner | 16 | Tree::Tree() |
17 | { |
||
38 | Werner | 18 | m_Dbh = 0; |
19 | m_Height = 0; |
||
20 | m_species = 0; |
||
40 | Werner | 21 | m_id = m_nextId++; |
3 | Werner | 22 | } |
38 | Werner | 23 | |
15 | Werner | 24 | /** get distance and direction between two points. |
38 | Werner | 25 | returns the distance (m), and the angle between PStart and PEnd (radians) in referenced param rAngle. */ |
3 | Werner | 26 | float dist_and_direction(const QPointF &PStart, const QPointF &PEnd, float &rAngle) |
27 | { |
||
28 | float dx = PEnd.x() - PStart.x(); |
||
29 | float dy = PEnd.y() - PStart.y(); |
||
30 | float d = sqrt(dx*dx + dy*dy); |
||
31 | // direction: |
||
32 | rAngle = atan2(dx, dy); |
||
33 | return d; |
||
34 | } |
||
35 | |||
30 | Werner | 36 | void Tree::stampOnGrid(ImageStamp& stamp, FloatGrid& grid) |
3 | Werner | 37 | { |
38 | |||
39 | // use formulas to derive scaling values... |
||
38 | Werner | 40 | rScale.setVar("height", m_Height); |
41 | rScale.setVar("dbh", m_Dbh); |
||
42 | hScale.setVar("height", m_Height); |
||
43 | hScale.setVar("dbh", m_Dbh); |
||
3 | Werner | 44 | |
45 | double r = rScale.execute(); |
||
46 | double h = hScale.execute(); |
||
47 | stamp.setScale(r, h); // stamp uses scaling values to calculate impact |
||
15 | Werner | 48 | mImpactRadius = r; |
3 | Werner | 49 | |
50 | float cell_value, r_cell, phi_cell; |
||
38 | Werner | 51 | QPoint ul = grid.indexAt(QPointF(m_Position.x()-r, m_Position.y()-r) ); |
52 | QPoint lr = grid.indexAt( QPointF(m_Position.x()+r, m_Position.y()+r) ); |
||
9 | Werner | 53 | QPoint centercell=grid.indexAt(position()); |
3 | Werner | 54 | grid.validate(ul); grid.validate(lr); |
55 | QPoint cell; |
||
56 | QPointF cellcoord; |
||
57 | int ix, iy; |
||
58 | mOwnImpact=0.f; |
||
6 | Werner | 59 | mImpactArea=0.f; |
3 | Werner | 60 | for (ix=ul.x(); ix<lr.x(); ix++) |
61 | for (iy=ul.y(); iy<lr.y(); iy++) { |
||
62 | cell.setX(ix); cell.setY(iy); |
||
32 | Werner | 63 | cellcoord = grid.cellCoordinates(cell); |
38 | Werner | 64 | r_cell = dist_and_direction(m_Position, cellcoord, phi_cell); |
9 | Werner | 65 | if (r_cell > r && cell!=centercell) |
3 | Werner | 66 | continue; |
67 | // get value from stamp at this location (given by radius and angle) |
||
68 | cell_value = stamp.get(r_cell, phi_cell); |
||
69 | // add value to cell |
||
6 | Werner | 70 | mOwnImpact+=(1. - cell_value); |
71 | mImpactArea++; |
||
72 | grid.valueAtIndex(cell)*=cell_value; |
||
3 | Werner | 73 | } |
74 | } |
||
75 | |||
30 | Werner | 76 | float Tree::retrieveValue(ImageStamp& stamp, FloatGrid& grid) |
3 | Werner | 77 | { |
78 | |||
38 | Werner | 79 | rScale.setVar("height", m_Height); |
80 | rScale.setVar("dbh", m_Dbh); |
||
81 | hScale.setVar("height", m_Height); |
||
82 | hScale.setVar("dbh", m_Dbh); |
||
3 | Werner | 83 | double r = rScale.execute(); |
84 | double h = hScale.execute(); |
||
85 | stamp.setScale(r, h); // stamp uses scaling values to calculate impact |
||
86 | |||
7 | Werner | 87 | float stamp_value, cell_value, r_cell, phi_cell; |
38 | Werner | 88 | QPoint ul = grid.indexAt(QPointF(m_Position.x()-r, m_Position.y()-r) ); |
89 | QPoint lr = grid.indexAt( QPointF(m_Position.x()+r, m_Position.y()+r) ); |
||
9 | Werner | 90 | QPoint centercell=grid.indexAt(position()); |
3 | Werner | 91 | grid.validate(ul); grid.validate(lr); |
92 | QPoint cell; |
||
93 | QPointF cellcoord; |
||
94 | int ix, iy; |
||
95 | float value=0.f; |
||
96 | |||
97 | int counting_cells=0; |
||
98 | for (ix=ul.x(); ix<lr.x(); ix++) |
||
99 | for (iy=ul.y(); iy<lr.y(); iy++) { |
||
100 | |||
101 | cell.setX(ix); cell.setY(iy); |
||
32 | Werner | 102 | cellcoord = grid.cellCoordinates(cell); |
38 | Werner | 103 | r_cell = dist_and_direction(m_Position, cellcoord, phi_cell); |
9 | Werner | 104 | if (r_cell>r && cell!=centercell) |
3 | Werner | 105 | continue; |
106 | counting_cells++; |
||
107 | // get value from stamp at this location (given by radius and angle) |
||
7 | Werner | 108 | stamp_value = stamp.get(r_cell, phi_cell); |
109 | cell_value = grid.valueAtIndex(QPoint(ix,iy)); |
||
110 | if (stamp_value>0.) |
||
111 | value += cell_value / stamp_value; |
||
3 | Werner | 112 | // sum up values of cell |
113 | //value += cell_value; |
||
7 | Werner | 114 | //value += grid.valueAtIndex(QPoint(ix,iy)); // - cell_value; |
3 | Werner | 115 | } |
9 | Werner | 116 | if (counting_cells>0) |
117 | mImpact = value / float(counting_cells); |
||
118 | else |
||
119 | mImpact=1; |
||
3 | Werner | 120 | return mImpact; |
121 | } |
||
122 | |||
38 | Werner | 123 | |
124 | void Tree::setup() |
||
125 | { |
||
126 | if (m_Dbh<=0 || m_Height<=0) |
||
127 | return; |
||
128 | // check stamp |
||
129 | Q_ASSERT_X(m_species!=0, "Tree::setup()", "species is NULL"); |
||
130 | m_stamp = m_species->stamp(m_Dbh, m_Height); |
||
131 | } |
||
39 | Werner | 132 | |
133 | void Tree::applyStamp() |
||
134 | { |
||
135 | Q_ASSERT(m_grid!=0); |
||
136 | if (!m_stamp) |
||
137 | return; |
||
138 | |||
40 | Werner | 139 | QPoint pos = m_grid->indexAt(m_Position); |
140 | int offset = m_stamp->offset(); |
||
141 | pos-=QPoint(offset, offset); |
||
142 | QPoint p; |
||
143 | |||
144 | int x,y; |
||
145 | for (x=0;x<m_stamp->size();++x) { |
||
146 | for (y=0;y<m_stamp->size(); ++y) { |
||
147 | p = pos + QPoint(x,y); |
||
148 | if (m_grid->isIndexValid(p)) |
||
149 | m_grid->valueAtIndex(p)+=(*m_stamp)(x,y); |
||
150 | } |
||
151 | } |
||
152 | m_statPrint++; // count # of stamp applications... |
||
39 | Werner | 153 | } |
40 | Werner | 154 | |
155 | double Tree::readStamp() |
||
156 | { |
||
157 | float crown_radius = dbh()/10; // cm -> m |
||
158 | const Stamp *stamp = m_species->readerStamp(crown_radius); |
||
159 | if (!stamp) |
||
160 | return 0.; |
||
161 | QPoint pos = m_grid->indexAt(m_Position); |
||
162 | int offset = stamp->offset(); |
||
163 | pos-=QPoint(offset, offset); |
||
164 | QPoint p; |
||
165 | |||
166 | int x,y; |
||
167 | double sum=0.; |
||
168 | for (x=0;x<stamp->size();++x) { |
||
169 | for (y=0;y<stamp->size(); ++y) { |
||
170 | p = pos + QPoint(x,y); |
||
171 | if (m_grid->isIndexValid(p)) |
||
172 | sum += m_grid->valueAtIndex(p) * (*stamp)(x,y); |
||
173 | } |
||
174 | } |
||
175 | mImpact = sum; |
||
176 | qDebug() << "Tree #"<< id() << "value" << sum; |
||
177 | return sum; |
||
178 | } |
||
179 | |||
180 | void Tree::resetStatistics() |
||
181 | { |
||
182 | m_statPrint=0; |
||
183 | m_nextId=1; |
||
184 | } |