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