void limitHoles(GeometryCollection& polygon, uint32_t maxHoles) {
    if (polygon.size() > 1 + maxHoles) {
        std::nth_element(polygon.begin() + 1,
                         polygon.begin() + 1 + maxHoles,
                         polygon.end(),
                         [] (const auto& a, const auto& b) {
                             return signedArea(a) > signedArea(b);
                         });
        polygon.resize(1 + maxHoles);
    }
}
std::vector<GeometryCollection> classifyRings(const GeometryCollection& rings) {
    std::vector<GeometryCollection> polygons;

    std::size_t len = rings.size();

    if (len <= 1) {
        polygons.push_back(rings);
        return polygons;
    }

    GeometryCollection polygon;
    int8_t ccw = 0;

    for (std::size_t i = 0; i < len; i++) {
        double area = signedArea(rings[i]);

        if (area == 0)
            continue;

        if (ccw == 0)
            ccw = (area < 0 ? -1 : 1);

        if (ccw == (area < 0 ? -1 : 1) && !polygon.empty()) {
            polygons.push_back(polygon);
            polygon.clear();
        }

        polygon.push_back(rings[i]);
    }

    if (!polygon.empty())
        polygons.push_back(polygon);

    return polygons;
}
static void processPolynodeBranch(ClipperLib::PolyNode* polynode, GeometryCollection& rings) {
    // Exterior ring.
    rings.push_back(fromClipperPath(polynode->Contour));
    assert(signedArea(rings.back()) > 0);

    // Interior rings.
    for (auto * ring : polynode->Childs) {
        rings.push_back(fromClipperPath(ring->Contour));
        assert(signedArea(rings.back()) < 0);
    }

    // PolyNodes may be nested in the case of a polygon inside a hole.
    for (auto * ring : polynode->Childs) {
        for (auto * subRing : ring->Childs) {
            processPolynodeBranch(subRing, rings);
        }
    }
}
void antipodalPairs(std::list<Point2D> &Q, std::list<std::pair<Point2D, Point2D> > &pairs) {
    std::list<Point2D>::iterator p = Q.begin(),
                                 q = Q.begin(),
                                 nextp, nextq,
                                 q0, p0 = Q.begin();
    pairs.clear();

    //si tengo pocos elementos
    if(Q.size() < 3) {
        for(std::list<Point2D>::iterator pp = Q.begin(); pp != Q.end(); pp++) {
            for( std::list<Point2D>:: iterator qq = pp; qq != Q.end(); ++qq) {
                pairs.push_back(std::make_pair(*pp,*qq));
            }
        }
        return;
    }

    nextp = p;
    nextp++; //el siguiente de p

    q++; //q es el next de p
    nextq = q;
    nextq++; //el siguiente de q
//revisar
    while(nextq != Q.end() && (signedArea(*p, *nextp, *nextq) > signedArea(*p, *nextp, *q))) {
        q = nextq;
        nextq++;
    }

    q0 = q;
//revisar si no va Q.end()
    while( q != p0) {
        p = nextp;

        std::pair<Point2D,Point2D> pq = std::make_pair(*p,*q);
        pairs.push_back(pq);
        //bucle infinito
        while(signedArea(*p, *nextp, *nextq) > signedArea(*p, *nextp, *q)) {
            q = nextq;
            nextq++;
            if(q == Q.end())
                q = Q.begin();

            pq = std::make_pair(*p,*q);
            if(pq != std::make_pair(*q0, *p0))
                pairs.push_back(pq);
            else
                return;
        }

        if(compareEqualFloat( signedArea(*p, *nextp, *nextq), signedArea(*p, *nextp, *q))) {
            if(pq != std::make_pair(*q0,Q.back()))
                pairs.push_back(std::make_pair(*p, *nextq));
            else
                pairs.push_back(std::make_pair(*nextp, *q));
        }
    }
}
Exemple #5
0
	bool isClockwise(const Points2D& points) {
		return (signedArea(points) >= 0);
	}
