1 /**********************************************************
2 * Version $Id$
3 *********************************************************/
4
5 ///////////////////////////////////////////////////////////
6 // //
7 // SAGA //
8 // //
9 // System for Automated Geoscientific Analyses //
10 // //
11 // Tool Library //
12 // Table_Tools //
13 // //
14 //-------------------------------------------------------//
15 // //
16 // separate_by_direction.cpp //
17 // //
18 // Copyright (C) 2008 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 "separate_by_direction.h"
64
65
66 ///////////////////////////////////////////////////////////
67 // //
68 // //
69 // //
70 ///////////////////////////////////////////////////////////
71
72 //---------------------------------------------------------
CSeparate_by_Direction(void)73 CSeparate_by_Direction::CSeparate_by_Direction(void)
74 {
75 Set_Name (_TL("Separate points by direction"));
76
77 Set_Author (SG_T("O. Conrad (c) 2008"));
78
79 Set_Description (_TW(
80 "Separates points by direction. Direction is determined as average direction of three consecutive points A, B, C. "
81 "If the angle between the directions of A-B and B-C is higher than given tolerance angle the point is dropped. "
82 "This tool has been designed to separate GPS tracks recorded by tractors while preparing a field. "
83 ));
84
85 //-----------------------------------------------------
86 Parameters.Add_Shapes_List(
87 NULL , "OUTPUT" , _TL("Ouput"),
88 _TL(""),
89 PARAMETER_OUTPUT
90 );
91
92 Parameters.Add_Shapes(
93 NULL , "POINTS" , _TL("Points"),
94 _TL(""),
95 PARAMETER_INPUT, SHAPE_TYPE_Point
96 );
97
98 Parameters.Add_Value(
99 NULL , "DIRECTIONS" , _TL("Number of Directions"),
100 _TL(""),
101 PARAMETER_TYPE_Double , 4.0, 2.0, true
102 );
103
104 Parameters.Add_Value(
105 NULL , "TOLERANCE" , _TL("Tolerance (Degree)"),
106 _TL(""),
107 PARAMETER_TYPE_Double , 5.0, 0.0, true
108 );
109 }
110
111
112 ///////////////////////////////////////////////////////////
113 // //
114 // //
115 // //
116 ///////////////////////////////////////////////////////////
117
118 //---------------------------------------------------------
On_Execute(void)119 bool CSeparate_by_Direction::On_Execute(void)
120 {
121 int iSector, dir_Field;
122 CSG_Shapes *pPoints;
123 CSG_Parameter_Shapes_List *pOutput;
124
125 //-----------------------------------------------------
126 pOutput = Parameters("OUTPUT") ->asShapesList();
127 pPoints = Parameters("POINTS") ->asShapes();
128 m_Tolerance = Parameters("TOLERANCE") ->asDouble() * M_DEG_TO_RAD;
129 m_nSectors = Parameters("DIRECTIONS") ->asInt();
130 m_dSector = M_PI_360 / m_nSectors;
131
132 if( !pPoints || !pPoints->is_Valid() || pPoints->Get_Count() < 3 )
133 {
134 return( false );
135 }
136
137 //-----------------------------------------------------
138 pOutput->Del_Items();
139
140 dir_Field = pPoints->Get_Field_Count();
141
142 for(iSector=0; iSector<m_nSectors; iSector++)
143 {
144 pOutput->Add_Item(SG_Create_Shapes(SHAPE_TYPE_Point, CSG_String::Format(SG_T("Direction %.2f"), iSector * m_dSector * M_RAD_TO_DEG), pPoints));
145 pOutput->Get_Shapes(iSector)->Add_Field(_TL("Direction"), SG_DATATYPE_Double);
146 }
147
148 //-----------------------------------------------------
149 int iPoint;
150 double dir_A, dir_B, dir, dif;
151 CSG_Shape *pt_A, *pt_B;
152
153 pt_B = pPoints->Get_Shape(pPoints->Get_Count() - 2);
154 pt_A = pPoints->Get_Shape(pPoints->Get_Count() - 1);
155
156 dir_A = SG_Get_Angle_Of_Direction(pt_B->Get_Point(0), pt_A->Get_Point(0));
157
158 for(iPoint=0; iPoint<pPoints->Get_Count() && Set_Progress(iPoint, pPoints->Get_Count()); iPoint++)
159 {
160 pt_B = pt_A;
161 pt_A = pPoints->Get_Shape(iPoint);
162
163 dir_B = dir_A;
164 dir_A = SG_Get_Angle_Of_Direction(pt_B->Get_Point(0), pt_A->Get_Point(0));
165
166 dif = fmod(dir_A - dir_B, M_PI_360);
167
168 if( dif > M_PI_180 )
169 {
170 dif -= M_PI_360;
171 }
172 else if( dif < -M_PI_180 )
173 {
174 dif += M_PI_360;
175 }
176
177 if( fabs(dif) <= m_Tolerance )
178 {
179 dir = dir_B + 0.5 * dif;
180
181 iSector = (int)(fmod(M_PI_360 + 0.5 * m_dSector + dir, M_PI_360) / m_dSector);
182
183 if( iSector >= 0 && iSector < m_nSectors )
184 {
185 pOutput->Get_Shapes(iSector)->Add_Shape(pt_B)->Set_Value(dir_Field, dir * M_RAD_TO_DEG);
186 }
187 }
188 }
189
190 //-----------------------------------------------------
191 for(iSector=pOutput->Get_Item_Count()-1; iSector>=0; iSector--)
192 {
193 if( pOutput->Get_Shapes(iSector)->Get_Count() == 0 )
194 {
195 delete(pOutput->Get_Shapes(iSector));
196
197 pOutput->Del_Item(iSector);
198 }
199 }
200
201 //-----------------------------------------------------
202 return( pOutput->Get_Item_Count() > 0 );
203 }
204
205
206 ///////////////////////////////////////////////////////////
207 // //
208 // //
209 // //
210 ///////////////////////////////////////////////////////////
211
212 //---------------------------------------------------------
213