bugGNU Octave - Bugs: bug #48427, legend objects in gnuplot

 
 

bug #48427: legend objects in gnuplot

Submitter:  Rik <rik5>
Submitted:  Wed 06 Jul 2016 10:46:26 PM UTC
   
 
Category:  Plotting with gnuplot Severity:  3 - Normal
Priority:  5 - Normal Item Group:  Regression
Status:  None Assigned to:  None
Originator Name:  Open/Closed:  * Open
Release:  * dev Operating System:  * Any
Fixed Release:  None Planned Release:  None
* Mandatory Fields

Add a New Comment Rich Markup
   

Jump to the original submission

Tue 12 Jul 2016 01:00:25 AM UTC, comment #14: 

If the legend position were specifically placed, then it might be possible to place a rectangle behind it of some arbitrary color.  Can't do such a thing though when the position/size are automatically chosen by gnuplot.

Dan Sebald <sebald>
Tue 12 Jul 2016 12:52:00 AM UTC, comment #13: 

I started trying to make the legend layout better match what Qt is doing.  gnuplot currently isn't the friendliest as to key layout.  Sizes are often specified as "characters", which of course changes with the font size.

But to my way of thinking, if the axes were set according to the gca's position, and the key position were set according to its position, then it should be a pretty close match.  gnuplot would just use whatever space is left for a sample.  I think the user could at least tweak things from there even though it might not match qt toolkit's layout.

I started down that path and it began to feel all too familiar.  This routine _actual_axis_position_.m is giving slightly unexpected results.  Then I searched my email and found it is this bug report from a while back

https://savannah.gnu.org/bugs/?47974#comment21
https://savannah.gnu.org/bugs/?47974#comment23
https://savannah.gnu.org/bugs/?47974#comment27
https://savannah.gnu.org/bugs/?47974#comment52
https://savannah.gnu.org/bugs/?47974#comment55

It would be best to work out what that _actual_axis_position_() should be doing before trying to make the axes/legend layout correct.

Dan Sebald <sebald>
Sat 09 Jul 2016 04:24:16 PM UTC, comment #12: 


