//=============================================================================
// Copyright (c) Kitware, Inc.
// All rights reserved.
// See LICENSE.txt for details.
//
// This software is distributed WITHOUT ANY WARRANTY; without even
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE.  See the above copyright notice for more information.
//=============================================================================
#include "smtk/bridge/polygon/internal/SweepEvent.h"

namespace smtk {
  namespace bridge {
    namespace polygon {

bool SweepEvent::operator < (const SweepEvent& other) const
{
  return
    (this->m_posn.x() < other.point().x() ||
     (this->m_posn.x() == other.point().x() &&
      (this->m_posn.y() < other.point().y() ||
       (this->m_posn.y() == other.point().y() &&
        (this->m_type < other.type() ||
         (this->m_type == other.type() &&
          ( // Types match, perform type-specific comparisons:
            (this->m_type == SEGMENT_START &&
             (this->m_edge < other.m_edge ||
              (this->m_edge == other.m_edge && this->m_indx < other.m_indx))) ||
            (this->m_type == SEGMENT_END &&
             (this->m_frag[0] < other.m_frag[0])) ||
            (this->m_type == SEGMENT_CROSS &&
             (this->m_frag[0] < other.m_frag[0] ||
              (this->m_frag[0] == other.m_frag[0] &&
               (this->m_frag[1] < other.m_frag[1]))))
          ))))))) ?
    true : false;
}

SweepEvent SweepEvent::SegmentStart(
  const internal::Point& p0,
  const internal::Point& p1,
  const smtk::model::Edge& edge,
  int segId)
{
  SweepEvent event;
  event.m_type = SEGMENT_START;
  if (p0.x() < p1.x() || (p0.x() == p1.x() && p0.y() < p1.y()))
    {
    event.m_posn = p0;
    event.m_frag[0] = +1;
    }
  else
    {
    event.m_posn = p1;
    event.m_frag[0] = -1;
    }
  event.m_edge = edge;
  event.m_indx = segId;
  return event;
}

SweepEvent SweepEvent::SegmentEnd(
  const internal::Point& posn,
  RegionIdSet::value_type fragId)
{
  SweepEvent event;
  event.m_type = SEGMENT_END;
  event.m_posn = posn;
  event.m_frag[0] = fragId;
  return event;
}

SweepEvent SweepEvent::SegmentCross(
  const internal::Point& crossPos,
  RegionIdSet::value_type fragId0,
  RegionIdSet::value_type fragId1)
{
  SweepEvent event;
  event.m_type = SEGMENT_CROSS;
  event.m_posn = crossPos;
  event.m_frag[0] = fragId0;
  event.m_frag[1] = fragId1;
  return event;
}

bool SweepEvent::RemoveCrossing(
  SweepEventSet& queue,
  FragmentId fragId0,
  FragmentId fragId1)
{
  for (SweepEventSet::iterator it = queue.begin(); it != queue.end(); ++it)
    {
    switch (it->m_type)
      {
    case SEGMENT_START:
      break;
    case SEGMENT_CROSS:
      if (
        static_cast<const FragmentId>(it->m_frag[0]) == fragId0 &&
        static_cast<const FragmentId>(it->m_frag[1]) == fragId1)
        {
        queue.erase(it);
        return true;
        }
      break;
    case SEGMENT_END:
      if (static_cast<const FragmentId>(it->m_frag[0]) == fragId0 ||
          static_cast<const FragmentId>(it->m_frag[0]) == fragId1)
        { // Terminate early... crossing event must come before either edge ends.
        return false;
        }
      break;
      }
    }
  return false;
}

    } // namespace polygon
  } //namespace bridge
} // namespace smtk
