1 /**********************************************************
2  * Version $Id: Grid_Profile_From_Lines.cpp 1921 2014-01-09 10:24:11Z oconrad $
3  *********************************************************/
4 
5 ///////////////////////////////////////////////////////////
6 //                                                       //
7 //                         SAGA                          //
8 //                                                       //
9 //      System for Automated Geoscientific Analyses      //
10 //                                                       //
11 //                     Tool Library                      //
12 //                     ta_profiles                       //
13 //                                                       //
14 //-------------------------------------------------------//
15 //                                                       //
16 //              Grid_Profile_From_Lines.cpp              //
17 //                                                       //
18 //                 Copyright (C) 2006 by                 //
19 //                      Olaf Conrad                      //
20 //                                                       //
21 //-------------------------------------------------------//
22 //                                                       //
23 // This file is part of 'SAGA - System for Automated     //
24 // Geoscientific Analyses'. SAGA is free software; you   //
25 // can redistribute it and/or modify it under the terms  //
26 // of the GNU General Public License as published by the //
27 // Free Software Foundation, either version 2 of the     //
28 // License, or (at your option) any later version.       //
29 //                                                       //
30 // SAGA is distributed in the hope that it will be       //
31 // useful, but WITHOUT ANY WARRANTY; without even the    //
32 // implied warranty of MERCHANTABILITY or FITNESS FOR A  //
33 // PARTICULAR PURPOSE. See the GNU General Public        //
34 // License for more details.                             //
35 //                                                       //
36 // You should have received a copy of the GNU General    //
37 // Public License along with this program; if not, see   //
38 // <http://www.gnu.org/licenses/>.                       //
39 //                                                       //
40 //-------------------------------------------------------//
41 //                                                       //
42 //    e-mail:     oconrad@saga-gis.org                   //
43 //                                                       //
44 //    contact:    Olaf Conrad                            //
45 //                Institute of Geography                 //
46 //                University of Goettingen               //
47 //                Goldschmidtstr. 5                      //
48 //                37077 Goettingen                       //
49 //                Germany                                //
50 //                                                       //
51 ///////////////////////////////////////////////////////////
52 
53 //---------------------------------------------------------
54 
55 
56 ///////////////////////////////////////////////////////////
57 //														 //
58 //														 //
59 //														 //
60 ///////////////////////////////////////////////////////////
61 
62 //---------------------------------------------------------
63 #include "Grid_Profile_From_Lines.h"
64 
65 
66 ///////////////////////////////////////////////////////////
67 //														 //
68 //														 //
69 //														 //
70 ///////////////////////////////////////////////////////////
71 
72 //---------------------------------------------------------
CGrid_Profile_From_Lines(void)73 CGrid_Profile_From_Lines::CGrid_Profile_From_Lines(void)
74 {
75 	CSG_Parameter	*pNode;
76 
77 	Set_Name		(_TL("Profiles from Lines"));
78 
79 	Set_Author		(SG_T("O.Conrad (c) 2006"));
80 
81 	Set_Description	(_TW(
82 		"Create profiles from a grid based DEM for each line of a lines layer. "
83 	));
84 
85 	Parameters.Add_Grid(
86 		NULL	, "DEM"			, _TL("DEM"),
87 		_TL(""),
88 		PARAMETER_INPUT
89 	);
90 
91 	Parameters.Add_Grid_List(
92 		NULL	, "VALUES"		, _TL("Values"),
93 		_TL("Additional values that shall be saved to the output table."),
94 		PARAMETER_INPUT_OPTIONAL
95 	);
96 
97 	pNode	= Parameters.Add_Shapes(
98 		NULL	, "LINES"		, _TL("Lines"),
99 		_TL(""),
100 		PARAMETER_INPUT, SHAPE_TYPE_Line
101 	);
102 
103 	Parameters.Add_Table_Field(
104 		pNode	, "NAME"		, _TL("Name"),
105 		_TL("Naming for split lines"),
106 		true
107 	);
108 
109 	Parameters.Add_Shapes(
110 		NULL	, "PROFILE"		, _TL("Profiles"),
111 		_TL(""),
112 		PARAMETER_OUTPUT_OPTIONAL, SHAPE_TYPE_Point
113 	);
114 
115 	Parameters.Add_Shapes_List(
116 		NULL	, "PROFILES"	, _TL("Profiles"),
117 		_TL(""),
118 		PARAMETER_OUTPUT_OPTIONAL, SHAPE_TYPE_Point
119 	);
120 
121 	Parameters.Add_Value(
122 		NULL	, "SPLIT"		, _TL("Each Line as new Profile"),
123 		_TL(""),
124 		PARAMETER_TYPE_Bool, false
125 	);
126 }
127 
128 //---------------------------------------------------------
~CGrid_Profile_From_Lines(void)129 CGrid_Profile_From_Lines::~CGrid_Profile_From_Lines(void)
130 {}
131 
132 
133 ///////////////////////////////////////////////////////////
134 //														 //
135 //														 //
136 //														 //
137 ///////////////////////////////////////////////////////////
138 
139 //---------------------------------------------------------
On_Execute(void)140 bool CGrid_Profile_From_Lines::On_Execute(void)
141 {
142 	int			iLine, iName;
143 
144 	//-----------------------------------------------------
145 	m_pDEM		= Parameters("DEM")		->asGrid();
146 	m_pValues	= Parameters("VALUES")	->asGridList();
147 	m_pLines	= Parameters("LINES")	->asShapes();
148 	iName		= Parameters("NAME")	->asInt();
149 
150 	//-----------------------------------------------------
151 	if( Parameters("SPLIT")->asBool() == false )
152 	{
153 		if( (m_pProfile = Parameters("PROFILE")->asShapes()) == NULL )
154 		{
155 			Parameters("PROFILE")->Set_Value(m_pProfile = SG_Create_Shapes(SHAPE_TYPE_Point));
156 		}
157 
158 		Init_Profile(m_pProfile, CSG_String::Format(SG_T("%s [%s]"), m_pDEM->Get_Name(), _TL("Profile")));
159 
160 		for(iLine=0; iLine<m_pLines->Get_Count() && Set_Progress(iLine, m_pLines->Get_Count()); iLine++)
161 		{
162 			Set_Profile(iLine, m_pLines->Get_Shape(iLine));
163 		}
164 
165 		return( true );
166 	}
167 
168 	//-----------------------------------------------------
169 	else
170 	{
171 		Parameters("PROFILES")->asShapesList()->Del_Items();
172 
173 		for(iLine=0; iLine<m_pLines->Get_Count() && Set_Progress(iLine, m_pLines->Get_Count()); iLine++)
174 		{
175 			Init_Profile(m_pProfile = SG_Create_Shapes(), iName < 0
176 				? CSG_String::Format(SG_T("%s [%s %d]"), m_pDEM->Get_Name(), _TL("Profile"), iLine + 1)
177 				: CSG_String::Format(SG_T("%s [%s %s]"), m_pDEM->Get_Name(), _TL("Profile"), m_pLines->Get_Shape(iLine)->asString(iName))
178 			);
179 
180 			Set_Profile(iLine, m_pLines->Get_Shape(iLine));
181 
182 			Parameters("PROFILES")->asShapesList()->Add_Item(m_pProfile);
183 		}
184 
185 		return( true );
186 	}
187 
188 	//-----------------------------------------------------
189 	return( false );
190 }
191 
192 
193 ///////////////////////////////////////////////////////////
194 //														 //
195 //														 //
196 //														 //
197 ///////////////////////////////////////////////////////////
198 
199 //---------------------------------------------------------
200 enum
201 {
202 	F_LINE_ID	= 0,
203 	F_ID,
204 	F_DIST,
205 	F_DIST_SURF,
206 	F_X,
207 	F_Y,
208 	F_Z,
209 	F_VALUES
210 };
211 
212 //---------------------------------------------------------
Init_Profile(CSG_Shapes * pPoints,const SG_Char * Name)213 bool CGrid_Profile_From_Lines::Init_Profile(CSG_Shapes *pPoints, const SG_Char *Name)
214 {
215 	if( pPoints )
216 	{
217 		pPoints->Create(SHAPE_TYPE_Point, Name);
218 
219 		pPoints->Add_Field("LINE_ID"	, SG_DATATYPE_Int);
220 		pPoints->Add_Field("ID"			, SG_DATATYPE_Int);
221 		pPoints->Add_Field("DIST"		, SG_DATATYPE_Double);
222 		pPoints->Add_Field("DIST_SURF"	, SG_DATATYPE_Double);
223 		pPoints->Add_Field("X"			, SG_DATATYPE_Double);
224 		pPoints->Add_Field("Y"			, SG_DATATYPE_Double);
225 		pPoints->Add_Field("Z"			, SG_DATATYPE_Double);
226 
227 		for(int i=0; i<m_pValues->Get_Grid_Count(); i++)
228 		{
229 			pPoints->Add_Field(m_pValues->Get_Grid(i)->Get_Name(), SG_DATATYPE_Double);
230 		}
231 
232 		return( true );
233 	}
234 
235 	return( false );
236 }
237 
238 //---------------------------------------------------------
Set_Profile(int Line_ID,CSG_Shape * pLine)239 bool CGrid_Profile_From_Lines::Set_Profile(int Line_ID, CSG_Shape *pLine)
240 {
241 	if( pLine && pLine->Get_Point_Count(0) > 1 )
242 	{
243 		for(int iPart=0; iPart<pLine->Get_Part_Count(); iPart++)
244 		{
245 			TSG_Point	A, B;
246 
247 			B	= pLine->Get_Point(0, iPart);
248 
249 			for(int iPoint=1; iPoint<pLine->Get_Point_Count(iPart); iPoint++)
250 			{
251 				A	= B;
252 				B	= pLine->Get_Point(iPoint, iPart);
253 
254 				bool bLastPoint = false;
255 
256 				if( iPart == pLine->Get_Part_Count() - 1 && iPoint == pLine->Get_Point_Count(iPart) - 1 )
257 				{
258 					bLastPoint = true;
259 				}
260 
261 				Set_Profile(Line_ID, iPoint == 1, A, B, bLastPoint);
262 			}
263 		}
264 
265 		return( true );
266 	}
267 
268 	return( false );
269 }
270 
271 //---------------------------------------------------------
Set_Profile(int Line_ID,bool bStart,const TSG_Point & A,const TSG_Point & B,bool bLastPoint)272 bool CGrid_Profile_From_Lines::Set_Profile(int Line_ID, bool bStart, const TSG_Point &A, const TSG_Point &B, bool bLastPoint)
273 {
274 	double		dx, dy, d, n;
275 	TSG_Point	p;
276 
277 	//-----------------------------------------------------
278 	dx	= fabs(B.x - A.x);
279 	dy	= fabs(B.y - A.y);
280 
281 	if( dx > 0.0 || dy > 0.0 )
282 	{
283 		if( dx > dy )
284 		{
285 			dx	/= Get_Cellsize();
286 			n	 = dx;
287 			dy	/= dx;
288 			dx	 = Get_Cellsize();
289 		}
290 		else
291 		{
292 			dy	/= Get_Cellsize();
293 			n	 = dy;
294 			dx	/= dy;
295 			dy	 = Get_Cellsize();
296 		}
297 
298 		if( B.x < A.x )
299 		{
300 			dx	= -dx;
301 		}
302 
303 		if( B.y < A.y )
304 		{
305 			dy	= -dy;
306 		}
307 
308 		//-------------------------------------------------
309 		for(d=0.0, p.x=A.x, p.y=A.y; d<=n; d++, p.x+=dx, p.y+=dy)
310 		{
311 			Add_Point(Line_ID, bStart, p);
312 
313 			bStart	= false;
314 		}
315 
316 		if( bLastPoint && SG_Get_Distance(p, B) > M_ALMOST_ZERO )
317 		{
318 			Add_Point(Line_ID, bStart, B);
319 		}
320 	}
321 
322 	//-----------------------------------------------------
323 	return( true );
324 }
325 
326 //---------------------------------------------------------
Add_Point(int Line_ID,bool bStart,const TSG_Point & Point)327 bool CGrid_Profile_From_Lines::Add_Point(int Line_ID, bool bStart, const TSG_Point &Point)
328 {
329 	int			x, y, i;
330 	double		z, Distance, Distance_2;
331 	CSG_Shape	*pPoint, *pLast;
332 
333 	if( Get_System().Get_World_to_Grid(x, y, Point) && m_pDEM->is_InGrid(x, y) )
334 	{
335 		z	= m_pDEM->asDouble(x, y);
336 
337 		if( bStart || m_pProfile->Get_Count() == 0 )
338 		{
339 			Distance	= 0.0;
340 			Distance_2	= 0.0;
341 		}
342 		else
343 		{
344 			pLast		= m_pProfile->Get_Shape(m_pProfile->Get_Count() - 1);
345 			Distance	= SG_Get_Distance(Point, pLast->Get_Point(0));
346 
347 			if( Distance == 0.0 )
348 			{
349 				return( false );
350 			}
351 
352 			Distance_2	= pLast->asDouble(F_Z) - z;
353 			Distance_2	= sqrt(Distance*Distance + Distance_2*Distance_2);
354 
355 			Distance	+= pLast->asDouble(F_DIST);
356 			Distance_2	+= pLast->asDouble(F_DIST_SURF);
357 		}
358 
359 		pPoint	= m_pProfile->Add_Shape();
360 		pPoint->Add_Point(Point);
361 
362 		pPoint->Set_Value(F_LINE_ID  , Line_ID);
363 		pPoint->Set_Value(F_ID       , m_pProfile->Get_Count());
364 		pPoint->Set_Value(F_DIST     , Distance);
365 		pPoint->Set_Value(F_DIST_SURF, Distance_2);
366 		pPoint->Set_Value(F_X        , Point.x);
367 		pPoint->Set_Value(F_Y        , Point.y);
368 		pPoint->Set_Value(F_Z        , z);
369 
370 		for(i=0; i<m_pValues->Get_Grid_Count(); i++)
371 		{
372 			pPoint->Set_Value(F_VALUES + i, m_pValues->Get_Grid(i)->asDouble(x, y));
373 		}
374 
375 		return( true );
376 	}
377 
378 	return( false );
379 }
380 
381 
382 ///////////////////////////////////////////////////////////
383 //														 //
384 //														 //
385 //														 //
386 ///////////////////////////////////////////////////////////
387 
388 //---------------------------------------------------------
389