示例#1
0
void StatsFilter::extractMetadata(PointTableRef table)
{
    uint32_t position(0);

    for (auto di = m_stats.begin(); di != m_stats.end(); ++di)
    {
        const Summary& s = di->second;

        MetadataNode t = m_metadata.addList("statistic");
        t.add("position", position++);
        s.extractMetadata(t);
    }

    // If we have X, Y, & Z dims, output bboxes
    auto xs = m_stats.find(Dimension::Id::X);
    auto ys = m_stats.find(Dimension::Id::Y);
    auto zs = m_stats.find(Dimension::Id::Z);
    if (xs != m_stats.end() &&
        ys != m_stats.end() &&
        zs != m_stats.end())
    {
        BOX3D box(xs->second.minimum(), ys->second.minimum(), zs->second.minimum(),
                  xs->second.maximum(), ys->second.maximum(), zs->second.maximum());
        pdal::Polygon p(box);

        MetadataNode mbox = Utils::toMetadata(box);
        MetadataNode box_metadata = m_metadata.add("bbox");
        MetadataNode metadata = box_metadata.add("native");
        MetadataNode boundary = metadata.add("boundary", p.json());
        MetadataNode bbox = metadata.add(mbox);
        SpatialReference ref = table.anySpatialReference();
        // if we don't get an SRS from the PointTableRef,
        // we won't add another metadata node
        if (!ref.empty())
        {
            p.setSpatialReference(ref);
            SpatialReference epsg4326("EPSG:4326");
            pdal::Polygon pdd = p.transform(epsg4326);
            BOX3D ddbox = pdd.bounds();
            MetadataNode epsg_4326_box = Utils::toMetadata(ddbox);
            MetadataNode dddbox = box_metadata.add("EPSG:4326");
            dddbox.add(epsg_4326_box);
            MetadataNode ddboundary = dddbox.add("boundary", pdd.json());


        }
    }
}
示例#2
0
void HexBin::done(PointTableRef table)
{
    m_grid->processSample();

    try
    {
        m_grid->findShapes();
        m_grid->findParentPaths();
    }
    catch (hexer::hexer_error& e)
    {
        m_metadata.add("error", e.what(),
            "Hexer threw an error and was unable to compute a boundary");
        m_metadata.add("boundary", "MULTIPOLYGON EMPTY",
            "Empty polygon -- unable to compute boundary");
        return;

    }


    std::ostringstream offsets;
    offsets << "MULTIPOINT (";
    for (int i = 0; i < 6; ++i)
    {
        hexer::Point p = m_grid->offset(i);
        offsets << p.m_x << " " << p.m_y;
        if (i != 5)
            offsets << ", ";
    }
    offsets << ")";

    m_metadata.add("edge_length", m_edgeLength, "The edge length of the "
        "hexagon to use in situations where you do not want to estimate "
        "based on a sample");
    m_metadata.add("estimated_edge", m_grid->height(),
        "Estimated computed edge distance");
    m_metadata.add("threshold", m_grid->denseLimit(),
        "Minimum number of points inside a hexagon to be considered full");
    m_metadata.add("sample_size", m_sampleSize, "Number of samples to use "
        "when estimating hexagon edge size. Specify 0.0 or omit options "
        "for edge_size if you want to compute one.");
    m_metadata.add("hex_offsets", offsets.str(), "Offset of hex corners from "
        "hex centers.");

    std::ostringstream polygon;
    polygon.setf(std::ios_base::fixed, std::ios_base::floatfield);
    polygon.precision(m_precision);
    m_grid->toWKT(polygon);

    if (m_outputTesselation)
    {
        MetadataNode hexes = m_metadata.add("hexagons");
        for (HexIter hi = m_grid->hexBegin(); hi != m_grid->hexEnd(); ++hi)
        {
            HexInfo h = *hi;

            MetadataNode hex = hexes.addList("hexagon");
            hex.add("density", h.density());

            hex.add("gridpos", Utils::toString(h.xgrid()) + " " +
                Utils::toString((h.ygrid())));
            std::ostringstream oss;
            // Using stream limits precision (default 6)
            oss << "POINT (" << h.x() << " " << h.y() << ")";
            hex.add("center", oss.str());
        }
        m_metadata.add("hex_boundary", polygon.str(),
            "Boundary MULTIPOLYGON of domain");
    }


    /***
      We want to make these bumps on edges go away, which means that
      we want to elimnate both B and C.  If we take a line from A -> C,
      we need the tolerance to eliminate B.  After that we're left with
      the triangle ACD and we want to eliminate C.  The perpendicular
      distance from AD to C is the hexagon height / 2, so we set the
      tolerance a little larger than that.  This is larger than the
      perpendicular distance needed to eliminate B in ABC, so should
      serve for both cases.

         B ______  C
          /      \
       A /        \ D

    ***/
    double tolerance = 1.1 * m_grid->height() / 2;

    double cull = m_cullArg->set() ? m_cullArea : (6 * tolerance * tolerance);

    SpatialReference srs(table.anySpatialReference());
    pdal::Polygon p(polygon.str(), srs);
    pdal::Polygon density_p(polygon.str(), srs);

    // If the SRS was geographic, use relevant
    // UTM for area and density computation
    if (srs.isGeographic())
    {
        // Compute a UTM polygon
        BOX3D box = p.bounds();
        int zone = SpatialReference::calculateZone(box.minx, box.miny);

        auto makezone = [] (int zone) -> std::string
        {

            std::ostringstream z;

            // Use WGS84 UTM zones
            z << "EPSG:327" << abs(zone);
            return z.str();
        };

        SpatialReference utm(makezone(zone));
        density_p = p.transform(utm);
    }

    if (m_doSmooth)
        p = p.simplify(tolerance, cull);

    std::string boundary_text = p.wkt(m_precision);

    m_metadata.add("boundary", boundary_text,
        "Approximated MULTIPOLYGON of domain");
    m_metadata.addWithType("boundary_json", p.json(), "json",
        "Approximated MULTIPOLYGON of domain");
    double area = density_p.area();

    double density = (double) m_count/ area ;
    if (std::isinf(density))
    {
        density = -1.0;
        area = -1.0;
    }

    m_metadata.add("density", density,
        "Number of points per square unit (total area)");
    m_metadata.add("area", area, "Area in square units of tessellated polygon");

    double moving_avg(0.0);
    double avg_count(0.0);

    double hex_area(((3 * SQRT_3)/2.0) * (m_grid->height() * m_grid->height()));
    int n(0);
    point_count_t totalCount(0);
    double totalArea(0.0);
    for (HexIter hi = m_grid->hexBegin(); hi != m_grid->hexEnd(); ++hi)
    {
        HexInfo h = *hi;
        totalCount += h.density();
        totalArea += hex_area;
        ++n;
    }

    double avg_density = totalArea /(double) totalCount;
    m_metadata.add("avg_pt_per_sq_unit", avg_density, "Number of points "
        "per square unit (tessellated area within inclusions)");

    double avg_spacing = std::sqrt(1/density);
    m_metadata.add("avg_pt_spacing", avg_spacing,
        "Avg point spacing (x/y units)");
}