From: Kevin H. <kph...@us...> - 2010-03-07 18:49:21
|
Update of /cvsroot/panorama/panorama/src/common In directory sfp-cvsdas-2.v30.ch3.sourceforge.com:/tmp/cvs-serv24219 Modified Files: Tag: panorama_0_19 Makefile.am Types.hpp Added Files: Tag: panorama_0_19 GenericInterval.hpp GenericLine2.hpp Log Message: Adding an interval and 2d line class. --- NEW FILE: GenericInterval.hpp --- /* * $Id: GenericInterval.hpp,v 1.1.2.1 2010/03/07 18:49:12 kpharris Exp $ * * Part of GNU Panorama * Copyright (C) 2010 Kevin Harris * * 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, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ #if !defined(PANORAMA_INTERVAL_HPP) #define PANORAMA_INTERVAL_HPP /* GenericInterval.hpp -- A simple class for use in creating/testing intervals. */ /** * @author Kevin Harris */ /* Revision History: 18May2001 Created this file, "Templatized" the class... Tested it some. Complicated it some more (allowing backwards intervals)... 08Jan2002 Added quite a few comments, before I forget what is going on. 23Sep2003 Changed the structure a little, moving member functions outside, setting some member functions to be templated. Also, added the < and > operators. 29Sep2003 Simplified things by removing the ability to be backwards (reversing an earlier change). Also, all references to comparison of the given type by '>' were removed, so that only the '<' operator must be provided for comparisons ( >, <, and inside/outside ) to work. 06Mar2010 Really removed all use of <=. Simplified the logic in a few functions. Cleaned up and renamed. */ #include "panorama/common/StringDumpable.hpp" #include <algorithm> namespace panorama { // // GenericInterval class: // A class representing a range of numbers (between to constraints) // // It can be used to find: // 1. If a number is inside an interval // 2. If a number is outside an interval // 3. If two intervals overlap // 4. If an interval is a subset of another // 5. Find the overlap of two intervals // 6. Subtract one interval from another // 7. If an interval is empty // 8. Output an interval (to a std::ostream) in the form [a,b] or [empty] // 9. If something is > or < and interval (either an interval itself, or // any other type that can be compared to a T by means of the < and <= // operators). I would have prefered to only use the < operator, but it // was neccessary to use the <= to allow comparing of intervals when // endpoints are equal (for overlap testing). // // Notes: // * Comparison of anything with an empty interval always returns false. // This may change in the future, if I find that something external doesn't // work properly because of this comparison. Do not rely on this behavior! // template <class T> class GenericInterval { private: T m_begin; T m_end; public: // This tag allows use in the StringDumpable.hpp toString functions // without requiring the overridden virtual functions. typedef bool CanBeStringDumpedTag; // // Sets the Interval to be empty // GenericInterval() : m_begin(T(0)), m_end(T(0)) { } // // Sets an Interval to a given range // GenericInterval(T a, T b) : m_begin(a), m_end(b) { if( m_end < m_begin ) { std::swap(m_begin, m_end); } } // GenericInterval(T,T) // // Find out if a point is inside the Interval (generic) // template <class U> bool inside(U d) const { // This empty check looks redundant, but really serves a purpose when Intervals have infinite endpoints. if( empty() ) { return false; } return((m_begin < d) && (d < m_end)); } // inside(T) const // // Find out if a point is outside the Interval (generic) // template <class U> bool outside(U d) const { // Can't be inside or outside an empty Interval. if( empty() ) { return false; } // The inverse of the 'inside' test above. This is done this way instead // of the >= and <= operators to minimize the number of operators that // must be defined for types used within an Interval. return(!((m_begin < d) && (d < m_end))); } // outside(T) const // // Find out if two Intervals overlap // bool overlaps(const GenericInterval& i2) const { if( empty() || i2.empty() ) { // If either one is empty, there can't be any overlap. return false; } // One interval must be completely to the left (endpoints excluded) of // the other to be non-overlapping. // i2.end() <= begin() || end() <= i2.begin() if( !(begin() < i2.end()) || !(i2.begin() < end()) ) { return false; } return true; } // overlaps(const GenericInterval&) const // // Return if the Interval i2 is a subset of this Interval. // bool subset(const GenericInterval& i2) const { if( empty() || i2.empty() ) { return false; } // return((begin() <= i2.begin()) && (i2.end() <= end())); return (!(i2.begin() < begin()) && !(end() < i2.end())); } // subset(const GenericInterval&) const bool empty() const { return !(this->m_begin < this->m_end); } T begin() const { return m_begin; } T end() const { return m_end; } void set(T begin, T end) { m_begin = begin; m_end = end; if( m_end < m_begin ) { std::swap(this->a, this->b); } } // set(T,T) // Functions required for the tag-based toString interface void collectInternalMembers(MemberStringDumpCollector& collector) const; blocxx::String toString(const Indentation& indent = Indentation(), StringDumpable::PrefixType prefix = StringDumpable::E_PREFIX_NONE ) const; blocxx::String name() const { return "Interval"; } }; // class GenericInterval<T> // // Return the overlap of Interval i1 and Interval i2 (as an Interval) // template <class T> GenericInterval<T> intersection(const GenericInterval<T>& i1, const GenericInterval<T>& i2) { GenericInterval<T> result; // result Interval (empty by default) // If either Interval is empty, return an empty Interval, as there can't be // any overlap. if( i1.empty() || i2.empty() ) { return result; } // FIXME! Rewrite this to be simpler. if( (i1.begin() <= i2.begin()) && (i2.begin() <= i1.end()) ) { result = GenericInterval<T>(i2.begin(), std::min(i1.end(), i2.end())); } else if( (i2.begin() <= i1.begin()) && (i1.begin() <= i2.end()) ) { result = GenericInterval<T>(i1.begin(), std::min(i1.end(), i2.end())); } else if( (i1.begin() <= i2.end()) && (i2.end() <= i1.end()) ) { result = GenericInterval<T>(std::max(i1.begin(), i2.begin()), i2.end()); } else if( (i2.begin() <= i1.end()) && (i1.end() <= i2.end()) ) { result = GenericInterval<T>(std::max(i1.begin(), i1.begin()), i1.end()); } else { // Is a case here even valid? // FIXME: FOOBARBAZ } return result; } // intersection(const GenericInterval&) const // // Return the Interval created by subtracting the Interval i2 from // Interval i1. If i1 is empty, returns empty. If i2 is empty, returns i1. // template <class T> GenericInterval<T> operator-(const GenericInterval<T>& i1, const GenericInterval<T>& i2) { if( i1.empty() || i2.empty() ) { // If the Interval is empty, it can't overlap, and thus cannot have // another Interval subtracted from it. // // If the second Interval is empty, then subtraction will do nothing. // // Both of these cases should work properly by just returning i1 return i1; } // If the the minimum component of i1 is less than i2, the entire region // from i1.begin() to i2.begin() is all that remains after subtraction. // That is, IFF they overlap, if not, then the subtraction is the same as // the original i1. if( i1.begin() <= i2.begin() ) { return(GenericInterval<T>(i1.begin(),std::min(i1.end(),i2.begin()))); } // If the the maximum component of i1 is greater than i2, the entire // region from i2.end() to i1.end() is all that remains after // subtraction. // That is, IFF they overlap, if not, then the subtraction is the same as // the original i1. else if( i2.end() <= i1.end() ) { return(GenericInterval<T>(std::max(i1.begin(),i2.end()),i1.end())); } // Return an empty Interval... return GenericInterval<T>(); } // operator-(const GenericInterval&, const GenericInterval&) // // Global comparison operators: // (GenericInterval, GenericInterval), (GenericInterval, template U), (template U, GenericInterval) // template <class T> inline bool operator <(const GenericInterval<T>& t1, const GenericInterval<T>& t2) { if( t1.empty() || t2.empty() ) { return false; } // Note that the <= is actually correct here, as being ON the endpoint is // not being within the Interval. // return (t1.begin() <= t2.begin()) && (t1.end() <= t2.begin()); return !(t2.begin() < t1.begin()) && !(t2.begin() < t1.end()); } template <class T> inline bool operator >(const GenericInterval<T>& t1, const GenericInterval<T>& t2) { if( t1.empty() || t2.empty() ) { return false; } // Note that the <= is actually correct here, as being ON the endpoint is // not being within the Interval. // return (t2.begin() <= t1.begin()) && (t2.end() <= t1.begin()); return !(t1.begin() < t2.begin()) && !(t1.begin() < t2.end()); } template <class T, class U> inline bool operator <(const GenericInterval<T>& t1, const U& u) { if( t1.empty() ) { return false; } // Note that the <= is actually correct here, as being ON the endpoint is // not being within the Interval. // return (t1.end() <= u); return !(u < t1.end()); } template <class T, class U> inline bool operator >(const GenericInterval<T>& t1, const U& u) { if( t1.empty() ) { return false; } // Note that the <= is actually correct here, as being ON the endpoint is // not being within the Interval. //return (u <= t1.begin()); return !(t1.begin() < u); } template <class T, class U> inline bool operator <(const U& u, const GenericInterval<T>& t1) { if( t1.empty() ) { return false; } // Note that the <= is actually correct here, as being ON the endpoint is // not being within the Interval. // return (u <= t1.begin()); return !(t1.begin() < u); } template <class T, class U> inline bool operator >(const U& u, const GenericInterval<T>& t1) { if( t1.empty() ) { return false; } // Note that the <= is actually correct here, as being ON the endpoint is // not being within the Interval. // return (t1.end() <= u); return !(u < t1.end()); } template <class T> void GenericInterval<T>::collectInternalMembers(MemberStringDumpCollector& collector) const { collector.addMember("begin", begin()); collector.addMember("end", end()); } template <class T> blocxx::String GenericInterval<T>::toString(const Indentation& indent, StringDumpable::PrefixType prefix) const { blocxx::String tag; if( prefix == StringDumpable::E_PREFIX_CLASSNAME ) { tag = GenericInterval<T>::name(); } if( empty() ) { return indent.initial() + tag + "[empty]"; } return indent.initial() + tag + "[" + panorama::toString(begin(), indent.indentInside(), prefix) + "," + panorama::toString(end(), indent.indentInside(), prefix) + "]"; } } // namespace panorama #endif /* !defined(PANORAMA_INTERVAL_HPP) */ Index: Makefile.am =================================================================== RCS file: /cvsroot/panorama/panorama/src/common/Attic/Makefile.am,v retrieving revision 1.1.2.7 retrieving revision 1.1.2.8 diff -C2 -d -r1.1.2.7 -r1.1.2.8 *** Makefile.am 6 Mar 2010 20:44:07 -0000 1.1.2.7 --- Makefile.am 7 Mar 2010 18:49:12 -0000 1.1.2.8 *************** *** 23,26 **** --- 23,28 ---- GenericONB.hpp \ GenericFrame.hpp \ + GenericInterval.hpp \ + GenericLine2.hpp \ Capabilities.hpp Index: Types.hpp =================================================================== RCS file: /cvsroot/panorama/panorama/src/common/Attic/Types.hpp,v retrieving revision 1.1.2.6 retrieving revision 1.1.2.7 diff -C2 -d -r1.1.2.6 -r1.1.2.7 *** Types.hpp 6 Mar 2010 20:44:07 -0000 1.1.2.6 --- Types.hpp 7 Mar 2010 18:49:12 -0000 1.1.2.7 *************** *** 35,38 **** --- 35,40 ---- #include "panorama/common/GenericONB.hpp" #include "panorama/common/GenericFrame.hpp" + #include "panorama/common/GenericInterval.hpp" + #include "panorama/common/GenericLine2.hpp" namespace panorama *************** *** 47,50 **** --- 49,54 ---- typedef GenericONB<NumberType> ONB; typedef GenericFrame<NumberType> Frame; + typedef GenericInterval<NumberType> Interval; + typedef GenericLine2<NumberType> Line2; } --- NEW FILE: GenericLine2.hpp --- /* * $Id: GenericLine2.hpp,v 1.1.2.1 2010/03/07 18:49:12 kpharris Exp $ * * Part of GNU Panorama * Copyright (C) 2010 Kevin Harris * * 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, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ #if !defined(PANORAMA_GENERICLINE2_HPP) #define PANORAMA_GENERICLINE2_HPP #include "panorama/common/GenericPoint2.hpp" #include "panorama/common/GenericVector2.hpp" #include "panorama/common/GenericInterval.hpp" #include <limits> namespace panorama { /** * * A simple 2d line. * * @author Kevin Harris <kph...@us...> * @version $Revision: 1.1.2.1 $ * */ template<class T> class GenericLine2 { protected: GenericPoint2<T> m_origin; GenericVector2<T> m_direction; GenericInterval<T> m_limits; public: // This tag allows use in the StringDumpable.hpp toString functions // without requiring the overridden virtual functions. typedef bool CanBeStringDumpedTag; GenericLine2(); GenericLine2(const GenericPoint2<T>& o, const GenericVector2<T>& v, const GenericInterval<T>& limits = GenericInterval<T>( std::numeric_limits<T>::min(), std::numeric_limits<T>::max() )); GenericLine2(const GenericPoint2<T>& p1, const GenericPoint2<T>& p2); virtual ~GenericLine2(); GenericLine2(const GenericLine2& old); GenericLine2& operator= (const GenericLine2& old); GenericPoint2<T> o() const { return m_origin; } GenericPoint2<T> origin() const { return m_origin; } GenericVector2<T> v() const { return m_direction; } GenericVector2<T> direction() const { return m_direction; } GenericPoint2<T> minimum() const { return(m_origin + m_limits.begin() * direction()); } GenericPoint2<T> maximum() const { return(m_origin + m_limits.end() * direction()); } GenericPoint2<T> point_at(const T& t) const { return(m_origin + direction() * t); } bool infinite() const { return ( (m_limits.begin() <= -std::numeric_limits<T>::max()) && (m_limits.end() >= std::numeric_limits<T>::max()) ); } GenericInterval<T> limits() const { return m_limits; } template<typename U> bool inside(U u) const { return m_limits.inside(u); } // Functions required for the tag-based toString interface void collectInternalMembers(MemberStringDumpCollector& collector) const; blocxx::String toString(const Indentation& indent = Indentation(), StringDumpable::PrefixType prefix = StringDumpable::E_PREFIX_NONE ) const; blocxx::String name() const { return "Line2"; } }; // class GenericLine2 template<class T> GenericLine2<T>::GenericLine2(): m_origin(T(0),T(0)), m_direction(T(1),T(0)), m_limits( -std::numeric_limits<T>::max(), std::numeric_limits<T>::max() ) { } // GenericLine2() template<class T> GenericLine2<T>::GenericLine2(const GenericPoint2<T>& o, const GenericVector2<T>& v, const GenericInterval<T>& limits): m_origin(o), m_direction(v), m_limits(limits) { } // GenericLine2() template<class T> GenericLine2<T>::GenericLine2(const GenericPoint2<T>& p1, const GenericPoint2<T>& p2): m_origin(p1), m_direction(p2 - p1), m_limits( std::numeric_limits<T>::min(), T(1) - std::numeric_limits<T>::epsilon() ) { } // GenericLine2() template<class T> GenericLine2<T>::~GenericLine2() { } // ~GenericLine2() template<class T> GenericLine2<T>::GenericLine2(const GenericLine2<T>& old): m_origin(old.m_origin), m_direction(old.m_direction), m_limits(old.m_limits) { } // GenericLine2(GenericLine2) template<class T> GenericLine2<T>& GenericLine2<T>::operator= (const GenericLine2<T>& old) { // Generic check for self-assignment if( &old != this ) { m_origin = old.m_origin; m_direction = old.m_direction; m_limits = old.m_limits; } return(*this); } // GenericLine2::operator=(GenericLine2) template <class T> void GenericLine2<T>::collectInternalMembers(MemberStringDumpCollector& collector) const { collector.addMember("origin", o()); collector.addMember("direction", v()); collector.addMember("limits", limits()); } template <class T> blocxx::String GenericLine2<T>::toString(const Indentation& indent, StringDumpable::PrefixType prefix) const { blocxx::String tag; if( prefix == StringDumpable::E_PREFIX_CLASSNAME ) { tag = GenericLine2<T>::name(); } return indent.initial() + tag + "|" + panorama::toString(o(), indent.indentInside(), prefix) + "," + panorama::toString(v(), indent.indentInside(), prefix) + "," + panorama::toString(limits(), indent.indentInside(), prefix) + "|"; } } // namespace panorama #endif /* !defined(PANORAMA_GENERICLINE2_HPP) */ |