|
From: Mojca M. <moj...@gm...> - 2006-02-02 02:23:05
|
Hello,
I experienced some problems with MetaPost driver recently when drawing
a function similar to sin(1000*x), ie. with sharp turns up and down.
MetaPost draws a continuous line instead of isolated line segments,
which is OK and even much better in most cases. But it uses "sharp"
corners (instead of the rounded ones) which then stick out way above
and below the line where the function passes through. (I have to check
how this is solved in PostScript.)
I don't say that MetaPost should use round corners. For example, it's
much better to use sharp (square) corners instead of the rounded ones
for drawing rectangular frames, but I intend to write a new terminal
(ConTeXt) based on metapost, so I would like to solve this problem.
Is there a way to distinguish rectangular frames (perhaps polygons as
well) from "random" functions which have to use rounded corners (at
least in my opinion), so that they don't stick out in extremely sharp
corners? Or does anyone have a better suggestion how to deal with this
problem? In the worst case I'll just use rounded corners everywhere.
One thing can be (has to be) fixed in the terminal itself however:
when MetaPost draws a rectangular frame, it uses continuous line from
4 line segments, but the beginning of the first line and the end of
the last line are "not properly connected" (the curve is not closed).
Thanks a lot,
Mojca Miklavec
|
|
From: Ethan A M. <merritt@u.washington.edu> - 2006-02-02 04:59:24
|
On Wednesday 01 February 2006 06:22 pm, Mojca Miklavec wrote: > > I experienced some problems with MetaPost driver recently when drawing > a function similar to sin(1000*x), ie. with sharp turns up and down. > MetaPost draws a continuous line instead of isolated line segments, > which is OK and even much better in most cases. But it uses "sharp" > corners (instead of the rounded ones) which then stick out way above > and below the line where the function passes through. (I have to check > how this is solved in PostScript.) Postscript has a command "setlinejoin" which selects either mitred, rounded, or beveled corners. http://www.capcode.de/help/setlinejoin Gnuplot's postscript driver allows you to select either "rounded" or "butt" (really mitred) in the "set term" command. Mike Sutton recently contributed an equivalent for the png/gif/jpeg driver. The plan is to add the same option to additional terminal types if they can support it. > One thing can be (has to be) fixed in the terminal itself however: > when MetaPost draws a rectangular frame, it uses continuous line from > 4 line segments, but the beginning of the first line and the end of > the last line are "not properly connected" (the curve is not closed). You are more than welcome to contribute a patch to fix this. The metapost driver does not seem to have an active champion right now, so it is only sporadically updated. But it's not obvious to me why the line would not be closed. The code appears to claim 2400 dpi resolution, which I should think is sufficient to give accurate line joins. But maybe the resolution is not truly as high as it claims. Or are you saying that it meets up properly, but the line-join at that corner is not consisent with the other line-joins? -- Ethan A Merritt Biomolecular Structure Center University of Washington, Seattle 98195-7742 |
|
From:
<br...@ph...> - 2006-02-02 18:00:42
|
Ethan A Merritt wrote: > On Wednesday 01 February 2006 06:22 pm, Mojca Miklavec wrote: >>One thing can be (has to be) fixed in the terminal itself however: >>when MetaPost draws a rectangular frame, it uses continuous line from >>4 line segments, but the beginning of the first line and the end of >>the last line are "not properly connected" (the curve is not closed). > But it's not obvious to me why the line would not be closed. Well, the terminal driver API currently has no way for the core to tell the driver the difference between a polyline that just happens to byte its own tail (i.e. end == start), and one that is actually meant to be a (non-filled) polygon. In the context of Postscript, that shows by the fact that PS_FLUSH_PATH never emits a "closepath" command in front of the "stroke". Only the point symbols, PS_polygon() and the filled-box operators emit closepath. Without the closepath, one of the corners of the graph box will not have neither a mitre, nor a round or any other join. As an example, look what this plot comes out as, in PostScript: set border 31 lt -1 lw 10 plot x and examine the lower left corner of the graph box. > Or are you saying that it meets up properly, but the line-join > at that corner is not consisent with the other line-joins? The problem is that at the tail-byting corner, there is no line join at all --- just two lines ends that happen to be in the same place. |
|
From: Ethan M. <merritt@u.washington.edu> - 2006-02-02 18:28:51
|
On Thursday 02 February 2006 10:04 am, Hans-Bernhard Br=F6ker wrote: > > Without the closepath, one of the corners of the graph box will not > have neither a mitre, nor a round or any other join. > > set border 31 lt -1 lw 10 > plot x > > and examine the lower left corner of the graph box. I understand. However, if you choose set term post rounded then this corner is rendered identically to the others. =20 This is one advantage of choosing the rounded joins and caps. Perhaps metapost can do the same? =2D-=20 Ethan A Merritt Biomolecular Structure Center University of Washington, Seattle WA |
|
From:
<br...@ph...> - 2006-02-02 18:40:37
|
Ethan Merritt wrote: > I understand. However, if you choose > set term post rounded > then this corner is rendered identically to the others. > This is one advantage of choosing the rounded joins and caps. It's also a rather indirect approach that only fixes the symptom, not the problem. Why should people be restricted to using round joins just to get a non-silly display of the graph box? |
|
From: Ethan M. <merritt@u.washington.edu> - 2006-02-02 19:05:12
|
On Thursday 02 February 2006 10:44 am, Hans-Bernhard Br=F6ker wrote:
> Ethan Merritt wrote:
> > I understand. However, if you choose
> > set term post rounded
> > then this corner is rendered identically to the others.
> > This is one advantage of choosing the rounded joins and caps.
>
> It's also a rather indirect approach that only fixes the symptom, not
> the problem. Why should people be restricted to using round joins
> just to get a non-silly display of the graph box?
[shrug]
Different problems may require different solutions.
I took Mojca's question to be along the lines of "what could the
metapost driver do differently?". So I gave a driver-oriented
answer. For the very specific case of drawing the plot border,
we could of course have the core code draw 1 + 1/8 of the=20
way around the perimeter, which should give a clean join at
all 4 corners. That change would not help any other line joins,
however.
We could think about adding a new terminal entry
point term->polyline(), which could handle this case and also
draw nice boundaries around term->filled_polygon() areas.
Or these call sites could also use the method above --
draw a polygon boundary as N + 1/2N segments and let the
driver merge these into a polyline if possible.
On the other hand, even if we did this the joins at
the endpoints of separately drawn vectors would be a problem.
E.g. when 2 or 3 zero-axis lines meet at the origin.
E.g. when different segments of a continuous line plot are
drawn separately so that they can have different colors.
=2D-=20
Ethan A Merritt
Biomolecular Structure Center
University of Washington, Seattle WA
|
|
From: Mojca M. <moj...@gm...> - 2006-02-04 23:59:21
|
On 2/2/06, Ethan A Merritt wrote: > On Wednesday 01 February 2006 06:22 pm, Mojca Miklavec wrote: > > > > I experienced some problems with MetaPost driver recently when drawing > > a function similar to sin(1000*x), ie. with sharp turns up and down. > > MetaPost draws a continuous line instead of isolated line segments, > > which is OK and even much better in most cases. But it uses "sharp" > > corners (instead of the rounded ones) which then stick out way above > > and below the line where the function passes through. (I have to check > > how this is solved in PostScript.) > > Postscript has a command "setlinejoin" which selects either > mitred, rounded, or beveled corners. > http://www.capcode.de/help/setlinejoin > > Gnuplot's postscript driver allows you to select either > "rounded" or "butt" (really mitred) in the "set term" command. > Mike Sutton recently contributed an equivalent for the png/gif/jpeg > driver. The plan is to add the same option to additional terminal > types if they can support it. (Metapost should support that option too: currently it's hardcoded.) One of my question was also: is it possible to set different linejoin for different elements? It's for example best if rectangular elements keep "mitered" linejoins, while function could be drawn with rounded linejoins if needed. This is one of the things that a terminal can't do. A terminal can solve the problem with closed paths (below), but can't guess if the line being drawn is a function or a frame (unless I try to draw the lines of type -1 and -2 with mitered linejoin and the rest with the rounded ones). On 2/2/06, Ethan Merritt wrote: > On Thursday 02 February 2006 10:44 am, Hans-Bernhard Br=F6ker wrote: > > Ethan Merritt wrote: > > > I understand. However, if you choose > > > set term post rounded > > > then this corner is rendered identically to the others. > > > This is one advantage of choosing the rounded joins and caps. > > > > It's also a rather indirect approach that only fixes the symptom, not > > the problem. Why should people be restricted to using round joins > > just to get a non-silly display of the graph box? > > [shrug] > Different problems may require different solutions. > > I took Mojca's question to be along the lines of "what could the > metapost driver do differently?". So I gave a driver-oriented > answer. For the very specific case of drawing the plot border, > we could of course have the core code draw 1 + 1/8 of the > way around the perimeter, which should give a clean join at > all 4 corners. That change would not help any other line joins, > however. > > We could think about adding a new terminal entry > point term->polyline(), which could handle this case and also > draw nice boundaries around term->filled_polygon() areas. > Or these call sites could also use the method above -- > draw a polygon boundary as N + 1/2N segments and let the > driver merge these into a polyline if possible. > > On the other hand, even if we did this the joins at > the endpoints of separately drawn vectors would be a problem. > E.g. when 2 or 3 zero-axis lines meet at the origin. > E.g. when different segments of a continuous line plot are > drawn separately so that they can have different colors. If three lines of different color meet in the same point, there's no solution anyway, I'm afraid. At the very beginning I wanted to ask for an additional function (polyline), but then I figured out that the Metapost terminal has a nice workaround for it: it always saves the last point and if the next line continues in the same point (without changing line type or color inbetween), it draws a continuous path rather than two separate lines. In the terminal I'm currently writing (which is almost the same as metapost) I did the same for the first & last point: I save the first point and when I draw the next line segment I check if the last point is the same as the first one. In that case I "close" the line. There might be exceptions to this rule of course where the results are only suboptimal, but this will at least draw the border properly in 99% cases. However, adding a new function like polyline(int npoints, int points[n][2], bool closed) would still be a cleaner solution. If a driver doesn't support it, it can still be drawn with n separate lines. I still have to study the 3d drawing capabilities in gnuplot, but I have a feeling that there's no function yet for drawing a polygon with colors specified in the corners, so that smooth shading could be used to get proper feeling of 3d (without "annoying" steps in shading). See http://www.math.ubc.ca/~cass/graphics/manual/pdf/ch14.pdf for example. Not many terminals could make use of it (perhaps PostScript-based ones, PDF and ConTeXt if author of ConTeXt's adds some trickery), but I guess that the source wouldn't need so many changes to calculate the color in edges of polygons. With quite some additional effort the bitmap terminals could be improved in that sense as well (each pixel could have the "proper" color; not really ray-tracing, but something similar). Thanks a lot, Mojca |
|
From: Ethan A M. <merritt@u.washington.edu> - 2006-02-05 00:39:48
|
Mojca Miklavec <moj...@gm...> wrote: > > Or these call sites could also use the method above -- > > draw a polygon boundary as N + 1/2N segments and let the > > driver merge these into a polyline if possible. I have decided that I do not like this option, because it will look bad on pen plotters. Of course maybe no one has a pen plotter any more... > In the terminal I'm currently writing (which is almost the same as > metapost) I did the same for the first & last point: I save the first > point and when I draw the next line segment I check if the last point > is the same as the first one. In that case I "close" the line. There > might be exceptions to this rule of course where the results are only > suboptimal, but this will at least draw the border properly in 99% > cases. I have been trying the same thing in the PostScript driver. It works fine for rectangles, but I must have failed to consider some reasonably common case because several of the demo plots no longer work correctly. If I get the demos working 100%, I'll put the patch on SourceForge so everyone can try it out. > However, adding a new function like polyline(int npoints, int > points[n][2], bool closed) would still be a cleaner solution. If a > driver doesn't support it, it can still be drawn with n separate > lines. That assumes the points are all known in advance of the driver call. That is probably always true for rectangles, but not for a general closed curve plot. So we would have to add a layer in the core code that accumulates a complete curve. I think. Maybe there's a clever way around it. But in any event, I suspect that adding new core code and adding a new driver entry to N drivers is going to be more work than teaching the few drivers who care to recognize short closed paths on the fly. > I still have to study the 3d drawing capabilities in gnuplot, but I > have a feeling that there's no function yet for drawing a polygon with > colors specified in the corners, so that smooth shading could be used > to get proper feeling of 3d (without "annoying" steps in shading). See > http://www.math.ubc.ca/~cass/graphics/manual/pdf/ch14.pdf for example. This has come up before, although there wasn't much discussion. To the best of my knowledge, only the svg driver could easily support this. It would be possible in TrueColor png and jpeg output, but it would require adding some pretty messy code to gd.trm. I did look into that at one point, and decided it was far too much trouble. I am not enough of a PostScript guru to know how one might do it there. > With quite some additional effort the bitmap terminals could be > improved in that sense as well (each pixel could have the "proper" > color; not really ray-tracing, but something similar). I am CC'ing Dan Sebald on this one, because it occurs to me there's an off chance that one could implement this by piggy-backing on his "with rgbimage" code. It might be possible to use libgd to create the desired gradient-filled rectangle in memory, and then feed that pixmap to any driver with a term->image entry point. Daniel, do you think that might work? If so, it would have the major advantage of being an almost entirely separate code module. If we're lucky, we might not have to touch individual drivers at all. -- Ethan A Merritt Biomolecular Structure Center University of Washington, Seattle 98195-7742 |
|
From: Daniel J S. <dan...@ie...> - 2006-02-05 03:22:54
|
Mojca Miklavec wrote: > On 2/5/06, Daniel J Sebald <dan...@ie...> wrote: > > > Didn't try it now, but I guess it only draws solid polygons and > simulates 3D. But I was asking for the what you describe as "to using > elements that have shading within as opposed to having the monocolored > elements". This is not that difficult to do in PostScript/PSTricks and > could be also done in ConTeXt (based on metapost). PDF supports that > as well, but might not be trivial with the current driver (don't know > how it works). It probably isn't a difficult thing to write a routine that does that. I think Ethan's idea may have been to use such a routine that already exists in library and then utilize that somehow. The difficult thing with gnuplot is usually figuring out a nice generic method that all terminals can use. > With quite some effort, one could do something like "ray-tracing" (I > don't know how it's called) and determine the color for each pixel > separately by determining the normal vector to the surface in the > point to which this pixel "corresponds to" (sorry, I guess that nobody > understands that sentence). Well, my understanding is that ray tracing is a very computationally intensive method of shading that mimicks real-world objects by bouncing light rays, either from some light source or the reverse direction. I think the best that could be achieved with gnuplot might be some kind of faux lighting assuming the light source is at an infinite point in space. But really, to have shading commands and such in gnuplot doesn't seem approrpriate. Dan |
|
From:
<br...@ph...> - 2006-02-05 01:02:03
|
Mojca Miklavec wrote: > At the very beginning I wanted to ask for an additional function > (polyline), but then I figured out that the Metapost terminal has a > nice workaround for it: it always saves the last point and if the next > line continues in the same point (without changing line type or color > inbetween), it draws a continuous path rather than two separate lines. There's no sane reason for implementing any "workaround" for this --- the terminal driver API already *has* a polyline function. That's why we have two functions, term->move() and term->vect(), instead of a single term->draw_line(from,to). Each term->move() conceptually starts a new polyline, each term->vect() extends it by one leg, any other call but term->vect() ends it. We don't need a term->polyline(). The only thing needed to complete the existing API in this area would be a term->closecycle() or some such, to distinguish between open and closed polylines. |
|
From: Mojca M. <moj...@gm...> - 2006-02-05 03:50:44
|
On 2/5/06, Hans-Bernhard Br=F6ker wrote:
> Mojca Miklavec wrote:
> > At the very beginning I wanted to ask for an additional function
> > (polyline), but then I figured out that the Metapost terminal has a
> > nice workaround for it: it always saves the last point and if the next
> > line continues in the same point (without changing line type or color
> > inbetween), it draws a continuous path rather than two separate lines.
>
> There's no sane reason for implementing any "workaround" for this ---
> the terminal driver API already *has* a polyline function. That's why
> we have two functions, term->move() and term->vect(), instead of a
> single term->draw_line(from,to). Each term->move() conceptually starts
> a new polyline, each term->vect() extends it by one leg, any other call
> but term->vect() ends it.
>
> We don't need a term->polyline(). The only thing needed to complete
> the existing API in this area would be a term->closecycle() or some
> such, to distinguish between open and closed polylines.
Thanks. It should also be described in the documentation that way.
It's not mentioned anywhere that every command other than vect() ends
a line. I thouht that
move(0,0)
vect(1,2)
linetype(2)
vect(0,1)
or
move(0,0)
vect(1,2)
put_text(3,3,"abc")
vect(0,1)
was a valid sequence of commands (according to your description it's
not). I followed the code sample in metapost.trm, which handles that
case "properly" (breaks the line in first case and continues the line
in the second case). Also,
move(0,0)
vector(1,1)
move(1,1)
vector(2,1)
would draw a continuous line in metapost rather than two separate ones.
However, move() and vector() lead to much more dirty code in terminals
in comparison to polyline(). Move starts the line, which is OK, but
EVERY other command has to start with
if(we're inside a line)
finish that line first
After some thinking I figured out that polyline() instead of move()
and vector() would be less memory-efficient for extremely long lines,
but at least an "endline(bool closed)" could help cleaning up some
code. endline(false) would reduce the need for an additional "if" in
just about every function and endline(true) would be a magic
combination which would fix the reported "bug" without additional
trickery in the terminals.
(I'm sorry for a sking a stupid newbie question: how many bytes can be
assumed for int? IE: may xmax and ymax exceed 32000?)
Thanks,
Mojca
|
|
From: Ethan A M. <merritt@u.washington.edu> - 2006-02-05 05:50:41
|
On Saturday 04 February 2006 07:50 pm, Mojca Miklavec wrote: > On 2/5/06, Hans-Bernhard Br=F6ker wrote: > > > > We don't need a term->polyline(). The only thing needed to complete > > the existing API in this area would be a term->closecycle() or some > > such, to distinguish between open and closed polylines. We don't need that either. I've just placed a patch for post.trm on SourceForge that simply keeps track of where the current polyline started. If that point is reached again, then the polyline is closed off with "closepath stroke" rather than "<xend> <yend> lineto stroke". Seems to work fine, but have a look and see if you can improve it further. As noted in a code comment, it seems to have the side effect of triggering a subsequent "1.000 UL". Harmless, but unnecessary. > I thought this was a valid sequence of commands > move(0,0) > vect(1,2) > put_text(3,3,"abc") > vect(0,1) It is a legal sequence of commands, although I don't think it can be generated by any existing operation in gnuplot. The second vect() command above will start a new polyline whose origin is somewhere in the string. =2D-=20 Ethan A Merritt Biomolecular Structure Center University of Washington, Seattle 98195-7742 |
|
From: Mojca M. <moj...@gm...> - 2006-02-08 04:58:16
|
On 2/5/06, Petr Mikulik wrote: > > implement that. Even more fancy method would be to determine the color > > of each pixel separately (by calculating normal vector & consequently > > the color for each pixel separately), but the first method would be > > far enough, the second one would take too much effort for too little > > gain in comparison to the first method. > > See > set pm3d interpolate nx,ny > > That does currently a bit of what you want (but not pixel-wise.) This makes the grid "finer", but not smooth. Consider my question equivalent to "can we draw a circle" if the program is only able to draw straight line segments. It's not the point in dividing lines into shorter segments, but in the proper support for splines or whatever. No, I didn't mean that gnuplot should support splines (although it would be nice to) since a line can be divided into segments which are short enough, but in 2D plots the number of possible divisions in one direction is limited. PostScript (and PDF) support smooth shading, which means that you can only define a color in the corners and PostScript will take care for "pixels" in the middle. See the example on http://pub.mojca.org/ps/smooth/. It's a bad approximation of a rainbow, but a good approximation of what gnuplot could be capable of with probably not that much effort. No matter how much you zoom in or out, you won't notice sharp steps. High nx & ny also mean long processing time when opening such files (it takes forever to zoom in and out and to move along such a page) and still only suboptimal results. Mathematica can't do that, but gnuplot could be better. Mojca |
|
From: Petr M. <mi...@ph...> - 2006-02-08 08:47:31
|
>> set pm3d interpolate nx,ny
>>
>> That does currently a bit of what you want (but not pixel-wise.)
>
> High nx & ny also mean long processing time when opening such files
> (it takes forever to zoom in and out and to move along such a page)
> and still only suboptimal results.
Yes, it eats a lot of memory.
> This makes the grid "finer", but not smooth.
>
> PostScript (and PDF) support smooth shading, which means that you can
> only define a color in the corners and PostScript will take care for
> "pixels" in the middle.
Wasn't this question discussion during the OpenGL driver? It is a bit
similar (colors for vertices). Aha, not the question here, since we are in
2D projections, not in 3D coordinats.
It would need to add
float r,g,b;
into the definition of gpiPoint.
Then there are these possibilities:
1. Add also
int fade_color
into gpiPoint. Then
void XX_filled_polygon (int points, gpiPoint *corners)
won't change.
2. Change
void XX_filled_polygon (int points, gpiPoint *corners, t_fade *fade)
The last new param will be ignored by most terminals.
3. As term->set_color() is called before each term->filled_polygon(),
the fading option could be passed at this point.
It is probably not difficult to implement. You can have a nice play.
---
PM
|
|
From: Mojca M. <moj...@gm...> - 2006-02-12 15:20:40
|
On 2/8/06, Petr Mikulik wrote: > > This makes the grid "finer", but not smooth. > > > > PostScript (and PDF) support smooth shading, which means that you can > > only define a color in the corners and PostScript will take care for > > "pixels" in the middle. > > Wasn't this question discussion during the OpenGL driver? It is a bit > similar (colors for vertices). Aha, not the question here, since we are i= n > 2D projections, not in 3D coordinats. > > It would need to add > float r,g,b; > into the definition of gpiPoint. > > Then there are these possibilities: > 1. Add also > int fade_color > into gpiPoint. Then > void XX_filled_polygon (int points, gpiPoint *corners) > won't change. > 2. Change > void XX_filled_polygon (int points, gpiPoint *corners, t_fade *f= ade) > The last new param will be ignored by most terminals. > 3. As term->set_color() is called before each term->filled_polygon(), > the fading option could be passed at this point. > > It is probably not difficult to implement. You can have a nice play. The proper color should probably be calculated first for each point as well= . Thans a lot for the guidelines. If nobody else is willing to investigate, I'll try to finish the new terminal first before starting to dig into this, so that I get some experience first. However, exactly at this point (filled_polygon, trickery with palettes, ...) proper documentation for current functionality is missing. ConTeXt is able to do many things (not "grestore" however, but this can be done in many other ways), but I'm a bit lost. PostScript terminal uses some "cryptic code" for patterns, palettes, ... that is not documented anywhere else. For example, there's exactly only one place where "previous_palette" is called. PostScript does only "grestore" and the source states that the command could probably be dropped since no other terminal is using it. Is PostScript "the" reference of how the functions are to be implemented in other terminals? Or who could help me with further suggestions what the "fill_polygon" and palette switching functions are supposed to do exactly? (sorry for going off-topic in this thread) Mojca |
|
From: Petr M. <mi...@ph...> - 2006-02-12 20:57:56
|
> However, exactly at this point (filled_polygon, trickery with > palettes, ...) proper documentation for current functionality is > missing. See src/README and term/README. > but I'm a bit lost. then you must investigate the code itself > PostScript terminal uses some "cryptic code" for patterns, palettes, > ... that is not documented anywhere else. Read postscript reference book(s). > For example, there's exactly only one place where "previous_palette" is > called. PostScript does only "grestore" and the source states that the > command could probably be dropped since no other terminal is using it. This API was needed in 1998 when I wrote the pm3d code. > Is PostScript "the" reference of how the functions are to be > implemented in other terminals? Or who could help me with further > suggestions what the "fill_polygon" and palette switching functions > are supposed to do exactly? You have to enjoy playing with the source code yourself. --- PM |