Esempio n. 1
0
bool CheckPolygonSelfIntersections(Iter beg, Iter end)
{
  Iter last = end;
  --last;

  for (Iter i = beg; i != last; ++i)
  {
    for (Iter j = i; j != end; ++j)
    {
      // do not check intersection of neibour segments
      if (std::distance(i, j) <= 1 || (i == beg && j == last))
        continue;

      Iter ii = base::NextIterInCycle(i, beg, end);
      Iter jj = base::NextIterInCycle(j, beg, end);
      PointD a = *i, b = *ii, c = *j, d = *jj;

      // check for rect intersection
      if (std::max(a.x, b.x) < std::min(c.x, d.x) || std::min(a.x, b.x) > std::max(c.x, d.x) ||
          std::max(a.y, b.y) < std::min(c.y, d.y) || std::min(a.y, b.y) > std::max(c.y, d.y))
      {
        continue;
      }

      double const s1 = OrientedS(a, b, c);
      double const s2 = OrientedS(a, b, d);
      double const s3 = OrientedS(c, d, a);
      double const s4 = OrientedS(c, d, b);

      // check if sections have any intersection
      if (s1 * s2 > 0.0 || s3 * s4 > 0.0)
        continue;

      // Common principle if any point lay exactly on section, check 2 variants:
      // - only touching (><) - don't return as intersection;
      // - 'X'-crossing - return as intersection;
      // 'X'-crossing defines when points lay in different cones.

      if (s1 == 0.0 && IsInSection(a, b, c))
      {
        PointD const prev = *base::PrevIterInCycle(j, beg, end);

        PointD test[] = {a, b};
        if (a == c)
          test[0] = *base::PrevIterInCycle(i, beg, end);
        if (b == c)
          test[1] = *base::NextIterInCycle(ii, beg, end);

        if (IsSegmentInCone(c, test[0], prev, d) == IsSegmentInCone(c, test[1], prev, d))
          continue;
      }

      if (s2 == 0.0 && IsInSection(a, b, d))
      {
        PointD const next = *base::NextIterInCycle(jj, beg, end);

        PointD test[] = {a, b};
        if (a == d)
          test[0] = *base::PrevIterInCycle(i, beg, end);
        if (b == d)
          test[1] = *base::NextIterInCycle(ii, beg, end);

        if (IsSegmentInCone(d, test[0], c, next) == IsSegmentInCone(d, test[1], c, next))
          continue;
      }

      if (s3 == 0.0 && IsInSection(c, d, a))
      {
        PointD const prev = *base::PrevIterInCycle(i, beg, end);

        PointD test[] = {c, d};
        if (c == a)
          test[0] = *base::PrevIterInCycle(j, beg, end);
        if (d == a)
          test[1] = *base::NextIterInCycle(jj, beg, end);

        if (IsSegmentInCone(a, test[0], prev, b) == IsSegmentInCone(a, test[1], prev, b))
          continue;
      }

      if (s4 == 0.0 && IsInSection(c, d, b))
      {
        PointD const next = *base::NextIterInCycle(ii, beg, end);

        PointD test[] = {c, d};
        if (c == b)
          test[0] = *base::PrevIterInCycle(j, beg, end);
        if (d == b)
          test[1] = *base::NextIterInCycle(jj, beg, end);

        if (IsSegmentInCone(b, test[0], a, next) == IsSegmentInCone(b, test[1], a, next))
          continue;
      }

      return true;
    }
  }

  return false;
}
Esempio n. 2
0
#include "geometry/polygon.hpp"
#include "geometry/triangle2d.hpp"

#include "base/macros.hpp"

#include "std/algorithm.hpp"


namespace
{
  typedef m2::PointD P;
}

UNIT_TEST(IsSegmentInCone)
{
  TEST(IsSegmentInCone(P(0,0),  P( 0, 3), P(-1,-1), P(1,-1)), ());
  TEST(IsSegmentInCone(P(0,0),  P( 2, 3), P(-1,-1), P(1,-1)), ());
  TEST(IsSegmentInCone(P(0,0),  P(-3, 3), P(-1,-1), P(1,-1)), ());
  TEST(IsSegmentInCone(P(0,0),  P(-3, 0), P(-1,-1), P(1,-1)), ());
  TEST(IsSegmentInCone(P(0,0),  P( 3, 0), P(-1,-1), P(1,-1)), ());
  TEST(!IsSegmentInCone(P(0,0), P( 0,-1), P(-1,-1), P(1,-1)), ());
  TEST(!IsSegmentInCone(P(0,0), P( 1,-3), P(-1,-1), P(1,-1)), ());
  TEST(!IsSegmentInCone(P(0,0), P(-1,-3), P(-1,-1), P(1,-1)), ());

  TEST(IsSegmentInCone(P(0,0),  P( 0, 3), P(-1,1), P(1,1)), ());
  TEST(IsSegmentInCone(P(0,0),  P( 2, 3), P(-1,1), P(1,1)), ());
  TEST(!IsSegmentInCone(P(0,0), P(-3, 3), P(-1,1), P(1,1)), ());
  TEST(!IsSegmentInCone(P(0,0), P(-3, 0), P(-1,1), P(1,1)), ());
  TEST(!IsSegmentInCone(P(0,0), P( 3, 0), P(-1,1), P(1,1)), ());
  TEST(!IsSegmentInCone(P(0,0), P( 0,-1), P(-1,1), P(1,1)), ());
  TEST(!IsSegmentInCone(P(0,0), P( 1,-3), P(-1,1), P(1,1)), ());