Menu

#591 Handle split contour lines as one continuous curve

None
pending-accepted
nobody
None
5
2025-08-15
2025-08-10
No

It is common practice to extract contour data using 'set table' with splot and reuse it in another plot.

If the generated contour is simple, it is output as a single continuous curve. However, in the case of more complex contours exceeding about 100 points, the output is split into several segmented curves.

Here is a simple example:

set term wxt

f(x,y) = x**2 + y**2

set xrange [-2:2]
set yrange [-2:2]
set zrange [0:4]
set isotropic
set xyplane 0

set samples    85
set isosamples 85

set table $contour
  unset surface
    set contour surface
      set cntrparam level discrete 3
      splot f(x,y) with lines
    unset contour
  set surface
unset table

set title "contour as line"
splot f(x,y) with lines notitle lc "#c0c0c0c0", \
      $contour using 1:2:3:(column(-1)+1) with lines lc variable lw 3 notitle
pause -1 "Hit <cr> to continue"

set title "contour as filled polygon"
splot $contour with polygons fc 'pink' notitle
pause -1 "Hit <cr> to continue"

In this example, the contour line stored in the $contour datablock consists of approximately 300 points but is split into three separate curves of up to 100 points each. The larger the samples and isosamples values, the more likely it is that curves will be divided. Additionally, applying smoothing methods such as cubicspline can increase the number of segments, exacerbating the issue.

Attached patch is a trial one to preserve the continuity of contour lines.

Specifically, in end_crnt_cntr(), it checks whether the last curve in the contour_list is continuous with the new curve to be added. If they are continuous, it merges them into a single curve; otherwise, it treats the new curve as a separate one.

2 Attachments

Discussion

  • Ethan Merritt

    Ethan Merritt - 2025-08-13

    I think you may be overlooking a simpler explanation, and simpler fix, for the discontinuities seen in this example.

    The 100 point per contour segment is a defined constant. In your example case bumping this up to 1000 points removes the discontinuities. One possible fix is to make this a limit that the user can set.

    diff --git a/src/contour.c b/src/contour.c
    index 8a0f6a054..a87a758b3 100644
    --- a/src/contour.c
    +++ b/src/contour.c
    @@ -79,7 +79,7 @@ typedef enum en_edge_position {
     #define FALSE    0
     #endif
    
    -#define MAX_POINTS_PER_CNTR    100
    +#define MAX_POINTS_PER_CNTR    1000
    
     #define SQR(x)  ((x) * (x))
    

    I am not sure, but I think that limit is there because in the old days PostScript output (and later other vector outputs like SVG) behaved poorly if there were long sequences of relative move/draw segments. Breaking after each 100 pts forced an absolute coordinate pair to be written, limiting the build-up of errors. The PostScript terminal itself limits such a sequence to 250 relative segments, but whoever wrote the contouring was more conservative and set the limit at 100. In version 5 development various terminals were modified to keep more precision, so probably this is less of an issue now than it used to be.

     
  • Ethan Merritt

    Ethan Merritt - 2025-08-14

    Fixed by commit 83cd1370

    Instead of building up a contour line using a fixed-length array of 100 points, dynamically allocate additional points as needed.

     
  • Ethan Merritt

    Ethan Merritt - 2025-08-14
    • status: open --> pending-accepted
    • Group: -->
     
  • Hiroki Motoyoshi

    Thanks for committing an improved implementation — much appreciated!

     

Log in to post a comment.

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.