/* GNU Ocrad - Optical Character Recognition program
Copyright (C) 2003-2019 Antonio Diaz Diaz.
This program 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.
This program 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 .
*/
#include
#include
#include
#include "rectangle.h"
#include "segment.h"
#include "mask.h"
int Mask::left( const int row ) const
{
if( top() <= row && row <= bottom() && data[row-top()].valid() )
return data[row-top()].left;
return -1;
}
int Mask::right( const int row ) const
{
if( top() <= row && row <= bottom() && data[row-top()].valid() )
return data[row-top()].right;
return -1;
}
void Mask::top( const int t )
{
if( t == top() ) return;
if( t < top() ) data.insert( data.begin(), top() - t, Csegment() );
else data.erase( data.begin(), data.begin() + ( t - top() ) );
Rectangle::top( t );
}
void Mask::bottom( const int b )
{
if( b != bottom() ) { Rectangle::bottom( b ); data.resize( height() ); }
}
void Mask::add_mask( const Mask & m )
{
if( m.top() < top() ) top( m.top() );
if( m.bottom() > bottom() ) bottom( m.bottom() );
for( int i = m.top(); i <= m.bottom(); ++i )
{
Csegment & seg = data[i-top()];
seg.add_csegment( m.data[i-m.top()] );
if( seg.left < left() ) left( seg.left );
if( seg.right > right() ) right( seg.right );
}
}
void Mask::add_point( const int row, const int col )
{
if( row < top() ) top( row ); else if( row > bottom() ) bottom( row );
data[row-top()].add_point( col );
if( col < left() ) left( col ); else if( col > right() ) right( col );
}
void Mask::add_rectangle( const Rectangle & re )
{
if( re.top() < top() ) top( re.top() );
if( re.bottom() > bottom() ) bottom( re.bottom() );
const Csegment rseg( re.left(), re.right() );
for( int i = re.top(); i <= re.bottom(); ++i )
{
Csegment & seg = data[i-top()];
seg.add_csegment( rseg );
if( seg.left < left() ) left( seg.left );
if( seg.right > right() ) right( seg.right );
}
}
bool Mask::includes( const Rectangle & re ) const
{
if( re.top() < top() || re.bottom() > bottom() ) return false;
const Csegment seg( re.left(), re.right() );
for( int i = re.top(); i <= re.bottom(); ++i )
if( !data[i-top()].includes( seg ) ) return false;
return true;
}
bool Mask::includes( const int row, const int col ) const
{
return ( row >= top() && row <= bottom() && data[row-top()].includes( col ) );
}
int Mask::distance( const Rectangle & re ) const
{
const Csegment seg( re.left(), re.right() );
int mindist = INT_MAX;
for( int i = bottom(); i >= top(); --i )
{
const int vd = re.v_distance( i );
if( vd >= mindist ) { if( i < re.top() ) break; else continue; }
const int hd = data[i-top()].distance( seg );
if( hd >= mindist ) continue;
const int d = Rectangle::hypoti( hd, vd );
if( d < mindist ) mindist = d;
}
return mindist;
}
int Mask::distance( const int row, const int col ) const
{
int mindist = INT_MAX;
for( int i = bottom(); i >= top(); --i )
{
const int vd = std::abs( i - row );
if( vd >= mindist ) { if( i < row ) break; else continue; }
const int hd = data[i-top()].distance( col );
if( hd >= mindist ) continue;
const int d = Rectangle::hypoti( hd, vd );
if( d < mindist ) mindist = d;
}
return mindist;
}