-
-
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
legend outside the plot area (return legend as pict?) #49
Comments
These are some notes for adding support to draw the plot legend outside the plot area. Doing this is surprisingly difficult, as the notes below show. Define new legend anchor typesThe location of the plot legend is controlled by the
We need to add NOTE unfortunately, this type is also used as an anchor to the labels on the plot and the new types would be invalid values for use as plot labels. Also the anchor type already contains Separate the legend size calculation from the drawing
The legend is actually drawn in We need at least a function which calculates the Also this function will need to be updated to recognize the new legend anchors and adjust the position of the legend accordingly. Make room for the legend when it is outsideWhen the legend is outside the plot, space will need to be reserved for it. This is done here (there is an equivalent place for 3D plots):
The
The We will need to construct such an entry for the legend, if the legend is to be rendered outside the plot area. Unfortunately, at this stage, we don't know about the legend yet! Note that the For example: for a Inform
|
(define (plot-area area renderer-list) |
The plot-area
function already receives a 2d-plot-area%
object will all the layout calculated, so it is already too late to inform it about the legend. The 2d-plot-area%
object is created in several places, and the legend will need to be passed here, so it can be used for size calculations:
(define (plot/dc renderer-tree dc x y width height |
plot/plot-gui-lib/plot/private/gui/plot2d.rkt
Line 116 in 18d8eca
(make-object 2d-plot-area% |
plot/plot-gui-lib/plot/private/gui/snip2d.rkt
Line 258 in 58b5d7e
(make-object 2d-plot-area% |
Same changes for 3D plots
While the drawing of the plot legend is handled in common, there is a different, 3d-plot-area%
object and it will need to be updated in the same way as the 2d-plot-area%
object.
In order to get to the legend entries early, the
personally I prefer option 3 since that makes it clear that two separate functionalities need to be provided. If we go with 2 we need to make sure that new render functions don't forget to send the label for the empty bounds. |
TODO list
|
The various plot renderer procedures for 2D and 3D plots used to render their data than return a legend entry to be used for constructing the legend. This means that the plot library can only know about the list of legend entries after the data is drawn on the plot. The `renderer2d` and `renderer3d` structures have been updated to add a slot for the legend entry and all renders have been updated so the legend entry is available without rendering the actual data. This was done so that legend entries can be drawn outside of the plot area, see #49 for all the commits related to that functionality.
The code which draws the plot legend used to calculate the legend dimensions and draw the legend in a single method of the `plot-device%` class. This has been separated in two: a method to calculate the legend dimensions and one to actually draw the legend. This is done in order to be able to place the plot legend outside the plot area, as part of #49
Thinks to do after completing this task:
|
In order to be able to calculate the space for legend entries when the legend is outside the plot area, the plot area object (for 2D and 3D plots) needs to have a access to the legend entries. This commit also introduces a new tyle `legend-anchor/c` and `LegendAnchor` for the legend anchor values. Anchoring the legend outside the plot is possible, but that functionality is not yet complete.
Hi @bdeket, I had a brief look at one of the images from the plot tests and didn't look at the code changes yet, but I would like to make sure we both have the same understanding of where to place the legend outside the plot area. Basically, the test image pr70-2.png is not what I had in mind for the "outside bottom right" location. The way I view it, there are 12 reasonable location for placing this legend outside the plot area (see image below). Originally, I thought to only provide configuration via AlignmentThe main difference is that I think the legends should be aligned with the plot area even when they are outside. For example, for position A, the top of the legend is aligned with the top of the plot area (and not with the top of the draw area) and position G is aligned with the bottom of the plot area. NamingThe other question is what to name these locations, because Overflow handlingFor the inside of the plot, when there are more legend entries than would fit in the plot area, they are clipped -- we want to make sure that the same things happen when the legend is outside. For example, when calculating the required space for the legend in positions A, B, C, G, H, I, only the width should be considered, not the height and I am not sure about the top and bottom locations. |
Hi @alex-hhh,
Also, I think this only applies to 2D, no? |
I updated the title of the issue to reflect the changes that were done. The original requests on the racket-users group were for placing the legend outside the plot area, and this is what was implemented. The "return legend as a pict" was only a possible solution for that problem, and one which did not take interactive plot snips into account. While returning the legend as a pict is possible (see #73), I am not convinced that it would be a useful functionality, and will only consider it if someone provides a reasonable use case for it. |
If I'm putting similar plots on the same page, I like to have one legend off to the side. With a pict, I get a default legend that can be put anywhere. p7 here has a hand-made solution |
I don't see how returning the legend as a pict would have helped you since the legend produced by the plot package is not in the format you used for the plots in the linked paper. Yes, there are valid reasons to have the legend separate from the actual plot, but such a legend can already be created with the pict package as you have demonstrated in that paper and I have also shown in the linked google groups post. The pict package offers additional flexibility as well. On a technical note, there are some interface problems with #73, which would make such a function difficult to use in most of the scenarios where it would actually be needed:
Perhaps when we implement multiple "linked" plots as part of #7, we might be able to provide a legend which is consistent across several plots, and provide an interface which produces several plots which line up plus a legend. Until than, users can create their own legends using the pict package, if they need the legend separate from the actual plot. |
The 2d-plot-area% for the overlays is only created if there are any overlays present and no unit tests were exercising that code path, so a unit test was also added to ensure that this plot area is not forgotten about.
Add test cases for all possible cases for outside legend placement for both 2D and 3D plots.
Currently, plot draws legends on the plot area.
It would be nice if plotting functions could return the plot and legend as two picts that could be combined using a pict combiner or progressive pict.
(edit) see also:
The text was updated successfully, but these errors were encountered: