-
Notifications
You must be signed in to change notification settings - Fork 37
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support for multiple dimensions #9
Comments
Capturing voice @artemp this morning on this:
|
So, something like: namespace mapbox { namespace geometry {
template <typename P, template <typename...> class Cont>
struct line_string : Cont<P> { ... };
namespace 2d {
template <class T> struct point { ... };
template <class T, template <typename...> class Cont = std::vector>
using line_string = mapbox::geometry::line_string<point<T>, Cont>;
}
namespace 3d {
template <class T> struct point { ... };
template <class T, template <typename...> class Cont = std::vector>
using line_string = mapbox::geometry::line_string<point<T>, Cont>;
}
}} |
@jfirebaugh not quite, here is what I have in mind
namespace geometry {
// Base pure data-structures, no methods
struct empty {};
template <typename T, int dim>
struct point {}; //
template <typename T>
struct point<T,2>
{
using value_type = T;
value_type x;
value_type y;
point() {}
point(value_type x_, value_type y_)
: x(x_), y(y_) {}
};
template <typename T>
struct point<T,3>
{
using value_type = T;
value_type x;
value_type y;
value_type z;
point() {}
point(value_type x_, value_type y_, value_type z_)
: x(x_), y(y_), z(z_) {}
};
template <typename T>
struct point<T,4>
{
using value_type = T;
value_type x;
value_type y;
value_type z;
value_type m;
point() {}
point(value_type x_, value_type y_, value_type z_, value_type m_)
: x(x_), y(y_), z(z_), m(m_) {}
};
template <typename T, template <typename...> class Cont = std::vector>
struct line_string : Cont<T>
{
using point_type = T;
using value_type = typename point_type::value_type;
using container_type = Cont<point_type>;
};
// TODO: add remaining types
} // geometry
Library should provide reference definitions for the most common use case e.g : namespace client {
// Define my geometry types add useful methods
struct point : geometry::point<double, 2>
{
using base_type = geometry::point<double,2>;
point() {}
point(double x_, double y_)
: base_type(x_, y_) {}
};
struct line_string : geometry::line_string<geometry::point<float, 3>>
{
using point_type = geometry::point<float, 3>;
void add_point(float x, float y, float z)
{
geometry::line_string<point_type>::emplace_back(x, y, z);
}
std::size_t num_points() const
{
return geometry::line_string<point_type>::size();
}
};
using geometry = mapbox::util::variant<geometry::empty,
point, // 2D double
line_string>; // 3D float
} // client definitions
struct printer
{
void operator()(client::point const& pt) const
{
std::cerr << "Point " << sizeof(pt) << std::endl;
std::cerr << "x=" << pt.x << ", y=" << pt.y << std::endl;
}
void operator()(client::line_string const& line) const
{
std::cerr << "LineString " << sizeof(line) << std::endl;
for (auto const& pt : line)
{
std::cerr << "x=" << pt.x << ", y=" << pt.y << " z=" << pt.z << std::endl;
}
}
template <typename T>
void operator() (T const& g) const
{
std::cerr << "Not implemented" << std::endl;
}
};
int main()
{
std::cerr << "Geometry base" << std::endl;
std::vector<client::geometry> v;
client::point pt(100,200); // 2D point double
v.push_back(std::move(pt));
client::line_string line; // 3D line float
line.add_point(100, 200, 1.0);
line.add_point(200, 100, 0.5);
line.add_point(100, 100, 1.0);
v.push_back(std::move(line));
for (auto const& geom : v)
{
mapbox::util::apply_visitor(printer(), geom);
}
return 0;
}
The above addresses both support for multiple dimensions and keeping base geometry bare-bones data. It's also flexible to allow mixing value_types and dimensions which can be useful in some cases. |
Hmm, I think we're getting ahead of ourselves. The goal was to create a set of simple, concrete types that could be shared across Mapbox projects. A solution that involves It looks to me like geojson-vt-cpp uses a |
This is not "what if" :) We're already using double,int,float,int64 geometries in a few places (cc/ @flippmoke ) and support for extra dimensions would be super useful in simplification, 2.5D (elevation) just to mention two. The main point with the above approach is that it's possible to instantiate concrete types using 2D points and The 'client' namespace is the way to split creation/accessor interface which is what #7 is about, no? It doesn't have to be 'client' and we can omit it from the first draft. But I think it can be useful, also it's optional (separate header). |
The current |
Hmm. I'm still skeptical. I don't get the "point" of a |
@jfirebaugh - I think I'm not explaining well. I'll try again :) Everything in |
Ah, I understand now. In that case, I think the proposals are pretty much the same, except that I'm including predefined |
@jfirebaugh - having separate d2/d3 namespaces will just duplicate code and make it less generic. Please, take a look again namespace geometry {
template <typename T, int dim>
struct point {}; //
template <typename T>
struct point<T,2>
{
using value_type = T;
value_type x;
value_type y;
point() {}
point(value_type x_, value_type y_)
: x(x_), y(y_) {}
};
template <typename T>
struct point<T,3>
{
using value_type = T;
value_type x;
value_type y;
value_type z;
point() {}
point(value_type x_, value_type y_, value_type z_)
: x(x_), y(y_), z(z_) {}
};
template <typename T>
struct point<T,4>
{
using value_type = T;
value_type x;
value_type y;
value_type z;
value_type m;
point() {}
point(value_type x_, value_type y_, value_type z_, value_type m_)
: x(x_), y(y_), z(z_), m(m_) {}
};
template <typename T, template <typename...> class Cont = std::vector>
struct line_string : Cont<T>
{
using point_type = T;
using value_type = typename point_type::value_type;
using container_type = Cont<point_type>;
};
// TODO: add remaining types
} // geometry
It solves nicely multi-dimensions without re-definitions^. Of course we can still have actual types instantiated in separate namespaces if needed. |
@artemp I think we largely agree but are missing each other. Maybe some concrete code will help. Here's what I propose. This keeps existing struct MyPoint { double x; double y; uint64_t extra; };
using geometry = mapbox::geometry::geometry_t<MyPoint>;
using line_string = geometry::line_string_type;
using polygon = geometry::polygon_type;
using multi_point = geometry::multi_point_type;
using multi_line_string = geometry::multi_line_string_type;
using multi_polygon = geometry::multi_polygon_type; cc @mourner |
Currently only 2D planar geometries are considered. Having looked at
geojson-vt-cpp
made me realise that sooner or later we'll want to use extra dimensions. In GIS world while not proper 3D - concept of 2.5D is widely used. Even notorious ESRI shapefiles have support for it:).What do people think ?
/cc @kkaefer @jfirebaugh @springmeyer @flippmoke @jakepruitt @mapsam @BergWerkGIS
The text was updated successfully, but these errors were encountered: