From: Alan G I. <ai...@am...> - 2009-10-13 19:09:36
|
What is the PyX equivalent to the following? 288 360 moveto 4 {144 0 rlineto 72 rotate} repeat closepath stroke Thanks, Alan Isaac |
From: Michael J G. <mic...@fa...> - 2009-10-14 10:23:21
|
Alan G Isaac venit, vidit, dixit 13.10.2009 21:09: > What is the PyX equivalent to the following? > > 288 360 moveto > 4 {144 0 rlineto 72 rotate} repeat closepath stroke > How about unit.set(defaultunit="pt") c = canvas.canvas([style.linewidth(1)]) x,y = 144,0 p = path.path(path.moveto(0,0)) for i in range(4): p.append(path.rlineto(x,y)) x,y = trafo.rotate(72).apply(x,y) p.append(path.closepath()) c.stroke(p, [trafo.translate(288,360)]) This results in 288 360 moveto 432 360 lineto 476.498 496.952 lineto 360 581.593 lineto 243.502 496.952 lineto closepath stroke for the ps (besides gsave and such). Using PyX-trafos on points is the closest you get to PS's rotated coordinate system, and there's no way to create a "repeat" or "rlineto". Of course you could do things differently in PyX, such as rotating a path.line around and joining those rather than appending path elements: unit.set(defaultunit="pt") c = canvas.canvas([style.linewidth(1)]) pl = path.line(0,0,144,0) p = path.path(path.moveto(0,0)) x0,y0 = 0,0 for i in range(4): p = p << pl x,y = p.atend() pl = pl.transformed(trafo.rotate(72, x=x, y=y)*trafo.translate(x-x0, y-y0)) x0, y0 = x,y p.append(path.closepath()) c.stroke(p, [trafo.translate(288,360)]) Cheers, Michael |
From: Alan G I. <ai...@am...> - 2009-10-14 21:01:56
|
On 10/14/2009 6:22 AM, Michael J Gruber wrote: > for i in range(4): > p.append(path.rlineto(x,y)) > x,y = trafo.rotate(72).apply(x,y) OK, that is very helpful. I'm getting a better feel for the model. Let me ponder this and then perhaps ask a follow up. Thanks! Alan |
From: Alan G I. <ai...@am...> - 2009-10-15 00:41:57
|
On 10/14/2009 6:22 AM, Michael J Gruber wrote: > c = canvas.canvas([style.linewidth(1)]) So I had wondered about this and did not understand the documentation. If one applies a line style to a canvas, I take it that it becomes the default for all stroke operations (by that canvas), including draw operations? Thanks, Alan PS Btw, it is great to be able to sum(mypaths,path()), but might it be worth defining mypath+0 to be mypath so we can just sum(mypaths)? Not sure this is a good idea but thought I'd throw it out there. |
From: Michael J G. <mic...@fa...> - 2009-10-15 08:37:54
|
Alan G Isaac venit, vidit, dixit 15.10.2009 02:26: > On 10/14/2009 6:22 AM, Michael J Gruber wrote: >> c = canvas.canvas([style.linewidth(1)]) > > So I had wondered about this and did > not understand the documentation. > > If one applies a line style to a canvas, I take > it that it becomes the default for all stroke operations > (by that canvas), including draw operations? It seems so ;) It's not documented (online draw style is), but it works that way. I found no clean way to set an overall default line width which is why I did it that way. Assigning to style._defaultlinewidth (and ..._pt) is something you should not try at home. > PS Btw, it is great to be able to sum(mypaths,path()), > but might it be worth defining mypath+0 to be mypath > so we can just sum(mypaths)? Not sure this is a good > idea but thought I'd throw it out there. Sounds useful. I haven't looked into what that would take codewise. Michael |
From: André W. <wo...@us...> - 2009-10-15 09:09:26
Attachments:
smime.p7s
|
Am 15.10.2009 um 10:36 schrieb Michael J Gruber: > Alan G Isaac venit, vidit, dixit 15.10.2009 02:26: >> On 10/14/2009 6:22 AM, Michael J Gruber wrote: >>> c = canvas.canvas([style.linewidth(1)]) >> >> So I had wondered about this and did >> not understand the documentation. >> >> If one applies a line style to a canvas, I take >> it that it becomes the default for all stroke operations >> (by that canvas), including draw operations? > > It seems so ;) > It's not documented (online draw style is), but it works that way. See canvas constructor at http://pyx.sourceforge.net/manual/node17.html There also is (or was) a canvas set method. However, I consider this a bad design and we are about to remove that (am I right, Jörg?). Its also questionable, whether the canvas constructor attrs-field is a good design decision. I remember having argued against it. Anyway, it is likely to stay(?). To my mind, the cleanest way of setting attributes is while inserting a canvas in another canvas. c = canvas() c2 = canvas() c.insert(c2, [style.linewidth(1)]) Maybe this is too much in terms of user friendliness, but I clearly like this solution most. > I found no clean way to set an overall default line width which is > why I > did it that way. Assigning to style._defaultlinewidth (and ..._pt) is > something you should not try at home. Hmm. It's hardcoded in style.py: _defaultlinewidth = 0.02 * unit.w_cm The intention of the width units is to be able to scale all line width by unit.set(wscale=...), however, the factor need to set the defaultlinewidth to, say, 1pt is nontrivial. Maybe we should make it possible to set the default linewidth without altering the wscale at all. However, I don't consider this to be that important. Other things clearly are, like doing a new release this year (which is a new year's pledge of mine, and I still hope to get it done). >> PS Btw, it is great to be able to sum(mypaths,path()), >> but might it be worth defining mypath+0 to be mypath >> so we can just sum(mypaths)? Not sure this is a good >> idea but thought I'd throw it out there. hmmm ... -0 ... I don't like it. Best, André -- by _ _ _ Dr. André Wobst, Amselweg 22, 85716 Unterschleißheim / \ \ / ) wo...@us..., http://www.wobsta.de/ / _ \ \/\/ / PyX - High quality PostScript and PDF figures (_/ \_)_/\_/ with Python & TeX: visit http://pyx.sourceforge.net/ |
From: Joerg L. <jo...@us...> - 2009-10-15 09:51:49
|
Hi, On 15.10.09, André Wobst wrote: > Am 15.10.2009 um 10:36 schrieb Michael J Gruber: > >> Alan G Isaac venit, vidit, dixit 15.10.2009 02:26: >>> On 10/14/2009 6:22 AM, Michael J Gruber wrote: >>>> c = canvas.canvas([style.linewidth(1)]) >>> >>> So I had wondered about this and did >>> not understand the documentation. >>> >>> If one applies a line style to a canvas, I take >>> it that it becomes the default for all stroke operations >>> (by that canvas), including draw operations? >> >> It seems so ;) >> It's not documented (online draw style is), but it works that way. > > See canvas constructor at http://pyx.sourceforge.net/manual/node17.html > > There also is (or was) a canvas set method. However, I consider this a > bad design and we are about to remove that (am I right, Jörg?). Yes, we wanted to get rid of this. AFAIR we mostly kept it for technical reasons. > Its also questionable, whether the canvas constructor attrs-field is a > good design decision. I remember having argued against it. Anyway, it is > likely to stay(?). To my mind, the cleanest way of setting attributes is > while inserting a canvas in another canvas. > > c = canvas() > c2 = canvas() > c.insert(c2, [style.linewidth(1)]) I also don't like the attrs argument of the canvas class too much, but the solution with two canvases is too complicated. Anyway, I have to say that in general you should use unit.set(wscale=...) instead of setting a default linewidth, since then also linewidth.thick, etc., work as wanted. As André has pointed out, though, finding the right scaling factor for a given line-width is non-trivial, although possible. Btw, that would be an argument for a more natural base for the linewidth. > However, I don't consider this to be that important. Other things > clearly are, like doing a new release this year (which is a new year's > pledge of mine, and I still hope to get it done). Yes :-) >>> PS Btw, it is great to be able to sum(mypaths,path()), >>> but might it be worth defining mypath+0 to be mypath >>> so we can just sum(mypaths)? Not sure this is a good >>> idea but thought I'd throw it out there. > > > hmmm ... -0 ... I don't like it. Same for me. Cheers, Jörg |
From: Michael S. <m-s...@us...> - 2009-10-15 10:11:58
|
Salut, On 15.10.09, Joerg Lehmann wrote: > On 15.10.09, André Wobst wrote: > > There also is (or was) a canvas set method. However, I consider this a > > bad design and we are about to remove that (am I right, Jörg?). > > Yes, we wanted to get rid of this. AFAIR we mostly kept it for technical > reasons. We had some discussions about canvas.clip at this point. I vaguely remember that there was an argument why clipping is different and should be kept as an attr of the canvas constructor. André, Jörg? > > Its also questionable, whether the canvas constructor attrs-field is a > > good design decision. I remember having argued against it. Anyway, it is > > likely to stay(?). To my mind, the cleanest way of setting attributes is > > while inserting a canvas in another canvas. > > > > c = canvas() > > c2 = canvas() > > c.insert(c2, [style.linewidth(1)]) > > I also don't like the attrs argument of the canvas class too much, but > the solution with two canvases is too complicated. > Anyway, I have to say that in general you should use > unit.set(wscale=...) instead of setting a default linewidth, since then > also linewidth.thick, etc., work as wanted. As André has pointed out, > though, finding the right scaling factor for a given line-width is > non-trivial, although possible. Btw, that would be an argument for a > more natural base for the linewidth. As wscale scales _only_ the linewidth (there is already the other parameter vscale for the rest), I fear that we introduce too many control parameters for the same thing. Either we keep wscale or we introduce a way to reset the defaultlinewidth. Concerning the "more natural" base for the linewidth, I insist on a good looking one ;-) > > However, I don't consider this to be that important. Other things > > clearly are, like doing a new release this year (which is a new year's > > pledge of mine, and I still hope to get it done). > > Yes :-) > > >>> PS Btw, it is great to be able to sum(mypaths,path()), > >>> but might it be worth defining mypath+0 to be mypath > >>> so we can just sum(mypaths)? Not sure this is a good > >>> idea but thought I'd throw it out there. Every time I want to combine paths, I have to learn again the difference between adding path elements to an other path, or adding whole subpaths. The result is of course different at the joinings. The behaviour is even different for paths and for normpaths. I then recognize that the variety of variants is wanted and reasonable. I think that a single notation such as "sum(mypaths, path())" is too implicit. One never knows what will happen. Btw: There used to be a "glue" which has been abandoned. Why? -- Michael Schindler Laboratoire de Physico-Chimie Théorique. ESPCI. 10 rue Vauquelin, 75231 Paris cedex 05, France. Tel: +33 (0)1 40 79 45 97 Fax: +33 (0)1 40 79 47 31 http: www.pct.espci.fr/~michael |
From: Alan G I. <ai...@am...> - 2009-10-15 21:24:29
|
On 10/15/2009 6:11 AM, Michael SCHINDLER wrote: > Every time I want to combine paths, I have to learn again the > difference between adding path elements to an other path, or adding > whole subpaths. The result is of course different at the joinings. The > behaviour is even different for paths and for normpaths. I then > recognize that the variety of variants is wanted and reasonable. I > think that a single notation such as "sum(mypaths, path())" is too > implicit. One never knows what will happen. OK, I'm not understanding this: `sum` will call `__add__` and that is well defined for paths, right? I hope you are not speaking against sum(mypaths, path()) because it is the only nice way I've found to turn a bunch of paths into subpaths of a single path. Cheers, Alan Isaac |
From: André W. <wo...@us...> - 2009-10-16 15:25:32
Attachments:
smime.p7s
|
Am 15.10.2009 um 23:24 schrieb Alan G Isaac: > OK, I'm not understanding this: > `sum` will call `__add__` and that is well defined for paths, right? Yes. > I hope you are not speaking against sum(mypaths, path()) > because it is the only nice way I've found to turn a bunch > of paths into subpaths of a single path. Yes. It's fine. Note that this is quite different from extending the path __add__ operation to allow for 0 + mypath[0]. BTW note that sum is designed for numerics only. That's why sum([]) returns 0 and sum(["spam", "eggs"]) is not allowed. By the way for strings it even doesn't work with sum(["spam", "eggs"], ""), which I think is weird (but explicitly enforced by BDFL). Anyway, sum(mypaths, path()) is fine. André -- by _ _ _ Dr. André Wobst, Amselweg 22, 85716 Unterschleißheim / \ \ / ) wo...@us..., http://www.wobsta.de/ / _ \ \/\/ / PyX - High quality PostScript and PDF figures (_/ \_)_/\_/ with Python & TeX: visit http://pyx.sourceforge.net/ |
From: Alan G I. <ai...@am...> - 2009-10-16 15:45:46
|
On 10/16/2009 11:25 AM, André Wobst wrote: > BTW note that sum is designed for numerics only. That seems a bit strong. How about, "numerics originally*. > That's why sum([]) > returns 0 and sum(["spam", "eggs"]) is not allowed. By the way for > strings it even doesn't work with sum(["spam", "eggs"], ""), which I > think is weird I consider it a bug (as a violation of duck typing). There is an efficiency reason to use `join`, but it is beyond weird to enforce it. > Anyway, sum(mypaths, path()) is fine. OK, good. Thanks, Alan |
From: André W. <wo...@us...> - 2009-10-16 16:17:56
Attachments:
smime.p7s
|
Am 16.10.2009 um 17:45 schrieb Alan G Isaac: > On 10/16/2009 11:25 AM, André Wobst wrote: >> BTW note that sum is designed for numerics only. > > That seems a bit strong. How about, "numerics originally*. > >> That's why sum([]) >> returns 0 and sum(["spam", "eggs"]) is not allowed. By the way for >> strings it even doesn't work with sum(["spam", "eggs"], ""), which I >> think is weird > > I consider it a bug (as a violation of duck typing). > There is an efficiency reason to use `join`, but it > is beyond weird to enforce it. Me too. But the numerics-only (without setting a start value) is a good starting point. That allows for a proper return value in case of an empty list in the first parameter of the sum function. For sum([], path.path()) it will be an empty path. That's perfect. And I agree: disallowing sum for strings at all is a weird decision. As this case is already caught, it could also just be done efficiently. "".join() with an empty separator doesn't look too efficient either. Anyway, we're clearly getting off-topic ... :-) André -- by _ _ _ Dr. André Wobst, Amselweg 22, 85716 Unterschleißheim / \ \ / ) wo...@us..., http://www.wobsta.de/ / _ \ \/\/ / PyX - High quality PostScript and PDF figures (_/ \_)_/\_/ with Python & TeX: visit http://pyx.sourceforge.net/ |
From: Alan G I. <ai...@am...> - 2009-10-15 02:51:07
|
On 10/14/2009 6:22 AM, Michael J Gruber wrote: > Using PyX-trafos on points is the > closest you get to PS's rotated coordinate system So is the following a fair statement? Where in PostScript you would transform the user space and construct paths in the transformed space, in Pyx you construct paths in a fixed user space but you can then transform these constructions. Is that about right? Alan Isaac |
From: Michael J G. <mic...@fa...> - 2009-10-15 08:45:13
|
Alan G Isaac venit, vidit, dixit 15.10.2009 04:50: > On 10/14/2009 6:22 AM, Michael J Gruber wrote: >> Using PyX-trafos on points is the >> closest you get to PS's rotated coordinate system > > So is the following a fair statement? > Where in PostScript you would transform the user space > and construct paths in the transformed space, > in Pyx you construct paths in a fixed user space > but you can then transform these constructions. > > Is that about right? I would say that pyx has no stack and no transformable user space as such. But in pyx there are several ways to use transforms: * apply trafos to coordinates (my 1st example) * apply trafos to paths (my 2nd example) * apply trafos to canvases Inserting and transforming canvases is a very powerful and useful method in pyx (see where I translate the canvas in the end), just not for assembling a path where you want the joints to be path connections. I guess that was a long way of saying "Yes" :) Michael |
From: Michael J G. <mic...@fa...> - 2009-10-15 12:00:57
|
André Wobst venit, vidit, dixit 15.10.2009 11:08: > Am 15.10.2009 um 10:36 schrieb Michael J Gruber: > >> Alan G Isaac venit, vidit, dixit 15.10.2009 02:26: >>> On 10/14/2009 6:22 AM, Michael J Gruber wrote: >>>> c = canvas.canvas([style.linewidth(1)]) >>> >>> So I had wondered about this and did >>> not understand the documentation. >>> >>> If one applies a line style to a canvas, I take >>> it that it becomes the default for all stroke operations >>> (by that canvas), including draw operations? >> >> It seems so ;) >> It's not documented (online draw style is), but it works that way. > > See canvas constructor at http://pyx.sourceforge.net/manual/node17.html I know that one, but is style.linewidth() an instance of trafo.trafo, canvas.clip, style.strokestyle or style.fillstyle? I tried anyways, and it worked, of course, because of the way attrs are handed down. > c = canvas() > c2 = canvas() > c.insert(c2, [style.linewidth(1)]) > > Maybe this is too much in terms of user friendliness, but I clearly > like this solution most. >From the user's perspective, this is completely unintuitive, because of the way that inserting a canvas on which you've stroked changes those lines after the fact, unless they've set their width explicitly, and because inserting a canvas inserts a reference or copy, not a deep (!) copy. Try and guess how many lines the following produces, and what width they will have. I know Andre will get it right ;) from pyx import * c = canvas.canvas() c2 = canvas.canvas() c.stroke(path.line(0,0,0,1)) c2.stroke(path.line(1,0,1,1)) c2.stroke(path.line(2,0,2,1), [style.linewidth(0.2)]) c.insert(c2, [style.linewidth(0.4)]) c.stroke(path.line(3,0,3,1)) c2.stroke(path.line(4,0,4,1)) c.writePDFfile(__file__[:-3]) How many (even long time) users will get it right? I don't propose changing the inherent pyx structure which leads to this. But I would really recommend against relying on it for something as simple as setting a default line style. Cheers, Michael SPOILER SPOILER SPOILER SPOILER SPOILER SPOILER SPOILER SPOILER SPOILER Full disclosure: I thought the line at 2 has width 0.4 (because of the order of "assignments" of linewidths) and wasn't sure whether the one at 4 would appear. But I remembered experimenting once with the difference between inserting a canvas, a copy of a canvas and a *deep* copy of a canvas, which explains this. |
From: Joerg L. <jo...@us...> - 2009-10-15 12:42:51
|
Hi Michael, On 15.10.09, Michael J Gruber wrote: > I know that one, but is style.linewidth() an instance of trafo.trafo, > canvas.clip, style.strokestyle or style.fillstyle? I tried anyways, and > it worked, of course, because of the way attrs are handed down. It's an instance of style.strokestyle. On 15.10.09, Michael J Gruber wrote: > from pyx import * >· > c = canvas.canvas() > c2 = canvas.canvas() >· > c.stroke(path.line(0,0,0,1)) > c2.stroke(path.line(1,0,1,1)) > c2.stroke(path.line(2,0,2,1), [style.linewidth(0.2)]) >· > c.insert(c2, [style.linewidth(0.4)]) >· > c.stroke(path.line(3,0,3,1)) > c2.stroke(path.line(4,0,4,1)) >· > c.writePDFfile(__file__[:-3]) >· > How many (even long time) users will get it right? Hey, but that should all be obvious :-) (i) Setting PS attributes is done via the usual PS operators encapsulated in a gsave/grestore pair. The "last" operator of course takes precedence. (ii) There are no copies what so ever involved, so it doesn't matter when - i.e. before or after inserting it - you modifiy the contents of a canvas. > I thought the line at 2 has width 0.4 (because of the order of > "assignments" of linewidths) and wasn't sure whether the one at 4 > would > appear. But I remembered experimenting once with the difference > between > inserting a canvas, a copy of a canvas and a *deep* copy of a canvas, > which explains this. As I said above, there is no copy happening at all! Best, Jörg |
From: Michael J G. <mic...@fa...> - 2009-10-15 14:49:38
|
Joerg Lehmann venit, vidit, dixit 15.10.2009 14:19: > Hi Michael, > > On 15.10.09, Michael J Gruber wrote: >> I know that one, but is style.linewidth() an instance of trafo.trafo, >> canvas.clip, style.strokestyle or style.fillstyle? I tried anyways, and >> it worked, of course, because of the way attrs are handed down. > > It's an instance of style.strokestyle. > > On 15.10.09, Michael J Gruber wrote: >> from pyx import * >> · >> c = canvas.canvas() >> c2 = canvas.canvas() >> · >> c.stroke(path.line(0,0,0,1)) >> c2.stroke(path.line(1,0,1,1)) >> c2.stroke(path.line(2,0,2,1), [style.linewidth(0.2)]) >> · >> c.insert(c2, [style.linewidth(0.4)]) >> · >> c.stroke(path.line(3,0,3,1)) >> c2.stroke(path.line(4,0,4,1)) >> · >> c.writePDFfile(__file__[:-3]) >> · >> How many (even long time) users will get it right? > > Hey, but that should all be obvious :-) Yeah, yeah, I should have said "Andre + Joerg + Michael" ;) > > (i) Setting PS attributes is done via the usual PS operators > encapsulated in a gsave/grestore pair. The "last" operator of course takes > precedence. Of course, the last one is the one when I insert c2 into c. But it does not take precedence. Because it's only the last in py(x) code, not the last one in the resulting ps/pdf code. This is obvious once you know the inner workings. But highly confusing if you think that "canvas.stroke" actually strokes something on a canvas, at the time when you say "stroke". It reminds me of the discussion we're having over at the git list. We can't figure out a user-friendly UI simply because we know the inner workings, so everything is obvious to us, and we can't comprehend how anyone could be confused... Cheers, Michael Cheers, Michael |
From: Alan G I. <ai...@am...> - 2009-10-15 21:44:13
|
So two things I am taking away from this conversation are: 1. PyX is likely to keep its current default line width of about half a point, because this is considered a better match for the traditional TeX fonts. 2. To reset the default line width, there is no "obvious" (to the ordinary user) way, but Michael G.'s method is considered acceptable: c = canvas.canvas(atrrs=[style.linewidth(1)]) Hope that's an accurate summary, Alan |
From: André W. <wo...@us...> - 2009-10-16 15:26:10
Attachments:
smime.p7s
|
Am 15.10.2009 um 23:28 schrieb Alan G Isaac: > So two things I am taking away from this conversation are: > > 1. PyX is likely to keep its current default line width > of about half a point, because this is considered a better > match for the traditional TeX fonts. > > 2. To reset the default line width, there is no "obvious" > (to the ordinary user) way, but Michael G.'s method is > considered acceptable: > c = canvas.canvas(atrrs=[style.linewidth(1)]) > > Hope that's an accurate summary, Indeed, you did very well! André -- by _ _ _ Dr. André Wobst, Amselweg 22, 85716 Unterschleißheim / \ \ / ) wo...@us..., http://www.wobsta.de/ / _ \ \/\/ / PyX - High quality PostScript and PDF figures (_/ \_)_/\_/ with Python & TeX: visit http://pyx.sourceforge.net/ |