1
2 ///////////////////////////////////////////////////////////
3 // //
4 // SAGA //
5 // //
6 // System for Automated Geoscientific Analyses //
7 // //
8 // Tool Library //
9 // Grid_Tools //
10 // //
11 //-------------------------------------------------------//
12 // //
13 // Grid_Interpolate_Value_Along_Line.cpp //
14 // //
15 // Copyright (C) 2019 by //
16 // Volker Wichmann //
17 // //
18 //-------------------------------------------------------//
19 // //
20 // This file is part of 'SAGA - System for Automated //
21 // Geoscientific Analyses'. SAGA is free software; you //
22 // can redistribute it and/or modify it under the terms //
23 // of the GNU General Public License as published by the //
24 // Free Software Foundation, either version 2 of the //
25 // License, or (at your option) any later version. //
26 // //
27 // SAGA is distributed in the hope that it will be //
28 // useful, but WITHOUT ANY WARRANTY; without even the //
29 // implied warranty of MERCHANTABILITY or FITNESS FOR A //
30 // PARTICULAR PURPOSE. See the GNU General Public //
31 // License for more details. //
32 // //
33 // You should have received a copy of the GNU General //
34 // Public License along with this program; if not, see //
35 // <http://www.gnu.org/licenses/>. //
36 // //
37 //-------------------------------------------------------//
38 // //
39 // e-mail: wichmann@laserdata //
40 // //
41 // contact: Volker Wichmann //
42 // LASERDATA GmbH //
43 // Management and analysis of //
44 // laserscanning data //
45 // Innsbruck, Austria //
46 // //
47 ///////////////////////////////////////////////////////////
48
49 //---------------------------------------------------------
50
51
52 ///////////////////////////////////////////////////////////
53 // //
54 // //
55 // //
56 ///////////////////////////////////////////////////////////
57
58 //---------------------------------------------------------
59 #include "Grid_Interpolate_Value_Along_Line.h"
60
61
62
63 ///////////////////////////////////////////////////////////
64 // //
65 // //
66 // //
67 ///////////////////////////////////////////////////////////
68
69 //---------------------------------------------------------
CGrid_Interpolate_Value_Along_Line(void)70 CGrid_Interpolate_Value_Along_Line::CGrid_Interpolate_Value_Along_Line(void)
71 {
72 Set_Name (_TL("Interpolate Values Along Line "));
73
74 Set_Author (SG_T("V. Wichmann (c) 2019"));
75
76 Set_Description (_TW(
77 "The tool allows one to change the values of the input grid along a line. "
78 "The values along the line will be interpolated linearly between the "
79 "start and the end point of the line. Thus you must assure that these "
80 "grid cells contain valid data. Optionally the changes can be limited "
81 "to grid cells with No Data only.\n"
82 "Once the tool is executed and running, you can use the 'Action' tool to "
83 "digitize a line. Use left mouse button clicks to set line vertices. "
84 "A right mouse button click will finish the line.\n\n"
85 ));
86
87 Set_Drag_Mode (TOOL_INTERACTIVE_DRAG_LINE);
88
89 Parameters.Add_Grid("",
90 "GRID" , _TL("Grid"),
91 _TL("The grid to modify."),
92 PARAMETER_INPUT
93 );
94
95 Parameters.Add_Shapes("",
96 "LINE" , _TL("Line"),
97 _TL("The digitized line."),
98 PARAMETER_OUTPUT, SHAPE_TYPE_Line
99 );
100
101 Parameters.Add_Value("",
102 "ONLY_NODATA" , _TL("Only No Data"),
103 _TL("Apply changes only to grid cells with No Data along the line."),
104 PARAMETER_TYPE_Bool, false
105 );
106 }
107
108 //---------------------------------------------------------
~CGrid_Interpolate_Value_Along_Line(void)109 CGrid_Interpolate_Value_Along_Line::~CGrid_Interpolate_Value_Along_Line(void)
110 {}
111
112
113 ///////////////////////////////////////////////////////////
114 // //
115 // //
116 // //
117 ///////////////////////////////////////////////////////////
118
119 //---------------------------------------------------------
On_Execute(void)120 bool CGrid_Interpolate_Value_Along_Line::On_Execute(void)
121 {
122 m_pGrid = Parameters("GRID")->asGrid();
123 m_pLine = Parameters("LINE")->asShapes();
124 m_bOnlyNoData = Parameters("ONLY_NODATA")->asBool();
125
126 m_pPoints = new CSG_Shapes(SHAPE_TYPE_Point);
127
128 m_bAdd = false;
129
130 DataObject_Update(m_pGrid, SG_UI_DATAOBJECT_SHOW_NEW_MAP);
131 DataObject_Update(m_pLine, SG_UI_DATAOBJECT_SHOW_LAST_MAP);
132
133 return( true );
134 }
135
136 //---------------------------------------------------------
On_Execute_Finish(void)137 bool CGrid_Interpolate_Value_Along_Line::On_Execute_Finish(void)
138 {
139 if( m_bAdd )
140 {
141 Set_Line();
142 }
143
144 delete( m_pPoints );
145
146 return( true );
147 }
148
149
150 ///////////////////////////////////////////////////////////
151 // //
152 // //
153 // //
154 ///////////////////////////////////////////////////////////
155
156 //---------------------------------------------------------
On_Execute_Position(CSG_Point ptWorld,TSG_Tool_Interactive_Mode Mode)157 bool CGrid_Interpolate_Value_Along_Line::On_Execute_Position(CSG_Point ptWorld, TSG_Tool_Interactive_Mode Mode)
158 {
159 switch( Mode )
160 {
161 default:
162 break;
163
164 case TOOL_INTERACTIVE_LDOWN:
165 if( !m_bAdd )
166 {
167 m_bAdd = true;
168 m_pLine->Create(SHAPE_TYPE_Line, CSG_String::Format(SG_T("Line [%s]"), m_pGrid->Get_Name()));
169 m_pLine->Add_Field("ID" , SG_DATATYPE_Int);
170 m_pLine->Add_Shape()->Set_Value(0, 1);
171 }
172
173 m_pLine->Get_Shape(0)->Add_Point(Get_System().Fit_to_Grid_System(ptWorld));
174
175 DataObject_Update(m_pLine);
176 break;
177
178 case TOOL_INTERACTIVE_RDOWN:
179 Set_Line();
180 m_bAdd = false;
181 break;
182 }
183
184 return( true );
185 }
186
187
188 ///////////////////////////////////////////////////////////
189 // //
190 // //
191 // //
192 ///////////////////////////////////////////////////////////
193
194 //---------------------------------------------------------
Set_Line(void)195 bool CGrid_Interpolate_Value_Along_Line::Set_Line(void)
196 {
197 TSG_Point A, B;
198 int Ax, Ay, Bx, By, Cx, Cy;
199 double Az, Bz, Cz, Length, tanAlpha;
200 CSG_Shape *pLine;
201
202
203 //-----------------------------------------------------
204 if( (pLine = m_pLine->Get_Shape(0)) == NULL || pLine->Get_Point_Count(0) < 2 )
205 {
206 return( false );
207 }
208
209 A = pLine->Get_Point(0, 0);
210 B = pLine->Get_Point(pLine->Get_Point_Count(0) - 1, 0);
211
212 if( !Get_System().Get_World_to_Grid(Ax, Ay, A) || !m_pGrid->is_InGrid(Ax, Ay) ||
213 !Get_System().Get_World_to_Grid(Bx, By, B) || !m_pGrid->is_InGrid(Bx, By) )
214 {
215 Error_Set(_TL("Please digitize a valid line!"));
216 return( false );
217 }
218
219 DataObject_Update(m_pLine);
220
221 //-----------------------------------------------------
222 m_pPoints->Create(SHAPE_TYPE_Point, SG_T(""));
223 m_pPoints->Add_Field("Length", SG_DATATYPE_Double);
224
225 //-----------------------------------------------------
226 B = pLine->Get_Point(0);
227
228 for(int i=1; i<pLine->Get_Point_Count(0); i++)
229 {
230 A = B;
231 B = pLine->Get_Point(i);
232
233 Set_Line(A, B);
234 }
235
236 //-----------------------------------------------------
237 if( m_pPoints->Get_Count() < 2 )
238 {
239 Error_Set(_TL("Line construction failed!"));
240 return( false );
241 }
242
243 if( m_pPoints->Get_Count() == 2 )
244 {
245 Message_Dlg(_TL("Line has only two points on grid cells, nothing to do!"));
246 return( true );
247 }
248
249 Az = m_pGrid->asDouble(Ax, Ay);
250 Bz = m_pGrid->asDouble(Bx, By);
251 Length = m_pPoints->Get_Record(m_pPoints->Get_Record_Count() - 1)->asDouble(0);
252 tanAlpha = (Bz - Az) / Length;
253
254 for(int i=1; i<m_pPoints->Get_Count() - 1; i++)
255 {
256 Cz = Az + tanAlpha * m_pPoints->Get_Shape(i)->asDouble(0);
257
258 Get_System().Get_World_to_Grid(Cx, Cy, m_pPoints->Get_Shape(i)->Get_Point(0));
259
260 if( m_bOnlyNoData && !m_pGrid->is_NoData(Cx, Cy) )
261 {
262 continue;
263 }
264
265 m_pGrid->Set_Value(Cx, Cy, Cz);
266 }
267
268
269 //-----------------------------------------------------
270 DataObject_Update(m_pGrid);
271
272 return( true );
273 }
274
275 //---------------------------------------------------------
Set_Line(TSG_Point A,TSG_Point B)276 void CGrid_Interpolate_Value_Along_Line::Set_Line(TSG_Point A, TSG_Point B)
277 {
278 double dx, dy, d, n;
279 TSG_Point p;
280
281 //-----------------------------------------------------
282 dx = fabs(B.x - A.x);
283 dy = fabs(B.y - A.y);
284
285 if( dx > 0.0 || dy > 0.0 )
286 {
287 if( dx > dy )
288 {
289 dx /= Get_Cellsize();
290 n = dx;
291 dy /= dx;
292 dx = Get_Cellsize();
293 }
294 else
295 {
296 dy /= Get_Cellsize();
297 n = dy;
298 dx /= dy;
299 dy = Get_Cellsize();
300 }
301
302 if( B.x < A.x )
303 {
304 dx = -dx;
305 }
306
307 if( B.y < A.y )
308 {
309 dy = -dy;
310 }
311
312 //-------------------------------------------------
313 for(d=0.0, p.x=A.x, p.y=A.y; d<=n; d++, p.x+=dx, p.y+=dy)
314 {
315 Add_Point(p);
316 }
317 }
318
319 //-----------------------------------------------------
320 return;
321 }
322
323 //---------------------------------------------------------
Add_Point(CSG_Point Point)324 void CGrid_Interpolate_Value_Along_Line::Add_Point(CSG_Point Point)
325 {
326 int x, y, i;
327 double z, Length;
328 CSG_Shape *pPoint, *pLast;
329
330 if( Get_System().Get_World_to_Grid(x, y, Point) )
331 {
332 z = m_pGrid->asDouble(x, y);
333
334 if( m_pPoints->Get_Count() == 0 )
335 {
336 Length = 0.0;
337 }
338 else
339 {
340 pLast = m_pPoints->Get_Shape(m_pPoints->Get_Count() - 1);
341 Length = SG_Get_Distance(Point, pLast->Get_Point(0));
342
343 if( Length == 0.0 )
344 {
345 return;
346 }
347
348 Length += pLast->asDouble(0);
349 }
350
351 pPoint = m_pPoints->Add_Shape();
352 pPoint->Add_Point(Point);
353 pPoint->Set_Value(0, Length);
354 }
355
356 return;
357 }
358
359
360 ///////////////////////////////////////////////////////////
361 // //
362 // //
363 // //
364 ///////////////////////////////////////////////////////////
365
366 //---------------------------------------------------------
367