// ====================================================================== // // Copyright (c) 1997 The CGAL Consortium // // This software and related documentation is part of an INTERNAL release // of the Computational Geometry Algorithms Library (CGAL). It is not // intended for general use. // // ---------------------------------------------------------------------- // // release : // release_date : 1999, October 01 // // file : include/CGAL/min_sqr_distance.C // package : bops (2.2) // source : include/CGAL/min_sqr_distance.C // revision : $Revision$ // revision_date : $Date$ // author(s) : Wolfgang Freiseisen // // coordinator : RISC Linz // (Wolfgang Freiseisen ) // // // ====================================================================== #ifndef CGAL_MIN_SQUARE_DISTANCE_H #include #endif #include #include #include CGAL_BEGIN_NAMESPACE template struct _Compare_point_x : public CGAL_STD::binary_function { bool operator()(const Point& p1, const Point& p2) const { return p1.x() < p2.x(); } }; template struct _Compare_point_y : public CGAL_STD::binary_function { bool operator()(const Point& p1, const Point& p2) const { return p1.y() < p2.y(); } }; template double minimal_square_distance2(ForwardIterator first, ForwardIterator last, I& T) /* ---------------------------------------------------------- Calculates the minimal square distance of a set of points in O(n^2) time and returns the (double) result; ---------------------------------------------------------- */ { typedef typename I::Point Point; ForwardIterator it= first; it++; double m, min_square_dist= T.double_squared_distance(*first, *it); ForwardIterator it1, it2; for( it1= first; it1 != last; it1++) for( it2= first; it2 != last; it2++) if( it1 != it2 ) { m= T.double_squared_distance(*it1, *it2); if(m < min_square_dist) min_square_dist= m; } return min_square_dist; } template double minimal_square_distance(ForwardIterator first, ForwardIterator last, I& T) /* ---------------------------------------------------------- Calculates the minimal square distance of a set of points in O(n log(n)) time by doing a sweep-line algorithm and returns the (double) result; See: K.Hinrichs, J.Nievergelt, P.Schorn, "Plane-sweep solves the closest pair problem elegantly", Inform. Process. Lett., 26, 1988, p. 255-261. or Rolf Klein: "Algorithmische Geometrie", chapter 2.3.1 ---------------------------------------------------------- */ { typedef typename I::dPoint Point; typedef _Compare_point_x Compare_point_by_x; typedef _Compare_point_y Compare_point_by_y; /* initialize vector */ long int size= 1; ForwardIterator it; for(it= first; it != last; it++) size++; //distance(first,last, size); #ifdef CGAL__MIN_SQR_DISTANCE_DEBUG_ON cout << "size: " << size << endl; #endif if( size < 3 ) { // trivial case return size == 2 ? T.squared_distance( T.to_dPoint(*first++), T.to_dPoint(*first)) : 0; } std::vector pts; pts.reserve(size); //copy(first, last, back_inserter(pts) ); for(it= first; it != last; it++) pts.push_back( T.to_dPoint(*it) ); //transform(first, last, pts.begin(), _to_double_Point); #ifdef CGAL__MIN_SQR_DISTANCE_DEBUG_ON showSequence( pts.begin(), pts.end()); #endif /* sort vector */ std::sort(pts.begin(), pts.end(), Compare_point_by_x()); #ifdef CGAL__MIN_SQR_DISTANCE_DEBUG_ON showSequence( pts.begin(), pts.end()); #endif /* initialize sweep status structure (sss) */ typedef std::multiset Set; typedef typename Set::const_iterator const_set_iterator; Set sss; std::vector ind_sss(pts.size()); ind_sss[0]= sss.insert( pts[0] ); ind_sss[1]= sss.insert( pts[1] ); #ifdef CGAL__MIN_SQR_DISTANCE_DEBUG_ON showSequence( sss.begin(), sss.end()); #endif double min_square_dist= T.squared_distance(pts[0], pts[1]); #ifdef CGAL__MIN_SQR_DISTANCE_DEBUG_ON cout << "min: " << min_square_dist << endl; #endif int l= 0, r=2, s= pts.size()-1; /* sweep */ while( r < s ) { if( min_square_dist < T.squared_distance_x(pts[l],pts[r]) ) { sss.erase(ind_sss[l++]); } else { /* insert new sweep - point */ ind_sss[r]= sss.insert( pts[r++] ); /* calculate new minimal distance */ /* calculates the minimal distance between point pt and the points in the sweep structure (SSS): dist(p,q):= square distance of the two points p and q. min_sss= min { dist(p,q) : p,q \in SSS \cup {pt} } return (double) min{ min_square_dist, min_sss } */ double M= std::sqrt( min_square_dist ); Point p_left= Point(pts[r].x(), pts[r].y() - M); const_set_iterator min_left= sss.lower_bound(p_left); Point p_right= Point(pts[r].x(), pts[r].y() + M); const_set_iterator min_right= sss.upper_bound(p_right); double m; for( const_set_iterator sit= min_left; sit != min_right; sit++) { m= T.squared_distance(pts[r], *sit); if( m < min_square_dist) min_square_dist= m; } #ifdef CGAL__MIN_SQR_DISTANCE_DEBUG_ON cout << "min-neu: " << min_square_dist << endl; #endif } #ifdef CGAL__MIN_SQR_DISTANCE_DEBUG_ON showSequence( sss.begin(), sss.end()); #endif } return min_square_dist; } CGAL_END_NAMESPACE