Files
secondo/Algebras/Raster2/Operators/toRegion.cpp

484 lines
19 KiB
C++
Raw Normal View History

2026-01-23 17:03:45 +08:00
/*
This file is part of SECONDO.
Copyright (C) 2011, University in Hagen, Department of Computer Science,
Database Systems for New Applications.
SECONDO 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.
SECONDO 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 SECONDO; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "toRegion.h"
#include "Algebras/Spatial/RobustSetOps.h"
#include "Algebras/Spatial/RegionTools.h"
namespace raster2 {
int toRegionFun
(Word* args, Word& result, int message, Word& local, Supplier s)
{
result = qp->ResultStorage(s);
Region* re = static_cast<Region*>(result.addr);
sbool* sbool1 = static_cast<sbool*>(args[0].addr);
if(!sbool1->isDefined()){
re->SetDefined(false);
return 0;
}
re->Clear();
grid2 grid = sbool1->getGrid();
double length = grid.getLength();
HalfSegment hs;
Region* buildRegionResult = new Region(0);
Region* buildHolesResult = new Region(0);
std::vector<std::vector<Point> > cycles;
std::vector<std::vector<Point> > holes;
double startX = 0.0;
double startY = 0.0;
Rectangle<2> bbox = sbool1->bbox();
double gridOriginX = grid.getOriginX();
double gridOriginY = grid.getOriginY();
RasterIndex<2> from = grid.getIndex(bbox.MinD(0), bbox.MinD(1));
RasterIndex<2> to = grid.getIndex(bbox.MaxD(0), bbox.MaxD(1));
for (RasterIndex<2> index=from; index < to; index.increment(from, to))
{
if ( sbool1->get(index) == true )
{
startX = index[0] * length + gridOriginX;
startY = index[1] * length + gridOriginY;
Point help(true, startX + length/2, startY + length/2);
if ( robust::contains(*buildRegionResult, help) == false )
{
std::vector<Point> cycle;
Point point1(true, startX, startY);
cycle.push_back(point1);
Point point2(true, startX, startY + length);
cycle.push_back(point2);
double currentX = startX;
double currentY = startY + length;
double lastX = startX;
double lastY = startY;
bool ende = false;
while ( ende == false )
{
if ( AlmostEqual(currentX, lastX)
&& !(AlmostEqual(currentY, lastY)) && currentY > lastY )
{
if (sbool1->atlocation(currentX - length/2,
currentY + length/2) == true )
{
Point point(true, currentX - length, currentY);
cycle.push_back(point);
lastX = currentX;
lastY = currentY;
currentX = currentX - length;
}
else if ( sbool1->atlocation(currentX + length/2,
currentY + length/2) == true )
{
Point point(true, currentX, currentY + length);
cycle.push_back(point);
lastX = currentX;
lastY = currentY;
currentY = currentY + length;
}
else if ( sbool1->atlocation(currentX + length/2,
currentY - length/2) == true )
{
Point point(true, currentX + length, currentY);
cycle.push_back(point);
lastX = currentX;
lastY = currentY;
currentX = currentX + length;
}
}
else if ( AlmostEqual(currentX, lastX)
&& !(AlmostEqual(currentY, lastY)) && currentY < lastY )
{
if ( sbool1->atlocation(currentX + length/2,
currentY - length/2) == true )
{
Point point(true, currentX + length, currentY);
cycle.push_back(point);
lastX = currentX;
lastY = currentY;
currentX = currentX + length;
}
else if (sbool1->atlocation(currentX - length/2,
currentY - length/2) == true )
{
Point point(true, currentX, currentY - length);
cycle.push_back(point);
lastX = currentX;
lastY = currentY;
currentY = currentY - length;
}
else if ( sbool1->atlocation(currentX - length/2,
currentY + length/2) == true )
{
Point point(true, currentX - length, currentY);
cycle.push_back(point);
lastX = currentX;
lastY = currentY;
currentX = currentX - length;
}
}
else if ( !(AlmostEqual(currentX, lastX)) && currentX > lastX
&& AlmostEqual(currentY, lastY) )
{
if ( sbool1->atlocation(currentX + length/2,
currentY + length/2) == true )
{
Point point(true, currentX, currentY + length);
cycle.push_back(point);
lastX = currentX;
lastY = currentY;
currentY = currentY + length;
}
else if ( sbool1->atlocation(currentX + length/2,
currentY - length/2) == true )
{
Point point(true, currentX + length, currentY);
cycle.push_back(point);
lastX = currentX;
lastY = currentY;
currentX = currentX + length;
}
else if (sbool1->atlocation(currentX - length/2,
currentY - length/2) == true )
{
Point point(true, currentX, currentY - length);
cycle.push_back(point);
lastX = currentX;
lastY = currentY;
currentY = currentY - length;
}
}
else if ( !(AlmostEqual(currentX, lastX)) && currentX < lastX
&& AlmostEqual(currentY, lastY) )
{
if ( sbool1->atlocation(currentX - length/2,
currentY - length/2) == true )
{
Point point(true, currentX, currentY - length);
cycle.push_back(point);
lastX = currentX;
lastY = currentY;
currentY = currentY - length;
}
else if ( sbool1->atlocation(currentX - length/2,
currentY + length/2) == true )
{
Point point(true, currentX - length, currentY);
cycle.push_back(point);
lastX = currentX;
lastY = currentY;
currentX = currentX - length;
}
else if ( sbool1->atlocation(currentX + length/2,
currentY + length/2) == true )
{
Point point(true, currentX, currentY + length);
cycle.push_back(point);
lastX = currentX;
lastY = currentY;
currentY = currentY + length;
}
}
if ( AlmostEqual(startX, currentX) &&
AlmostEqual(startY, currentY) )
{
ende = true;
}
}
if(!getDir(cycle))
{
reverseCycle(cycle);
}
cycles.push_back(cycle);
if(buildRegionResult){
delete buildRegionResult;
}
buildRegionResult = buildRegion(cycles);
}
}
else if ( sbool1->get(index) == false )
{
startX = index[0] * length + gridOriginX;
startY = index[1] * length + gridOriginY;
Point help(true, startX + length/2, startY + length/2);
if ( (robust::contains(*buildRegionResult, help) == true) &&
(robust::contains(*buildHolesResult, help) == false) )
{
std::vector<Point> cycle;
Point point1(true, startX, startY);
cycle.push_back(point1);
Point point2(true, startX, startY + length);
cycle.push_back(point2);
double currentX = startX;
double currentY = startY + length;
double lastX = startX;
double lastY = startY;
bool ende = false;
while ( ende == false )
{
Point p1(true, currentX - length/2, currentY + length/2);
Point p2(true, currentX + length/2, currentY + length/2);
Point p3(true, currentX + length/2, currentY - length/2);
Point p4(true, currentX - length/2, currentY - length/2);
if ( AlmostEqual(currentX, lastX)
&& !(AlmostEqual(currentY, lastY)) && currentY > lastY )
{
if ((sbool1->atlocation(currentX - length/2,
currentY + length/2) == false)
&& (robust::contains(*buildRegionResult, p1) == true))
{
Point point(true, currentX - length, currentY);
cycle.push_back(point);
lastX = currentX;
lastY = currentY;
currentX = currentX - length;
}
else if ((sbool1->atlocation(currentX + length/2,
currentY + length/2) == false)
&& (robust::contains(*buildRegionResult, p2) == true))
{
Point point(true, currentX, currentY + length);
cycle.push_back(point);
lastX = currentX;
lastY = currentY;
currentY = currentY + length;
}
else if ((sbool1->atlocation(currentX + length/2,
currentY - length/2) == false)
&& (robust::contains(*buildRegionResult, p3) == true))
{
Point point(true, currentX + length, currentY);
cycle.push_back(point);
lastX = currentX;
lastY = currentY;
currentX = currentX + length;
}
}
else if ( AlmostEqual(currentX, lastX)
&& !(AlmostEqual(currentY, lastY)) && currentY < lastY )
{
if ((sbool1->atlocation(currentX + length/2,
currentY - length/2) == false)
&& (robust::contains(*buildRegionResult, p3) == true))
{
Point point(true, currentX + length, currentY);
cycle.push_back(point);
lastX = currentX;
lastY = currentY;
currentX = currentX + length;
}
else if ((sbool1->atlocation(currentX - length/2,
currentY - length/2) == false)
&& (robust::contains(*buildRegionResult, p4) == true))
{
Point point(true, currentX, currentY - length);
cycle.push_back(point);
lastX = currentX;
lastY = currentY;
currentY = currentY - length;
}
else if ((sbool1->atlocation(currentX - length/2,
currentY + length/2) == false)
&& (robust::contains(*buildRegionResult, p1) == true))
{
Point point(true, currentX - length, currentY);
cycle.push_back(point);
lastX = currentX;
lastY = currentY;
currentX = currentX - length;
}
}
else if ( !(AlmostEqual(currentX, lastX)) && currentX > lastX
&& AlmostEqual(currentY, lastY) )
{
if ((sbool1->atlocation(currentX + length/2,
currentY + length/2) == false)
&& (robust::contains(*buildRegionResult, p2) == true))
{
Point point(true, currentX, currentY + length);
cycle.push_back(point);
lastX = currentX;
lastY = currentY;
currentY = currentY + length;
}
else if ((sbool1->atlocation(currentX + length/2,
currentY - length/2) == false)
&& (robust::contains(*buildRegionResult, p3) == true))
{
Point point(true, currentX + length, currentY);
cycle.push_back(point);
lastX = currentX;
lastY = currentY;
currentX = currentX + length;
}
else if ((sbool1->atlocation(currentX - length/2,
currentY - length/2) == false)
&& (robust::contains(*buildRegionResult, p4) == true))
{
Point point(true, currentX, currentY - length);
cycle.push_back(point);
lastX = currentX;
lastY = currentY;
currentY = currentY - length;
}
}
else if ( !(AlmostEqual(currentX, lastX)) && currentX < lastX
&& AlmostEqual(currentY, lastY) )
{
if ((sbool1->atlocation(currentX - length/2,
currentY - length/2) == false)
&& (robust::contains(*buildRegionResult, p4) == true))
{
Point point(true, currentX, currentY - length);
cycle.push_back(point);
lastX = currentX;
lastY = currentY;
currentY = currentY - length;
}
else if ((sbool1->atlocation(currentX - length/2,
currentY + length/2) == false)
&& (robust::contains(*buildRegionResult, p1) == true))
{
Point point(true, currentX - length, currentY);
cycle.push_back(point);
lastX = currentX;
lastY = currentY;
currentX = currentX - length;
}
else if ((sbool1->atlocation(currentX + length/2,
currentY + length/2) == false)
&& (robust::contains(*buildRegionResult, p2) == true))
{
Point point(true, currentX, currentY + length);
cycle.push_back(point);
lastX = currentX;
lastY = currentY;
currentY = currentY + length;
}
}
if ( AlmostEqual(startX, currentX) &&
AlmostEqual(startY, currentY) )
{
ende = true;
}
}
holes.push_back(cycle);
if(buildHolesResult){
delete buildHolesResult;
}
buildHolesResult = buildRegion(holes);
if(getDir(cycle))
{
reverseCycle(cycle);
}
cycles.push_back(cycle);
if(buildRegionResult){
delete buildRegionResult;
}
buildRegionResult = buildRegion(cycles);
}
}
}
std::swap(*re, *buildRegionResult);
delete buildRegionResult;
delete buildHolesResult;
return 0;
}
ListExpr toRegionTypeMap(ListExpr args)
{
NList type(args);
if (type.length() != 1)
return type.typeError("Expect one argument.");
if ( type.first() == NList(sbool::BasicType()))
{
return NList(Region::BasicType()).listExpr();
}
return NList::typeError
("Expecting a sbool.");
}
}