/* ---- This file is part of SECONDO. Copyright (C) 2004, 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 ---- May, 2007 Leonardo Azevedo, Rafael Brand */ //--------------------------------------------------------------------------- #ifndef GERARASTERSECONDOCPP #define GERARASTERSECONDOCPP #define MAX_VECTORS_PART 255 #include "GenerateRaster.h" //#include "Segment.cpp" #include "ClipCel.cpp" #include "../RTree/Plane.cpp" #include "Signature4CRS.cpp" #include "../RTree/coord.cpp" //#include "rotinas.cpp" #define CoordinateX 0 #define CoordinateY 1 #define ROUNDING_CONSTANT 0.000001 unsigned is_equal(long double a, long double b); //#define DEBUGMESSAGES Signature4CRS* GeraRasterSecondo::generateRaster(const long id, const Region *region, const Line *line, const Points *points, int potency, SignatureType signatureType) { Rectangle<2> RectMBR; if (region != NULL) RectMBR = region->BoundingBox(); else if (line != NULL) RectMBR = line->BoundingBox(); else RectMBR = points->BoundingBox(); MBR mbr(Coordinate((long int)RectMBR.MinD(CoordinateX), (long int)RectMBR.MinD(CoordinateY)), Coordinate((long int)RectMBR.MaxD(CoordinateX), (long int)RectMBR.MaxD(CoordinateY))); Plane plane = minimumPlane( potency, mbr ); long cellSize = 0x1lu << plane.potency(); unsigned numberOfCellsX, numberOfCellsY; double blockArea=0; ClipCel clipCel[PRODUCT]; HalfSegment hs; Point pt(0,0); //swapMatrix is used to indicate, in the full cell step, //when the filling must change from empty to full and vice versa static int swapMatrix[ PRODUCT ]; //calculatedGrid is used to store the cells that already have their filling //defined in the execution of the algorithm of border filling, //so that these cells would not be considered during the determination of //the full cells filling static int calculatedGrid[PRODUCT]; memset(swapMatrix,0, PRODUCT * sizeof( int )); memset(calculatedGrid,0, PRODUCT * sizeof( int )); Coordinate min,max; min.x = mbr.min.x & (0xFFFFFFFFlu << plane.potency()); min.y = mbr.min.y & (0xFFFFFFFFlu << plane.potency()); // The min coordinate should be less or equal to the min Coordinate // of the plane calculated or will be one cell size to the right. // So, when they are different, I just set the min coordinate // to plane.min and take off the number of cells in X and/or in Y. numberOfCellsX = plane.numberOfCellsX(); numberOfCellsY = plane.numberOfCellsY(); if (min.x != plane.min.x) { plane.min.x = min.x; numberOfCellsX--; } if (min.y != plane.min.y) { plane.min.y = min.y; numberOfCellsY--; } max.x = min.x + numberOfCellsX * cellSize ; max.y = min.y + numberOfCellsY * cellSize ; if ( plane.max.x != max.x) { numberOfCellsX--; } if ( plane.max.y != max.y ) { numberOfCellsY--; } Signature4CRS::RasterMap4CRS rasterMap4CRS(id, mbr, numberOfCellsX, numberOfCellsY, plane.potency()); rasterMap4CRS.setGroupOfBits(Signature4CRS::Empty); blockArea=cellSize*cellSize; Coordinate currentCell, endCell; RealCoordinate entryPoint, coord; unsigned cornerCoordinate; long double xCurrentCell, yCurrentCell; Point lp, rp; bool insideAbove; uchar numberOfVectors = 0; int matrixPosition; unsigned nCurrentSegment = 0; bool endOfParts = false; if (region != NULL) region->SelectFirst(); else if (line != NULL) line->SelectFirst(); else points->SelectFirst(); while(!endOfParts) { #ifdef DEBUGMESSAGES cout << "Checking segment " << nCurrentSegment << std::endl; #endif if (region != NULL){ region->GetHs(hs); lp = hs.GetLeftPoint(); rp = hs.GetRightPoint(); insideAbove = hs.GetAttr().insideAbove; } else if (line != NULL){ line->GetHs(hs); lp = hs.GetLeftPoint(); rp = hs.GetRightPoint(); } else { points->GetPt(pt); lp = pt; rp = pt; } if (points != NULL || hs.IsLeftDomPoint()) //works only with left segments { nCurrentSegment++; currentCell = findCell(lp, plane); endCell = findCell(rp, plane); //visits the floodFill from bottom to top, to be able to use the //parameter InsideAbove if (nCurrentSegment == 0) // First segment { if ( ( currentCell.x > MAX_DIMENSION_GRID ) || ( currentCell.y > MAX_DIMENSION_GRID ) ) { cout << "Overflow - Dimention of the grid" << std::endl; return NULL; } } entryPoint.x = lp.GetX(); entryPoint.y = lp.GetY(); Segment segment(RealCoordinate(lp.GetX(), lp.GetY()), RealCoordinate(rp.GetX(), rp.GetY()), insideAbove,nCurrentSegment); while (currentCell != endCell) { xCurrentCell = currentCell.x * cellSize + plane.min.x; yCurrentCell = currentCell.y * cellSize + plane.min.y; matrixPosition = currentCell.y * numberOfCellsX + currentCell.x; #ifdef DEBUGMESSAGES cout << "matrixPosition: " << matrixPosition << std::endl; #endif Coordinate coordSupDir; Segment sInside; bool inside,isIntersectionPoint; RealCoordinate intersectionPoint; coordSupDir.x = (long int)(xCurrentCell+cellSize); coordSupDir.y = (long int)(yCurrentCell+cellSize); clipCel[matrixPosition].handleSegment(Coordinate( (long int)xCurrentCell,(long int)yCurrentCell), coordSupDir,segment,sInside, inside, isIntersectionPoint,intersectionPoint, signatureType); //for lines and points, only inconclusive cells are calculated if (region == NULL) { if (signatureType == SIGNAT_3CRS) rasterMap4CRS.block(currentCell.x,currentCell.y, Signature4CRS::Weak); else rasterMap4CRS.block(currentCell.x,currentCell.y, clipCel[matrixPosition].evaluateType(blockArea)); } else calculatedGrid[matrixPosition] = 1; if ( isIntersectionPoint ) coord = intersectionPoint; else { if ( !(is_equal(sInside.p1.x,entryPoint.x) && is_equal(sInside.p1.y,entryPoint.y)) ) coord = sInside.p1; else coord = sInside.p2; } if ( is_equal(entryPoint.x, xCurrentCell) || is_equal(entryPoint.x, xCurrentCell + cellSize) ) { if(!is_equal(coord.x, entryPoint.x) && !is_equal(coord.y, entryPoint.y)){ if(insideAbove) swapMatrix[matrixPosition] += 1; else swapMatrix[matrixPosition] -= 1; } } // Find out the next cell cornerCoordinate = 0; // upper right corner if ( is_equal(coord.y,yCurrentCell + cellSize) && is_equal(coord.x,xCurrentCell + cellSize) ) { currentCell.y++; currentCell.x++; //does not change swapMatrix when itīs a vertical line over //the edge of the cell if (coord.x != entryPoint.x) { if(insideAbove) swapMatrix[matrixPosition] += 1; else swapMatrix[matrixPosition] -= 1; } cornerCoordinate = 1; } else // upper left corner if ( is_equal(coord.y,yCurrentCell + cellSize) && is_equal(coord.x,xCurrentCell) ) { currentCell.y++; if (coord.x != entryPoint.x) { if(insideAbove) swapMatrix[matrixPosition] += 1; else swapMatrix[matrixPosition] -= 1; } cornerCoordinate = 1; } else //do not change swapMatrix on the inferior corners, so it //will not count the swap twice //lower right corner if ( is_equal(coord.y,yCurrentCell) && is_equal(coord.x,xCurrentCell + cellSize) ) { currentCell.x++; cornerCoordinate = 1; if(insideAbove) swapMatrix[matrixPosition] += 1; else swapMatrix[matrixPosition] -= 1; } else //lower left corner if ( is_equal(coord.y,yCurrentCell) && is_equal(coord.x,xCurrentCell) ) { cornerCoordinate = 1; //if ( endPoint.y >= yCurrentCell ) //{ // currentCell.x--; //} //else { //if ( endPoint.x >= xCurrentCell ) { currentCell.y--; // if(insideAbove) // swapMatrix[matrixPosition] += 1; // else // swapMatrix[matrixPosition] -= 1; } //else //{ // currentCell.x--; // currentCell.y--; // if(insideAbove) // swapMatrix[matrixPosition] += 1; // else // swapMatrix[matrixPosition] -= 1; //} } } if ( !cornerCoordinate ) { //Intersection with cel.top if ( is_equal(coord.y,yCurrentCell + plane.sizeOfCell) ) { currentCell.y++; } //Intersection with cel.left else if ( is_equal(coord.x,xCurrentCell)) { currentCell.x--; if(insideAbove) swapMatrix[matrixPosition] += 1; else swapMatrix[matrixPosition] -= 1; } //Intersection with cel.right else if ( is_equal(coord.x,xCurrentCell + plane.sizeOfCell) ) { currentCell.x++; if(insideAbove) swapMatrix[matrixPosition] += 1; else swapMatrix[matrixPosition] -= 1; } //Intersection with cel.bottom else //if ( is_equal(coord.y,yCurrentCell)) { currentCell.y--; } } entryPoint = coord; numberOfVectors++; //if the number of vector is larger than the maximum number of vertices //than itīs necessary to raise the size of the cell so less vectors will //be considered. This increment of the size of the cell resolves, //for example, the problem that occurs an infinite loop navigating //through the cells. This error ocurred on the generation of the 3cr //for the polilyne sequoia11-185839. This error could be resolved, //though, since now we are storing the signature 4crs and not 4drs; //we are not storing vectors anymore if ( numberOfVectors >= MAX_VECTORS_PART ) { return NULL; } } //end of while (currentCell != endCell) //calculates the swapMatrix of the endCell //checl of the right point is exactly in the border of the cell if (!is_equal(currentCell.x * cellSize + plane.min.x, rp.GetX())) { xCurrentCell = currentCell.x * cellSize + plane.min.x; yCurrentCell = currentCell.y * cellSize + plane.min.y; if(points != NULL || line != NULL) { if (signatureType == SIGNAT_3CRS) rasterMap4CRS.block(currentCell.x,currentCell.y, Signature4CRS::Weak); else rasterMap4CRS.block(currentCell.x,currentCell.y, clipCel[matrixPosition].evaluateType(blockArea)); } matrixPosition = currentCell.y * numberOfCellsX + currentCell.x; Coordinate coordSupDir; Segment sInside; bool inside,isIntersectionPoint; RealCoordinate intersectionPoint; coordSupDir.x = (long int)(xCurrentCell+cellSize); coordSupDir.y = (long int)(yCurrentCell+cellSize); clipCel[matrixPosition].handleSegment(Coordinate((long int)xCurrentCell, (long int)yCurrentCell),coordSupDir,segment, sInside, inside, isIntersectionPoint,intersectionPoint, signatureType); calculatedGrid[matrixPosition] = 1; if ( isIntersectionPoint ) coord = intersectionPoint; else { if ( !(is_equal(sInside.p1.x,entryPoint.x) && is_equal(sInside.p1.y,entryPoint.y)) ) coord = sInside.p1; else coord = sInside.p2; } if (is_equal(entryPoint.x, xCurrentCell) || is_equal(entryPoint.x, xCurrentCell + cellSize)) { if(insideAbove) swapMatrix[matrixPosition] += 1; else swapMatrix[matrixPosition] -= 1; } } } if (region != NULL) { region->SelectNext(); endOfParts = region->EndOfHs(); } else if (line != NULL) { line->SelectNext(); endOfParts = line->EndOfHs(); } else { points->SelectNext(); endOfParts = points->EndOfPt(); } } #ifdef DEBUGMESSAGES for(int posy=numberOfCellsY - 1; posy>=0; posy--) { for(int posx=0; posx