From: Alan G I. <ai...@am...> - 2009-10-16 21:37:09
|
A picture is worth 1000 words: import pyx from pyx.path import path, moveto, rlineto, closepath c = pyx.canvas.canvas(attrs=[pyx.style.linewidth(1),pyx.style.linejoin(0)]) triangle = path(moveto(0,0), rlineto(6,0)) x,y = pyx.trafo.rotate(120).apply(6,0) triangle.extend([rlineto(x,y),closepath()]) c.stroke(triangle) c.writeEPSfile('c:/temp/temp.eps') As you see, the corners are cut off of every vertex of the triangle. (Current SVN.) Cheers, Alan Isaac |
From: Michael S. <m-s...@us...> - 2009-10-17 13:27:24
|
Hello, On 16.10.09, Alan G Isaac wrote: > As you see, the corners are cut off of every vertex of > the triangle. (Current SVN.) The effect you describe is well known. In fact, we discussed about it many years ago and decided to leave it like it is. The problem is that the true bounding box of a picture does depend on both the paths and the respective linewidth. It is simple to calculate bounding boxes for lines; for curves it is more difficult. PyX calculates these two. Including also the linewidth and stroke effects coming from the different linejoin parameters is really difficult. We decided not to do this, as it would lead to a reimplementation of ghostscript. This is why canvas.writeEPSfile and the equivalent for PDF take a parameter "bboxenlarge". This is meant to serve as a workaround for the above problem. It is set to 1pt by default. As you increased the linewidth to 1cm, you should play also with this parameter. You may also use ghostscript to calculate the true bounding box: gs -dNOPAUSE -q -dBATCH -sDEVICE=bbox Michael -- 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-17 15:23:54
|
On 10/17/2009 9:26 AM, Michael SCHINDLER wrote: > The problem is that > the true bounding box of a picture does depend on both the paths and > the respective linewidth. It is simple to calculate bounding boxes for > lines; for curves it is more difficult. PyX calculates these two. > Including also the linewidth and stroke effects coming from the > different linejoin parameters is really difficult. We decided not to > do this, as it would lead to a reimplementation of ghostscript. Did you consider using Bless's bbox code (comes with ps2eps, GPL license)? It would be really nice to get a better bounding box. Thanks, Alan Isaac |
From: Joerg L. <jo...@us...> - 2009-10-18 11:56:27
|
Hi, On 17.10.09, Alan G Isaac wrote: > On 10/17/2009 9:26 AM, Michael SCHINDLER wrote: > > The problem is that > > the true bounding box of a picture does depend on both the paths and > > the respective linewidth. It is simple to calculate bounding boxes for > > lines; for curves it is more difficult. PyX calculates these two. > > Including also the linewidth and stroke effects coming from the > > different linejoin parameters is really difficult. We decided not to > > do this, as it would lead to a reimplementation of ghostscript. > > Did you consider using Bless's bbox code (comes with ps2eps, GPL license)? I guess, you mean this code: http://www.tex.ac.uk/tex-archive/support/ps2eps/src/C/bbox.c Unfortunately, it requires having a rasterized version of the graphics output. > It would be really nice to get a better bounding box. From a perfectionists point of view, I would agree. Practically, however, it only very seldomnly happened that the bounding box produced by PyX was not good enough. Best, Jörg |
From: Axel F. <fre...@us...> - 2009-10-18 12:59:30
|
Hi, Another proposal: I'm using the following code when I need a precise Bounding Box - letting ghostscript do the job: def GetBB(c, filename="-", resolution=100, gscommand="grep -v -E '^%%(HiRes)?BoundingBox' | gs", gsoptions="", textalphabits=4, graphicsalphabits=4, ciecolor=False, **kwargs): gscommand += " -dEPSCrop -dNOPAUSE -dQUIET -dBATCH -r%i -q -sDEVICE=bbox -sOutputFile=%s" % (resolution, filename) if gsoptions: gscommand += " %s" % gsoptions if textalphabits is not None: gscommand += " -dTextAlphaBits=%i" % textalphabits if graphicsalphabits is not None: gscommand += " -dGraphicsAlphaBits=%i" % graphicsalphabits if ciecolor: gscommand += " -dUseCIEColor" gscommand += " -" pipe_in, pipe_out, pipe_err = os.popen3(gscommand) c.writeEPSfile(pipe_in, **kwargs) pipe_in.close() for line in pipe_err.readlines(): m=re.match(r"^%%HiResBoundingBox: ([-0-9\.]*) ([-0-9\.]*) ([0-9\.]*) ([0-9\.]*)$",line) if m != None: b = map(lambda x: unit.length(float(x),unit="pt"), m.groups()) return bbox.bbox(b[0],b[1],b[2],b[3]) raise IOError("Can't determine BoundingBox") It's more or less a copy of "canvas.pipeGS", however: - as ghostscript writes the bbox onto the standard error-stream, I need "os.popen3" to get the result from within python. - I use a trivial regexp to get the boundingboxes-Data - I use "grep" to guarantee that pyx is not passing its BoundingBox-Date to ghostscript. With that code, I can pass an arbitrary canvas to "GetBB", and it will return the precise boundingBox - including linewidth. However, the huge problem is: my ghostscript gives wrong results for negative coordinates - maybe it's just a question of the parameters? Axel On Sun, Oct 18, 2009 at 01:56:12PM +0200, Joerg Lehmann wrote: > Hi, > > On 17.10.09, Alan G Isaac wrote: > > On 10/17/2009 9:26 AM, Michael SCHINDLER wrote: > > > The problem is that > > > the true bounding box of a picture does depend on both the paths and > > > the respective linewidth. It is simple to calculate bounding boxes for > > > lines; for curves it is more difficult. PyX calculates these two. > > > Including also the linewidth and stroke effects coming from the > > > different linejoin parameters is really difficult. We decided not to > > > do this, as it would lead to a reimplementation of ghostscript. > > > > Did you consider using Bless's bbox code (comes with ps2eps, GPL license)? > > I guess, you mean this code: > > http://www.tex.ac.uk/tex-archive/support/ps2eps/src/C/bbox.c > > Unfortunately, it requires having a rasterized version of the graphics > output. > > > It would be really nice to get a better bounding box. > > From a perfectionists point of view, I would agree. Practically, > however, it only very seldomnly happened that the bounding box produced > by PyX was not good enough. > > Best, > > Jörg |
From: André W. <wo...@us...> - 2009-10-19 14:04:07
Attachments:
smime.p7s
|
Alan, I just want to note, that the situation has already improved a lot. In earlier versions, PyX did not calculate proper bounding boxes for bezier curves and did not take into account the line width at all in the calculation of the bounding boxes. This is fixed for some time already. It is related to some rework in the output system, where we now are able to keep the graphics state (and thus the current line width at the moment). The only errors left result from path (element) endings. We do not acknowledge linecap, linejoin, and miterlimit. It is possible to add that, but nobody did it so far. We would also need to implement this for all path elements, not just the normpaths, as we certainly don't want to force everything to become normpaths. However, the issue should be still manageable, as we only need to take into account the path element ends. Still, I don't see somebody just implementing it in the near future. Best, André Am 16.10.2009 um 23:36 schrieb Alan G Isaac: > A picture is worth 1000 words: > > import pyx > from pyx.path import path, moveto, rlineto, closepath > c = pyx.canvas.canvas(attrs=[pyx.style.linewidth > (1),pyx.style.linejoin(0)]) > triangle = path(moveto(0,0), rlineto(6,0)) > x,y = pyx.trafo.rotate(120).apply(6,0) > triangle.extend([rlineto(x,y),closepath()]) > c.stroke(triangle) > c.writeEPSfile('c:/temp/temp.eps') > > As you see, the corners are cut off of every vertex of > the triangle. (Current SVN.) > > Cheers, > Alan Isaac > > ------------------------------------------------------------------------------ > Come build with us! The BlackBerry(R) Developer Conference in SF, CA > is the only developer event you need to attend this year. Jumpstart > your > developing skills, take BlackBerry mobile applications to market and > stay > ahead of the curve. Join us from November 9 - 12, 2009. Register now! > http://p.sf.net/sfu/devconference > _______________________________________________ > PyX-user mailing list > PyX...@li... > https://lists.sourceforge.net/lists/listinfo/pyx-user -- 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-21 16:04:41
|
On 10/19/2009 10:03 AM, André Wobst wrote: > the issue should be still manageable, as we only need to take into > account the path element ends. > > Still, I don't see somebody just implementing it in the near future. Understood. Perhaps making it easy to get a bounding box from GhostScript (if installed) would be worth while? I'm going to guess that most PyX users install GhostScript. (?) In the meantime, I can work around this. Thanks, Alan |
From: Axel F. <fre...@us...> - 2009-10-21 16:33:56
|
Hi, On Wed, Oct 21, 2009 at 12:04:19PM -0400, Alan G Isaac wrote: > On 10/19/2009 10:03 AM, André Wobst wrote: > > the issue should be still manageable, as we only need to take into > > account the path element ends. > > > > Still, I don't see somebody just implementing it in the near future. > > Understood. > Perhaps making it easy to get a bounding box from GhostScript > (if installed) would be worth while? I'm going to guess that > most PyX users install GhostScript. (?) then just use my example - maybe changed like this: def GetBB(c, filename="-", resolution=100, gscommand="grep -v -E '^%%(HiRes)?BoundingBox' | gs", gsoptions="", textalphabits=4, graphicsalphabits=4, ciecolor=False, xshift = 10, yshift = 10, **kwargs): gscommand += " -dEPSFit -dNOPAUSE -dQUIET -dBATCH -r%i -q -sDEVICE=bbox -sOutputFile=%s" % (resolution, filename) if gsoptions: gscommand += " %s" % gsoptions if textalphabits is not None: gscommand += " -dTextAlphaBits=%i" % textalphabits if graphicsalphabits is not None: gscommand += " -dGraphicsAlphaBits=%i" % graphicsalphabits if ciecolor: gscommand += " -dUseCIEColor" gscommand += " -" pipe_in, pipe_out, pipe_err = os.popen3(gscommand) c1 = canvas.canvas() c1.insert(c,[trafo.translate(xshift,yshift)]) c1.writeEPSfile(pipe_in, **kwargs) pipe_in.close() for line in pipe_err.readlines(): m=re.match(r"^%%HiResBoundingBox: ([-0-9\.]*) ([-0-9\.]*) ([0-9\.]*) ([0-9\.]*)$",line) if m != None: b = map(lambda x: unit.length(float(x),unit="pt"), m.groups()) return bbox.bbox(b[0]-xshift,b[1]-yshift,b[2]-10,b[3]-10) raise IOError("Can't determine BoundingBox") This includes a simple translation in order to obtain positive bounding boxes (may be you have to pass larger values for xshift and yshift). In the example: c = pyx.canvas.canvas(attrs=[pyx.style.linewidth(1),pyx.style.linejoin(0)]) triangle = path(moveto(0,0), rlineto(6,0)) x,y = pyx.trafo.rotate(120).apply(6,0) triangle.extend([rlineto(x,y),closepath()]) c.stroke(triangle) bbox = GetBB(c) c.writeEPSfile("bbox",bbox=bbox) I obtain a perfect bounding box;-) Axel |
From: Alan G I. <ai...@am...> - 2009-10-24 15:00:19
|
On 10/21/2009 12:33 PM, Axel Freyn wrote: > bbox = GetBB(c) > c.writeEPSfile("bbox",bbox=bbox) > > I obtain a perfect bounding box;-) Thanks. I'd like to see something like this in PyX, even though it depends on GhostScript... Alan |