/* ---- This file is part of SECONDO. Copyright (C) 2017, 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 "PointsT.h" #include "RegionT.h" #include "SimpleLineT.h" #include "SpatialAlgebra.h" #include "Tools/Flob/MMDbArray.h" templateclass Array> void PointsT::Sort(const bool exact /*= true*/) { assert( !IsOrdered() ); if(exact){ points.Sort( PointCompare ); } else{ points.Sort(PointCompareAlmost); } ordered = true; } /* Function supporting the RemoveDuplicates function. This function checks whether in an array of points a point exists which is AlmostEqual to the given one. The search is restricted to the range in array given by the indices __min__ and __max__. */ templateclass Array> bool AlmostContains( const Array& points, const Point& p, int min, int max, int size){ if(min>max){ return false; } Point pa(true); if(min==max){ // search around the position found // search left of min int pos = min; double x = p.GetX(); points.Get(pos,&pa); while(pos>=0 && AlmostEqual(pa.GetX(),x)){ if(AlmostEqual(pa,p)){ return true; } pos--; if(pos>=0){ points.Get(pos,&pa); } } // search right of min pos=min+1; if(posclass Array> void PointsT::RemoveDuplicates() { assert(IsOrdered()); //Point allPoints[points.Size()]; Array allPoints(points.Size()); Point p(true); for(int i=0;iclass Array> bool PointsT::Contains( const Point& p, const Geoid* geoid /*=0*/ ) const { assert( IsDefined() ); assert( p.IsDefined() ); assert( IsOrdered() ); assert( !geoid || geoid->IsDefined() ); if( IsEmpty() ) return false; if( !p.Inside( bbox, geoid ) ) return false; int pos; return Find( p, pos, false ); // find using AlmostEqual } templateclass Array> templateclass Array2> bool PointsT::Contains( const PointsT& ps, const Geoid* geoid /*=0*/ ) const { assert( IsDefined() ); assert( IsOrdered() ); assert( ps.IsDefined() ); assert( ps.IsOrdered() ); assert( !geoid || geoid->IsDefined() ); if(!IsDefined() || !ps.IsDefined() || (geoid && !geoid->IsDefined()) ){ return false; } if( IsEmpty() && ps.IsEmpty() ) return true; if( IsEmpty() || ps.IsEmpty() ) return false; if( !bbox.Contains( ps.BoundingBox(), geoid ) ) return false; object obj; status stat; SelectFirst_pp( *this, ps, obj, stat ); while( stat != endsecond && stat != endboth ) { if( obj == second || stat == endfirst ) return false; SelectNext_pp( *this, ps, obj, stat ); } return true; } templateclass Array> templateclass Array2> bool PointsT::Inside( const PointsT& ps, const Geoid* geoid /*=0*/ ) const { assert( IsDefined() ); assert( IsOrdered() ); assert( ps.IsDefined() ); assert( ps.IsOrdered() ); assert( !geoid || geoid->IsDefined() ); return ps.Contains( *this, geoid ); } templateclass Array> templateclass Array2> bool PointsT::Inside( const LineT& l, const Geoid* geoid /*=0*/ ) const { assert( IsDefined() ); assert( IsOrdered() ); assert( l.IsDefined() ); assert( l.IsOrdered() ); assert( !geoid || geoid->IsDefined() ); if( IsEmpty() ) return true; if( l.IsEmpty() ) return false; if( !l.BoundingBox().Contains( bbox, geoid ) ) return false; Point p(true); for( int i = 0; i < Size(); i++ ) { Get( i, p ); if( !l.Contains( p, geoid ) ) return false; } return true; } templateclass Array> templateclass Array2> bool PointsT::Inside( const RegionT& r, const Geoid* geoid /*=0*/ ) const { assert( IsDefined() ); assert( IsOrdered() ); assert( r.IsDefined() ); assert( r.IsOrdered() ); assert( !geoid || geoid->IsDefined() ); if(geoid){ cout << __PRETTY_FUNCTION__ << ": Spherical geometry not implemented." <class Array> templateclass Array2> bool PointsT::Intersects( const PointsT& ps, const Geoid* geoid /*=0*/ ) const { assert( IsDefined() ); assert( IsOrdered() ); assert( ps.IsDefined() ); assert( ps.IsOrdered() ); assert( !geoid || geoid->IsDefined() ); if( IsEmpty() || ps.IsEmpty() || (geoid && !geoid->IsDefined()) ) return false; if( !bbox.Intersects( ps.BoundingBox(), geoid ) ) return false; object obj; status stat; SelectFirst_pp( *this, ps, obj, stat ); while( stat != endboth ) { if( obj == both ) return true; SelectNext_pp( *this, ps, obj, stat ); } return false; } templateclass Array> templateclass Array2> bool PointsT::Intersects( const LineT& l, const Geoid* geoid /*=0*/ ) const { assert( IsDefined() ); assert( IsOrdered() ); assert( l.IsDefined() ); assert( l.IsOrdered() ); assert( !geoid || geoid->IsDefined() ); if(geoid){ cout << __PRETTY_FUNCTION__ << ": Spherical geometry not implemented." <IsDefined())) return false; if( !BoundingBox().Intersects( l.BoundingBox(), geoid ) ) return false; Point p(true); for( int i = 0; i < Size(); i++ ) { Get( i, p ); if( l.Contains( p, geoid ) ) return true; } return false; } templateclass Array> templateclass Array2> bool PointsT::Intersects( const RegionT& r, const Geoid* geoid /*=0*/ ) const { assert( IsDefined() ); assert( IsOrdered() ); assert( r.IsDefined() ); assert( r.IsOrdered() ); assert( !geoid || geoid->IsDefined() ); if(geoid){ cout << __PRETTY_FUNCTION__ << ": Spherical geometry not implemented." <IsDefined()) ) return false; if( !BoundingBox().Intersects( r.BoundingBox(), geoid ) ) return false; Point p(true); for( int i = 0; i < Size(); i++ ) { Get( i, p ); if( r.Contains( p, geoid ) ) return true; } return false; } templateclass Array> templateclass Array2> bool PointsT::Adjacent( const RegionT& r, const Geoid* geoid /*=0*/ ) const { assert( IsDefined() ); assert( IsOrdered() ); assert( r.IsDefined() ); assert( r.IsOrdered() ); assert( !geoid || geoid->IsDefined() ); if(geoid){ cout << __PRETTY_FUNCTION__ << ": Spherical geometry not implemented." <IsDefined())) return false; if( !BoundingBox().Intersects( r.BoundingBox(), geoid ) ) return false; Point p(true); bool found = false; for( int i = 0; i < Size(); i++ ) { Get( i, p ); if( !r.Contains( p, geoid ) ) continue; // At least one point is contained in the region // If it is not inside the region, then the // function will return true. found = true; if( r.InnerContains( p, geoid ) ) return false; } return found; } templateclass Array> templateclass Array2> void PointsT::Intersection(const Point& p, PointsT& result, const Geoid* geoid /*=0*/) const{ result.Clear(); if(!IsDefined() || ! p.IsDefined() || (geoid && !geoid->IsDefined()) ){ result.SetDefined(false); return; } if(this->Contains(p, geoid)){ result += p; } } templateclass Array> templateclass Array2, templateclass Array3> void PointsT::Intersection( const PointsT& ps, PointsT& result, const Geoid* geoid /*=0*/ ) const { result.Clear(); if( !IsDefined() || !ps.IsDefined() || (geoid && !geoid->IsDefined()) ) { result.SetDefined( false ); return; } result.SetDefined( true ); assert( ordered ); assert( ps.ordered ); if( IsEmpty() || ps.IsEmpty() ){ return; } object obj; status stat; Point p(true); SelectFirst_pp( *this, ps, obj, stat ); result.StartBulkLoad(); while( stat != endboth ) { if( obj == both ) { int GotPt = ps.GetPt( p ); assert( GotPt ); result += p; } SelectNext_pp( *this, ps, obj, stat ); } result.EndBulkLoad( false, false ); } templateclass Array> templateclass Array2, templateclass Array3> void PointsT::Intersection( const LineT& l, PointsT& result, const Geoid* geoid /*=0*/ ) const { result.Clear(); if( !IsDefined() || !l.IsDefined() || (geoid && !geoid->IsDefined()) ) { result.SetDefined( false ); return; } result.SetDefined( true ); assert( IsOrdered() ); assert( l.IsOrdered() ); if( IsEmpty() || l.IsEmpty() ) return; Point p(true); result.StartBulkLoad(); for( int i = 0; i < Size(); i++ ) { Get( i, p ); if( l.Contains( p, geoid ) ) result += p; } result.EndBulkLoad( false, false ); } /* Computes the set of points that is located in r. */ templateclass Array> templateclass Array2, templateclass Array3> void PointsT::Intersection( const RegionT& r, PointsT& result, const Geoid* geoid /*=0*/ ) const { result.Clear(); if( !IsDefined() || !r.IsDefined() || (geoid && !geoid->IsDefined()) ) { result.SetDefined( false ); return; } result.SetDefined( true ); assert( IsOrdered() ); assert( r.IsOrdered() ); if( IsEmpty() || r.IsEmpty() ) return; Point p(true); result.StartBulkLoad(); for( int i = 0; i < Size(); i++ ) { Get( i, p ); if( r.Contains( p, geoid ) ) result += p; } result.EndBulkLoad( false, false ); } templateclass Array> templateclass Array2, templateclass Array3> void PointsT::Intersection( const SimpleLineT& l, PointsT& result, const Geoid* geoid /*=0*/ ) const { result.Clear(); if( !IsDefined() || !l.IsDefined() || (geoid && !geoid->IsDefined()) ) { result.SetDefined( false ); return; } result.SetDefined( true ); assert( IsOrdered() ); assert( l.IsOrdered() ); if( IsEmpty() || l.IsEmpty() ) return; Point p(true); result.StartBulkLoad(); for( int i = 0; i < Size(); i++ ) { Get( i, p ); if( l.Contains( p, geoid ) ) result += p; } result.EndBulkLoad( false, false ); } templateclass Array> templateclass Array2> void PointsT::Minus( const Point& p, PointsT& ps, const Geoid* geoid /*=0*/ ) const { ps.Clear(); if( !IsDefined() || !p.IsDefined() || (geoid && !geoid->IsDefined()) ) { ps.SetDefined( false ); return; } ps.SetDefined( true ); assert( ordered ); ps.StartBulkLoad(); Point pi(true); for( int i = 0; i < Size(); i++ ) { Get( i, pi ); if( !AlmostEqual(pi, p) ) ps += pi; } ps.EndBulkLoad( false, false ); } templateclass Array> templateclass Array2, templateclass Array3> void PointsT::Minus( const PointsT& ps, PointsT& result, const Geoid* geoid /*=0*/ ) const { result.Clear(); if( !IsDefined() || !ps.IsDefined() || (geoid && !geoid->IsDefined()) ) { result.SetDefined( false ); return; } result.SetDefined( true ); assert( ordered ); assert( ps.ordered ); result.StartBulkLoad(); int size1 = this->Size(); int size2 = ps.Size(); int pos1 = 0, pos2 = 0; Point p1(true), p2(true); while(pos1Get(pos1, p1); ps.Get(pos2, p2); if( AlmostEqual(p1, p2) ) { pos1++; } else if (p1 < p2) { result += p1; pos1++; } else { // *p1 > *p2 pos2++; } } while(pos1Get(pos1, p1); result += p1; pos1++; } result.EndBulkLoad( false, false ); } templateclass Array> templateclass Array2, templateclass Array3> void PointsT::Minus( const LineT& l, PointsT& result, const Geoid* geoid /*=0*/ ) const { result.Clear(); if( !IsDefined() || !l.IsDefined() || (geoid && !geoid->IsDefined()) ) { result.SetDefined( false ); return; } result.SetDefined( true ); assert( IsOrdered() ); assert( l.IsOrdered() ); Point p(true); result.StartBulkLoad(); for( int i = 0; i < Size(); i++ ) { Get( i, p ); if( !l.Contains( p, geoid ) ) result += p; } result.EndBulkLoad( false, false ); } templateclass Array> templateclass Array2, templateclass Array3> void PointsT::Minus( const RegionT& r, PointsT& result, const Geoid* geoid /*=0*/ ) const { result.Clear(); if( !IsDefined() || !r.IsDefined() || (geoid && !geoid->IsDefined())) { result.SetDefined( false ); return; } result.SetDefined( true ); assert( IsOrdered() ); assert( r.IsOrdered() ); Point p(true); result.StartBulkLoad(); for( int i = 0; i < Size(); i++ ) { Get( i, p ); if( !r.Contains( p, geoid ) ) result += p; } result.EndBulkLoad( false, false ); } templateclass Array> templateclass Array2, templateclass Array3> void PointsT::Minus( const SimpleLineT& l, PointsT& result, const Geoid* geoid /*=0*/ ) const { result.Clear(); if( !IsDefined() || !l.IsDefined() || (geoid && !geoid->IsDefined()) ) { result.SetDefined( false ); return; } result.SetDefined( true ); assert( IsOrdered() ); assert( l.IsOrdered() ); Point p(true); result.StartBulkLoad(); for( int i = 0; i < Size(); i++ ) { Get( i, p ); if( !l.Contains( p, geoid ) ) result += p; } result.EndBulkLoad( false, false ); } templateclass Array> templateclass Array2> void PointsT::Union( const Point& p, PointsT& result, const Geoid* geoid /*=0*/ ) const { result.Clear(); if( !IsDefined() || !p.IsDefined() || (geoid && !geoid->IsDefined()) ) { result.SetDefined( false ); return; } result.SetDefined( true ); assert( ordered ); result.StartBulkLoad(); Point pi(true); bool inserted = false; for( int i = 0; i < Size(); i++) { Get( i, pi ); if( !inserted && pi == p ) inserted = true; if( !inserted && pi > p ) { result += p; inserted = true; } result += pi; } if( !inserted ) result += p; result.EndBulkLoad( false, true ); } templateclass Array> templateclass Array2, templateclass Array3> void PointsT::Union( const PointsT& ps, PointsT& result, const Geoid* geoid /*=0*/ ) const { result.Clear(); if( !IsDefined() || !ps.IsDefined() || (geoid && !geoid->IsDefined()) ) { result.SetDefined( false ); return; } result.SetDefined( true ); assert( ordered ); assert( ps.ordered ); object obj; status stat; SelectFirst_pp( *this, ps, obj, stat ); Point p(true); result.StartBulkLoad(); while( stat != endboth ) { if( obj == first || obj == both ) { int GotPt = GetPt( p ); assert( GotPt ); } else if( obj == second ) { int GotPt = ps.GetPt( p ); assert( GotPt ); } result += p; SelectNext_pp( *this, ps, obj, stat ); } result.EndBulkLoad( false, true ); } templateclass Array> templateclass Array2, templateclass Array3> void PointsT::Union( const LineT& line, LineT& result, const Geoid* geoid /*=0*/ ) const{ line.Union(*this,result,geoid); } templateclass Array> templateclass Array2, templateclass Array3> void PointsT::Union( const RegionT& region, RegionT& result, const Geoid* geoid /*=0*/) const{ region.Union(*this,result,geoid); } templateclass Array> templateclass Array2, templateclass Array3> void PointsT::Union(const SimpleLineT& line, SimpleLineT& result, const Geoid* geoid /*=0*/) const{ line.Union(*this,result, geoid); } templateclass Array> double PointsT::Distance( const Point& p, const Geoid* geoid /* = 0 */ ) const { assert( !IsEmpty() ); assert( p.IsDefined() ); assert( !geoid || geoid->IsDefined() ); double result = std::numeric_limits::max(); for( int i = 0; i < Size(); i++ ){ Point pi(true); Get( i, pi ); if( AlmostEqual( p, pi ) ){ return 0.0; } result = MIN( result, pi.Distance( p, geoid ) ); } return result; } templateclass Array> templateclass Array2> double PointsT::Distance( const PointsT& ps, const Geoid* geoid /* = 0 */ ) const { assert( !IsEmpty() ); assert( !ps.IsEmpty() ); assert( !geoid || geoid->IsDefined() ); double result = std::numeric_limits::max(); Point pi(true), pj(true); for( int i = 0; i < Size(); i++ ){ Get( i, pi ); for( int j = 0; j < ps.Size(); j++ ){ ps.Get( j, pj ); if( AlmostEqual( pi, pj ) ){ return 0.0; } result = MIN( result, pi.Distance( pj, geoid ) ); } } return result; } templateclass Array> double PointsT::Distance( const Rectangle<2>& r, const Geoid* geoid/*=0*/ ) const { assert( IsDefined() ); assert( !IsEmpty() ); assert( r.IsDefined() ); assert( !geoid || geoid->IsDefined() ); double result = std::numeric_limits::max(); Point pi(true); for( int i = 0; i < Size(); i++ ) { Get( i, pi ); result = MIN( result, pi.Distance( r, geoid ) ); } return result; } templateclass Array> bool PointsT::Intersects( const Rectangle<2>& r, const Geoid* geoid/*=0*/ ) const { assert( IsDefined() ); assert( !IsEmpty() ); assert( r.IsDefined() ); assert( !geoid || geoid->IsDefined() ); if(!BoundingBox().Intersects(r,geoid)){ return false; } Point pi(true); for( int i = 0; i < Size(); i++ ) { Get( i, pi ); if(pi.Intersects(r,geoid)){ return true; } } return false; } templateclass Array> templateclass Array2> void PointsT::Translate( const Coord& x, const Coord& y, PointsT& result ) const { result.Clear(); if( !IsDefined() ) { result.SetDefined( false ); return; } result.SetDefined( true ); assert( ordered ); result.StartBulkLoad(); Point p(true); for( int i = 0; i < Size(); i++ ) { Get( i, p ); p.Translate( x, y ); result += p; } result.EndBulkLoad( false, false ); } templateclass Array> templateclass Array2> void PointsT::Scale( const Coord& x, const Coord& y, PointsT& result ) const { result.Clear(); if( !IsDefined() ) { result.SetDefined( false ); return; } result.SetDefined( true ); result.Resize(Size()); result.StartBulkLoad(); Point p(true); for( int i = 0; i < Size(); i++ ) { Get( i, p ); p.Scale( x, y ); result += p; } result.EndBulkLoad( true, true ); } templateclass Array> templateclass Array2> void PointsT::Rotate( const Coord& x, const Coord& y, const double alpha, PointsT& result ) const { result.Clear(); if(!IsDefined()){ result.SetDefined(false); return; } result.SetDefined(true); result.Resize(Size()); double s = sin(alpha); double c = cos(alpha); double m00 = c; double m01 = -s; double m02 = x - x*c + y*s; double m10 = s; double m11 = c; double m12 = y - x*s-y*c; result.StartBulkLoad(); Point p(true); Point rot(true,0,0); for( int i = 0; i < Size(); i++ ) { Get( i, p ); rot.Set( m00*p.GetX() + m01*p.GetY() + m02, m10*p.GetX() + m11*p.GetY() + m12); result += rot; } result.EndBulkLoad( true, false ); } templateclass Array> Point PointsT::theCenter() const{ Point res(true,0,0); if(!IsDefined() || (Size()==0)){ res.SetDefined(false); } else { int size = Size(); double x = 0.0; double y = 0.0; for(int i=0;iclass Array> size_t PointsT::HashValue() const { if( IsEmpty() ) // IsEmpty() includes undef return 0; size_t h = 0; for( int i = 0; i < Size() && i < 5; i++ ) { Point p(true,0,0); points.Get( i, &p ); h = h + (size_t)(5 * p.GetX() + p.GetY()); } return h; } templateclass Array> bool PointsT::IsValid() const { if( IsEmpty() ) // IsEmpty() includes undef return true; Point p1(true), p2(true); Get( 0, p1 ); if( !p1.IsDefined() ){ std::cerr << __PRETTY_FUNCTION__ << ": Undefined Point!" << std::endl; std::cerr << "\tp1 = "; p1.Print(std::cerr); std::cerr << std::endl; return false; } for( int i = 1; i < Size(); i++ ) { Get( i, p2 ); if( !p2.IsDefined() ){ std::cerr << __PRETTY_FUNCTION__ << ": Undefined Point!" << std::endl; std::cerr << "\tp2 = "; p2.Print(std::cerr); std::cerr << std::endl; return false; } if( AlmostEqual( p1, p2 ) ){ std::cerr << __PRETTY_FUNCTION__ << ": Almost equal Points!" << endl; std::cerr << "\tp1 = "; p1.Print(std::cerr); std::cerr << "\n\tp2 = "; p2.Print(std::cerr); std::cerr << std::endl; return false; } p1 = p2; } return true; } templateclass Array> void PointsT::Clear() { points.clean(); pos = -1; ordered = true; bbox.SetDefined( false ); } templateclass Array> void PointsT::CopyFrom( const Attribute* right ) { const PointsT *ps = (const PointsT*)right; assert( ps->IsOrdered() ); *this = *ps; } templateclass Array> int PointsT::Compare( const Attribute* arg ) const { const PointsT* ps = (const PointsT*)arg; return Compare(ps); } templateclass Array> templateclass Array2> int PointsT::Compare( const PointsT* ps) const{ if( !ps ) return (-2); if(!IsDefined() && !ps->IsDefined()){ return 0; } if(!IsDefined()){ return -1; } if(!ps->IsDefined()){ return 1; } if( IsEmpty() && ps->IsEmpty() ) return 0; if( IsEmpty() ) return -1; if( ps->IsEmpty() ) return 1; if( Size() > ps->Size() ) return 1; if( Size() < ps->Size() ) return -1; Point p1(true), p2(true); for( int i = 0; i < Size(); i++ ) { Get( i, p1); ps->Get( i, p2 ); if( p1 > p2 ) return 1; if( p1 < p2 ) return -1; } return 0; } templateclass Array> int PointsT::CompareAlmost( const Attribute* arg ) const { const PointsT* ps = (const PointsT*)arg; return CompareAlmost(ps); } templateclass Array> templateclass Array2> int PointsT::CompareAlmost( const PointsT* ps ) const { if( !ps ) return (-2); if(!IsDefined() && !ps->IsDefined()){ return 0; } if(!IsDefined()){ return -1; } if(!ps->IsDefined()){ return 1; } if( IsEmpty() && ps->IsEmpty() ) return 0; if( IsEmpty() ) return -1; if( ps->IsEmpty() ) return 1; if( Size() > ps->Size() ) return 1; if( Size() < ps->Size() ) return -1; Point p1(true), p2(true); for( int i = 0; i < Size(); i++ ) { Get( i, p1); ps->Get( i, p2 ); if( !AlmostEqual(p1, p2) ) { if( p1 > p2 ) return 1; if( p1 < p2 ) return -1; } } return 0; } templateclass Array> bool PointsT::Adjacent( const Attribute* arg ) const { return false; // for points which takes double values, we can not decide whether they are //adjacent or not. } templateclass Array> PointsT* PointsT::Clone() const { return new PointsT( *this ); } templateclass Array> std::ostream& PointsT::Print( std::ostream &os ) const { return os << *this; } templateclass Array> inline PointsT::PointsT( const int initsize ) : StandardSpatialAttribute<2>(true), points( initsize ), bbox( false ), ordered( true ) { } templateclass Array> inline PointsT::PointsT( const PointsT& ps ) : StandardSpatialAttribute<2>(ps.IsDefined()), points( ps.Size() ), bbox( ps.BoundingBox() ), ordered( ps.IsOrdered() ) { convertDbArrays(ps.points,points); } templateclass Array> template class Array2> inline PointsT::PointsT( const PointsT& ps ) : StandardSpatialAttribute<2>(ps.IsDefined()), points( ps.Size() ), bbox( ps.BoundingBox() ), ordered( ps.isOrdered() ) { convertDbArrays(ps.points,points); } templateclass Array> inline const Rectangle<2> PointsT::BoundingBox(const Geoid* geoid /*=0*/) const { // no special implementation for spherical geometry required! return bbox; } templateclass Array> inline bool PointsT::Get( const int i, Point& p ) const { assert( IsDefined() ); return points.Get( i, p ); } templateclass Array> inline int PointsT::Size() const { return points.Size(); } templateclass Array> inline bool PointsT::IsEmpty() const { return !IsDefined() || (points.Size() == 0); } templateclass Array> inline bool PointsT::IsOrdered() const { return ordered; } templateclass Array> inline int PointsT::NumOfFLOBs() const { return 1; } templateclass Array> inline bool PointsT::operator==(const Point& p) const{ if(!IsDefined() && !p.IsDefined()){ return true; } if(!IsDefined() || !p.IsDefined()){ return false; } if(Size()!=1){ return false; } Point p1(true); Get(0,p1); return AlmostEqual(p,p1); } templateclass Array> inline Flob *PointsT::GetFLOB(const int i) { assert( i >= 0 && i < NumOfFLOBs() ); return &points; } templateclass Array> inline size_t PointsT::Sizeof() const { return sizeof( *this ); } templateclass Array> inline void PointsT::SelectFirst() const { if( IsEmpty() ){ pos = -1; } else { pos = 0; } } templateclass Array> inline void PointsT::SelectNext() const { if( pos >= 0 && pos < Size() - 1 ) { pos++; } else { pos = -1; } } templateclass Array> inline bool PointsT::EndOfPt() const { return pos == -1; } templateclass Array> inline bool PointsT::GetPt(Point& p ) const { if( pos >= 0 && pos <= Size()-1 ){ points.Get( pos, &p ); return true; } return false; } templateclass Array> inline void PointsT::Resize(const int newSize){ if(newSize>Size()){ points.resize(newSize); } } templateclass Array> inline void PointsT::TrimToSize(){ points.TrimToSize(); } templateclass Array1, templateclass Array2> void SelectFirst_pp( const PointsT& P1, const PointsT& P2, object& obj, status& stat ) { P1.SelectFirst(); P2.SelectFirst(); Point p1(true), p2(true); bool gotP1 = P1.GetPt( p1 ), gotP2 = P2.GetPt( p2 ); if( !gotP1 && !gotP2 ) { obj = none; stat = endboth; } else if( !gotP1 ) { obj = second; stat = endfirst; } else if( !gotP2 ) { obj = first; stat = endsecond; } else //both defined { stat = endnone; if( p1 < p2 ) obj = first; else if( p1 > p2 ) obj = second; else obj = both; } } templateclass Array1, template class Array2> void SelectNext_pp( const PointsT& P1, const PointsT& P2, object& obj, status& stat ) { // 1. get the current elements Point p1(true), p2(true); bool gotP1 = P1.GetPt( p1 ), gotP2 = P2.GetPt( p2 ); //2. move the pointers if( !gotP1 && !gotP2 ) { //do nothing } else if( !gotP1 ) { P2.SelectNext(); gotP2 = P2.GetPt( p2 ); } else if( !gotP2 ) { P1.SelectNext(); gotP1 = P1.GetPt( p1 ); } else //both currently defined { if( p1 < p2 ) //then hs1 is the last output { P1.SelectNext(); gotP1 = P1.GetPt( p1 ); } else if( p1 > p2 ) { P2.SelectNext(); gotP2 = P2.GetPt( p2 ); } else { P1.SelectNext(); gotP1 = P1.GetPt( p1 ); P2.SelectNext(); gotP2 = P2.GetPt( p2 ); } } //3. generate the outputs if( !gotP1 && !gotP2 ) { obj = none; stat = endboth; } else if( !gotP1 ) { obj = second; stat = endfirst; } else if( !gotP2 ) { obj = first; stat = endsecond; } else //both defined { stat = endnone; if( p1 < p2 ) obj = first; else if( p1 > p2 ) obj = second; else obj = both; } }