1 /**********************************************************
2 * Version $Id: GSPoints_Pattern_Analysis.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 // statistics_points //
13 // //
14 //-------------------------------------------------------//
15 // //
16 // GSPoints_Pattern_Analysis.cpp //
17 // //
18 // Copyright (C) 2010 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 Hamburg //
47 // Germany //
48 // //
49 ///////////////////////////////////////////////////////////
50
51 //---------------------------------------------------------
52
53
54 ///////////////////////////////////////////////////////////
55 // //
56 // //
57 // //
58 ///////////////////////////////////////////////////////////
59
60 //---------------------------------------------------------
61 #include "GSPoints_Pattern_Analysis.h"
62
63
64 ///////////////////////////////////////////////////////////
65 // //
66 // //
67 // //
68 ///////////////////////////////////////////////////////////
69
70 //---------------------------------------------------------
CGSPoints_Pattern_Analysis(void)71 CGSPoints_Pattern_Analysis::CGSPoints_Pattern_Analysis(void)
72 {
73 //-----------------------------------------------------
74 Set_Name (_TL("Spatial Point Pattern Analysis"));
75
76 Set_Author ("O.Conrad (c) 2010");
77
78 Set_Description(
79 _TL("Basic measures for spatial point patterns.")
80 );
81
82 //-----------------------------------------------------
83 Parameters.Add_Shapes("",
84 "POINTS" , _TL("Points"),
85 _TL(""),
86 PARAMETER_INPUT, SHAPE_TYPE_Point
87 );
88
89 Parameters.Add_Table_Field("POINTS",
90 "WEIGHT" , _TL("Weight"),
91 _TL(""),
92 true
93 );
94
95 Parameters.Add_Shapes("",
96 "CENTRE" , _TL("Mean Centre"),
97 _TL(""),
98 PARAMETER_OUTPUT, SHAPE_TYPE_Point
99 );
100
101 Parameters.Add_Shapes("",
102 "STDDIST" , _TL("Standard Distance"),
103 _TL(""),
104 PARAMETER_OUTPUT, SHAPE_TYPE_Polygon
105 );
106
107 Parameters.Add_Double("STDDIST",
108 "STEP" , _TL("Vertex Distance [Degree]"),
109 _TL(""),
110 5.0, 0.1, true, 20.0, true
111 );
112
113 Parameters.Add_Shapes("",
114 "BBOX" , _TL("Bounding Box"),
115 _TL(""),
116 PARAMETER_OUTPUT, SHAPE_TYPE_Polygon
117 );
118 }
119
120
121 ///////////////////////////////////////////////////////////
122 // //
123 ///////////////////////////////////////////////////////////
124
125 //---------------------------------------------------------
On_Execute(void)126 bool CGSPoints_Pattern_Analysis::On_Execute(void)
127 {
128 CSG_Shapes *pPoints = Parameters("POINTS")->asShapes();
129
130 if( pPoints->Get_Count() <= 1 )
131 {
132 Error_Set(_TL("not enough points to perform pattern analysis"));
133
134 return( false );
135 }
136
137 int iPoint, Weight = Parameters("WEIGHT")->asInt();
138
139 CSG_Simple_Statistics X, Y, D;
140
141 //-----------------------------------------------------
142 for(iPoint=0; iPoint<pPoints->Get_Count() && Set_Progress(iPoint, pPoints->Get_Count()); iPoint++)
143 {
144 TSG_Point p = pPoints->Get_Shape(iPoint)->Get_Point(0);
145
146 double w = Weight < 0 ? 1.0 : pPoints->Get_Shape(iPoint)->asDouble(Weight);
147
148 X.Add_Value(p.x, w);
149 Y.Add_Value(p.y, w);
150 }
151
152 if( X.Get_Range() == 0.0 && Y.Get_Range() == 0.0 )
153 {
154 Error_Set(_TL("no variation in point pattern"));
155
156 return( false );
157 }
158
159 //-----------------------------------------------------
160 double StdDist = 0.0;
161
162 for(iPoint=0; iPoint<pPoints->Get_Count() && Set_Progress(iPoint, pPoints->Get_Count()); iPoint++)
163 {
164 TSG_Point p = pPoints->Get_Shape(iPoint)->Get_Point(0);
165
166 double w = Weight < 0 ? 1.0 : pPoints->Get_Shape(iPoint)->asDouble(Weight);
167
168 D.Add_Value(SG_Get_Distance(X.Get_Mean(), Y.Get_Mean(), p.x, p.y), w);
169
170 StdDist += w * (SG_Get_Square(p.x - X.Get_Mean()) + SG_Get_Square(p.y - Y.Get_Mean()));
171 }
172
173 if( D.Get_Weights() == 0.0 )
174 {
175 Error_Set(_TL("number of valid points or sum of weights equals zero"));
176
177 return( false );
178 }
179
180 StdDist = sqrt(StdDist / D.Get_Weights());
181
182 //-----------------------------------------------------
183 CSG_Shapes *pShapes; CSG_Shape *pShape;
184
185 pShapes = Parameters("CENTRE")->asShapes();
186
187 pShapes ->Create(SHAPE_TYPE_Point, CSG_String::Format("%s [%s]", pPoints->Get_Name(), _TL("Centre")));
188 pShapes ->Add_Field("X_CENTRE", SG_DATATYPE_Double);
189 pShapes ->Add_Field("Y_CENTRE", SG_DATATYPE_Double);
190 pShapes ->Add_Field("N_POINTS", SG_DATATYPE_Double);
191 pShapes ->Add_Field("STDDIST" , SG_DATATYPE_Double);
192 pShapes ->Add_Field("MEANDIST", SG_DATATYPE_Double);
193
194 pShape = pShapes->Add_Shape();
195
196 pShape ->Set_Value(0, X.Get_Mean ());
197 pShape ->Set_Value(1, Y.Get_Mean ());
198 pShape ->Set_Value(2, D.Get_Count ());
199 pShape ->Set_Value(3, StdDist );
200 pShape ->Set_Value(4, D.Get_StdDev());
201
202 pShape ->Add_Point(X.Get_Mean(), Y.Get_Mean());
203
204 //-----------------------------------------------------
205 pShapes = Parameters("STDDIST")->asShapes();
206
207 pShapes ->Create(SHAPE_TYPE_Polygon, CSG_String::Format("%s [%s]", pPoints->Get_Name(), _TL("Standard Distance")));
208 pShapes ->Add_Field("X_CENTRE", SG_DATATYPE_Double);
209 pShapes ->Add_Field("Y_CENTRE", SG_DATATYPE_Double);
210 pShapes ->Add_Field("N_POINTS", SG_DATATYPE_Double);
211 pShapes ->Add_Field("STDDIST" , SG_DATATYPE_Double);
212
213 pShape = pShapes->Add_Shape();
214
215 pShape ->Set_Value(0, X.Get_Mean ());
216 pShape ->Set_Value(1, Y.Get_Mean ());
217 pShape ->Set_Value(2, X.Get_Count());
218 pShape ->Set_Value(3, StdDist );
219
220 double dTheta = Parameters("STEP")->asDouble() * M_DEG_TO_RAD;
221
222 for(double Theta=0.0; Theta<=M_PI_360; Theta+=dTheta)
223 {
224 pShape->Add_Point(
225 X.Get_Mean() + StdDist * cos(Theta),
226 Y.Get_Mean() + StdDist * sin(Theta)
227 );
228 }
229
230 //-----------------------------------------------------
231 pShapes = Parameters("BBOX")->asShapes();
232
233 pShapes ->Create(SHAPE_TYPE_Polygon, CSG_String::Format("%s [%s]", pPoints->Get_Name(), _TL("Bounding Box")));
234
235 pShapes ->Add_Field("XMIN", SG_DATATYPE_Double);
236 pShapes ->Add_Field("XMAX", SG_DATATYPE_Double);
237 pShapes ->Add_Field("YMIN", SG_DATATYPE_Double);
238 pShapes ->Add_Field("YMAX", SG_DATATYPE_Double);
239
240 pShape = pShapes->Add_Shape();
241
242 pShape ->Set_Value(0, X.Get_Minimum());
243 pShape ->Set_Value(1, X.Get_Maximum());
244 pShape ->Set_Value(2, Y.Get_Minimum());
245 pShape ->Set_Value(3, Y.Get_Maximum());
246
247 pShape ->Add_Point(X.Get_Minimum(), Y.Get_Minimum());
248 pShape ->Add_Point(X.Get_Minimum(), Y.Get_Maximum());
249 pShape ->Add_Point(X.Get_Maximum(), Y.Get_Maximum());
250 pShape ->Add_Point(X.Get_Maximum(), Y.Get_Minimum());
251
252 //-----------------------------------------------------
253 return( true );
254 }
255
256
257 ///////////////////////////////////////////////////////////
258 // //
259 // //
260 // //
261 ///////////////////////////////////////////////////////////
262
263 //---------------------------------------------------------
264