Exemplo n.º 1
0
// ============================================================================
/// Splits polygon in two
QList<QPolygonF> splitPolygonRandomly( const QPolygonF& polygon, QLineF* pdebugout )
{
	QRectF br = polygon.boundingRect();
	
	// get random angle on cutting
	double angle = random01()* 6.28;
	
	// cut throught the center
	QPointF center = br.center();
	double upper = br.width() + br.height(); // upper bound for any of the polygon's dimensions
	
	QPointF p1( center.x() - upper*sin(angle), center.y() - upper*cos(angle) );
	QPointF p2( center.x() + upper*sin(angle), center.y() + upper*cos(angle) );
	
	// debug
	if ( pdebugout ) *pdebugout = QLineF( p1, p2 );
	
	return splitPolygon( polygon, QLineF( p1, p2 ) );
}
Exemplo n.º 2
0
/*!
 *  Note that this has complexity O(n^2) but should not count since
 *  triangulation has O(n^3).
 *
 *  \param globalverts the global vertices vector
 *  \param polylist the global list of polygons
 *  \return zero on success, and a negative integer if some error occured.
 */
int SimplePolygon::fixAndTriangulate( DCTPVec2dvector &globalverts, simplepolygonvector &polylist )
{
  Vec2d min, max;

  if( getMinMax( globalverts, min, max ) )
  {
//    std::cerr << "Ignoring degenerate polygon..." << std::endl;
    return -1;
  }
//  while( removeLinearPoints( globalverts, min, max ) ) { }
  while( splitPolygon( globalverts, polylist, min, max ) ) { }
  while( intersectPolygon( globalverts, polylist ) ) { }
  if( isReversed( globalverts ) )
  {
//    std::cerr << "Ignoring reversed polygon." << std::endl;
    return 0; // no error here...
  }

  // Ok, we have a valid polygon, so triangulate it.
  triangulate( globalverts, polylist );
  return 0;
}
Exemplo n.º 3
0
void ConvexPolygon::booleanDifference(const ConvexPolygon &hole, std::vector<ConvexPolygon> &list) const
{
    // Special case: this polygon is entirely swallowed by the hole
    if(hole.envelopes(*this))
        return;

    // Special case: the hole is entirely inside this polygon
    if(envelopes(hole)) {
        Points p1, p2;
        splitPolygon(*this, hole, p1, p2);
        ConvexPolygon::make(p1, list);
        ConvexPolygon::make(p2, list);
        return;
    }

    // Common case: hole intersects with this polygon.
    std::vector<bool> visited(vertexCount());
    std::queue<unsigned int> queue;
    queue.push(0);

    // Perform intersection
    unsigned int oldsize = list.size();
    Points poly;
    while(!queue.empty()) {
        int i = queue.front();
        while(i < vertexCount()) {
            // Stop if we've already been here
            if(visited[i])
                break;
            visited[i] = true;

            // Include point if it is not inside the hole
            bool inhole = hole.hasPoint(vertex(i));
            if(!inhole)
                poly.push_back(vertex(i));

            // Check for intersections
            Point isect[2];
            int isectv[2];
            findIntersections(*this, i, i+1, hole, isect, isectv);

            if(isectv[0] >= 0) {
                // Intersection found: this is the start of a hole,
                // except when this edge started inside the hole.
                poly.push_back(isect[0]);
                if(!inhole) {
                    // Start tracing the hole
                    int j = isectv[0];
                    do {
                        // Check for intersections
                        // The first hole edge may intersect with another edges
                        Point hisect[2];
                        int hisectv[2];
                        findIntersections(hole, j+1, j, *this, hisect, hisectv);

                        // There is always one intersection (the one that got us here)
                        if((j == isectv[0] && hisectv[1] >= 0) || (j != isectv[0] && hisectv[0] >= 0)) {
                            // Pick the intersection that is not the one we came in on
                            Point ip;
                            int iv;
                            if(hisectv[1] < 0 || glm::distance2(hisect[0],isect[0]) > glm::distance(hisect[1],isect[0])) {
                                ip = hisect[0];
                                iv = hisectv[0];
                            } else {
                                ip = hisect[1];
                                iv = hisectv[1];
                            }

                            queue.push(i+1);

                            // Avoid adding duplicate point of origin
                            if(glm::distance2(poly.front(), ip) > 0.0001)
                                poly.push_back(ip);
                            i = iv;
                            break;
                        } else {
                            // No intersections? Just add the hole vertex then
                            poly.push_back(hole.vertex(j));
                        }
 
                        if(--j < 0)
                            j = hole.vertexCount() - 1;
                    } while(j != isectv[0]);
                }
            }
            ++i;
        }

        // Partition the generated polygon into convex polygons
        // and add them to the list.
        if(poly.size() >= 3) {
            try {
                ConvexPolygon::make(poly, list);
            } catch(const algorithm::GeometryException &e) {
                // Bad polygons generated... The algorithm works well
                // enough most of the time, let's just roll back the error.
                int changes = list.size() - oldsize;
#ifndef NDEBUG
                cerr << "booleanDifference error: " << e.what() << " (" << changes << " change(s) rolled back)\n";
#endif
                while(changes-->0)
                    list.pop_back();
                list.push_back(*this);
                return;
            }
        }
        poly.clear();
        queue.pop();
    }
}