std::shared_ptr<TileData> ClientGeoJsonSource::parse(const Tile& _tile, std::vector<char>& _rawData) const {

    if (!m_store) { return nullptr; }

    auto data = std::make_shared<TileData>();

    auto id = _tile.getID();

    auto tile = m_store->getTile(id.z, id.x, id.y); // uses a mutex lock internally for thread-safety

    Layer layer(""); // empty name will skip filtering by 'collection'

    for (auto& it : tile.features) {

        Feature feat(m_id);

        const auto& geom = it.tileGeometry;
        const auto type = it.type;

        switch (type) {
            case geojsonvt::TileFeatureType::Point: {
                feat.geometryType = GeometryType::points;
                for (const auto& pt : geom) {
                    const auto& point = pt.get<geojsonvt::TilePoint>();
                    feat.points.push_back(transformPoint(point));
                }
                break;
            }
            case geojsonvt::TileFeatureType::LineString: {
                feat.geometryType = GeometryType::lines;
                for (const auto& r : geom) {
                    Line line;
                    for (const auto& pt : r.get<geojsonvt::TileRing>().points) {
                        line.push_back(transformPoint(pt));
                    }
                    feat.lines.emplace_back(std::move(line));
                }
                break;
            }
            case geojsonvt::TileFeatureType::Polygon: {
                feat.geometryType = GeometryType::polygons;
                for (const auto& r : geom) {
                    Line line;
                    for (const auto& pt : r.get<geojsonvt::TileRing>().points) {
                        line.push_back(transformPoint(pt));
                    }
                    // Polygons are in a flat list of rings, with ccw rings indicating
                    // the beginning of a new polygon
                    if (signedArea(line) >= 0 || feat.polygons.empty()) {
                        feat.polygons.emplace_back();
                    }
                    feat.polygons.back().push_back(std::move(line));
                }
                break;
            }
            default: break;
        }

        feat.props = *it.tags.map;
        layer.features.emplace_back(std::move(feat));

    }

    data->layers.emplace_back(std::move(layer));

    return data;

}
float my::AbstractPolygon::area()const
{
    return std::abs( signedArea(glm::cross(edgeVector(0), edgeVector(1))) );
}
std::vector<Vec3d> ClosedPolygon::getEqualDistancePoints(int numSides, const Vec3d& center)
{
	std::vector<Vec3d> result;

	int N = closedPoints.size();

	if(N < 1)	return result; // empty polygon

	for(int i = 0; i < N; i++)
		lines.push_back(Line(closedPoints[i], closedPoints[(i+1) % N], i));

	this->computeLengths();

	// Distance to walk on polygon
	double segmentLength = this->closedLength / numSides;

	// Locate start point using vecUp
	Vec3d startPoint;
	int startIndex = 0;

	Plane halfPlane(vecUp, center);
	//testPlanes1.push_back(halfPlane);

	double minDist = DBL_MAX;

	// Test intersection with all lines and remember minimum one
	for(int i = 0; i < N; i++)
	{
		Vec3d pointIntersect;

		int res = halfPlane.LineIntersect(lines[i], pointIntersect);

		if(res == INTERSECT || res == ENDPOINT_INTERSECT)
		{
			Vec3d toIntsect = pointIntersect - center;

			if(toIntsect.norm() < minDist && dot(toIntsect, vecB) > 0)
			{
				minDist = toIntsect.norm();

				startPoint = pointIntersect;
				startIndex = i;
			}
		}
	}

	double t = lines[startIndex].timeAt(startPoint);
	int index = startIndex;

	// Compute equal-dist points on polygon
	for(int s = 0; s < numSides; s++)
	{
		// Add new point
		result.push_back(lines[index].pointAt(t));

		walk(segmentLength, t, index, &t, &index);
	}

	// if polygon is opposite direction then reverse 
	if( signedArea(result, plane.n, center) < 0 )
	{
		std::reverse(result.begin(), result.end());
		std::rotate(result.begin(), result.begin()+result.size()-1 , result.end());
	}

	return closedPoints = result;
}
 double signedArea(const P2Vector &points) {
   return signedArea(points, p2_adapt_ident());
 }