0

I am clearly misunderstanding how closed curves and filling a closed curve works in PyX. I'm building a closed curve from four parts, but the filling fails depending on how I define one of the four curves. Below is a minimal working/failing example and the output. Why does the first definition of upArc work but the second one does not?

from pyx import *
c = canvas.canvas()
cL = canvas.canvas()
cR = canvas.canvas()


upArc = path.path(path.arc(0,3,1,180,0))
right = path.line(1,3,1,0)
downArc = path.path(path.arcn(0,0,1,0,180))
left  = path.line(-1,0,-1,3)
p = upArc+right+downArc<<left

cR.fill(p,[color.rgb.blue])
cR.stroke(p)


upArc = path.path(path.arc(0,0,1,180,0)).transformed(trafo.translate(0,3))
right = path.line(1,3,1,0)
downArc = path.path(path.arcn(0,0,1,0,180))
left  = path.line(-1,0,-1,3)
p = upArc+right+downArc<<left

cL.fill(p,[color.rgb.blue])
cL.stroke(p)



c.insert(cL,[trafo.translate(-2,0)])
c.insert(cR,[trafo.translate( 2,0)])
c.writePDFfile("minfail")

A picture of the results. A picture of the results.

Rami Luisto
  • 229
  • 1
  • 9
  • You can use `c.draw(p, [trafo.translate(2, 0), deco.filled([color.rgb.blue]), deco.stroked(])])` to stroke and fill in one step on the canvas `c`. This is better, as the path will be contained once only in the output. – wobsta May 29 '18 at 06:31
  • Thank you also for this, @wobsta, I had the feeling that my code has superfluous repetition (in other places as well); once I start to feel more at home with the structure of PyX I have to figure out how to do these things properly instead of just in the minimal working fashion. All advice and comments on the way are thus much welcomed! – Rami Luisto May 29 '18 at 13:07

1 Answers1

1

PyX uses the postscript path model, which can contain several subpaths within a path. (Think of using a path element moveto within a path.) When filling such paths, things like you observe happen. Note that the arc contains an implicit moveto at the beginning, which for filling is taken like a lineto, but not for stroking. This is why it makes a difference to use the add operator + and the join operator <<. Switching to join resolves your problem.

(You can use

print(p.normpath().normsubpaths)

to see, that you have several normsubpaths when adding the paths, even though the arclen does not alter, as the moveto commands from one normsubpath to the next are not part of the arc length.)

wobsta
  • 721
  • 4
  • 5
  • Thank you, this was frustrating me to no end! I clearly need to re-read the PyX manual and study (again) how postscipt works under the hood, but with this I'll be able to finish a few illustrations before diving into the deep end. – Rami Luisto May 29 '18 at 13:03
  • Note that when joining paths, PyX inserts straight lines automatically from the previous endpoint to the next starting point. So you can omit creating the lines. At the end you should close the path by `p.append(path.closepath())`. When filling, it doesn't matter, as it automacially closes the path, i.e. each normsubpath separately. This is the actual reason for your observed behaviour. Stroking however doesn't show this final closing line ... which is precisely how Postscript works with paths. – wobsta May 30 '18 at 05:21
  • Ah, this should also help remove some redundancy, since I have in several places felt a bit silly typing `x,y = p1.atend()`, `a,b = p2.atbegin()`, `p3 = path.line(x,y,a,b)` etc. Thank you once more! – Rami Luisto May 30 '18 at 12:50