Files
secondo/Algebras/Raster/Signature/Signature4CRS.cpp
2026-01-23 17:03:45 +08:00

327 lines
10 KiB
C++

/*
----
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
*/
//---------------------------------------------------------------------------
#include "Signature4CRS.h"
long sameScales = 0, differentScales = 0;
#define larger(a,b) ((a>b) ? a : b)
#define smaller(a,b) ((a<b) ? a : b)
Signature4CRS::Signature4CRS( unsigned long id, MBR mbr, unsigned dx,
unsigned dy, unsigned potency, void* buffer,
long bufSize ) :
//map( &(attr_map.header) ),
sizeOfBlock( 0x1lu << potency ),
attr_map( id,mbr,dx,dy,potency )
{
memcpy( attr_map.bits0, buffer, bufSize );
map = new RasterMap4CRS::Header( id, mbr, dx, dy, potency ) ;
}
Signature4CRS::Signature4CRS( unsigned long id, Coordinate min, Coordinate max,
unsigned long sizeOfBlock, unsigned dx,
unsigned dy, const Weight weight[] ) :
//map( &(attr_map.header) ),
sizeOfBlock( sizeOfBlock )
{
//cout << "Signature4CRS::Signature4CRS 2" << endl;
MBR mbr;
mbr.min = min;
mbr.max = max;
unsigned potency = 0x1lu >> sizeOfBlock;
map = new RasterMap4CRS::Header( id, mbr, dx, dy, potency ) ;
register unsigned i, j, step;
Weight current;
GroupOfBits bits0 = 0, bits1 = 0;
attr_map.header.id = id;
attr_map.header.mbr.min = min;
attr_map.header.mbr.max = max;
attr_map.header.dx = dx;
attr_map.header.dy = dy;
for( i = 0; (sizeOfBlock >> i) != 0; i++ ){
attr_map.header.potency = i - 1;
}
map->potency = attr_map.header.potency;
for( i = 0; i < MAX_BITS; i++ )
{
attr_map.bits0[ i ] = attr_map.bits1[ i ] = 0;
}
for( step = 8 * sizeof( unsigned long ), i = j = 0; i < dx * dy; i++ )
{
step--;
current = weight[ i ];
bits0 |= ((current & 0x1lu) >> 0) << step;
bits1 |= ((current & 0x2lu) >> 1) << step;
if( step == 0 )
{
attr_map.bits0[ j ] = bits0;
attr_map.bits1[ j ] = bits1;
j++;
step = 8 * sizeof( GroupOfBits );
bits0 = bits1 = 0;
}
}
if( step != 0 && j < MAX_BITS )
{
attr_map.bits0[ j ] = bits0;
attr_map.bits1[ j ] = bits1;
}
}
void Signature4CRS::RasterMap4CRS::setGroupOfBits(Weight o)
{
memset(bits0,o,MAX_BITS*sizeof(GroupOfBits));
memset(bits1,o,MAX_BITS*sizeof(GroupOfBits));
}
Signature4CRS::Weight Signature4CRS::RasterMap4CRS::block( int x, int y ) const
{
if((x > -1 && y > -1) && ((unsigned)x < header.dx && (unsigned)y < header.dy))
{
unsigned index = x*header.dy + y,
position = index / (8 * sizeof( GroupOfBits )),
displacement = 8 * sizeof( GroupOfBits ) - 1
- (index % (8 * sizeof( GroupOfBits )));
return (Weight) ((bits0[ position ] & (0x1lu << displacement) ? 0x1 : 0x0) |
(bits1[ position ] & (0x1lu << displacement) ? 0x2 : 0x0));
}
else {
return Empty;
}
}
Signature4CRS::Weight Signature4CRS::block( Coordinate min,
unsigned long sizeOfBlock ) const
{
return block( min.x, min.y, sizeOfBlock );
}
Signature4CRS::Weight Signature4CRS::resolutionChange(int x, int y,
unsigned long sizeOfBlock) const
{
double totalWeight = 0;
int factor = (unsigned) (sizeOfBlock/this->sizeOfBlock),
startX = x < 0 ? 0 : x,
startY = y < 0 ? 0 : y,
endX = x + factor > (int) map->dx ? map->dx : x + factor,
endY = y + factor > (int) map->dy ? map->dy : y + factor,
i, j;
for( i = startX; i < endX; i++ )
for( j = startY; j < endY; j++ )
{
Weight current = block( i, j );
switch( current )
{
case Full : totalWeight += 1; break;
case Strong : totalWeight += FACTOR_AREA_STRONG; break;
case Weak : totalWeight += FACTOR_AREA_WEAK; break;
case Empty : break;
}
}
unsigned long factor2 = (factor * (long) factor);
// factor2: number of cells of the smaller size that fits
// in a cell of the larger size
double weight = double(totalWeight / factor2 * 100 );
// Sets the weight of the group of cells according to the individual weight
// of each cell (rounding the value)
if ( weight == 0.0 ) return Signature4CRS::Empty; // weight = 0
if ( weight == 100.0 ) return Signature4CRS::Full; // weight = 100
if ( weight > 50.0 ) return Signature4CRS::Strong; // weight (50,100)
// if ( weight > 0 )
return Signature4CRS::Weak; // weight (0, 50)
}
Signature4CRS::Weight Signature4CRS::block( long minX, long minY,
unsigned long sizeOfBlock ) const
{
Coordinate min=map->mbr.min;
min.x = min.x & (0xFFFFFFFFlu << map->potency);
min.y = min.y & (0xFFFFFFFFlu << map->potency);
minX = minX & (0xFFFFFFFFlu << map->potency);
minY = minY & (0xFFFFFFFFlu << map->potency);
int x = (int) ((minX - min.x) / this->sizeOfBlock),
y = (int) ((minY - min.y) / this->sizeOfBlock);
if( (unsigned long)this->sizeOfBlock == sizeOfBlock )
return block( x, y );
else
if( (unsigned long)this->sizeOfBlock < sizeOfBlock )
{
unsigned temWeak = 0;
unsigned long fullCells = 0;
#ifdef APPROXIMATE_AREA
return resolutionChange( x, y, sizeOfBlock);
#endif
int factor = (unsigned) (sizeOfBlock/this->sizeOfBlock),
startX = x < 0 ? 0 : x,
startY = y < 0 ? 0 : y,
endX = x + factor > (int) map->dx ? map->dx : x + factor,
endY = y + factor > (int) map->dy ? map->dy : y + factor,
i, j;
for( i = startX; i < endX; i++ )
for( j = startY; j < endY; j++ )
{
Weight current = block( i, j );
//cout << "weight " << i << ", " << j << " = " << current << endl;
switch( current )
{
case Full : fullCells += 2; break;
case Strong : fullCells += 1; break;
case Weak : temWeak = 1; break;
case Empty : break;
}
}
unsigned long factor2 = (factor * (long) factor);
// factor2: number of cells of the smaller size that fit in a cell
// with larger size
if( fullCells == 2 * factor2 )
return Full;
//if the "weight" of full cells equals the number of total cells
//than returns full (100% of weight)
else
if( fullCells > factor2 )
return Strong;
//if the "weight" of full cells is larger than half of the total
// number of cells then returns Strong ]50%,100%[ of weight
else
if( fullCells < factor2 )
return (temWeak || fullCells > 0 ) ? Weak : Empty;
//if the "weight" of full cells is smaller than half of the
// total number of cells and exists weak or strong or full
// than returns wead ]0%,50%] of weight else, returns empty
else
return temWeak ? Strong : Weak;
//if the "weight" of full cells equals half the number
//of total cells and there is no weak cell, then returns strong
//else returns weak
}
else
{
//cout << "Critical error in " __FILE__ << ", line " << __LINE__ << endl;
abort();
return Empty;
}
}
int existsIntersection( const Signature4CRS* a, const Signature4CRS* b )
{
unsigned long sizeOfBlock = MAX( a->sizeOfBlock, b->sizeOfBlock );
unsigned potency = MAX( a->map->potency, b->map->potency );
Coordinate min( MAX( a->map->mbr.min.x, b->map->mbr.min.x ),
MAX( a->map->mbr.min.y, b->map->mbr.min.y ) ),
max( MIN( a->map->mbr.max.x, b->map->mbr.max.x ),
MIN( a->map->mbr.max.y, b->map->mbr.max.y ) );
long i, j, maybe = 0;
(a->sizeOfBlock == b->sizeOfBlock ?
sameScales :
differentScales)++;
min.x = min.x & (0xFFFFFFFFlu << potency);
min.y = min.y & (0xFFFFFFFFlu << potency);
max.x = max.x & (0xFFFFFFFFlu << potency);
max.y = max.y & (0xFFFFFFFFlu << potency);
for( i = min.x; i <= max.x; i += sizeOfBlock )
for( j = min.y; j <= max.y; j += sizeOfBlock )
{
Signature4CRS::Weight blockA = a->block( i, j, sizeOfBlock ),
blockB = b->block( i, j, sizeOfBlock );
if( blockA == Signature4CRS::Empty || blockB == Signature4CRS::Empty )
continue; // Does not have intersection
else if( (blockA == Signature4CRS::Full
|| blockB == Signature4CRS::Full) ||
(blockA == Signature4CRS::Strong
&& blockB == Signature4CRS::Strong) )
return 2;
else
maybe = 1;
}
return maybe;
}
void Signature4CRS::RasterMap4CRS::block(unsigned x, unsigned y, Weight weight)
{
if( x < header.dx && y < header.dy && weight != Empty )
{
unsigned index = x*header.dy + y,
position = index / (8 * sizeof( GroupOfBits )),
displacement = 8 * sizeof( GroupOfBits ) - 1
- (index % (8 * sizeof( GroupOfBits )));
bits0[ position ] |= ((weight & 0x1lu) >> 0) << displacement;
bits1[ position ] |= ((weight & 0x2lu) >> 1) << displacement;
}
}
Signature4CRS& Signature4CRS::operator=(const Signature4CRS& a)
{
this->attr_map = a.fullMap();
return *this;
}
int Signature4CRS::operator == ( const Signature4CRS& a ) const
{
return !memcmp( &attr_map, &a.attr_map, sizeof attr_map );
}
//---------------------------------------------------------------------------