Menu

#815 new plotting style 'marks', 'linesmarks' and new object 'mark'

Version 5
open
nobody
None
5
2024-05-25
2024-04-15
No

This patch introduces new 2D plotting styles 'marks', 'linesmarks' and 'mark' object.

For more information, see the attached documentation about the patch.
The sample programs for the figures in the documentaion are also attached as the tar+gzipped archive file.

4 Attachments

Discussion

1 2 > >> (Page 1 of 2)
  • Ethan Merritt

    Ethan Merritt - 2024-04-19

    First-pass review of gnuplotmarks patch

    I have only glanced at the code, so these comments are based mostly on
    reading the pdf description and trying it out. Any or all of these
    points may be worth discussion; perhaps we should start a thread on
    the gnuplot-beta mailing list? It's not very active these days but
    still I think people are more likely to see it there than will see it
    here on the patch tracker.

    • I think the general goal and approach is worth doing.

    • An unmentioned difference between "with polygons" and "with marks"
      is that polygon rendering uses the pm3d code path; the mark code is
      purely 2D. This may not be obvious to the user, but may end up
      making a difference in applying colors, fill style, borders, etc.

    • I like that it is terminal-independent. This means it can
      replace the recent commit series 6bc3c0eb..edcd8dbb that added
      a small number of terminal-dependent special point types.
      The functional equivalence is shown by Figure 3.

    • The "mode" parameter is not a good idea, given that gnuplot uses
      fillstyle everywhere else to control the fill and border propertie.
      "mode" is both confusing and less capable than allowing a fillstyle
      to be attached to a mark object or to a plot "with marks".
      I do realize that there are several wrinkles here. A mark that
      consists of a polyline does not necessarily have either a "fill area"
      or a "border", so some adjustment to the terminology may be needed.
      If this ends up requiring an addition or revision to fillstyle syntax,
      that's still acceptatble.

    • The large chunk of code in set.c is more like a plot mode
      (calling df_open, reading data, etc) than a typical "set" command.
      Because it calls df_open and df_readline, it needs to be protected
      against recursive or conflicting use of function blocks
      (see commit 44d9343f, Bug #2702). I would prefer putting this code
      elsewhere, maybe in a new source file.

    • I don't know whether it's a bug or my misunderstanding, but I can't
      get the variable pointsize scaling to work for "plot with marks".

      # example
      $triangle << EOD
      0 0.5
      0.433 -0.25
     -0.433 -0.25
      0 0.5
      EOD
    
      set mark 2 $triangle
      # OK
      plot 'silver.dat' using 1:2 with marks mt 2
    
     # OK but size is not a close match to "with points pt 9 ps 3"
      plot 'silver.dat' using 1:2 with marks mt 2 ps 3
    
    # Command not accepted
      plot 'silver.dat' using 1:2:(4.0) with marks mt 2 ps variable
    
    # Does not work
      plot 'silver.dat' using 1:2:(4.0) with marks mt 2 units ps
    
    • "show mark" command

      gnuplot> show mark 2
      0 0.5 3 -1
      0.433 -0.25 3 -1
      -0.433 -0.25 3 -1
      0 0.5 3 -1

    I think "3" means fill+border? Please switch to using a fillstyle.
    What is the "-1"?
    Would it be feasible to report instead "mark 2 $triangle"?

    • "set mark 3 $triangle fillcolor 'blue'"
      This command is accepted but so far as I can see the color has no effect.
      Is there a way to set a fixed, or at least a default, color for the mark?

    • plot with linesmarks
      I realize that this was already an issue for "plot with linespoints",
      but the current program design isn't flexible enough to permit
      specifying both a complete set of line properties and a complete set
      of point (or in this case mark) properties in a single plot component.
      Is it really so bad to require "plot <foo> with lines, '' with marks"
      rather than providing a separate plot style that combines the two parts?</foo>

     
    • Hiroki Motoyoshi

      I have just posted an announcement of the creation of this ticket to gnuplot-beta.

      plot with linesmarks
      I realize that this was already an issue for "plot with linespoints",
      but the current program design isn't flexible enough to permit
      specifying both a complete set of line properties and a complete set
      of point (or in this case mark) properties in a single plot component.
      Is it really so bad to require "plot <foo> with lines, '' with marks"
      rather than providing a separate plot style that combines the two parts?</foo>

      The style 'marks' was initially thought of as objects similar to 'circles', 'ellipses', 'boxxy', or 'vectors'. Later, I added the 'units ps' keyword and the 'linesmarks' style, thinking they might have value as an alternative to the 'points' style. However, I don't have many feelings about 'linesmarks', so until the linespoints issue can be resolved, it is fine to remove 'linesmarks' from this implementation.

      Incidentally, one difference between 'linesmarks' and 'lines' + 'marks' is the presence of the keywords 'pointinterval' and 'pointnumber'. However, the processing of these options belongs to 'marks', not 'lines'. Removing this process simplifies the code.

       
    • Hiroki Motoyoshi

      • "show mark" command
        I think "3" means fill+border? Please switch to using a fillstyle.

      Yes. As you say, "3" means fill+border, but it is inappropriate as the default value for mode. In the code at hand, the default value of mode has been changed to follow the fillstyle. Also change the mode value as follows.

      mode(0) FILLSTYLE
      mode(1) STROKE ONLY
      mode(2) FILL ONLY
      mode(3) FILL AND STROKE
      

      What is the "-1"?

      "-1" means the fill color using a fillcolor or linecolor setting.

      Would it be feasible to report instead "mark 2 $triangle"?

      It can be done with,

      set print $triangle
      show mark 2 
      unset print
      
       
    • Hiroki Motoyoshi

      • "set mark 3 $triangle fillcolor 'blue'"
        This command is accepted but so far as I can see the color has no effect. Is there a way to set a fixed, or at least a default, color for the mark?

      I would rather not accept such an option, but how can I implement this?

      To give the mark a fixed color, specify fillcolor as an integer in the fourth column of the input data. If you give this column a value of -1 (the default value), it will use the fillcolor or linecolour setting; as with polygons, you can specify a different color for each segment separated by whitespace.

      set mark 2 $triangle using 1:2:(3):(0xff0000)
      

      In the code at hand,

      set mark 2 $triangle using 1:2:(0):(0xff0000)
      

      also works as expected.

       
    • Hiroki Motoyoshi

      The "mode" parameter is not a good idea, given that gnuplot uses
      fillstyle everywhere else to control the fill and border propertie.
      "mode" is both confusing and less capable than allowing a fillstyle
      to be attached to a mark object or to a plot "with marks".
      I do realize that there are several wrinkles here. A mark that
      consists of a polyline does not necessarily have either a "fill area"
      or a "border", so some adjustment to the terminology may be needed.
      If this ends up requiring an addition or revision to fillstyle syntax,
      that's still acceptatble.

      This 'mode' parameter gives more freedom in the definition of marks; it is a feature for those who want to make deeper use of marks, and should be left in place.

      In the code at hand, the value of mode has been changed as follows

      mode(0) FILLSTYLE
      mode(1) STROKE ONLY
      mode(2) FILL ONLY
      mode(3) FILL AND STROKE
      

      The default value has also been changed to mode=0 instead of mode=3.

      Users who do not want to actively use mode can use fillstyle by default. This means that mode can be omitted in the input sequence to set mark, so it is sufficient to give only the (x,y) coordinates when defining the mark.

      In the current implementation, a mark contains polylines and polygon's borders, both of which are considered as 'stroke' and have the same color and thickness.

      The introduction of 'mode' is also necessary to facilitate the realisation of Fig. 3 in marks.

       
    • Hiroki Motoyoshi

      I like that it is terminal-independent. This means it can
      replace the recent commit series 6bc3c0eb..edcd8dbb that added
      a small number of terminal-dependent special point types.
      The functional equivalence is shown by Figure 3.

      As noted in the patch documentation, there is a notice regarding this.

      In gnuplot, drawing to terminals is done using scaled integer coordinates per terminal. If the scaling is not sufficient for bitmap terminals or even vector terminals in some cases, the mark shape may be distorted due to quantization errors. This distortion is especially noticeable when the mark is smaller.

      On the other hand, the 'points' style draws the shape in a way that is optimized for the terminal, resulting in a clean shape with little distortion. For example, a circle mark is drawn as a polygon in the 'marks' style, but in the 'points' style, it is drawn using the terminal's native 'circle function'.

      In addition, for the 'wxt' and 'pngcairo' terminals, hinting is performed internally, which may distort the shape. You can see the effect by trying different hinting settings on the wxt terminal.

      Apart from the above notices, the advantage is that the same shape can be used for any terminal.

      I don't know whether it's a bug or my misunderstanding, but I can't
      get the variable pointsize scaling to work for "plot with marks".

      As your example shows, 'pointsize' and scaling (by the 3rd and 4th column) conflict in the current implementation. I'm not sure which one to use if 'pointsize' and scaling are specified at the same time. The 'pointsize' option was introduced to make the 'marks' style similar to the 'points' style, but one option is to eliminate the 'pointsize' option and keep only scaling to reduce user confusion.

      OK but size is not a close match to "with points pt 9 ps 3"

      Even the 'points' style has different point sizes for each terminal, so there is no guarantee that the marks drawn in the 'marks' style will match the size of the 'points' style.

       
  • Hiroki Motoyoshi

    Attached '001_change_mode_default.patch' is a patch file againt 'gnuplot_marks.patch'
    This patch changes the drawing style for mode=0 to follow the fillstyle setting.

    Edited

    It seems the patch did not successfully attach.

    Sorry. I attached file.

     

    Last edit: Hiroki Motoyoshi 2024-04-22
  • Ethan Merritt

    Ethan Merritt - 2024-04-22

    It seems the patch did not successfully attach.

     
  • Ethan Merritt

    Ethan Merritt - 2024-04-22

    variable mark size in a plot

    I don't know whether it's a bug or my misunderstanding, but I can't
    get the variable pointsize scaling to work for "plot with marks".

    As your example shows, 'pointsize' and scaling (by the 3rd and 4th column) conflict in the current implementation. I'm not sure which one to use if 'pointsize' and scaling are specified at the same time.

    I am still confused about this. My understanding, perhaps wrong, was that set mark does not specify what the coordinate units are, so this must be added later by the units keyword in a plot or set object command. So if I want the mark to be interpreted in terms of point size units in a plot command I say plot using 1:2 with marks units ps to use a scale factor of one, and plot using 1:2:(3) with marks [units ps] to make the marks 3x larger. The units ps may be optional because this is the default? But either way it doesn't work. The marks do not scale either with or without an explicit units keyword. How do I tell it to take the scale factor from the third column? Normally this would be ps variable but it doesn't accept that.

    'mode' vs 'fillstyle'

    I think you may have misunderstood the point I tried to make earlier about using the existing 'fillstyle' property rather than introducing a new 'mode' property. I did not mean to use the global fillstyle instead of a per-mark property. I meant that if you are going to store an extra property for each mark, why limit this to two flags (bits 0 and 1 in 'mode')? Why not store a full set of fillstyle properties? That would give consistent syntax with other object types and plot styles. Example:

      set mark 2 $triangle fillstyle transparent solid 0.50 border lc "black"
      show mark 2
      0       0.5     804     0x000000
      0.433   -0.25   804     0x000000
     -0.433  -0.25    804     0x000000
      0       0.5     804     0x000000
    

    Here 804 is the result of feeding fillstyle 'transparent solid 0.5' through term.c:style_from_fill().

    However the color is problematic. I show 0x000000 ss the RGB representation of lc "black" but is this to be the border color or the fill color? That same ambiguity is present everywhere a fillstyle occurs and is an on-going headache I don't have a good cure for.

    Does that make more sense now? I'm still exploring your new code so this is only a first thought, not a final opinion.

     
    • Hiroki Motoyoshi

      variable mark size in a plot

      My understanding, perhaps wrong, was that set mark does not specify what the coordinate units are, so this must be added later by the units keyword in a plot or set object command.

      Your description is correct! And "units ps" is the default in the current implementation. In addition, pointsize defaults to 1.0.

      So if I want the mark to be interpreted in terms of point size units in a plot command I say plot using 1:2 with marks units ps to use a scale factor of one, and plot using 1:2:(3) with marks [units ps] to make the marks 3x larger. The units ps may be optional because this is the default? But either way it doesn't work. The marks do not scale either with or without an explicit units keyword. How do I tell it to take the scale factor from the third column?

      The current implementation does not do that and only refers to pointsize to determine the size. However, this does not allow us to change the aspect ratio, so as you said, in the next patch, I have modified it so that the size is determined by multiplying pointsize and xscale(yscale).

      Normally this would be ps variable but it doesn't accept that.

      The current implementation did not handle the 'ps variable' option.
      They are fixed to accept the 'ps variable' option in the next patch.

      mode vs fillstyle

      Thank you for the detailed explanation. It finally makes sense to me.

      I had not considered such an idea at all because fill and stroke were sufficient for my use cases. If this is realized, something like 'fillstyle variable' might be feasible. However, I hope to keep the data given to 'set mark' command as simple as possible. We must carefully consider whether this feature is necessary and what to do with fillstyle codes that seem like a cipher to ordinary users. I rather think it would be useful to add the ability to specify line thickness (whether it can be implemented or not).

      Anyway, one idea I have is to add an additional column to the set mark input data, as follows.

      x y 
      x y mode 
      x y mode color 
      x y mode color fillstyle
      

      The meaning of 'mode' is the same as before. The above addition of a column would be a good compromise between the simplicity of manually preparing mark data and the high functionality of setting a full-spec fillstyle. 

      Adding the following option you tried as a feature to support setting fillstyle would be helpful (it is not easy for me to implement).

      set mark 1 $element1
      set mark 1 append $element2 fillstyle transparent solid 0.5 fc "black"
      set mark 1 append $element3 fillstyle solid 1 noborder fc "blue"
      

      In these settings, the 'fillstyle' option of 'set mark' will overwrite the value of column 5 (or default value) of $element2 or $element3. The remaining question is how to generate the 'fillstyle' raw code such as '804' when creating the data manually.

       
  • Hiroki Motoyoshi

    Attached '002_ps_variable.patch' is a patch file againt 'gnuplot_marks.patch' + '001'.
    This patch add the 'ps variable' handling.

     
  • Ethan Merritt

    Ethan Merritt - 2024-04-25

    After playing a bit using "plot with marks" I have a suggestion. I think that the pointsize property should behave for marks as much as possible exactly as it does for "plot with points".

    1. Add the PLOT_STYLE_HAS_POINT property to the MARKS plot style so that the pointsize keyword is parsed and interpreted using the lp_parse routine shared by other plot styles.
    2. If a pointsize is provided in the plot command it is used as a multiplier for whatever size the mark would otherwise have been drawn. Thus it acts on marks using "units xx" etc just as it would for "units ps".
    3. pointsize variable consumes an input column, and again it acts as a multiplier for the marks regardless of what units are used to define them.
    4. I think the size field of the marks_options structure is no longer needed (but I didn't remove it).
    5. See simple examples in the comments header for the patch set.

    I attach a small patchset that I used to test out these ideas. I was looking only at plot commands, not "set object mark", so it is quite possible I unintentionally broke something there.

    I also got some funny results from a test case using a function-defined mark mark type, but I'm not sure whether that's something I broke, something I misunderstand, or something that was already there and not working. I will investigate further.

     
    • Hiroki Motoyoshi

      Thanks for the patch, I was worried about interference using lp_parse as no other plotting style has both POINT and FILL styles at the same time. As there doesn't seem to be any major problem, I agree to apply your patch.

      The execution of 'Fig11_formulas.gp' failed, but this is due to a restriction on the word order of the options, caused by introducing of 'lp_parse'.

      # NG.
      'with marks mt k ps 1 fs solid 0.0 border lw 1 '
                                                ^
      ## OK
      'with marks mt k ps 1 lw 1 fs solid 0.0 border '
                            ^
      

      Additional modifications have been made in line with this.
      The attached small patch files are after "0001-EAM-Make-ps-N-and-ps-var-act-as-they-do-for-other-pl.patch".

      • 003_use_lp_parse_result_for_pi_pn.patch

      As well as the change to 'pointsize' handling, the values of 'pointinterval' and 'pointnumber' are also changed to use the result of 'lp_parse()'. This patch makes the 'pointinterval' and 'pointnumber' options available also for 'marks' style. This is because this is useful for 'lines + marks' combinations.

      • 004_stop_forcing_units_ps_for_FUNC.patch

      This is a patch to stop forcing 'units ps' when the ps option is specified or when plotting a function.

      • 005_struct_marks_opts_member_reorganized.patch

      This patch changed internal handling of 'marktype variable'. Previously, it was determined by whether 'marks_options.tag' was negative or not. Now, a member 'variable' to distingwish whether the marktype is 'variable' or not has been introduced to the struct 'marks_opt'. In addition, the 'size', 'number' and 'interval' members, which are no longer used in marks_opts, have been removed.

       
  • Ethan Merritt

    Ethan Merritt - 2024-04-26

    I've now had a look through all the code. Here are my comments.

    Code consolidation
    A loop like this appears many times in the code

                for (this = first_mark, prev = NULL;
                     this != NULL;
                     prev = this, this = this->next) {
                    /* is this the mark we want? */
                    if (e->type == this->tag) {
                        mark = this;
                        break;
                    }
                }
    

    These should be replaced by a call to a shared utility routine
    (struct mark_data *) get_mark(int tag)
    I realize the loops are not truly identical, so some care is needed.

    Difference between show and save
    Please follow the current practice used by the rest of the program:
    save_FOO() can write either to a file or to stderr.
    show_FOO() always writes to stderr.
    As an implementation convenience, show_FOO() may be implemented internally
    as save_FOO(stderr).

    Key entries
    I attach a patch that revises the code path for drawing a mark in the plot key so that the code path is more like that for "plot with points". The order of adding key elements is a little tricky because some terminals do not correctly preserve the full graphics state across the call to do_key_sample().

    Fill style
    Another thought about how to make it convenient for the user to give a full fill style when defining a mark. What if rather than requiring four columns
    using (x):(y):(mode):(color)
    this syntax would be accepted
    set mark N $DATA using (x):(y) <fillstyle-specifier> <color-specifier>
    The program can translate the fill and color specifiers into integer values stored in the mark structure but the user does not need to construct those bit codes manually.
    A save_mark(N) routine would have to back-translate the values to reconstruct the input syntax but that should be straightforward.
    Do you think that would work?

    Limitation of set mark
    The implementation of set_mark() worries me a bit. It does open/read/close on the input stream twice; once to count vertices, then a second time to read and store the data.
    This means it cannot be used for piped input, right?
    Is there a reason not to use a single pass and reallocate space for the vertices incrementally?
    I think this should either be documented as an intentional limitation with error messages added to the program where needed, or changed to use a single-pass algorithm.

    Interesting trick for compact definition of mark vertices
    This form already works (explicit columns)

    array Diamond = [ {0,0.5}, {0.5,0}, {0,-0.5}, {-0.5,0}, {0,0.5} ]
    set mark 1 Diamond using 2:3
    

    Maybe the program should default to using 2:3 if the data source is an array? That would allow omitting the using specifier, making it simply set mark 1 Diamond.

     
    • Hiroki Motoyoshi

      Five small patch files include the responses to your point about ‘Code consolidation’ and ‘Limitation of set mark’ are attached.

      006_add_empty_option_for_set_mark.patch

      This introduces a new syntax for explicitly defining an empty mark.

      set mark <tag> empty
      

      In the future, this feature may be removed if it proves unnecessary.

      007_consolidate_codes_as_get_mark.patch

      This is a patch to address your point "Code consolidation", defining the 'get_mark()' function and refactoring 'graphics.c' to use it.

      008_add_new_struct_mark_data_member_vertices.patch

      This patch adds a 'vertices' member to 'struct mark_data' that holds the number of vertices (including number of empty rows) contained in marks. Previously, 'mark.polygon.type' was used for that role.

      009_add_push_mark_and_get_previous_mark_function.patch

      This introduces functions for use in next '010_...' patch.

      • Fixed get_mark() after '007_consolidate_codes_as_get_mark.patch'
      • Introducing the 'get_previous_mark()' function
      • introducing the 'push_mark()' function

      010_refactoring_set_mark.patch

      Patch to address your point "Limitation of set mark", including refactoring of the 'set_mark()' function.

      • Adding a new member, 'asize', to 'struct mark_data'.
      • Introducing the 'mark_reallocate()' function.
      • Introducing the 'mark_free()' function
      • Fixed the 'mark_append()' function to use 'mark_reallocate()'
      • Modified 'set mark' to read file in 1-pass
      • Use 'get_mark()' function for adding new marks to the list
       
    • Hiroki Motoyoshi

      Difference between show and save
      Please follow the current practice used by the rest of the program:
      save_FOO() can write either to a file or to stderr.
      show_FOO() always writes to stderr.
      As an implementation convenience, show_FOO() may be implemented internally
      as save_FOO(stderr).

      In the current implementation, the 'save' command does not support marks at all. It would be helpful if you could advise what output would be desirable. Simply put, the output could be something like.

      set mark 1 ‘-’
      DATA...
      e
      

      However, the current implementation of 'set mark' does not allow ‘-’ as input.' What is missing in the current implementation to make ‘-’ available in the 'set_mark()' function?

       
      • Ethan Merritt

        Ethan Merritt - 2024-04-28

        Thanks. It will take me some time to look through your revised code.

        As to how to save the mark definitions, yeah - good question.
        I'm not sure what is best. I can think of several options
        1 - Don't save them at all
        2 - Add a field to the mark structure that is a string containing a copy of the original command that created it; write that string into the save file.
        3 - For each mark save the vertices in a datablock (see below)

        $MARK_1 << EOM
        0       0.5
        0.5     0 
        0       -0.5
        -0.5    0
        0       0.5
        EOM
        set mark 1 $MARK_1
        

        4 - For each mark save the vertices in an array

        array MARK_1 = [ {0,0.5}, {0.5, 0}, {0,-0.5}, {-0.5,0}, {0,0.5}]
        set mark MARK_1 using 2:3
        

        Probably it would be good to make it a separate command "save marks", analogous to the existing "save datablocks" command.

         
  • Ethan Merritt

    Ethan Merritt - 2024-04-28

    After applying these patches

    gnuplot> load 'Fig01_02_iris_marks.gp'
    gnuplot> load 'Fig03_04_linesmarks.gp'
    Thread 1 "gnuplot" received signal SIGSEGV, Segmentation fault.
    set_mark () at set.c:3316
    3316                    prev->next = mark;
    (gdb) list
    3311                if (action == MARK_ACTION_APPEND || action == MARK_ACTION_COPY) {
    3312                    mark_append(this, mark); /* append to existing mark */
    3313                    mark_free(mark);
    3314                } else {
    3315                    prev = get_previous_mark(first_mark, this);
    3316                    prev->next = mark;
    3317                    mark->next = this->next; /* replace to new mark */
    3318                    mark_free(this);
    3319                }
    3320            }
    (gdb) print prev
    $1 = (struct mark_data *) 0x0
    
     
    • Hiroki Motoyoshi

      Sorry.

      The bug occurred in the 'set_mark' function when replacing a newly constructed mark with an existing mark with the same tag number. No special processing was done as required if the mark to be replaced was the first element in the mark list.

      Please look at the attached patch file,

      011_BUGFIX_special_treatment_of_replacing_first_mark_in_mark_list.patch

       
  • Ethan Merritt

    Ethan Merritt - 2024-04-29

    Comments/problems 29 April

    missing "break" statement after set.c:371 set_mark();
    - example of failure: set mark 1 empty; show mark 1

    Not documented: set mark N append <already-defined tag="" number="">
    - copies an existing tag
    - what is the intended use for this?</already-defined>

    Mark symbols are not drawn in the key if the key is outside the plot
    - it looks like the mark is clipped even though do_sample_key_mark()
    passes clip=FALSE to do_mark()

    comment in plot_marks "stored in yhigh" should be "stored in z"
    comment in eval_plots "pick up the special..." should be "options specific to marks"

    "set object mark" needs to accept keyword "center" (synonym for "at")
    - example of failure:
    set obj 1 mark mt 1 at 1,1; save "foo"; load "foo"

    compiler warning
    graphics.c:3120:9: warning: ‘mark’ may be used uninitialized [-Wmaybe-uninitialized]

    Attached patch:
    - move get_mark() to gadgets.c
    - substitute get_mark() for in-line code in show.c
    - move function prototypes to the header file corresponding to the
    source file that implements that function
    - remove unused variables and unnecessary function calls from set_mark()

     
    • Hiroki Motoyoshi

      Attached are multiple patches including the bug fixes that address your "Comments/problems 29 April". I believe many of the features you have noted so far have been implemented in these patches.

      Hopefully this will help us finalize the 'marks' style specification.

      012_BUGFIX_for_Apr_29_comments.patch

      This patch addresses the following bugs.

      • missing "break" statement after set.c:371 set_mark();
      • mark symbols are not drawn in the key if the key is outside the plot
      • comment in plot_marks "stored in yhigh" should be "stored in z"
      • comment in eval_plots "pick up the special..." should be "options specific to marks"
      • "set object mark" needs to accept keyword "center" (synonym for "at")
      • compiler warning: graphics.c:3120:9: warning: ‘mark’ may be used uninitialized [-Wmaybe-uninitialized]

      013_save_mark_object.patch

      This patch allows the save command to handle mark objects.

      014_show_mark.patch

      Would it be feasible to report instead "mark 2 $triangle"?

      Difference between show and save
      Please follow the current practice used by the rest of the program:
      save_FOO() can write either to a file or to stderr.
      show_FOO() always writes to stderr.

      In addition, the following requests at the early stage of the project is also implemented in this patch.

      Would it be feasible to report instead "mark 2 $triangle"?

      show mark N $datablock
      

      015_save_marks.patch

      This patch is the first implementation of 'save marks'.
      The 'save_marks()' function in this patch is revised by "017_introducing_fillstyle_column_for_set_mark_input_data.patch" to treat the 5 column format.

      After '017_introducing_fillstyle_column_for_set_mark_input_data.patch', the following script

      $box <<EOD
      0 0
      0 1
      1 1
      1 0
      0 0
      EOD
      
      set mark 1 $box
      
      save marks "foo"
      

      generats the file "foo" like

      $MARK_1 <<EOM
      0       0       0       -1      3
      0       1       0       -1      3
      1       1       0       -1      3
      1       0       0       -1      3
      0       0       0       -1      3
      EOM
      set mark 1 $MARK_1
      undefine $MARK_1
      

      016_free_mark.patch

      In this patch, the code to free the mark structure was consolidated as the 'free_mark()' function.

      017_introducing_fillstyle_column_for_set_mark_input_data.patch

      This patch introduces 'fillstyle' as the fifth column of the set mark input data.

      Now, the 'set mark' command takes the following four patterns of data as input.

      x y 
      x y mode 
      x y mode color 
      x y mode color fillstyle
      

      The reason for leaving the 'mode' column is that the 'fillstyle' code returned by the 'style_from_fill()' function does not include border information. The 'mode' column specifies either STROKE or FILL attributes as a drawing method familiar in the cairo library, svg, postscript, etc.
      The 5 columns of input data is useful for reproduction of marks with 'save' or 'load' command.

      Instead, it also provides a convenience method by introducing the following options,

      set mark N $DATA <fillstyle-specifier> <color-specifier>
      

      With these options, the value of 'mode', 'color', 'fillstyle' column data are overrided by these option.
      Using '<fillstyle-specifier>', STROKE or FILL can be controlled as follows</fillstyle-specifier>

      For example,

         without '<fillstyle-specifier>' -> mode = 0 (follows the plot command's fillstyle)
         fillstyle empty                 -> mode = 1 (STROKE only)
         fillstyle solid... noborder     -> mode = 2 (FILL only)
         fillstyle solid... border       -> mode = 3 (STROKE and FILL)
      

      018_remove_MARK_ACTION_COPY_in_set_mark.patch

      This patch removing the undocumented syntax,

      set mark N append <already-defined tag number>
      

      It was introduced to compose a variation on an existing complicated mark with a different paint or stroke attribute, but was not found to be very useful. Use the following command instead. This is more useful because you can make full use of the 'using' and 'fillstyle' options.

      show mark 1 $mark_1
      set mark 2 $mark_1 fs transparent solid 0.3 
      
       
      • Hiroki Motoyoshi

        The show_mark() function introduced in ‘014_show_mark.patch’ had a bug regarding the initialization of the datablock variable. A patch to fix this bug is attached.

        019_BUGFIX_initializing_datablock_in_show_mark.patch

        EDIT

        Sorry, it is found that this patch can't fix the bug.

        SEGV was occurring when loading a lot of data into set mark. The cause of the bug was that the fillstyle member of the mark_data struct was not properly handled in the mark's reallocation when loading data in set mark.

        The attached "020_BUGFIX_fillstyle_reallocation_in_set_mark.patch" fixes this bug.

         

        Last edit: Hiroki Motoyoshi 2024-05-02
        • Hiroki Motoyoshi

          Some updates were made.

          021_show_marks_datablock_handling.patch

          The handling of output to datablock in the 'show_mark()' function was corrected with reference to the 'new_block()' function.

          022_save_marks_uses_pseudo_file.patch

          "save marks" output changed to use pseudo file as follows.

          set mark 1 '-'
          x1 y1 ...
          x2 y2 ...
           : : :
          e
          

          023_careful_comparison_of_fillstyle_type.patch

          Changed to use '(style & 0xf)' for comparison with FS_EMPTY in response to changes made by 'commit 83e4eadb78c8e7a4a41ff9805d9052d42daa0ad3'.

          024_defining_subroutine_read_mark_data_and_refactoring_set_mark.patch

          This patch makes the data reading part of the 'set_mark()' function using 'df_open()' a subroutine ('read_mark_data()'), making set_mark() itself more compact.

          This is also in preparation for the following comment.

          The large chunk of code in set.c is more like a plot mode
          (calling df_open, reading data, etc) than a typical "set" command.
          Because it calls df_open and df_readline, it needs to be protected
          against recursive or conflicting use of function blocks
          (see commit 44d9343f, Bug #2702). I would prefer putting this code
          elsewhere, maybe in a new source file.

          025_special_treatment_of_array_input_without_any_data_modification.patch

          This patch is intended to implement the following proposal,

          Interesting trick for compact definition of mark vertices
          This form already works (explicit columns)
          array Diamond = [ {0,0.5}, {0.5,0}, {0,-0.5}, {-0.5,0}, {0,0.5} ]
          set mark 1 Diamond using 2:3
          Maybe the program should default to using 2:3 if the data source is an array? That would allow omitting the using specifier, making it simply set mark 1 Diamond.

          After this patch, the following command can be accepted.

          array Diamond = [ {0,0.5}, {0.5,0}, {0,-0.5}, {-0.5,0}, {0,0.5} ]
          set mark 1 Diamond fillstyle solid 0.5 fc "red"
          
           

          Last edit: Hiroki Motoyoshi 2024-05-03
          • Ethan Merritt

            Ethan Merritt - 2024-05-03

            Heh. You are working too fast for me to keep up. I was just about to commit a consolidated version of your work through patchset 018 and a round of adjustments I made in response but was still in the process of testing thoroughly.

            I will see if 021-025 are useful on top of what I have here at the moment; otherwise I suggest you wait for me to commit what I have to the master branch and we can both work off that starting tomorrow.

            Here's a summary of what I did and where it stands. See also the commit messages.

            • I committed your patchsets through 018 and my intervening contributions, with the exception of patchsets 14 and 17.

            • 014_show_mark was a misunderstanding of what I tried to say earlier. I apologize for the confusion. The point I was trying to make was that gnuplot's show commands are intended to help the user remember what state the program is in during an interactive session. They write only to stderr and the output is generally not in the form of executable commands. I think you misinterpreted my attempt at an example of what the program might include in the output from show; what I was trying to suggest was that if a mark had been created by the command set mark 8 $heart using 1:2 that show mark 1 might report something like marktype 8, polygon vertices 37, data source $heart. I think that is much more helpful than a dump of the 37 vertices. A further thought was that it might remember and report back the entire set mark command; if we were to implement that then it would also be useful as output from save, but let's defer that discussion to later because your current save code is working nicely.

            • 017_introducing_fillstyle_column I did not apply because after much experimentation I decided your original idea of three values per vertex x:y:mode was in fact a better choice.

            • The code at that point (3fca5d997 marks 18 - remove MARK_ACTION_COPY) compiles and runs correctly on the test figures

            • I then did a bunch of code cleanup to remove unused variables, misplaced prototypes, whitespace, and a few things that produced compiler warnings. No change to the functional code.

            • Then I revised the mark data structure back to hold only x:y:mode and added a per-mark fillstyle and fillcolor. The commit message is below.

            • Tonight I have been working on sanity checks and error messages for things like failure to open or read the file provided to set mark.

            Read the commit message below (or the full set once I push it to SourceForge). Try out the code and let me know if you're OK with the revision. The test figures still work fine with the exception of the two-color marktype 10 in Figure 11.

            commit 059c46d5d4b8448931e6c2b507a476841ca6d4f7
            Author: Ethan A Merritt <merritt@u.washington.edu>
            Date:   Tue Apr 30 20:41:08 2024 -0700
            
                Revise the marks structure and reduce associated data storage
            
                Store only three properties per vertex:  x y mode
            
                The mode parameter is back to Hiroki Motoyoshi's original concept
                    0 = inherit fillstyle from mark or from parent plot or object
                    1 = stroke only
                    2 = fill only
                    3 = stroke and fill
            
                "set mark" now takes an optional fill style and fill color.
                Note that this fill style includes border color / noborder.
                If you set an explicit fillstyle, fill color, or border in "set mark"
                this will override anything in the parent plot or object properties.
                Otherwise these properties are inherited from the parent plot or object.
            
                Regardless of the active fill style, the mode parameter associated with
                each set of vertices in the mark controlls whether the vertices are
                used as a fill boundary, a set of lines, or both.
            
                TODO:
            
                    Since there is no 4th vertex property, you can't switch colors
                    in the middle of a mark definition.  On the other hand, the fill
                    and stroke colors can be different from the start.
                    It would not be that much work to add back a vertex color if needed.
            
             
            • Hiroki Motoyoshi

              I had assumed that only the final code would be committed to the main branch once the discussion and specification work here had settled down. I apologize for the haste in getting things done. I also apologize for the sending many patch files in incomplete states.

              Thank you for reviewing codes deeply and committing the modified codes.

              014_show_mark was a misunderstanding of what I tried to say earlier. I apologize for the confusion. The point I was trying to make was that gnuplot's show commands are intended to help the user remember what state the program is in during an interactive session. They write only to stderr and the output is generally not in the form of executable commands. I think you misinterpreted my attempt at an example of what the program might include in the output from show; what I was trying to suggest was that if a mark had been created by the command set mark 8 $heart using 1:2 that show mark 1 might report something like marktype 8, polygon vertices 37, data source $heart. I think that is much more helpful than a dump of the 37 vertices. A further thought was that it might remember and report back the entire set mark command; if we were to implement that then it would also be useful as output from save, but let's defer that discussion to later because your current save code is working nicely.

              With your detailed explanation, it make sense for me what 'show' command should print. I agree with you that 'show' command shoud print like "marktype 8, polygon vertices 37, data source $heart".

              I would still like to have the ability to copy the contents of the mark's data to a datablock separately from that, so I hope you can discuss this later. I would still like to have the ability to copy the contents of the mark's data to a datablock separately from it, so I hope we can discuss the specification of this later.

              017_introducing_fillstyle_column I did not apply because after much experimentation I decided your original idea of three values per vertex x:y:mode was in fact a better choice.

              Then I revised the mark data structure back to hold only x:y:mode and added a per-mark fillstyle and fillcolor. The commit message is below.

              There have been some interesting applications of the 'fillstyle' column in practice. But it is a trade-off between interesting application and memory inefficiency, as all rows will have memory allocations. In this respect, the idea of removing them makes sense.

              It is important to note that I'm afraid I have to disagree with removing the color column. You mentioned the "original idea of three values," but I originally proposed the four values format, including the 'color' column. As you said, the SourceForge code breaks the tenth mark in Fig11_formulas.gp by removing the color column.

              The color column follows the format of the 'fillcolor rgb variable' in the ‘with polygons’ style. The color column is necessary to represent a pseudo-hall by filling it with the same color as the background in the 'append' process, as in the tenth mark in 'Fig11_formulas.gp'. This feature is one of my motivations for creating the original patch because the gnuplot's polygon routine can not draw transparent holes. If possible, I request that the color column be revived and reverted to four values.

              If memory efficiency is the biggest issue, you can pack the integer values from two or three columns: mode(2bit) and colour(32bit RGBA) can be packed (34bit) to fit into a double. Even, a pack (42bit) of mode (2bit), colour (24bit RGB) and fillstyle (16bit) will also fit into a double. The trade-off is the packing and unpacking process.

              I then did a bunch of code cleanup to remove unused variables, misplaced prototypes, whitespace, and a few things that produced compiler warnings. No change to the functional code.

              Tonight I have been working on sanity checks and error messages for things like failure to open or read the file provided to set mark.

              I appreciate you for revising my insufficient codes.

              I also will look into your revised version of codes in the SourceForge.

               
1 2 > >> (Page 1 of 2)

Log in to post a comment.