-
Notifications
You must be signed in to change notification settings - Fork 216
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
[WIP] [Feature] Plotly extension #693
base: develop
Are you sure you want to change the base?
Conversation
- Currently only 3D points are supported
- Linestring - Segment - Multipoint - Multilinestring
Do I understand correctly that Plotly is only able to draw plots, so it is not for drawing geometries and what this PR does is allowing to represent Boost.Geometry linear geometry as a scattered line plot? If that's the case I don't understand how this is useful. A linestring, a geometry, is not a plot line. Plus AFAIU it is not possible to draw other geometries. What is the purpose of using Plotly with Boost.Geometry? |
I started brainstorming use of plotly (or others) for general shapes drawing, see https://gitter.im/boostorg/geometry?at=5e6d0b8e17d3e742347c5346 Since plotly can draw geometric shapes, https://plotly.com/python/shapes/, as well as can draw on top of popular maps, https://plotly.com/python/maps/, evaluating its API for general purpose visualisation of geometries seems to me like a valid idea. |
The main purpose of using plotly is for its mesh plot and it's UI. We can represent every geometry as a plot except that polygons won't be filled in the 2D plot. But plotly is great for showing 3D plots and mesh plots too. And if someone really wants the polygon to be filled, (which can only be done in 2D) they can use the existing svg_mapper. This plugin adds the functionality of displaying 3D geometries which is unavailable in svg mapper. |
Thanks I needed this. The chart-studio of plotly creates area charts with the the x and y-axis as borders. So I thought it isn't possible to fill polygons. Maybe there is some other way. I will look into that. Thanks a lot. |
@mloskot Right, I'm not familiar with Plotly, thanks. So it is possible to represent geometries and (I saw gitter discussion) @sudo-panda needs to display 3D geometries.
Do I understand correctly that Plotly use their own data format based on Json? Or did they adapt some well known format for representing geometrical data? Why not use widely known solution for that (at least according to my limited knowledge of the subject), i.e. GeoJSON? Aside from displaying on maps it would allow to import geometries in various databases and GIS programs? I have nothing against adding Plotly IO. I'm just confused why this particular format was chosen. I also don't know how widely used it is. If it is well known and popular it could be added it in the official release instead of extensions. |
|
||
class json_plotter : boost::noncopyable | ||
{ | ||
std::ostream& m_stream; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, so the stream has to live outside this class. It is like in svg_mapper
so I understand that you replicated the existing design. This is error-prone since when the object outside is destroyed then this is a dangling reference.
So I'm wondering about a different design, i.e. owning the stream instead of the reference. E.g.:
template <typename Stream>
class plotly_plotter
{
public:
template <typename ...Ts>
plotly_stream(Ts &&... params)
: m_stream(std::forward<Ts>(params)...)
{}
private:
Stream m_stream;
};
What do you think? Do you have different ideas?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah that seems better. I was thinking why the above design was implemented in svg_mapper
. The only reason I could find is if some external changes are required by the user that isn't supported by svg_mapper
. This isn't required by plotly_plotter
at all then. Can you tell me that actual reason for this design?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you tell me that actual reason for this design?
I don't really know I have only a few ideas though. @barendgehrels do you remember why exactly does the svg_mapper
store the reference to the stream instead of owning it?
Back then perfect forwarding was impossible. The code in my previous comment requires C++11 but Boost.Geometry right now requires C++03 (this will change soon). And various streams can have various interfaces, e.g. no open()
member function so there must be a way of passing parameters into its constructor.
In some cases the stream objects are already created, e.g. std::cout
, std::cerr
, etc. AFAIU it is possible to account for that by creating a std::ostream
from another stream's streambuf
:
plotly_plotter<std::ostream> plotter(std::cout.rdbuf());
But this would be more confusing than simply calling:
plotly_plotter plotter(std::cout);
With non-owning relationship the same stream can be shared by several mappers/plotters. I don't know if that makes sense but it is possible nevertheless.
The user can keep and e.g. close and reopen ofstream
buffer instead of creating the svg_mapper
/plotly_plotter
object each time.
The only reason I could find is if some external changes
Right, though the owned stream could be exposed with some getter function if needed.
Btw, I'm not saying that you should start implementing what I have proposed above. I'm only brainstorming. E.g. now after listing the potential reasons above I'm not sure whether or not my proposal was good.
On the other hand maybe passing a reference as a template parameter could work with the design I proposed. So the user would be able to do both things, store a stream object or a reference. Unless there are some issues I'm not taking into account.
plotly_plotter<std::ostream &> plotter(std::cout);
And last but not least I'm not sure if the design should be different than svg_mapper
because the users may expect that the tools work the same and either expect that a reference is stored in plotly_plotter
or that an object is stored in svg_mapper
. We should probably be consistent one way or another.
@mloskot do you have some thoughts about it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For now I have put it inside the class itself as I think it's better to make it safe than just copy the existing design as:
- It is an extension so the design need not be matched with integral parts of Boost Geometry.
- I see no possible requirement for keeping it outside other than the one mentioned above as we are going to shift to C++11 soon.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Although I can't remember exactly, I think @awulkiew has figured it out right.
It was to allow user to plug in a stream object of their choice, and with simple interface.
I did not suggest plotly as replacement for GeoJSON which on its own is a preferred geo format indeed. I considered plotly more as an alternative to SVG, for nice rendering of geometries, with axis, with scaling possibility, loadable into plotly-aware viewers, etc. I don't know if plotly does support GeoJSON well. By the way, there is also MapML, e.g. GDAL/OGR has just received support for it OSGeo/gdal#2374 I just thought exploring new ways to visualise geometries may be of interest to those looking for ways to start digging Boost.Geometry, who are keen in visualisations, I/O formats, etc. |
I have currently added support for 3D points. Support for others will be added soon.
This extension just outputs json. If you want to view it you will require to wrap it in html.