///////////////////////////////////////////////////////////
// //
// SAGA //
// //
// System for Automated Geoscientific Analyses //
// //
// Tool Library //
// shapes_tools //
// //
//-------------------------------------------------------//
// //
// Shapes_Cut.cpp //
// //
// Copyright (C) 2006 by //
// Olaf Conrad //
// //
//-------------------------------------------------------//
// //
// This file is part of 'SAGA - System for Automated //
// Geoscientific Analyses'. SAGA is free software; you //
// can redistribute it and/or modify it under the terms //
// of the GNU General Public License as published by the //
// Free Software Foundation, either version 2 of the //
// License, or (at your option) any later version. //
// //
// SAGA is distributed in the hope that it will be //
// useful, but WITHOUT ANY WARRANTY; without even the //
// implied warranty of MERCHANTABILITY or FITNESS FOR A //
// PARTICULAR PURPOSE. See the GNU General Public //
// License for more details. //
// //
// You should have received a copy of the GNU General //
// Public License along with this program; if not, see //
// . //
// //
//-------------------------------------------------------//
// //
// e-mail: oconrad@saga-gis.org //
// //
// contact: Olaf Conrad //
// Institute of Geography //
// University of Goettingen //
// Goldschmidtstr. 5 //
// 37077 Goettingen //
// Germany //
// //
///////////////////////////////////////////////////////////
//---------------------------------------------------------
#include "shapes_cut.h"
///////////////////////////////////////////////////////////
// //
// //
// //
///////////////////////////////////////////////////////////
//---------------------------------------------------------
bool Cut_Shapes(CSG_Shapes *pPolygons, int Method, CSG_Shapes *pShapes, CSG_Shapes *pCut, double Overlap)
{
if( !pCut || !pShapes || !pShapes->is_Valid() || !pPolygons || !pPolygons->is_Valid() || !pPolygons->Get_Extent().Intersects(pShapes->Get_Extent()) || pPolygons->Get_Type() != SHAPE_TYPE_Polygon )
{
return( false );
}
pCut->Create(pShapes->Get_Type(), CSG_String::Format("%s [%s]", pShapes->Get_Name(), _TL("Cut")), pShapes, pShapes->Get_Vertex_Type());
//-----------------------------------------------------
CSG_Shapes Intersect(SHAPE_TYPE_Polygon);
CSG_Shape_Polygon *pIntersect = Overlap > 0.0 && pShapes->Get_Type() == SHAPE_TYPE_Polygon
? (CSG_Shape_Polygon *)Intersect.Add_Shape() : NULL;
//-----------------------------------------------------
for(int iShape=0; iShapeGet_Count() && SG_UI_Process_Set_Progress(iShape, pShapes->Get_Count()); iShape++)
{
CSG_Shape *pShape = pShapes->Get_Shape(iShape);
bool bAdd = false;
for(int iPolygon=0; !bAdd && iPolygonGet_Count(); iPolygon++)
{
CSG_Shape_Polygon *pPolygon = (CSG_Shape_Polygon *)pPolygons->Get_Shape(iPolygon);
switch( Method )
{
case 2: // center
bAdd = pPolygon->Contains(pShapes->Get_Type() == SHAPE_TYPE_Polygon
? ((CSG_Shape_Polygon *)pShape)->Get_Centroid() : (TSG_Point)pShape->Get_Extent().Get_Center()
);
break;
case 1: // intersects
bAdd = pPolygon->Intersects(pShape) != INTERSECTION_None;
if( bAdd && pIntersect )
{
bAdd = SG_Polygon_Intersection(pPolygon, pShape, pIntersect)
&& Overlap <= pIntersect->Get_Area() / ((CSG_Shape_Polygon *)pShape)->Get_Area();
}
break;
default: // completely contained
bAdd = pPolygon->Intersects(pShape) == INTERSECTION_Contains;
break;
}
}
//-------------------------------------------------
if( bAdd )
{
pCut->Add_Shape(pShape);
}
}
//-----------------------------------------------------
return( pCut->Get_Count() > 0 );
}
//---------------------------------------------------------
CSG_Shapes * Cut_Shapes(CSG_Shapes *pPolygons, int Method, CSG_Shapes *pShapes, double Overlap)
{
CSG_Shapes *pCut = SG_Create_Shapes();
if( Cut_Shapes(pPolygons, Method, pShapes, pCut, Overlap) )
{
return( pCut );
}
delete(pCut);
return( NULL );
}
///////////////////////////////////////////////////////////
// //
///////////////////////////////////////////////////////////
//---------------------------------------------------------
bool Cut_Shapes(CSG_Rect Extent, int Method, CSG_Shapes *pShapes, CSG_Shapes *pCut)
{
if( !pCut || !pShapes || !pShapes->is_Valid() || !Extent.Intersects(pShapes->Get_Extent()) )
{
return( false );
}
pCut->Create(pShapes->Get_Type(), CSG_String::Format("%s [%s]", pShapes->Get_Name(), _TL("Cut")), pShapes, pShapes->Get_Vertex_Type());
//-----------------------------------------------------
for(int iShape=0; iShapeGet_Count() && SG_UI_Process_Set_Progress(iShape, pShapes->Get_Count()); iShape++)
{
CSG_Shape *pShape = pShapes->Get_Shape(iShape);
bool bAdd;
switch( Method )
{
case 2: // center
bAdd = Extent.Contains(pShapes->Get_Type() == SHAPE_TYPE_Polygon
? ((CSG_Shape_Polygon *)pShape)->Get_Centroid() : (TSG_Point)pShape->Get_Extent().Get_Center()
);
break;
case 1: // intersects
bAdd = pShape->Intersects(Extent) != INTERSECTION_None;
break;
default: // completely contained
bAdd = pShape->Intersects(Extent) == INTERSECTION_Contained;
break;
}
//-------------------------------------------------
if( bAdd )
{
pCut->Add_Shape(pShape);
}
}
//-----------------------------------------------------
return( pCut->Get_Count() > 0 );
}
//---------------------------------------------------------
CSG_Shapes * Cut_Shapes(CSG_Rect Extent, int Method, CSG_Shapes *pShapes)
{
CSG_Shapes *pCut = SG_Create_Shapes();
if( Cut_Shapes(Extent, Method, pShapes, pCut) )
{
return( pCut );
}
delete(pCut);
return( NULL );
}
///////////////////////////////////////////////////////////
// //
///////////////////////////////////////////////////////////
//---------------------------------------------------------
CSG_String Cut_Methods_Str(void)
{
return( CSG_String::Format("%s|%s|%s",
_TL("completely contained"),
_TL("intersects"),
_TL("center")
));
}
//---------------------------------------------------------
bool Cut_Set_Extent(CSG_Rect Extent, CSG_Shapes *pExtent, bool bClear)
{
if( pExtent )
{
if( bClear )
{
pExtent->Create(SHAPE_TYPE_Polygon, _TL("Extent [Cut]"));
pExtent->Add_Field("ID", SG_DATATYPE_Int);
}
if( pExtent->Get_Type() == SHAPE_TYPE_Polygon )
{
CSG_Shape *pShape = pExtent->Add_Shape();
pShape->Set_Value("ID", pExtent->Get_Count());
pShape->Add_Point(Extent.Get_XMin(), Extent.Get_YMin());
pShape->Add_Point(Extent.Get_XMin(), Extent.Get_YMax());
pShape->Add_Point(Extent.Get_XMax(), Extent.Get_YMax());
pShape->Add_Point(Extent.Get_XMax(), Extent.Get_YMin());
pShape->Add_Point(Extent.Get_XMin(), Extent.Get_YMin());
return( true );
}
}
return( false );
}
///////////////////////////////////////////////////////////
// //
// //
// //
///////////////////////////////////////////////////////////
//---------------------------------------------------------
CShapes_Cut::CShapes_Cut(void)
{
Set_Name (_TL("Copy Shapes from Region"));
Set_Author ("O.Conrad (c) 2006");
Set_Description (_TW(
"Copies all shapes that belong to the specified region."
));
//-----------------------------------------------------
Parameters.Add_Shapes_List(
"" , "SHAPES" , _TL("Shapes"),
_TL(""),
PARAMETER_INPUT
);
Parameters.Add_Shapes_List(
"" , "CUT" , _TL("Copy"),
_TL(""),
PARAMETER_OUTPUT
);
Parameters.Add_Choice(
"" , "METHOD" , _TL("Method"),
_TL(""),
Cut_Methods_Str(), 1
);
Parameters.Add_Choice(
"" , "EXTENT" , _TL("Region"),
_TL(""),
CSG_String::Format("%s|%s|%s|%s",
_TL("user defined"),
_TL("grid project"),
_TL("shapes layer extent"),
_TL("polygons")
), 0
);
//-----------------------------------------------------
Parameters.Add_Double("", "AX", _TL("Left" ), _TL(""), 0.0);
Parameters.Add_Double("", "BX", _TL("Right" ), _TL(""), 1.0);
Parameters.Add_Double("", "AY", _TL("Bottom" ), _TL(""), 0.0);
Parameters.Add_Double("", "BY", _TL("Top" ), _TL(""), 1.0);
Parameters.Add_Double("", "DX", _TL("Horizontal Range"), _TL(""), 1.0, 0.0, true);
Parameters.Add_Double("", "DY", _TL("Vertical Range" ), _TL(""), 1.0, 0.0, true);
Parameters.Add_Grid_System(
"" , "GRID_SYS" , _TL("Grid System"),
_TL("")
);
Parameters.Add_Shapes(
"" , "SHAPES_EXT" , _TL("Shapes"),
_TL(""),
PARAMETER_INPUT
);
Parameters.Add_Shapes(
"" , "POLYGONS" , _TL("Polygons"),
_TL(""),
PARAMETER_INPUT, SHAPE_TYPE_Polygon
);
Parameters.Add_Double(
"" , "OVERLAP" , _TL("Minimum Overlap"),
_TL("minimum overlapping area as percentage of the total size of the input shape. applies to polygon layers only."),
50.0, 0.0, true, 100.0, true
);
}
///////////////////////////////////////////////////////////
// //
///////////////////////////////////////////////////////////
//---------------------------------------------------------
int CShapes_Cut::On_Parameter_Changed(CSG_Parameters *pParameters, CSG_Parameter *pParameter)
{
if( pParameter->Cmp_Identifier("SHAPES") )
{
if( pParameter->asShapesList()->Get_Item_Count() > 0 )
{
CSG_Rect Extent(pParameter->asShapesList()->Get_Shapes(0)->Get_Extent());
for(int i=1; iasShapesList()->Get_Item_Count(); i++)
{
Extent.Union(pParameter->asShapesList()->Get_Shapes(i)->Get_Extent());
}
pParameters->Set_Parameter("AX", Extent.Get_XMin ());
pParameters->Set_Parameter("AY", Extent.Get_YMin ());
pParameters->Set_Parameter("BX", Extent.Get_XMax ());
pParameters->Set_Parameter("BY", Extent.Get_YMax ());
pParameters->Set_Parameter("DX", Extent.Get_XRange());
pParameters->Set_Parameter("DY", Extent.Get_YRange());
}
}
else if( pParameters->Get_Parameter("EXTENT")->asInt() == 0 )
{
double ax = pParameters->Get_Parameter("AX")->asDouble();
double ay = pParameters->Get_Parameter("AY")->asDouble();
double bx = pParameters->Get_Parameter("BX")->asDouble();
double by = pParameters->Get_Parameter("BY")->asDouble();
double dx = pParameters->Get_Parameter("DX")->asDouble();
double dy = pParameters->Get_Parameter("DY")->asDouble();
if( ax > bx ) { double d = ax; ax = bx; bx = d; }
if( ay > by ) { double d = ay; ay = by; by = d; }
if ( pParameter->Cmp_Identifier("DX") )
{
bx = ax + dx;
}
else if( pParameter->Cmp_Identifier("AX")
|| pParameter->Cmp_Identifier("BX") )
{
dx = bx - ax;
}
else if( pParameter->Cmp_Identifier("DY") )
{
by = ay + dy;
}
else if( pParameter->Cmp_Identifier("AY")
|| pParameter->Cmp_Identifier("BY") )
{
dy = by - ay;
}
pParameters->Set_Parameter("AX", ax);
pParameters->Set_Parameter("AY", ay);
pParameters->Set_Parameter("BX", bx);
pParameters->Set_Parameter("BY", by);
pParameters->Set_Parameter("DX", dx);
pParameters->Set_Parameter("DY", dy);
}
return( CSG_Tool::On_Parameter_Changed(pParameters, pParameter) );
}
//---------------------------------------------------------
int CShapes_Cut::On_Parameters_Enable(CSG_Parameters *pParameters, CSG_Parameter *pParameter)
{
if( pParameter->Cmp_Identifier("EXTENT") )
{
pParameters->Set_Enabled("AX" , pParameter->asInt() == 0);
pParameters->Set_Enabled("AY" , pParameter->asInt() == 0);
pParameters->Set_Enabled("BX" , pParameter->asInt() == 0);
pParameters->Set_Enabled("BY" , pParameter->asInt() == 0);
pParameters->Set_Enabled("DX" , pParameter->asInt() == 0);
pParameters->Set_Enabled("DY" , pParameter->asInt() == 0);
pParameters->Set_Enabled("GRID_SYS" , pParameter->asInt() == 1);
pParameters->Set_Enabled("SHAPES_EXT", pParameter->asInt() == 2);
pParameters->Set_Enabled("POLYGONS" , pParameter->asInt() == 3);
}
if( pParameter->Cmp_Identifier("SHAPES")
|| pParameter->Cmp_Identifier("METHOD") )
{
bool bEnable = pParameters->Get_Parameter("METHOD")->asInt() == 1; // intersects
if( bEnable )
{
CSG_Parameter_Shapes_List *pShapes = pParameters->Get_Parameter("SHAPES")->asShapesList();
bEnable = false;
for(int i=0; !bEnable && iGet_Item_Count(); i++)
{
bEnable = pShapes->Get_Shapes(i)->Get_Type() == SHAPE_TYPE_Polygon;
}
}
pParameters->Set_Enabled("OVERLAP" , bEnable);
}
return( CSG_Tool::On_Parameter_Changed(pParameters, pParameter) );
}
///////////////////////////////////////////////////////////
// //
///////////////////////////////////////////////////////////
//---------------------------------------------------------
bool CShapes_Cut::On_Execute(void)
{
CSG_Parameter_Shapes_List *pShapes = Parameters("SHAPES")->asShapesList();
if( pShapes->Get_Item_Count() < 1 )
{
return( false );
}
//-----------------------------------------------------
CSG_Rect Extent;
CSG_Shapes Polygons(SHAPE_TYPE_Polygon), *pPolygons = NULL;
switch( Parameters("EXTENT")->asInt() )
{
case 0: // user defined
Extent.Assign(
Parameters("AX")->asDouble(),
Parameters("AY")->asDouble(),
Parameters("BX")->asDouble(),
Parameters("BY")->asDouble()
);
break;
case 1: // grid project
Extent.Assign(Parameters("GRID_SYS")->asGrid_System()->Get_Extent());
break;
case 2: // shapes extent
Extent.Assign(Parameters("SHAPES_EXT")->asShapes()->Get_Extent());
break;
case 3: // polygons
pPolygons = Parameters("POLYGONS")->asShapes();
break;
}
if( !pPolygons )
{
CSG_Shape *pPolygon = Polygons.Add_Shape();
pPolygon->Add_Point(Extent.Get_XMin(), Extent.Get_YMin());
pPolygon->Add_Point(Extent.Get_XMin(), Extent.Get_YMax());
pPolygon->Add_Point(Extent.Get_XMax(), Extent.Get_YMax());
pPolygon->Add_Point(Extent.Get_XMax(), Extent.Get_YMin());
pPolygons = &Polygons;
}
//-----------------------------------------------------
CSG_Parameter_Shapes_List *pCuts = Parameters("CUT")->asShapesList();
pCuts->Del_Items();
int Method = Parameters("METHOD")->asInt();
double Overlap = Parameters("OVERLAP")->asDouble() / 100.0;
for(int i=0; iGet_Item_Count(); i++)
{
CSG_Shapes *pCut = Cut_Shapes(pPolygons, Method, pShapes->Get_Shapes(i), Overlap);
if( pCut )
{
pCuts->Add_Item(pCut);
}
}
//-----------------------------------------------------
return( pCuts->Get_Item_Count() > 0 );
}
///////////////////////////////////////////////////////////
// //
// //
// //
///////////////////////////////////////////////////////////
//---------------------------------------------------------