Example #1
0
inline MetadataNode toMetadata(PointTableRef table)
{
    const PointLayoutPtr layout(table.layout());
    MetadataNode root;

    for (const auto& id : layout->dims())
    {
        MetadataNode dim("dimensions");
        dim.add("name", layout->dimName(id));
        Dimension::Type::Enum t = layout->dimType(id);
        dim.add("type", Dimension::toName(Dimension::base(t)));
        dim.add("size", layout->dimSize(id));
        root.addList(dim);
    }

    return root;
}
Example #2
0
void Stage::serialize(MetadataNode root, PipelineWriter::TagMap& tags) const
{
    for (Stage *s : m_inputs)
        s->serialize(root, tags);

    auto tagname = [tags](const Stage *s)
    {
        const auto ti = tags.find(s);
        return ti->second;
    };

    MetadataNode anon("pipeline");
    anon.add("type", getName());
    anon.add("tag", tagname(this));
    m_options.toMetadata(anon);
    for (Stage *s : m_inputs)
        anon.addList("inputs", tagname(s));
    root.addList(anon);
}
Example #3
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)");
}
Example #4
0
void HexBin::done(PointTableRef table)
{
    m_grid->processSample();
    m_grid->findShapes();
    m_grid->findParentPaths();

    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("threshold", m_density, "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.");
    if (m_outputTesselation)
    {

        MetadataNode hexes = m_metadata.add("hexagons");
        for (HexIter hi = m_grid->hexBegin(); hi != m_grid->hexEnd(); ++hi)
        {
            using namespace boost;

            HexInfo h = *hi;

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

            hex.add("gridpos", lexical_cast<std::string>(h.xgrid()) + " " +
                lexical_cast<std::string>(h.ygrid()));
            std::ostringstream oss;
            // Using stream limits precision (default 6)
            oss << "POINT (" << h.x() << " " << h.y() << ")";
            hex.add("center", oss.str());
        }
    }

    std::ostringstream polygon;
    polygon.setf(std::ios_base::fixed, std::ios_base::floatfield);
    polygon.precision(m_options.getValueOrDefault<uint32_t>("precision", 8));
    m_grid->toWKT(polygon);
    m_metadata.add("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;
    m_metadata.add("smoothed_boundary",
        Geometry::smoothPolygon(polygon.str(), tolerance),
        "Smoothed boundary MULTIPOLYGON of domain");
    double area = Geometry::computeArea(polygon.str());

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

}