Exemple #1
0
/**
 *  Is the given polygon completely encosed by this one
 * @param poly Another polygon
 * @return True if the given polygon is enclosed by this, false otherwise
 */
bool ConvexPolygon::contains(const ConvexPolygon &poly) const {
  // Basically just have to test if each point is inside us, this could be
  // slow
  const Vertex2D *current = poly.head();
  for (size_t i = 0; i < poly.numVertices(); ++i) {
    if (!this->contains(*current))
      return false;
    current = current->next();
  }
  return true;
}
    /**
    * Compute the polygon that defines the intersection between two 
    * other concex polygons using the method of chasing edges
    * @param P :: A reference to the first polygon
    * @param Q :: A reference to the second polygon
    * @returns A new polygon defining the region of intersection
    */
    ConvexPolygon intersectionByORourke(const ConvexPolygon &P, const ConvexPolygon &Q)
    {
      const size_t nverts_p(P.numVertices()), nverts_q(Q.numVertices());
      const V2D origin(0.0,0.0);

      size_t count_p(0), count_q(0); // Number of vertices visited
      unsigned int inflag(Unknown);
      bool firstPoint(true);
      // Avoid vertex list reallocations
      Vertex2DList originAB(3);
      originAB[0] = origin;
      Vertex2DList aHB(3);
      Vertex2DList bHA(3);

      // Final list
      Vertex2DList intersectList;
      do
      {
        size_t pi(0), pim1(0), qi(0), qim1(0);
      
        // Compute a vector between the previous point in the direction of the next
        pim1 = (pi + nverts_p - 1) % nverts_p;
        qim1 = (qi + nverts_q - 1) % nverts_q;
        V2D edge_p = P[pi] - P[pim1];
        V2D edge_q = Q[qi] - Q[qim1];

        // Orientations
        originAB[1] = edge_p;
        originAB[2] = edge_q;
        int cross = ConvexPolygon(originAB).orientation();
        aHB[0] = Q[qim1];
        aHB[1] = Q[qi];
        aHB[2] = P[pi];
        int aHB_dir = ConvexPolygon(aHB).orientation();
        bHA[0] = P[pim1];
        bHA[1] = P[pi];
        bHA[2] = Q[qi];
        int bHA_dir = ConvexPolygon(bHA).orientation();
        // Test for line intersection
        V2D intersect;
        unsigned int type = intersection(P[pim1],P[pi], Q[qim1],Q[qi], intersect);
        if( type == 1 || type == 2 )
        {
          if( inflag == Unknown && firstPoint )
          {
            count_p = count_q = 0;
            firstPoint = false;
          }
          if( aHB_dir > 0 ) inflag = Pin;
          else if( bHA_dir > 0 ) inflag = Qin;
          else {};
          intersectList.insert(intersect);
        }

        // Deal with advance of indices
        /* Special case: A & B overlap and oppositely oriented. */
        if ( type == 3 && edge_p.scalar_prod(edge_q) < 0.0 )
        {
          throw std::runtime_error("Single segment intersection");
        }
        /* Special case: A & B parallel and separated. */
        else if ( cross == 0 && (aHB_dir < 0) && (bHA_dir < 0) )
        {
          throw std::runtime_error("AxB=0 and both are left-hand oriented so no intersection");
        }
        /* Special case: A & B collinear. */
        else if ( cross == 0 && (aHB_dir == 0) && (bHA_dir == 0) ) 
        {
          /* Advance but do not output point. */
          if ( inflag == Pin )
            qi = advanceVertex(qi, count_q, nverts_q, false, Q[qi], intersectList);
          else
            pi = advanceVertex(pi, count_p, nverts_p, false, P[pi], intersectList);
        }
        /* Generic cases. */
        else if ( cross >= 0 ) 
        {
          if ( bHA_dir > 0)
            pi = advanceVertex(pi, count_p, nverts_p, inflag == Pin, P[pi], intersectList);
          else
            qi = advanceVertex(qi, count_q, nverts_q, inflag == Qin, Q[qi], intersectList);
        }
        else /* if ( cross < 0 ) */
        {
          if ( aHB_dir > 0)
            qi = advanceVertex(qi, count_q, nverts_q, inflag == Qin, Q[qi], intersectList);
          else
            pi = advanceVertex(pi, count_p, nverts_p, inflag == Pin, P[pi], intersectList);
        }
      }
      while( (count_p < nverts_p || count_q < nverts_q) && 
        (count_p < 2*nverts_p) && (count_q < 2*nverts_q) );

      if( intersectList.size() < 3 )
      {
        throw std::runtime_error("Intersection points do not form a bounded polygon.");
      }

      return ConvexPolygon(intersectList);
    }