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