/** * 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); }