> I indended 'case "patch"' by an extra space
> (http://hg.savannah.gnu.org/hgweb/octave/rev/43646269998d).


OK, thanks.


> The color of the pyramid changes dramatically after calling legend which I
> don't think was intended. This is with gnuplot 5.0.1 which I think is a
> pretty buggy version, but still. I'd rather leave that alone.


I lean more toward just placing the patch in the legend because in some instances the user could specify a color triad and get something close to what they want.  This is useful for images, for fairly smooth surfaces, etc.

The result you are seeing is not a bug, but a limitation of gnuplot, one that I've wanted to address for a decade or more. It's that gnuplot does not have a true hidden surface algorithm. It has a hidden line algorithm, but that is slightly more straightforward.  However, it really isn't the nature of the problem that is difficult; it is all of the underlying book-keeping that goes with breaking up potentially intersecting finite elements into sub-pieces, discarding this piece, reordering that piece, etc.

Instead, many years ago someone implemented what is known as the painter's algorithm in which one takes, say, the average depth value of the element and then does a simple sort on that list, drawing the elements in succession. It is quite common for surfaces to overlap incorrectly with the painters algorithm, especial with intersecting surfaces. If one makes the number of pieces small enough, generally this overlap is not noticeable. But in the case of this pyramid, there are only four elements, so any sort order or overlap flaw becomes very noticeable. As with any limited solution, designers become content that it is good enough, so the idea of writing a correct solution becomes a lower priority and less willingness to modify.

What makes the pyramid tricky is that the four triangles all share that common point, so depending upon the type of depth sort, the order can get mixed up on rotation. Introducing the legend probably adds another piece to the sort list and that might cause some elements to be rearrange. But, even without the legend, I think just rotating the surface reveals the same issue. Anyway, as soon as I saw this pyramid demo months or years ago, I knew there would be a problem.  If I can find some other way of fixing this with some type of gnuplot configuration, I'll create a separate patch.


> I changed create_spacingspec to return an empty string and it seems to work
> fine for
>
> demo legend
>
> But maybe you can check that more closely.


I tried this too and it works. However, I'm going to try something slightly more extensive because changing that font size also changes the size of the sample, i.e., gnuplot's automatic layout mode.  I don't think that is the way Octave intends to work--changing the font size doesn't change the sample size.  Let me try to make that whole legend layout a little more non-automatic.  I sent a post to the gnuplot maintainers list about some inconsistencies in scaling/units, so I'm waiting on that.

Dan Sebald <sebald>
Sat 09 Jul 2016 01:30:41 PM UTC, comment #11: 

I indended 'case "patch"' by an extra space (http://hg.savannah.gnu.org/hgweb/octave/rev/43646269998d).

Maybe legends for surface and patch objects aren't worth the time.  I tried your patch along with


demo("patch", 7)
legend("pyramid power")


The color of the pyramid changes dramatically after calling legend which I don't think was intended.  This is with gnuplot 5.0.1 which I think is a pretty buggy version, but still.  I'd rather leave that alone.

I changed create_spacingspec to return an empty string and it seems to work fine for


demo legend


But maybe you can check that more closely.


Rik <rik5>
Group administrator
Fri 08 Jul 2016 07:49:00 PM UTC, comment #10: 

BTW, I've noticed for some time that the "patch" case of _gnuplot_draw_axes_.m is one character short of alignment with the rest of the cases.  I've always wanted to change that when I modify something in that case condition, but it would be a few structural changes amidst a big blob of cosmetic changes.  Perhaps you are the one to make just a simple indentation since you've done a lot of that elsewhere in the code.

Dan Sebald <sebald>
Fri 08 Jul 2016 07:30:50 PM UTC, comment #9: 

Attached is a very limited method for generating what looks like a key sample for surfaces and patches.  It creates a phantom line having the desired color of the surface/patch key sample and makes the linewidth 11, roughly matching gnuplot key rectangular patch sample.

The color is a poor approximation to what is desired, but it is the best that can be done with the current state of gnuplot.  gnuplot can do limited interpolation, but not for key samples.  As for the interpolated color in the pyramid example, I'd rather spend such time on gnuplot creating a true hidden surface algorithm so that the pyramid comes out correct.  Anyway...

Try the following commands:


demo("legend", 18)
demo("patch", 7)
legend("pyramid power")



(file #37777)

Dan Sebald <sebald>
Thu 07 Jul 2016 04:09:05 PM UTC, comment #8: 

@Dan: legend.m sets the properties of the patch object for the legend based on the surface.  Here is the code:


            case "surface"
              facecolor = get (hplt, "facecolor");
              edgecolor = get (hplt, "edgecolor");
              cdata = sum (get (ca(1), "clim")) / 2;
              if (! strcmp (facecolor, "none") || ! strcmp (edgecolor, "none"))
                p1 = patch ("xdata", ([0, linelength, linelength, 0] +
                                      xoffset + xk * xstep) / lpos(3),
                            "ydata", (lpos(4) - yoffset -
                                      [yk-0.3, yk-0.3, yk+0.3, yk+0.3] .* ystep) / lpos(4),
                            "facecolor", facecolor, "edgecolor", edgecolor,
                            "cdata", cdata, "userdata", hplt);
                hobjects(end+1) = p1;
              endif


When facecolor is "flat", rather than an RGB specification, then the color comes from the cdata property.

Trivial example:


hp = patch;  # triangle patch, colored black
get (hp, 'facecolor')
ans =

   0   0   0
set (hp, 'cdata', [0 1 0]);  # set cdata to green, patch is still black
set (hp, 'facecolor', 'flat');  # now patch becomes green.


So, I think you just need to copy over the properties "facecolor", "edgecolor", and "cdata".



Rik <rik5>
Group administrator
Thu 07 Jul 2016 08:14:32 AM UTC, comment #7: 

OK, I see the problems you mention and maybe one or two more.  Let me address these one at a time.  First, I tried to add the patch to the key for the surface demo.  Conceptually, I have it working (by placing a bogus entry into the plot list that has the proper color and title) but I don't know where the color to use for the patch is coming from.  It might be that the opengl toolkits are choosing some color at random.

Well, given the surface handle, we can search through the legend group for a match in the "userdata".  For each entry there is a "text" type and a "patch"/"line" type.  I'm expecting that patch or line to have the proper color that should appear in the legend.  But it doesn't have a proper color for a surface.  Let's compare:


>> demo ('area', 1);
area example 1:
 ## Verify identity sin^2 + cos^2 = 1
 clf;
 t = linspace (0, 2*pi, 100)';
 y = [sin(t).^2, cos(t).^2];
 area (t, y);
 axis tight
 legend ('sin^2', 'cos^2', 'location', 'NorthEastOutside');
 title ('area() plot');

>> kids = get(gcf, 'children');
>> grandkids = get(kids(1), 'children');
>> get(grandkids(1),"type")
ans = patch
>> get(grandkids(1),"facecolor")
ans =

   0.00000   0.50000   0.00000

>> demo("legend", 18);
legend example 18:
 clf;
 colormap (cool (64));
 surf (peaks ());
 legend ('peaks()');
 title ('legend() works for surface objects too');

>> kids = get(gcf, 'children');
>> grandkids = get(kids(1), 'children');
>> get(grandkids(1),"facecolor")
ans = flat
>>


What is shown in the above is that for the area demo there is a patch of dark green to go along with presumably the dark green patch in the plot.  That good.  But for the legend demo "peaks" the color that is given is "flat".  Is that a valid color?  The "facelighting" property is also "flat" and that makes sense.  So, where is the color coming from in the 'qt' terminal?  Is it just picking the first entry in the palette?  The entry associated with zero?

In any case, it seems to me that the legend entry should have a valid color that the user can see and set.

Now, if I continue with that peaks example and set the color of that legend entry manually, it works:


set(grandkids(1),'facecolor','red')


No surprise, I guess.  It's just that Octave should fill in that proper initial color, I think.

Dan Sebald <sebald>
Thu 07 Jul 2016 02:23:21 AM UTC, comment #6: 

Okay, that was easy.  I pushed your cset here (http://hg.savannah.gnu.org/hgweb/octave/rev/21f3cbd5c708).

Running 'demo legend' I notice two instances that look off.

First, there is no color patch associated with a surface object, although the text appears next to a blank space.


surf (peaks ())
legend ("abc")


Second, the spacing between legend text objects when the fontsize is changed is incorrect.


demo legend 1


That is controlled by the create_spacingspec() function which is only used when creating the legend.  Maybe it is no longer needed?  There is a note in the function about why it was created.

Finally, the legend object in OpenGL has a background color that can be changed with the 'Color' property.  In gnuplot, it appears that the 'Color' is set to "none" because it is transparent.  I don't know if that can be fixed


Rik <rik5>
Group administrator
Thu 07 Jul 2016 02:15:15 AM UTC, comment #5: 

I see you are removing all strcmpi() from _gnuplot_draw_axes_.m.  The patch I attached has strcmpi in it.  Here's an update.


(file #37745)

Dan Sebald <sebald>
Thu 07 Jul 2016 01:54:35 AM UTC, comment #4: 

The attached seems to work for a couple types of plots (this with and those without hggroups).  Note that the key titles also seem to appear within the 'hlgnd' variable passed into the routine, i.e., hlgnd.string, but because of the way that kids is accessed from the end and reduced makes it kind of clumsy to know an index into hlgnd.string--could do the same kind of pruning of hlgnd.string, but the placing of hggroup kids onto the kids list makes such an approach clumsy.

(file #37744)

Dan Sebald <sebald>
Thu 07 Jul 2016 12:30:36 AM UTC, comment #3: 

Okay, I know the problem but not the solution.  In old versions of Octave, the DisplayName property which holds the legend key was pushed down to the first object in an hggroup.  Now Octave correctly follows Matlab and the DisplayName property is set on the hggroup itself.

Rik <rik5>
Group administrator
Thu 07 Jul 2016 12:24:23 AM UTC, comment #2: 

Thanks for looking at this.  The missing space is a simple fix.  See the attached diff.

How is one supposed to add "title" to the plot invocation?  The data is available in the hlgnd.strings variable.

(file #37743)

Rik <rik5>
Group administrator
Wed 06 Jul 2016 11:24:48 PM UTC, comment #1: 

Looking at the drawnow() output there is a key:


set key box reverse Left vertical spacing 1.25font ",10" textcolor rgb "#000000" enhanced;


(Should have space between '1.25' and 'font', but it doesn't make a difference.)

However there are no title specs in the plots:


plot "-" binary format='%float64' record=201 using ($1):($2) title "" with filledcurve lc rgb "#0000ff" fillstyle transparent solid 1.000000 \


for the key entries.  They were probably lost somewhere along the way, and now the key is treated as paper thin (no entries) so comes out as a horizontal line (i.e., box with no height).

Dan Sebald <sebald>
Wed 06 Jul 2016 10:46:26 PM UTC, original submission:  

The legend object for hggroup objects used to work.  Now it displays just a thin black line.

Sample code to reproduce:


graphics_toolkit gnuplot
demo ("area", 1)



Rik <rik5>
Group administrator

 

(Note: upload size limit is set to 16384 kB, after insertion of the required escape characters.)

Attach Files:
   
   
Comment:
   

 

Depends on the following items: None found

Items that depend on this one: None found

 

Carbon-Copy List
  • -email is unavailable- added by sebald (Posted a comment)
  • -email is unavailable- added by rik5 (Submitted the item)
  • -email is unavailable- added by rik5
  •  

    There are 0 votes so far. Votes easily highlight which items people would like to see resolved in priority, independently of the priority of the item set by tracker managers.

    Only group members can vote.

     

    Follow 6 latest changes.

    Date Changed by Updated Field Previous Value => Replaced by
    2016-07-08 sebald Attached File- Added octave-gnuplot_legend_phantom_line_bug48427-djs2016jul08.patch, #37777
    2016-07-07 rik5 Summarylegend no longer correct for hggroup objects with gnuplot legend objects in gnuplot
    2016-07-07 sebald Attached File- Added octave-gnuplot_displayname_bug48427-djs2016jul07.patch, #37745
    2016-07-07 sebald Attached File- Added octave-gnuplot_displayname_bug48427-djs2016jul06.patch, #37744
    2016-07-07 rik5 Attached File- Added fontspc.diff, #37743
    2016-07-06 rik5 Carbon-Copy- Added sebald

    Back to the top

    Powered by Savane 3.13-f8d8.
    Corresponding source code