text: // Boost.Geometry (aka GGL, Generic Geometry Library)
  
  // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
  // Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
  // Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
  
  // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
  // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
  
  // Use, modification and distribution is subject to the Boost Software License,
  // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  // http://www.boost.org/LICENSE_1_0.txt)
  
  #ifndef BOOST_GEOMETRY_STRATEGIES_SIDE_INFO_HPP
  #define BOOST_GEOMETRY_STRATEGIES_SIDE_INFO_HPP
  
  
  #include <utility>
  
  
  namespace boost { namespace geometry
  {
  
  
  /*!
  \brief Class side_info: small class wrapping for sides (-1,0,1)
  */
  class side_info
  {
  public :
      inline side_info(int side_a1 = 0, int side_a2 = 0,
              int side_b1 = 0, int side_b2 = 0)
      {
          sides[0].first = side_a1;
          sides[0].second = side_a2;
          sides[1].first = side_b1;
          sides[1].second = side_b2;
      }
  
      template <int Which>
      inline void set(int first, int second)
      {
          sides[Which].first = first;
          sides[Which].second = second;
      }
  
      template <int Which, int Index>
      inline void correct_to_zero()
      {
          if (Index == 0)
          {
              sides[Which].first = 0;
          }
          else
          {
              sides[Which].second = 0;
          }
      }
  
      template <int Which, int Index>
      inline int get() const
      {
          return Index == 0 ? sides[Which].first : sides[Which].second;
      }
  
  
      // Returns true if both lying on the same side WRT the other
      // (so either 1,1 or -1-1)
      template <int Which>
      inline bool same() const
      {
          return sides[Which].first * sides[Which].second == 1;
      }
  
      inline bool collinear() const
      {
          return sides[0].first == 0
              && sides[0].second == 0
              && sides[1].first == 0
              && sides[1].second == 0;
      }
  
      inline bool crossing() const
      {
          return sides[0].first * sides[0].second == -1
              && sides[1].first * sides[1].second == -1;
      }
  
      inline bool touching() const
      {
          return (sides[0].first * sides[1].first == -1
              && sides[0].second == 0 && sides[1].second == 0)
              || (sides[1].first * sides[0].first == -1
              && sides[1].second == 0 && sides[0].second == 0);
      }
  
      template <int Which>
      inline bool one_touching() const
      {
          // This is normally a situation which can't occur:
          // If one is completely left or right, the other cannot touch
          return one_zero<Which>()
              && sides[1 - Which].first * sides[1 - Which].second == 1;
      }
  
      inline bool meeting() const
      {
          // Two of them (in each segment) zero, two not
          return one_zero<0>() && one_zero<1>();
      }
  
      template <int Which>
      inline bool zero() const
      {
          return sides[Which].first == 0 && sides[Which].second == 0;
      }
  
      template <int Which>
      inline bool one_zero() const
      {
          return (sides[Which].first == 0 && sides[Which].second != 0)
              || (sides[Which].first != 0 && sides[Which].second == 0);
      }
  
      inline bool one_of_all_zero() const
      {
          int const sum = std::abs(sides[0].first)
                  + std::abs(sides[0].second)
                  + std::abs(sides[1].first)
                  + std::abs(sides[1].second);
          return sum == 3;
      }
  
  
      template <int Which>
      inline int zero_index() const
      {
          return sides[Which].first == 0 ? 0 : 1;
      }
  
  
      inline void debug() const
      {
          std::cout << sides[0].first << " "
              << sides[0].second << " "
              << sides[1].first << " "
              << sides[1].second 
  			<< std::endl;
      }
  
  
      inline void reverse()
      {
          std::swap(sides[0], sides[1]);
      }
  
  //private :
      std::pair<int, int> sides[2];
  
  };
  
  
  }} // namespace boost::geometry
  
  
  #endif // BOOST_GEOMETRY_STRATEGIES_SIDE_INFO_HPP
  