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