1
2 ///////////////////////////////////////////////////////////
3 // //
4 // SAGA //
5 // //
6 // System for Automated Geoscientific Analyses //
7 // //
8 // Tool Library //
9 // shapes_tools //
10 // //
11 //-------------------------------------------------------//
12 // //
13 // Shapes_Cut.cpp //
14 // //
15 // Copyright (C) 2006 by //
16 // Olaf Conrad //
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: oconrad@saga-gis.org //
40 // //
41 // contact: Olaf Conrad //
42 // Institute of Geography //
43 // University of Goettingen //
44 // Goldschmidtstr. 5 //
45 // 37077 Goettingen //
46 // Germany //
47 // //
48 ///////////////////////////////////////////////////////////
49
50 //---------------------------------------------------------
51 #include "shapes_cut.h"
52
53
54 ///////////////////////////////////////////////////////////
55 // //
56 // //
57 // //
58 ///////////////////////////////////////////////////////////
59
60 //---------------------------------------------------------
Cut_Shapes(CSG_Shapes * pPolygons,int Method,CSG_Shapes * pShapes,CSG_Shapes * pCut,double Overlap)61 bool Cut_Shapes(CSG_Shapes *pPolygons, int Method, CSG_Shapes *pShapes, CSG_Shapes *pCut, double Overlap)
62 {
63 if( !pCut || !pShapes || !pShapes->is_Valid() || !pPolygons || !pPolygons->is_Valid() || !pPolygons->Get_Extent().Intersects(pShapes->Get_Extent()) || pPolygons->Get_Type() != SHAPE_TYPE_Polygon )
64 {
65 return( false );
66 }
67
68 pCut->Create(pShapes->Get_Type(), CSG_String::Format("%s [%s]", pShapes->Get_Name(), _TL("Cut")), pShapes, pShapes->Get_Vertex_Type());
69
70 //-----------------------------------------------------
71 CSG_Shapes Intersect(SHAPE_TYPE_Polygon);
72 CSG_Shape_Polygon *pIntersect = Overlap > 0.0 && pShapes->Get_Type() == SHAPE_TYPE_Polygon
73 ? (CSG_Shape_Polygon *)Intersect.Add_Shape() : NULL;
74
75 //-----------------------------------------------------
76 for(int iShape=0; iShape<pShapes->Get_Count() && SG_UI_Process_Set_Progress(iShape, pShapes->Get_Count()); iShape++)
77 {
78 CSG_Shape *pShape = pShapes->Get_Shape(iShape);
79
80 bool bAdd = false;
81
82 for(int iPolygon=0; !bAdd && iPolygon<pPolygons->Get_Count(); iPolygon++)
83 {
84 CSG_Shape_Polygon *pPolygon = (CSG_Shape_Polygon *)pPolygons->Get_Shape(iPolygon);
85
86 switch( Method )
87 {
88 case 2: // center
89 bAdd = pPolygon->Contains(pShapes->Get_Type() == SHAPE_TYPE_Polygon
90 ? ((CSG_Shape_Polygon *)pShape)->Get_Centroid() : (TSG_Point)pShape->Get_Extent().Get_Center()
91 );
92 break;
93
94 case 1: // intersects
95 bAdd = pPolygon->Intersects(pShape) != INTERSECTION_None;
96
97 if( bAdd && pIntersect )
98 {
99 bAdd = SG_Polygon_Intersection(pPolygon, pShape, pIntersect)
100 && Overlap <= pIntersect->Get_Area() / ((CSG_Shape_Polygon *)pShape)->Get_Area();
101 }
102 break;
103
104 default: // completely contained
105 bAdd = pPolygon->Intersects(pShape) == INTERSECTION_Contains;
106 break;
107 }
108 }
109
110 //-------------------------------------------------
111 if( bAdd )
112 {
113 pCut->Add_Shape(pShape);
114 }
115 }
116
117 //-----------------------------------------------------
118 return( pCut->Get_Count() > 0 );
119 }
120
121 //---------------------------------------------------------
Cut_Shapes(CSG_Shapes * pPolygons,int Method,CSG_Shapes * pShapes,double Overlap)122 CSG_Shapes * Cut_Shapes(CSG_Shapes *pPolygons, int Method, CSG_Shapes *pShapes, double Overlap)
123 {
124 CSG_Shapes *pCut = SG_Create_Shapes();
125
126 if( Cut_Shapes(pPolygons, Method, pShapes, pCut, Overlap) )
127 {
128 return( pCut );
129 }
130
131 delete(pCut);
132
133 return( NULL );
134 }
135
136
137 ///////////////////////////////////////////////////////////
138 // //
139 ///////////////////////////////////////////////////////////
140
141 //---------------------------------------------------------
Cut_Shapes(CSG_Rect Extent,int Method,CSG_Shapes * pShapes,CSG_Shapes * pCut)142 bool Cut_Shapes(CSG_Rect Extent, int Method, CSG_Shapes *pShapes, CSG_Shapes *pCut)
143 {
144 if( !pCut || !pShapes || !pShapes->is_Valid() || !Extent.Intersects(pShapes->Get_Extent()) )
145 {
146 return( false );
147 }
148
149 pCut->Create(pShapes->Get_Type(), CSG_String::Format("%s [%s]", pShapes->Get_Name(), _TL("Cut")), pShapes, pShapes->Get_Vertex_Type());
150
151 //-----------------------------------------------------
152 for(int iShape=0; iShape<pShapes->Get_Count() && SG_UI_Process_Set_Progress(iShape, pShapes->Get_Count()); iShape++)
153 {
154 CSG_Shape *pShape = pShapes->Get_Shape(iShape);
155
156 bool bAdd;
157
158 switch( Method )
159 {
160 case 2: // center
161 bAdd = Extent.Contains(pShapes->Get_Type() == SHAPE_TYPE_Polygon
162 ? ((CSG_Shape_Polygon *)pShape)->Get_Centroid() : (TSG_Point)pShape->Get_Extent().Get_Center()
163 );
164 break;
165
166 case 1: // intersects
167 bAdd = pShape->Intersects(Extent) != INTERSECTION_None;
168 break;
169
170 default: // completely contained
171 bAdd = pShape->Intersects(Extent) == INTERSECTION_Contained;
172 break;
173 }
174
175 //-------------------------------------------------
176 if( bAdd )
177 {
178 pCut->Add_Shape(pShape);
179 }
180 }
181
182 //-----------------------------------------------------
183 return( pCut->Get_Count() > 0 );
184 }
185
186 //---------------------------------------------------------
Cut_Shapes(CSG_Rect Extent,int Method,CSG_Shapes * pShapes)187 CSG_Shapes * Cut_Shapes(CSG_Rect Extent, int Method, CSG_Shapes *pShapes)
188 {
189 CSG_Shapes *pCut = SG_Create_Shapes();
190
191 if( Cut_Shapes(Extent, Method, pShapes, pCut) )
192 {
193 return( pCut );
194 }
195
196 delete(pCut);
197
198 return( NULL );
199 }
200
201
202 ///////////////////////////////////////////////////////////
203 // //
204 ///////////////////////////////////////////////////////////
205
206 //---------------------------------------------------------
Cut_Methods_Str(void)207 CSG_String Cut_Methods_Str(void)
208 {
209 return( CSG_String::Format("%s|%s|%s",
210 _TL("completely contained"),
211 _TL("intersects"),
212 _TL("center")
213 ));
214 }
215
216 //---------------------------------------------------------
Cut_Set_Extent(CSG_Rect Extent,CSG_Shapes * pExtent,bool bClear)217 bool Cut_Set_Extent(CSG_Rect Extent, CSG_Shapes *pExtent, bool bClear)
218 {
219 if( pExtent )
220 {
221 if( bClear )
222 {
223 pExtent->Create(SHAPE_TYPE_Polygon, _TL("Extent [Cut]"));
224 pExtent->Add_Field("ID", SG_DATATYPE_Int);
225 }
226
227 if( pExtent->Get_Type() == SHAPE_TYPE_Polygon )
228 {
229 CSG_Shape *pShape = pExtent->Add_Shape();
230
231 pShape->Set_Value("ID", pExtent->Get_Count());
232
233 pShape->Add_Point(Extent.Get_XMin(), Extent.Get_YMin());
234 pShape->Add_Point(Extent.Get_XMin(), Extent.Get_YMax());
235 pShape->Add_Point(Extent.Get_XMax(), Extent.Get_YMax());
236 pShape->Add_Point(Extent.Get_XMax(), Extent.Get_YMin());
237 pShape->Add_Point(Extent.Get_XMin(), Extent.Get_YMin());
238
239 return( true );
240 }
241 }
242
243 return( false );
244 }
245
246
247 ///////////////////////////////////////////////////////////
248 // //
249 // //
250 // //
251 ///////////////////////////////////////////////////////////
252
253 //---------------------------------------------------------
CShapes_Cut(void)254 CShapes_Cut::CShapes_Cut(void)
255 {
256 Set_Name (_TL("Copy Shapes from Region"));
257
258 Set_Author ("O.Conrad (c) 2006");
259
260 Set_Description (_TW(
261 "Copies all shapes that belong to the specified region."
262 ));
263
264 //-----------------------------------------------------
265 Parameters.Add_Shapes_List(
266 "" , "SHAPES" , _TL("Shapes"),
267 _TL(""),
268 PARAMETER_INPUT
269 );
270
271 Parameters.Add_Shapes_List(
272 "" , "CUT" , _TL("Copy"),
273 _TL(""),
274 PARAMETER_OUTPUT
275 );
276
277 Parameters.Add_Choice(
278 "" , "METHOD" , _TL("Method"),
279 _TL(""),
280 Cut_Methods_Str(), 1
281 );
282
283 Parameters.Add_Choice(
284 "" , "EXTENT" , _TL("Region"),
285 _TL(""),
286 CSG_String::Format("%s|%s|%s|%s",
287 _TL("user defined"),
288 _TL("grid project"),
289 _TL("shapes layer extent"),
290 _TL("polygons")
291 ), 0
292 );
293
294 //-----------------------------------------------------
295 Parameters.Add_Double("", "AX", _TL("Left" ), _TL(""), 0.0);
296 Parameters.Add_Double("", "BX", _TL("Right" ), _TL(""), 1.0);
297 Parameters.Add_Double("", "AY", _TL("Bottom" ), _TL(""), 0.0);
298 Parameters.Add_Double("", "BY", _TL("Top" ), _TL(""), 1.0);
299 Parameters.Add_Double("", "DX", _TL("Horizontal Range"), _TL(""), 1.0, 0.0, true);
300 Parameters.Add_Double("", "DY", _TL("Vertical Range" ), _TL(""), 1.0, 0.0, true);
301
302 Parameters.Add_Grid_System(
303 "" , "GRID_SYS" , _TL("Grid System"),
304 _TL("")
305 );
306
307 Parameters.Add_Shapes(
308 "" , "SHAPES_EXT" , _TL("Shapes"),
309 _TL(""),
310 PARAMETER_INPUT
311 );
312
313 Parameters.Add_Shapes(
314 "" , "POLYGONS" , _TL("Polygons"),
315 _TL(""),
316 PARAMETER_INPUT, SHAPE_TYPE_Polygon
317 );
318
319 Parameters.Add_Double(
320 "" , "OVERLAP" , _TL("Minimum Overlap"),
321 _TL("minimum overlapping area as percentage of the total size of the input shape. applies to polygon layers only."),
322 50.0, 0.0, true, 100.0, true
323 );
324 }
325
326
327 ///////////////////////////////////////////////////////////
328 // //
329 ///////////////////////////////////////////////////////////
330
331 //---------------------------------------------------------
On_Parameter_Changed(CSG_Parameters * pParameters,CSG_Parameter * pParameter)332 int CShapes_Cut::On_Parameter_Changed(CSG_Parameters *pParameters, CSG_Parameter *pParameter)
333 {
334 if( pParameter->Cmp_Identifier("SHAPES") )
335 {
336 if( pParameter->asShapesList()->Get_Item_Count() > 0 )
337 {
338 CSG_Rect Extent(pParameter->asShapesList()->Get_Shapes(0)->Get_Extent());
339
340 for(int i=1; i<pParameter->asShapesList()->Get_Item_Count(); i++)
341 {
342 Extent.Union(pParameter->asShapesList()->Get_Shapes(i)->Get_Extent());
343 }
344
345 pParameters->Set_Parameter("AX", Extent.Get_XMin ());
346 pParameters->Set_Parameter("AY", Extent.Get_YMin ());
347 pParameters->Set_Parameter("BX", Extent.Get_XMax ());
348 pParameters->Set_Parameter("BY", Extent.Get_YMax ());
349 pParameters->Set_Parameter("DX", Extent.Get_XRange());
350 pParameters->Set_Parameter("DY", Extent.Get_YRange());
351 }
352 }
353
354 else if( pParameters->Get_Parameter("EXTENT")->asInt() == 0 )
355 {
356 double ax = pParameters->Get_Parameter("AX")->asDouble();
357 double ay = pParameters->Get_Parameter("AY")->asDouble();
358 double bx = pParameters->Get_Parameter("BX")->asDouble();
359 double by = pParameters->Get_Parameter("BY")->asDouble();
360 double dx = pParameters->Get_Parameter("DX")->asDouble();
361 double dy = pParameters->Get_Parameter("DY")->asDouble();
362
363 if( ax > bx ) { double d = ax; ax = bx; bx = d; }
364 if( ay > by ) { double d = ay; ay = by; by = d; }
365
366 if ( pParameter->Cmp_Identifier("DX") )
367 {
368 bx = ax + dx;
369 }
370 else if( pParameter->Cmp_Identifier("AX")
371 || pParameter->Cmp_Identifier("BX") )
372 {
373 dx = bx - ax;
374 }
375 else if( pParameter->Cmp_Identifier("DY") )
376 {
377 by = ay + dy;
378 }
379 else if( pParameter->Cmp_Identifier("AY")
380 || pParameter->Cmp_Identifier("BY") )
381 {
382 dy = by - ay;
383 }
384
385 pParameters->Set_Parameter("AX", ax);
386 pParameters->Set_Parameter("AY", ay);
387 pParameters->Set_Parameter("BX", bx);
388 pParameters->Set_Parameter("BY", by);
389 pParameters->Set_Parameter("DX", dx);
390 pParameters->Set_Parameter("DY", dy);
391 }
392
393 return( CSG_Tool::On_Parameter_Changed(pParameters, pParameter) );
394 }
395
396 //---------------------------------------------------------
On_Parameters_Enable(CSG_Parameters * pParameters,CSG_Parameter * pParameter)397 int CShapes_Cut::On_Parameters_Enable(CSG_Parameters *pParameters, CSG_Parameter *pParameter)
398 {
399 if( pParameter->Cmp_Identifier("EXTENT") )
400 {
401 pParameters->Set_Enabled("AX" , pParameter->asInt() == 0);
402 pParameters->Set_Enabled("AY" , pParameter->asInt() == 0);
403 pParameters->Set_Enabled("BX" , pParameter->asInt() == 0);
404 pParameters->Set_Enabled("BY" , pParameter->asInt() == 0);
405 pParameters->Set_Enabled("DX" , pParameter->asInt() == 0);
406 pParameters->Set_Enabled("DY" , pParameter->asInt() == 0);
407 pParameters->Set_Enabled("GRID_SYS" , pParameter->asInt() == 1);
408 pParameters->Set_Enabled("SHAPES_EXT", pParameter->asInt() == 2);
409 pParameters->Set_Enabled("POLYGONS" , pParameter->asInt() == 3);
410 }
411
412 if( pParameter->Cmp_Identifier("SHAPES")
413 || pParameter->Cmp_Identifier("METHOD") )
414 {
415 bool bEnable = pParameters->Get_Parameter("METHOD")->asInt() == 1; // intersects
416
417 if( bEnable )
418 {
419 CSG_Parameter_Shapes_List *pShapes = pParameters->Get_Parameter("SHAPES")->asShapesList();
420
421 bEnable = false;
422
423 for(int i=0; !bEnable && i<pShapes->Get_Item_Count(); i++)
424 {
425 bEnable = pShapes->Get_Shapes(i)->Get_Type() == SHAPE_TYPE_Polygon;
426 }
427 }
428
429 pParameters->Set_Enabled("OVERLAP" , bEnable);
430 }
431
432 return( CSG_Tool::On_Parameter_Changed(pParameters, pParameter) );
433 }
434
435
436 ///////////////////////////////////////////////////////////
437 // //
438 ///////////////////////////////////////////////////////////
439
440 //---------------------------------------------------------
On_Execute(void)441 bool CShapes_Cut::On_Execute(void)
442 {
443 CSG_Parameter_Shapes_List *pShapes = Parameters("SHAPES")->asShapesList();
444
445 if( pShapes->Get_Item_Count() < 1 )
446 {
447 return( false );
448 }
449
450 //-----------------------------------------------------
451 CSG_Rect Extent;
452 CSG_Shapes Polygons(SHAPE_TYPE_Polygon), *pPolygons = NULL;
453
454 switch( Parameters("EXTENT")->asInt() )
455 {
456 case 0: // user defined
457 Extent.Assign(
458 Parameters("AX")->asDouble(),
459 Parameters("AY")->asDouble(),
460 Parameters("BX")->asDouble(),
461 Parameters("BY")->asDouble()
462 );
463 break;
464
465 case 1: // grid project
466 Extent.Assign(Parameters("GRID_SYS")->asGrid_System()->Get_Extent());
467 break;
468
469 case 2: // shapes extent
470 Extent.Assign(Parameters("SHAPES_EXT")->asShapes()->Get_Extent());
471 break;
472
473 case 3: // polygons
474 pPolygons = Parameters("POLYGONS")->asShapes();
475 break;
476 }
477
478 if( !pPolygons )
479 {
480 CSG_Shape *pPolygon = Polygons.Add_Shape();
481
482 pPolygon->Add_Point(Extent.Get_XMin(), Extent.Get_YMin());
483 pPolygon->Add_Point(Extent.Get_XMin(), Extent.Get_YMax());
484 pPolygon->Add_Point(Extent.Get_XMax(), Extent.Get_YMax());
485 pPolygon->Add_Point(Extent.Get_XMax(), Extent.Get_YMin());
486
487 pPolygons = &Polygons;
488 }
489
490 //-----------------------------------------------------
491 CSG_Parameter_Shapes_List *pCuts = Parameters("CUT")->asShapesList();
492
493 pCuts->Del_Items();
494
495 int Method = Parameters("METHOD")->asInt();
496
497 double Overlap = Parameters("OVERLAP")->asDouble() / 100.0;
498
499 for(int i=0; i<pShapes->Get_Item_Count(); i++)
500 {
501 CSG_Shapes *pCut = Cut_Shapes(pPolygons, Method, pShapes->Get_Shapes(i), Overlap);
502
503 if( pCut )
504 {
505 pCuts->Add_Item(pCut);
506 }
507 }
508
509 //-----------------------------------------------------
510 return( pCuts->Get_Item_Count() > 0 );
511 }
512
513
514 ///////////////////////////////////////////////////////////
515 // //
516 // //
517 // //
518 ///////////////////////////////////////////////////////////
519
520 //---------------------------------------------------------
521