Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.postscript > #2861 > unrolled thread
| Started by | Lawrence D’Oliveiro <lawrencedo99@gmail.com> |
|---|---|
| First post | 2016-10-05 18:24 -0700 |
| Last post | 2016-10-19 17:15 -0700 |
| Articles | 20 on this page of 42 — 10 participants |
Back to article view | Back to comp.lang.postscript
Getting Rid Of PostScript Lawrence D’Oliveiro <lawrencedo99@gmail.com> - 2016-10-05 18:24 -0700
Re: Getting Rid Of PostScript Lawrence D’Oliveiro <lawrencedo99@gmail.com> - 2016-10-06 14:50 -0700
Re: Getting Rid Of PostScript jdaw1 <jdawiseman@gmail.com> - 2016-10-06 15:45 -0700
Re: Getting Rid Of PostScript Lawrence D’Oliveiro <lawrencedo99@gmail.com> - 2016-10-06 17:44 -0700
Re: Getting Rid Of PostScript Mark Carroll <mtbc@bcs.org> - 2016-10-07 08:47 +0100
Re: Getting Rid Of PostScript Lawrence D’Oliveiro <lawrencedo99@gmail.com> - 2016-10-07 15:08 -0700
Re: Getting Rid Of PostScript luser droog <luser.droog@gmail.com> - 2016-10-07 18:47 -0700
Re: Getting Rid Of PostScript Mark Carroll <mtbc@bcs.org> - 2016-10-08 12:34 +0100
Re: Getting Rid Of PostScript luser droog <luser.droog@gmail.com> - 2016-10-07 18:39 -0700
Re: Getting Rid Of PostScript Lawrence D’Oliveiro <lawrencedo99@gmail.com> - 2016-10-07 19:07 -0700
Re: Getting Rid Of PostScript luser droog <luser.droog@gmail.com> - 2016-10-12 15:32 -0700
Re: Getting Rid Of PostScript Lawrence D’Oliveiro <lawrencedo99@gmail.com> - 2016-10-12 17:06 -0700
Re: Getting Rid Of PostScript rodd@panix.com (Rod Dorman) - 2016-10-13 19:07 +0000
Re: Getting Rid Of PostScript Lawrence D’Oliveiro <lawrencedo99@gmail.com> - 2016-10-13 15:02 -0700
Re: Getting Rid Of PostScript rodd@panix.com (Rod Dorman) - 2016-10-14 20:13 +0000
Re: Getting Rid Of PostScript Lawrence D’Oliveiro <lawrencedo99@gmail.com> - 2016-10-14 14:39 -0700
Re: Getting Rid Of PostScript Martin Leese <please@see.Web.for.e-mail.INVALID> - 2016-10-16 10:40 -0600
Re: Getting Rid Of PostScript Lawrence D’Oliveiro <lawrencedo99@gmail.com> - 2016-10-17 18:06 -0700
Re: Getting Rid Of PostScript Alan <alan.isaac@gmail.com> - 2016-10-17 18:44 -0700
Re: Getting Rid Of PostScript Lawrence D’Oliveiro <lawrencedo99@gmail.com> - 2016-10-17 22:43 -0700
Re: Getting Rid Of PostScript Martin Leese <please@see.Web.for.e-mail.INVALID> - 2016-10-18 10:13 -0600
Re: Getting Rid Of PostScript Lawrence D’Oliveiro <lawrencedo99@gmail.com> - 2016-10-18 15:28 -0700
Re: Getting Rid Of PostScript Lawrence D’Oliveiro <lawrencedo99@gmail.com> - 2016-10-18 15:35 -0700
Re: Getting Rid Of PostScript Ross Presser <rpresser@gmail.com> - 2016-10-18 23:05 -0700
Re: Getting Rid Of PostScript Carlos <angus@quovadis.com.ar> - 2016-10-19 19:23 +0200
Re: Getting Rid Of PostScript Lawrence D’Oliveiro <lawrencedo99@gmail.com> - 2016-10-19 17:17 -0700
Re: Getting Rid Of PostScript Ross Presser <rpresser@gmail.com> - 2016-10-21 09:18 -0700
Re: Getting Rid Of PostScript Lawrence D’Oliveiro <lawrencedo99@gmail.com> - 2016-10-21 18:10 -0700
Re: Getting Rid Of PostScript Ross Presser <rpresser@gmail.com> - 2016-10-21 09:14 -0700
Re: Getting Rid Of PostScript Markus Triska <triska@metalevel.at> - 2016-10-19 20:55 +0200
Re: Getting Rid Of PostScript Lawrence D’Oliveiro <lawrencedo99@gmail.com> - 2016-10-19 17:57 -0700
Re: Getting Rid Of PostScript Lawrence D’Oliveiro <lawrencedo99@gmail.com> - 2016-10-24 16:54 -0700
Re: Getting Rid Of PostScript Carlos <angus@quovadis.com.ar> - 2016-10-25 16:26 +0200
Re: Getting Rid Of PostScript Lawrence D’Oliveiro <lawrencedo99@gmail.com> - 2016-10-25 10:32 -0700
Re: Getting Rid Of PostScript Carlos <angus@quovadis.com.ar> - 2016-10-25 21:06 +0200
Re: Getting Rid Of PostScript Lawrence D’Oliveiro <lawrencedo99@gmail.com> - 2016-11-14 15:15 -0800
Re: Getting Rid Of PostScript Carlos <angus@quovadis.com.ar> - 2016-11-16 00:17 +0100
Re: Getting Rid Of PostScript Carlos <angus@quovadis.com.ar> - 2016-11-21 18:37 +0100
Re: Getting Rid Of PostScript Carlos <angus@quovadis.com.ar> - 2016-11-21 18:39 +0100
Re: Getting Rid Of PostScript Markus Triska <triska@metalevel.at> - 2016-10-25 20:52 +0200
Re: Getting Rid Of PostScript Alan <alan.isaac@gmail.com> - 2016-10-19 16:41 -0700
Re: Getting Rid Of PostScript Lawrence D’Oliveiro <lawrencedo99@gmail.com> - 2016-10-19 17:15 -0700
Page 2 of 3 — ← Prev page 1 [2] 3 Next page →
| From | Martin Leese <please@see.Web.for.e-mail.INVALID> |
|---|---|
| Date | 2016-10-18 10:13 -0600 |
| Message-ID | <nu5hm5$k6i$1@dont-email.me> |
| In reply to | #2903 |
Lawrence D’Oliveiro wrote: > On Tuesday, October 18, 2016 at 2:44:24 PM UTC+13, Alan wrote: >> On Monday, October 17, 2016 at 9:07:05 PM UTC-4, Lawrence D’Oliveiro wrote: >> >>> PostScript still wouldn’t be as good a graphics language as Python. >> I don't even know what this claim means. > > It means what it says. The key is the definition of "good". If you define good to mean "supported by Adobe" then the answer becomes clear. Other definitions lead to different answers. Different computer languages have different strengths and weaknesses. Discussions about which are good, better or best go nowhere. -- Regards, Martin Leese E-mail: please@see.Web.for.e-mail.INVALID Web: http://members.tripod.com/martin_leese/
[toc] | [prev] | [next] | [standalone]
| From | Lawrence D’Oliveiro <lawrencedo99@gmail.com> |
|---|---|
| Date | 2016-10-18 15:28 -0700 |
| Message-ID | <ea302921-8502-4ec3-9832-41234dea194c@googlegroups.com> |
| In reply to | #2904 |
On Wednesday, October 19, 2016 at 5:13:15 AM UTC+13, Martin Leese wrote:
>
> On Monday, October 17, 2016 at 9:07:05 PM UTC-4, Lawrence D’Oliveiro wrote:
>
>> PostScript still wouldn’t be as good a graphics language as Python.
>
> The key is the definition of "good".
“Good” as in “fit for purpose”. For example, here is an elementary example: computing a fillet arc at a corner between two intersecting straight lines: <http://default-cube.deviantart.com/art/Fillet-631797773>.
In the Python code <https://github.com/ldo/qahirah_examples/blob/master/fillet>, the lines are defined by three points p0, p1 and p2, so they intersect at p1. Given the radius r of the fillet circle, we need to compute two points, t1 and t2, where the fillet arc is tangent to the lines. Having computed “inset” (the distance of t1 and t2 from p1), determining t1 and t2 is quite easy, e.g.:
t1 = p1 + Vector.unit((p0 - p1).angle()) * inset
This is because Python lets me define a “Vector” type in my Cairo binding (which Cairo itself does not have!), complete with a full set of corresponding arithmetic operations, so that I can compute both the x- and y-coordinate of a point in a single formula.
PostScript has no such type, so at a minimum you would have to write out the above formula twice, once for each coordinate. On top of having to write out your own formulas for computing vector directions.
[toc] | [prev] | [next] | [standalone]
| From | Lawrence D’Oliveiro <lawrencedo99@gmail.com> |
|---|---|
| Date | 2016-10-18 15:35 -0700 |
| Message-ID | <effed4e0-4474-44f0-b9c8-1c28cd17b95c@googlegroups.com> |
| In reply to | #2904 |
On Wednesday, October 19, 2016 at 5:13:15 AM UTC+13, Martin Leese wrote: > If you define good to mean "supported by Adobe" then > the answer becomes clear. What becomes clear is that PostScript is hardly “supported” by Adobe any more. The company itself thinks its fortunes now lie elsewhere. Look at the forlorn wishlist accumulating in the “PostScript desiderata” thread; look also at the bugs people keep finding with Distiller, that have gone unfixed for so long. Basically, the only implementation of PostScript still worth using is Ghostscript. Is PostScript itself still worth using? Only for backward compatibility; not for anything new.
[toc] | [prev] | [next] | [standalone]
| From | Ross Presser <rpresser@gmail.com> |
|---|---|
| Date | 2016-10-18 23:05 -0700 |
| Message-ID | <4bf74c64-049f-436d-b19d-0a5b2e41883b@googlegroups.com> |
| In reply to | #2906 |
On Tuesday, October 18, 2016 at 6:35:39 PM UTC-4, Lawrence D’Oliveiro wrote: > Basically, the only implementation of PostScript still worth using > is Ghostscript. Is PostScript itself still worth using? Only for > backward compatibility; not for anything new. I continue to be confused as to why you are proseletyzing against Postscript in a group named comp.lang.postscript. The group isn't named comp.lang.kill-all-postscript-lovers. Can you take it elsewhere, or are you congentially incapable of leaving people to their own enthusiasms?
[toc] | [prev] | [next] | [standalone]
| From | Carlos <angus@quovadis.com.ar> |
|---|---|
| Date | 2016-10-19 19:23 +0200 |
| Message-ID | <20161019192339.28665fad@samara.DOMA> |
| In reply to | #2907 |
[Ross Presser <rpresser@gmail.com>, 2016-10-18 23:05] > On Tuesday, October 18, 2016 at 6:35:39 PM UTC-4, Lawrence > D’Oliveiro wrote: > > Basically, the only implementation of PostScript still worth using > > is Ghostscript. Is PostScript itself still worth using? Only for > > backward compatibility; not for anything new. > > I continue to be confused as to why you are proseletyzing against > Postscript in a group named comp.lang.postscript. The group isn't > named comp.lang.kill-all-postscript-lovers. Can you take it > elsewhere, or are you congentially incapable of leaving people to > their own enthusiasms? I disagree. I think criticism of PostScript and negative opinions should be welcome, especially when they are founded. In my case, they don't diminish my enthusiasm about the language at all. But in any case, by request, he's mainly restricting criticism to this thread, so if you don't like to read it, why don't you just ignore the thread? Any newsreader should have that capability. --
[toc] | [prev] | [next] | [standalone]
| From | Lawrence D’Oliveiro <lawrencedo99@gmail.com> |
|---|---|
| Date | 2016-10-19 17:17 -0700 |
| Message-ID | <f5ce2ffa-83a1-454e-8144-b231532c8e62@googlegroups.com> |
| In reply to | #2908 |
On Thursday, October 20, 2016 at 6:24:13 AM UTC+13, Carlos wrote: > > ... why don't you just ignore the thread? Which, of course, the trolls are never going to do. You can tell they are trolls: they love to criticize and complain about others, yet they cannot actually offer any evidence (such as working code) in support of their criticisms. For example, consider that I began this thread by offering examples of code, with and without using PostScript, to show how the latter was so much simpler than the former. Yet it seems nobody has paid the slightest bit of notice.
[toc] | [prev] | [next] | [standalone]
| From | Ross Presser <rpresser@gmail.com> |
|---|---|
| Date | 2016-10-21 09:18 -0700 |
| Message-ID | <c067bacb-1e54-42a2-9994-768017f6861a@googlegroups.com> |
| In reply to | #2912 |
On Wednesday, October 19, 2016 at 8:17:17 PM UTC-4, Lawrence D’Oliveiro wrote: > On Thursday, October 20, 2016 at 6:24:13 AM UTC+13, Carlos wrote: > > > > ... why don't you just ignore the thread? > > Which, of course, the trolls are never going to do. > > You can tell they are trolls: they love to criticize and complain > about others, yet they cannot actually offer any evidence (such as > working code) in support of their criticisms. You seem to have a misunderstanding of the word "troll". Perhaps you are trying to refer to people who dislike your preference. That is not a troll. A troll is one who posts outrageous or inflammatory language solely to watch the fireworks spread. I am not trolling. I admit I am complaining. I am not trolling. > For example, consider that I began this thread by offering > examples of code, with and without using PostScript, to show how > the latter was so much simpler than the former. Yet it seems > nobody has paid the slightest bit of notice. Nobody has paid the slightest bit of notice because practically nobody is interested. You have a hobby horse: you want people to use Python and Cairo instead of Postscript. That's interesting in its own right. But declaring that Postscript *MUST* *BE* *ABANDONED* in favor of your hobby horse just doesn't make good conversation.
[toc] | [prev] | [next] | [standalone]
| From | Lawrence D’Oliveiro <lawrencedo99@gmail.com> |
|---|---|
| Date | 2016-10-21 18:10 -0700 |
| Message-ID | <97412cc8-8144-49cc-a4b2-aba860ff6445@googlegroups.com> |
| In reply to | #2915 |
On Saturday, October 22, 2016 at 5:18:16 AM UTC+13, Ross Presser wrote: > > On Wednesday, October 19, 2016 at 8:17:17 PM UTC-4, Lawrence > D’Oliveiro wrote: > >> You can tell they are trolls: they love to criticize and complain >> about others, yet they cannot actually offer any evidence (such as >> working code) in support of their criticisms. > > You seem to have a misunderstanding of the word "troll". Well, somebody who posts just to say “I’m not interested in reading what you post” would seem to fit the bill. > Nobody has paid the slightest bit of notice because practically > nobody is interested. I rest my case.
[toc] | [prev] | [next] | [standalone]
| From | Ross Presser <rpresser@gmail.com> |
|---|---|
| Date | 2016-10-21 09:14 -0700 |
| Message-ID | <08b471b2-48e5-40d0-b1af-f25414484d60@googlegroups.com> |
| In reply to | #2908 |
On Wednesday, October 19, 2016 at 1:24:13 PM UTC-4, Carlos wrote: > But in any case, by > request, he's mainly restricting criticism to this thread, so if you > don't like to read it, why don't you just ignore the thread? Any > newsreader should have that capability. Well, his discouragement was all over every thread. If he's stopped spreading it around so much then it's not so objectionable.
[toc] | [prev] | [next] | [standalone]
| From | Markus Triska <triska@metalevel.at> |
|---|---|
| Date | 2016-10-19 20:55 +0200 |
| Message-ID | <m2bmyg6ue8.fsf@metalevel.at> |
| In reply to | #2906 |
Lawrence D’Oliveiro <lawrencedo99@gmail.com> writes:
> Look at the forlorn wishlist accumulating in the “PostScript
> desiderata” thread; look also at the bugs people keep finding with
> Distiller, that have gone unfixed for so long.
This is not the first time that a deep need is not met. For example,
there was a similar problem with version control systems for decades:
No good system even remotely in sight. Then, after decades, suddenly
several amazing contenders entered the scene, and one of them changed
the landscape significantly. In my view, the last word on this is not
yet spoken, and until this is all fixed, a list is nice to have.
> Basically, the only implementation of PostScript still worth using is
> Ghostscript. Is PostScript itself still worth using? Only for backward
> compatibility; not for anything new.
That is not my experience at all. For example, only recently I wanted to
typeset the cycle graph C_{100} for a scientific publication. Space was
tight, much like in the lines of this paragraph. I wanted a layout that
showed:
-) the *number* of each node
-) the *weight* of each node, either 1 or -1
-) whether the node is part of a kernel.
A few simple PostScript definitions sufficed to let me quickly and
easily experiment with many different layouts of this graph and the
variants I needed.
In this case and many others like it, PostScript was invaluable to me to
quickly try different layouts, using a suitable domain-specific language
that I implemented within PostScript itself.
If you want to try this yourself, here is the data I visualized:
The nodes (of 1..100 in total) that constitute the kernel:
1 3 6 9 12 15 18 20 23 25 27 30 33 36 39 41 43 46 48 51 54 57 60 63 66
68 71 73 75 78 80 83 86 89 92 95 97 99
The weight of each node, as a PostScript array:
/weights [-1 -1 1 -1 1 1 -1 -1 1 1 -1 1 -1 -1 1 -1 1 1 -1 1 -1 -1 1
1 -1 -1 1 -1 1 1 -1 -1 1 1 -1 1 -1 -1 1 1 -1 -1 1 -1 1 1 -1 1 -1 -1
1 -1 1 1 -1 -1 1 1 -1 1 -1 -1 1 -1 1 1 -1 1 -1 -1 1 1 -1 -1 1 -1 1 1
-1 1 -1 -1 1 -1 1 1 -1 -1 1 1 -1 1 -1 -1 1 1 -1 -1 1 -1] def
And yes, I indirectly used GhostScript to easily inspect these layouts.
I say "indirectly" because I actually previewed these graphs directly
within Emacs (where I also wrote the PostScript code), which uses
GhostScript to convert the PostScript file to a PNG file which is then
displayed within Emacs. Personally, I have no need for a second program
that does the same as GhostScript, so a single implementation of
PostScript is sufficient for me and no argument against the language.
All the best,
Markus
[toc] | [prev] | [next] | [standalone]
| From | Lawrence D’Oliveiro <lawrencedo99@gmail.com> |
|---|---|
| Date | 2016-10-19 17:57 -0700 |
| Message-ID | <68890a35-ae58-4755-b6be-5f8a7d4b0362@googlegroups.com> |
| In reply to | #2909 |
On Thursday, October 20, 2016 at 7:55:31 AM UTC+13, Markus Triska wrote:
> Lawrence D’Oliveiro writes:
>
>> Basically, the only implementation of PostScript still worth using is
>> Ghostscript. Is PostScript itself still worth using? Only for backward
>> compatibility; not for anything new.
>
> That is not my experience at all.
You agree with the first part, though: the only implementation still worth using is Ghostscript.
> For example, only recently I wanted to
> typeset the cycle graph C_{100} for a scientific publication. Space was
> tight, much like in the lines of this paragraph. I wanted a layout that
> showed:
>
> -) the *number* of each node
> -) the *weight* of each node, either 1 or -1
> -) whether the node is part of a kernel.
>
> A few simple PostScript definitions sufficed to let me quickly and
> easily experiment with many different layouts of this graph and the
> variants I needed.
>
> In this case and many others like it, PostScript was invaluable to me to
> quickly try different layouts, using a suitable domain-specific language
> that I implemented within PostScript itself.
>
> And yes, I indirectly used GhostScript to easily inspect these layouts.
> I say "indirectly" because I actually previewed these graphs directly
> within Emacs (where I also wrote the PostScript code), which uses
> GhostScript to convert the PostScript file to a PNG file which is then
> displayed within Emacs.
I use Emacs too, but not for that. For this kind of graphical visualization, I prefer to use Jupyter with the IPython kernel.
First, some definitions to create and manage a drawing surface:
from IPython.display import \
display_png
import qahirah as qah
from qahirah import \
CAIRO, \
Colour, \
Matrix, \
Path, \
Rect, \
Vector
pix = qah.ImageSurface.create \
(
format = CAIRO.FORMAT_RGB24,
dimensions = (400, 400)
)
ctx = None
def reset() :
"(re)initializes the drawing context, wiping out any existing drawing."
global ctx
del ctx
ctx = qah.Context.create(pix)
(ctx
.save()
.set_source_colour(Colour.grey(.95))
.paint()
.restore()
.select_font_face("sens serif", CAIRO.FONT_SLANT_NORMAL, CAIRO.FONT_WEIGHT_NORMAL)
)
#end reset
def display() :
"(re)displays what has been drawn."
display_png(pix.to_png_bytes(), raw = True)
#end display
The data you provided, converted to Python form:
kernel = \
{
1, 3, 6, 9, 12, 15, 18, 20, 23, 25,
27, 30, 33, 36, 39, 41, 43, 46, 48, 51,
54, 57, 60, 63, 66, 68, 71, 73, 75, 78,
80, 83, 86, 89, 92, 95, 97, 99,
}
weights = \
[
-1, -1, 1, -1, 1, 1, -1, -1, 1, 1,
-1, 1, -1, -1, 1, -1, 1, 1, -1, 1,
-1, -1, 1, 1, -1, -1, 1, -1, 1, 1,
-1, -1, 1, 1, -1, 1, -1, -1, 1, 1,
-1, -1, 1, -1, 1, 1, -1, 1, -1, -1,
1, -1, 1, 1, -1, -1, 1, 1, -1, 1,
-1, -1, 1, -1, 1, 1, -1, 1, -1, -1,
1, 1, -1, -1, 1, -1, 1, 1, -1, 1,
-1, -1, 1, -1, 1, 1, -1, -1, 1, 1,
-1, 1, -1, -1, 1, 1, -1, -1, 1, -1,
]
def in_kernel(node_nr) :
"node_nr is in [1 .. 100]."
return \
(node_nr - 1) in kernel
#end in_kernel
def get_weight(node_nr) :
"node_nr is in [1 .. 100]."
return \
weights[node_nr - 1]
#end get_weight
Here is an example routine which, given a “draw_node” action that actually draws each node, lays them out in a square grid:
def draw_nodes_grid(draw_node) :
reset()
cell_dims = pix.dimensions / Vector(10, 10)
for row in range(10) :
for col in range(10) :
node_nr = row * 10 + col + 1
bounds = Rect.from_corners((0, 0), cell_dims) + cell_dims * Vector(col, row)
ctx.save()
draw_node(ctx, bounds, node_nr)
ctx.restore()
#end col
#end for
display()
#end draw_nodes_grid
Here is an initial stab at a node-drawing routine: “make_draw_node_1” creates the actual routine, given four colours to indicate the state of being in the kernel or not, or having a positive or negative weight.
def make_draw_node_1(in_kernel_colour, not_kernel_colour, pos_weight_colour, neg_weight_colour) :
def draw_node(g, bounds, nr) :
fill_colour = (not_kernel_colour, in_kernel_colour)[in_kernel(nr)]
border_colour = {-1 : neg_weight_colour, 1 : pos_weight_colour}[get_weight(nr)]
(g
.set_source_colour(fill_colour)
.new_path()
.rectangle(bounds)
.fill()
.set_source_colour(border_colour)
.set_line_width(3)
.rectangle(bounds.inset((1.5, 1.5)))
.stroke()
)
label = "%d" % nr
label_extents = g.text_extents(label)
(g
.set_font_size(12)
.move_to(bounds.middle + Vector(- label_extents.x_bearing - label_extents.advance.x / 2, label_extents.height / 2))
.show_text(label)
)
#end draw_node
return \
draw_node
#end make_draw_node_1
The actual drawing of the graphic is done with a sequence like
example_draw_node = make_draw_node_1 \
(
in_kernel_colour = Colour.from_hsva((0.5, 0.5, 0.9, 1)),
not_kernel_colour = Colour.from_hsva((0, 0, 0, 0)),
pos_weight_colour = Colour.from_hsva((0, 0, 0, 1)),
neg_weight_colour = Colour.from_hsva((0, 0, 0.5, 1)),
)
draw_nodes_grid(example_draw_node)
You can see how you can use that as a starting point for further layout and rendering experiments.
Another thing you can do with IPython is add interactive “widgets” to cell output: this way, the user can drag sliders etc which your function can interpret as variable parameters and redraw the graphics.
[toc] | [prev] | [next] | [standalone]
| From | Lawrence D’Oliveiro <lawrencedo99@gmail.com> |
|---|---|
| Date | 2016-10-24 16:54 -0700 |
| Message-ID | <66538ba6-282f-4b3d-b8ba-94b93903385f@googlegroups.com> |
| In reply to | #2913 |
On Thursday, October 20, 2016 at 1:58:00 PM UTC+13, I wrote some Python code. It is worth pointing out some salient features of this code, that take advantage of the advanced capabilities of Python. > def draw_nodes_grid(draw_node) : Note that the actual drawing of a node is implemented by the “draw_node” function which is passed as the argument, while “draw_nodes_grid” itself only implements the layout of the entire diagram. > reset() > cell_dims = pix.dimensions / Vector(10, 10) See how the x- and y-dimensions of a single cell are computed from the dimensions of the drawing area by a single division? > for row in range(10) : > for col in range(10) : > node_nr = row * 10 + col + 1 > bounds = Rect.from_corners((0, 0), cell_dims) + cell_dims * Vector(col, row) And here we have the bounds of a cell computed from the row and column number, again both x- and y-coordinates determined in a single expression. > def make_draw_node_1(in_kernel_colour, not_kernel_colour, pos_weight_colour, neg_weight_colour) : > > def draw_node(g, bounds, nr) : > .... > #end draw_node > > return \ > draw_node > #end make_draw_node_1 Here we have a function returning a function. Each invocation of the outer function returns a new instance of the inner function; each instance can have different values for the arguments passed to the outer function, and will refer to its own values for those arguments, independent of any other instance. This is called “lexical binding”, and is an essential part of treating functions as first-class objects. > example_draw_node = make_draw_node_1 \ > ( > in_kernel_colour = Colour.from_hsva((0.5, 0.5, 0.9, 1)), > not_kernel_colour = Colour.from_hsva((0, 0, 0, 0)), > pos_weight_colour = Colour.from_hsva((0, 0, 0, 1)), > neg_weight_colour = Colour.from_hsva((0, 0, 0.5, 1)), > ) > draw_nodes_grid(example_draw_node) Here the diagram is generated with one particular draw_node function using one particular colour scheme. Would anybody like to try doing this in PostScript? It would take at least twice as much work. And it still wouldn’t be interactive.
[toc] | [prev] | [next] | [standalone]
| From | Carlos <angus@quovadis.com.ar> |
|---|---|
| Date | 2016-10-25 16:26 +0200 |
| Message-ID | <nunq2l$cib$1@dont-email.me> |
| In reply to | #2921 |
On 25/10/2016 1:54, Lawrence D’Oliveiro wrote:
> On Thursday, October 20, 2016 at 1:58:00 PM UTC+13, I wrote some
> Python code. It is worth pointing out some salient features of this
> code, that take advantage of the advanced capabilities of Python.
I don't think anything you showed here demonstrated any advanced
capabilities of Python (at least not with respect to PostScript).
>> def draw_nodes_grid(draw_node) :
>
> Note that the actual drawing of a node is implemented by the
> “draw_node” function which is passed as the argument, while
> “draw_nodes_grid” itself only implements the layout of the entire
> diagram.
You can do that in PostScript, too. Pass a block to a procedure, then
call it with exec.
>> reset()
>> cell_dims = pix.dimensions / Vector(10, 10)
>
> See how the x- and y-dimensions of a single cell are computed from
> the dimensions of the drawing area by a single division?
Come on. Just because you wrote a vector library in Python and not in
PostScript, that doesn't make Python better.
/celldims pix /dimensions get 10 10 Vector Vdiv def
assuming pix is a dictionary. Here is the start of a vector library:
/Vector { 2 packedarray } bind def
/x { 0 get } bind def
/y { 1 get } bind def
/xy { aload pop } bind def
/Vop { 3 1 roll
xy 3 -1 roll xy
3 -1 roll 4 index exec
3 1 roll exch 3 index exec
exch Vector
exch pop } bind def
/Vdiv { { div } Vop } bind def
>> for row in range(10) :
>> for col in range(10) :
>> node_nr = row * 10 + col + 1
>> bounds = Rect.from_corners((0, 0), cell_dims) + cell_dims * Vector(col, row)
>
> And here we have the bounds of a cell computed from the row and
> column number, again both x- and y-coordinates determined in a
> single expression.
0 1 9 { /row exch def % for
0 1 9 { /col exch def % for
/nodenr row 10 mul col add 1 add def
/bounds 0 0 Vector celldims Rectfromcorners
celldims col row Vector Vmul
Radd
def
...
} for
} for
Again, a matter of libraries
/Vmul { { mul } Vop } bind def
/Vadd { { add } Vop } bind def
/Vsub { { sub } Vop } bind def
/min { 2 copy gt { exch } if pop } bind def
/max { 2 copy lt { exch } if pop } bind def
/Rect { 4 packedarray } bind def
/width { 2 get } bind def
/height { 3 get } bind def
/w+h { dup width exch height } bind def
/Rectfromcorners {
2 copy { min } Vop
3 1 roll { max } Vop
1 index Vsub
exch xy 3 -1 roll xy Rect
} bind def
/Radd {
1 index x 2 index y Vector Vadd xy
3 -1 roll w+h Rect
} bind def
>> def make_draw_node_1(in_kernel_colour, not_kernel_colour, pos_weight_colour, neg_weight_colour) :
>>
>> def draw_node(g, bounds, nr) :
>> ....
>> #end draw_node
>>
>> return \
>> draw_node
>> #end make_draw_node_1
>
> Here we have a function returning a function. Each invocation of the
> outer function returns a new instance of the inner function; each
> instance can have different values for the arguments passed to the
> outer function, and will refer to its own values for those
> arguments, independent of any other instance. This is called
> “lexical binding”, and is an essential part of treating functions as
> first-class objects.
That's a facility the Python compiler provides because it's otherwise
impossible to return custom functions. You don't need the
interpreter's help in PostScript, because procedures are arrays, and
you can easily create arrays programmatically. (By the way, this is a
recurring topic in this newsgroup lately.)
So, again, it's just a matter of libraries. (Although I don't think
you could do it in Python with just a library.)
Try this:
/makeadder {
1 dict begin
/n exch def
{ n add } bindcurrent
end
} bind def
And then "4 makeadder ==".
Here is a couple procedures that let you do that:
% copies array recursively
% <array> -> <new array>
/deepcopy {
dup xcheck exch
dup length array copy
dup length 1 sub 0 exch 1 exch { % for % a i
2 copy 2 copy get dup type
dup /arraytype eq exch /packedarraytype eq or % a i a i e ?
{ % ifelse
deepcopy put
}
{
pop pop pop
} ifelse
pop
} for
exch { cvx } if
} bind def
% recursively replaces elements in <array> found in <dict>
% <array> <dict> -> -
/replaceall {
1 index length 1 sub 0 1 3 -1 roll { % for 0 1 length-1
3 copy 3 -1 roll exch % a d i d a i
get % a d i d e
2 copy known % a d i d e ?
% ifelse
{ % a d i d e
get % a d i v
3 index 3 1 roll % a d a i v
put
} % else
{ % a d i d e
dup type /arraytype eq % a d i d e ?
{ exch replaceall }
{ pop pop } ifelse
pop
} ifelse % a d
} for
pop pop
} bind def
% bind names existing in currentdict
% proc -> proc
/bindcurrent {
deepcopy dup currentdict replaceall
} bind def
>> example_draw_node = make_draw_node_1 \
>> (
>> in_kernel_colour = Colour.from_hsva((0.5, 0.5, 0.9, 1)),
>> not_kernel_colour = Colour.from_hsva((0, 0, 0, 0)),
>> pos_weight_colour = Colour.from_hsva((0, 0, 0, 1)),
>> neg_weight_colour = Colour.from_hsva((0, 0, 0.5, 1)),
>> )
>> draw_nodes_grid(example_draw_node)
>
> Here the diagram is generated with one particular draw_node function
> using one particular colour scheme.
>
> Would anybody like to try doing this in PostScript? It would take at
> least twice as much work. And it still wouldn’t be interactive.
I don't think it would take more work than doing it in Python,
assuming you already have the libraries. I think everybody agrees that
Cairo, the library, allows you to do things for which, apparently,
there isn't a PostScript library yet. But nothing you wrote proves
that Python, the programming language, is more capable than PostScript.
--
[toc] | [prev] | [next] | [standalone]
| From | Lawrence D’Oliveiro <lawrencedo99@gmail.com> |
|---|---|
| Date | 2016-10-25 10:32 -0700 |
| Message-ID | <41c5fbb5-a268-4cc1-8522-73f92980ce69@googlegroups.com> |
| In reply to | #2922 |
On Wednesday, October 26, 2016 at 3:26:52 AM UTC+13, Carlos wrote:
>
> On 25/10/2016 1:54, Lawrence D’Oliveiro wrote:
>
>> Note that the actual drawing of a node is implemented by the
>> “draw_node” function which is passed as the argument, while
>> “draw_nodes_grid” itself only implements the layout of the entire
>> diagram.
>
> You can do that in PostScript, too. Pass a block to a procedure, then
> call it with exec.
But you don’t get the lexical binding, which is what really makes them useful.
>> cell_dims = pix.dimensions / Vector(10, 10)
>>>
>> See how the x- and y-dimensions of a single cell are computed from
>> the dimensions of the drawing area by a single division?
>
> Come on. Just because you wrote a vector library in Python and not in
> PostScript, that doesn't make Python better.
You didn’t notice that the operation was done with the standard division operator, then? Python allows you to define custom overloads for the standard operators. This way, you can write your expressions using notation much closer to the original maths.
> assuming pix is a dictionary. Here is the start of a vector library:
>
> /Vector { 2 packedarray } bind def
> /x { 0 get } bind def
> /y { 1 get } bind def
> /xy { aload pop } bind def
>
> /Vop { 3 1 roll
> xy 3 -1 roll xy
> 3 -1 roll 4 index exec
> 3 1 roll exch 3 index exec
> exch Vector
> exch pop } bind def
>
> /Vdiv { { div } Vop } bind def
Not much of a start, don’t you think <https://groups.google.com/d/msg/comp.lang.postscript/fEyXR90-wq4/AsOwYiltBgAJ>?
> Again, a matter of libraries
Which PostScript is, frankly, no help with.
> [Lexical binding is] a facility the Python compiler provides because it's
> otherwise impossible to return custom functions. You don't need the
> interpreter's help in PostScript, because procedures are arrays, and
> you can easily create arrays programmatically. (By the way, this is a
> recurring topic in this newsgroup lately.)
But you cannot do the lexical binding. Not in a reentrant fashion.
> Try this:
How many lines of PostScript code have you written so far? Compare it to how many lines of Python code I needed to write. And your solution isn’t even complete yet.
[toc] | [prev] | [next] | [standalone]
| From | Carlos <angus@quovadis.com.ar> |
|---|---|
| Date | 2016-10-25 21:06 +0200 |
| Message-ID | <20161025210647.55ecd219@samara.DOMA> |
| In reply to | #2923 |
[Lawrence D’Oliveiro <lawrencedo99@gmail.com>, 2016-10-25 10:32]
> On Wednesday, October 26, 2016 at 3:26:52 AM UTC+13, Carlos wrote:
> >
> > On 25/10/2016 1:54, Lawrence D’Oliveiro wrote:
> >
> >> Note that the actual drawing of a node is implemented by the
> >> “draw_node” function which is passed as the argument, while
> >> “draw_nodes_grid” itself only implements the layout of the entire
> >> diagram.
> >
> > You can do that in PostScript, too. Pass a block to a procedure,
> > then call it with exec.
>
> But you don’t get the lexical binding, which is what really makes
> them useful.
You can get the PostScript equivalent, as previously explained (more
below).
> >> cell_dims = pix.dimensions / Vector(10, 10)
> >>>
> >> See how the x- and y-dimensions of a single cell are computed from
> >> the dimensions of the drawing area by a single division?
> >
> > Come on. Just because you wrote a vector library in Python and not
> > in PostScript, that doesn't make Python better.
>
> You didn’t notice that the operation was done with the standard
> division operator, then? Python allows you to define custom overloads
> for the standard operators. This way, you can write your expressions
> using notation much closer to the original maths.
Operator overloading is a controversial issue. Some like it, some don't.
Some think having it in a language makes it better, some think it makes
it worse. In any case, you can never write your expressions close to
mathematical notation in PostScript, so that's not a good reason to
prefer overloading. I don't think much would be gained if people could
multiply vectors using "mul" instead of "Vmul".
>
> > assuming pix is a dictionary. Here is the start of a vector library:
> >
> > /Vector { 2 packedarray } bind def
> > /x { 0 get } bind def
> > /y { 1 get } bind def
> > /xy { aload pop } bind def
> >
> > /Vop { 3 1 roll
> > xy 3 -1 roll xy
> > 3 -1 roll 4 index exec
> > 3 1 roll exch 3 index exec
> > exch Vector
> > exch pop } bind def
> >
> > /Vdiv { { div } Vop } bind def
>
> Not much of a start, don’t you think
> <https://groups.google.com/d/msg/comp.lang.postscript/fEyXR90-wq4/AsOwYiltBgAJ>?
Just the necessary to translate to PostScript the snippets you are
posting.
>
> > Again, a matter of libraries
>
> Which PostScript is, frankly, no help with.
It helps with the writing; coding in PostScript is enjoyable.
> > [Lexical binding is] a facility the Python compiler provides
> > because it's otherwise impossible to return custom functions. You
> > don't need the interpreter's help in PostScript, because procedures
> > are arrays, and you can easily create arrays programmatically. (By
> > the way, this is a recurring topic in this newsgroup lately.)
>
> But you cannot do the lexical binding. Not in a reentrant fashion.
Yes you can, but the interpreter won't do it automatically for you. I
just showed you! I don't know what you mean by "not in a reentrant
fashion"; if you found a case where it doesn't work please tell me.
Did you try it at all?
GS>/add1 1 makeadder def /add4 4 makeadder def
GS>8 add1 add5 ==
13
> > Try this:
>
> How many lines of PostScript code have you written so far? Compare it
> to how many lines of Python code I needed to write.
What? You wrote more lines. Or wasn't the code for Vector and Rectangle
classes written by you? I mean, line for line, PostScript wins hands
down. Compare:
def __sub__(v1, v2) :
"difference between two Vectors."
return \
(
lambda : NotImplemented,
lambda : type(v1)(v1.x - v2.x, v1.y - v2.y)
)[isinstance(v2, Vector)]()
#end __sub__
with
/Vsub { { sub } Vop } bind def % vector difference
> And your solution isn’t even complete yet.
Well, you didn't post a complete solution either, just some snippets
(the code in the original message also wasn't complete). If you want,
post a complete solution and I'll try to produce a PostScript
equivalent, so you can see Python isn't better :)
--
[toc] | [prev] | [next] | [standalone]
| From | Lawrence D’Oliveiro <lawrencedo99@gmail.com> |
|---|---|
| Date | 2016-11-14 15:15 -0800 |
| Message-ID | <8fc71ab3-e706-4f17-a7d6-c1d685577bf4@googlegroups.com> |
| In reply to | #2925 |
On Wednesday, October 26, 2016 at 8:07:32 AM UTC+13, Carlos wrote:
> Operator overloading is a controversial issue.
No it isn’t. Even common-or-garden languages like C or Java have operator overloading.
Or did you mean *custom* operator overloads? It may be “controversial” the way C++ does it (complicated and clunky). But Python handles it in a very simple way.
> Just the necessary to translate to PostScript the snippets you are
> posting.
The Python code I included in that posting was not “snippets”, it was the complete program.
> What? You wrote more lines. Or wasn't the code for Vector and Rectangle
> classes written by you? I mean, line for line, PostScript wins hands
> down. Compare:
>
> def __sub__(v1, v2) :
> "difference between two Vectors."
> return \
> (
> lambda : NotImplemented,
> lambda : type(v1)(v1.x - v2.x, v1.y - v2.y)
> )[isinstance(v2, Vector)]()
> #end __sub__
>
> with
>
> /Vsub { { sub } Vop } bind def % vector difference
Fine. If you want to include all that code, then by all means provide PostScript equivalents for all 6826 lines (current count) of my Cairo binding <https://github.com/ldo/qahirah>. Then we can compare.
How many lines of PostScript would that take? I predict you will not be able to do it all, no matter how many lines you write.
[toc] | [prev] | [next] | [standalone]
| From | Carlos <angus@quovadis.com.ar> |
|---|---|
| Date | 2016-11-16 00:17 +0100 |
| Message-ID | <20161116001758.670c83db@samara.DOMA> |
| In reply to | #2936 |
[Lawrence D’Oliveiro <lawrencedo99@gmail.com>, 2016-11-14 15:15]
> On Wednesday, October 26, 2016 at 8:07:32 AM UTC+13, Carlos wrote:
>
> > Operator overloading is a controversial issue.
>
> No it isn’t. Even common-or-garden languages like C or Java have
> operator overloading.
Well, yes, even PostScript has it.
> Or did you mean *custom* operator overloads? It may be
> “controversial” the way C++ does it (complicated and clunky). But
> Python handles it in a very simple way.
That's what I meant. I think in a language like PostScript it's better
not to do it, for two main reasons: first (already mentioned), there is
no mathematical notation in PostScript; and second, operators provide
almost all of the code legibility, so the less ambiguous their names,
the better.
But what's great about PostScript is its flexibility. Almost any
language feature is just a library away. If you like operator
overloading, you can have it in PostScript!
Here's an example with a not very sophisticated library (~250 lines).
It's the same vector library stub as last time, but now overloading the
mul operator.
/vectortype /packedarraytype {
dup length 2 eq exch { /numbertype isa and } forall
} deftype
/Vector { 2 packedarray } bind def
/x { 0 get } bind def
/y { 1 get } bind def
/xy { aload pop } bind def
/Vop { 3 1 roll
xy 3 -1 roll xy
3 -1 roll 4 index exec
3 1 roll exch 3 index exec
exch Vector
exch pop } bind def
/Vmul { { mul } Vop } bind def
/mul [/vectortype /vectortype] { Vmul } defmethod
/mul [/vectortype /numbertype] {
exch 2 copy x mul
3 1 roll y mul Vector
} defmethod
GS>1.5 2 Vector dup == dup type == dup dup mul == 5 mul ==
[1.5 2]
vectortype
[2.25 4]
[7.5 10]
> > Just the necessary to translate to PostScript the snippets you are
> > posting.
>
> The Python code I included in that posting was not “snippets”, it was
> the complete program.
In _that_ posting there were just snippets. In the referred one, there
was some code interspersed with commentary. Are you saying the code
without the commentary make up a complete, working program? In that
case, I shall try to translate it to PostScript. Can I see what the
output is?
> > What? You wrote more lines. Or wasn't the code for Vector and
> > Rectangle classes written by you? I mean, line for line, PostScript
> > wins hands down. Compare:
> >
> > def __sub__(v1, v2) :
> > "difference between two Vectors."
> > return \
> > (
> > lambda : NotImplemented,
> > lambda : type(v1)(v1.x - v2.x, v1.y - v2.y)
> > )[isinstance(v2, Vector)]()
> > #end __sub__
> >
> > with
> >
> > /Vsub { { sub } Vop } bind def % vector difference
>
> Fine. If you want to include all that code, then by all means provide
> PostScript equivalents for all 6826 lines (current count) of my Cairo
> binding <https://github.com/ldo/qahirah>. Then we can compare.
Actually, it was you who wanted to include my library code in the line
count, while excluding yours. We can count it or not, it's the same to
me. In any case, I'll only write the code needed for the task at hand;
if you want to include library code in the count, I don't expect you to
count your code not involved in the task.
> How many lines of PostScript would that take? I predict you will not
> be able to do it all, no matter how many lines you write.
That's an easy prediction; PostScript doesn't have facilities to load
or access DLLs. But that's not what this is about, is it? This is about
the *languages*, no the libraries.
--
[toc] | [prev] | [next] | [standalone]
| From | Carlos <angus@quovadis.com.ar> |
|---|---|
| Date | 2016-11-21 18:37 +0100 |
| Message-ID | <o0vbbe$qi9$1@dont-email.me> |
| In reply to | #2937 |
The purpose of this experiment is to demonstrate that there isn't a
lack of features in PostScript with respect to other programming or
scripting languages. On the contrary, the flexibility of PostScript
allows you to add features to the language, something not really
possible in many other languages.
As Markus said, PostScript is malleable. With it you can make a
program right away, or make bricks and parts to make it, or make tools
to help you to make parts.... etc. In many other languages you can
only use and combine the set of parts they come with.
In this particular case, if you like to work with closures and objects
that encapsulate vectors and rectangles, you can do it equally well in
Python as in PostScript. You can easily adapt PostScript to your
preferred way of coding.
The following is a line-for-line translation of the code in this
message:
https://groups.google.com/d/msg/comp.lang.postscript/fEyXR90-wq4/muGN64FvBgAJ
It's not idiomatic PostScript, and uses features maybe I wouldn't, but
the point is that in PostScript you *can*. When a PostScript
programmer rejects certain features or programming styles, it usually
isn't a case of sour grapes.
The support code (the "library") follows in the next message. To run
this, just do
gs library-code.ps this-code.ps
or equivalent. There is no operator overloading here. I can post the
proto-libray if you want to play with it (it works, I just didn't want
to bother with it).
%!PS
/pix << /dimensions 400 400 Vector >> def
/reset {
gsave
.95 setgray
0 0 pix /dimensions get xy rectfill
grestore
/Helvetica 12 selectfont
} bind def
/display {
showpage
} bind def
/kernel << [ 1 3 6 9 12 15 18 20 23 25
27 30 33 36 39 41 43 46 48 51
54 57 60 63 66 68 71 73 75 78
80 83 86 89 92 95 97 99 ] { true } forall
>> def
/weights [ -1 -1 1 -1 1 1 -1 -1 1 1
-1 1 -1 -1 1 -1 1 1 -1 1
-1 -1 1 1 -1 -1 1 -1 1 1
-1 -1 1 1 -1 1 -1 -1 1 1
-1 -1 1 -1 1 1 -1 1 -1 -1
1 -1 1 1 -1 -1 1 1 -1 1
-1 -1 1 -1 1 1 -1 1 -1 -1
1 1 -1 -1 1 -1 1 1 -1 1
-1 -1 1 -1 1 1 -1 -1 1 1
-1 1 -1 -1 1 1 -1 -1 1 -1
] def
%: nodenr -> bool
/inkernel { kernel exch known } bind def
%: nodenr -> 1|-1
/weight { 1 sub weights exch get } bind def
%: drawnodeproc ->
/drawnodesgrid {
reset
6 dict begin
/drawnode exch def
/celldims pix /dimensions get 10 10 Vector Vdiv def
0 1 9 { /row exch def % for
0 1 9 { /col exch def % for
/nodenr row 10 mul col add 1 add def
/bounds 0 0 Vector celldims Rectfromcorners
celldims col row Vector Vmul
Radd
def
gsave
bounds nodenr drawnode
grestore
} for
} for
end
showpage
} bind def
%: inkernelcolour notkernelcolour posweightcolour negweightcolour -> drawnodeproc
/makedrawnode1 {
6 dict begin
/negweightcolour exch def /posweightcolour exch def
/notkernelcolour exch def /inkernelcolour exch def
%: bounds nr ->
{
5 dict begin
/nr exch def /bounds exch def
/fillcolour nr inkernel { inkernelcolour } { notkernelcolour } ifelse def
/bordercolour << -1 negweightcolour 1 posweightcolour >> nr weight get def
fillcolour setcolorp
newpath
bounds Rfill
bordercolour setcolorp
3 setlinewidth
bounds 1.5 1.5 Vector Rinset Rstroke
/label nr 10 5 string cvrs def
/extents label stringextents def
bounds Rmiddle extents width 2 div neg extents height 2 div neg Vector Vadd
aload pop moveto
label show
end
} bindcurrent
end
} bind def
/exampledrawnode
0.5 0.5 0.9 SolidPattern ColorfromHSBP
0 0 0 EmptyPattern ColorfromHSBP
0 0 0 SolidPattern ColorfromHSBP
0 0 0.5 SolidPattern ColorfromHSBP
makedrawnode1
def
/exampledrawnode load drawnodesgrid
--
[toc] | [prev] | [next] | [standalone]
| From | Carlos <angus@quovadis.com.ar> |
|---|---|
| Date | 2016-11-21 18:39 +0100 |
| Message-ID | <o0vbfc$qi9$2@dont-email.me> |
| In reply to | #2948 |
On 21/11/2016 18:37, Carlos wrote:
> The support code (the "library") follows in the next message.
Here it is:
%!PS
% PART 0 - min & max
/min { 2 copy gt { exch } if pop } bind def
/max { 2 copy lt { exch } if pop } bind def
% PART 1 - Geometric things
% vector: 2 numbers (x y) in an array
%: x y -> vector
/Vector { 2 packedarray } bind def
/x { 0 get } bind def
/y { 1 get } bind def
/xy { dup x exch y } bind def
%: x1 y1 x2 y2 -> vector1 vector2
/2Vectors {
Vector
3 1 roll Vector
exch
} bind def
% applies op to corresponding components
% v1 v2 op ==
% v1 x v2 x op v1 y v2 y op Vector
%: v1 v2 op -> vector
/Vop { 3 1 roll
xy 3 -1 roll xy
3 -1 roll 4 index exec
3 1 roll exch 3 index exec
exch Vector
exch pop } bind def
% vector operators. all signatures are
%: vector vector op -> vector
/Vdiv { { div } Vop } bind def
/Vmul { { mul } Vop } bind def
/Vadd { { add } Vop } bind def
/Vsub { { sub } Vop } bind def
% scalar mul and div
%: vector n -> vector
/Vsmul { dup Vector Vmul } bind def
/Vsdiv { dup Vector Vdiv } bind def
% rectangle: (x y width height)
%: x y width height -> Rect
/Rect { 4 packedarray } bind def
%: x1 y1 x2 y2 -> rect
/Rectfromcorners {
2 copy { min } Vop
3 1 roll { max } Vop
1 index Vsub
exch xy 3 -1 roll xy
Rect
} bind def
/width { 2 get } bind def
/height { 3 get } bind def
%: rect -> width height
/w+h { dup width exch height } bind def
% center point
%: rect -> vector
/Rmiddle { dup xy Vector exch w+h Vector 2 Vsdiv Vadd } bind def
% make rect a little smaller
%: rect vector -> rect
/Rinset {
2 copy exch xy Vector Vadd
3 1 roll
2 Vsmul exch w+h Vector exch Vsub
exch aload pop 3 -1 roll aload pop
Rect
} bind def
% move rect
%: rect vector -> rect
/Radd {
1 index x 2 index y Vector Vadd xy
3 -1 roll w+h Rect
} bind def
% fill and stroke
%: rect ->
/Rfill { aload pop rectfill } bind def
/Rstroke { aload pop rectstroke } bind def
% PART 3 - Colors
/SolidPattern <<
/PatternType 1
/PaintProc { pop 0 0 10 10 rectfill }
/BBox [ 0 0 10 10 ] /XStep 5 /YStep 5
/PaintType 2 /TilingType 1
>> matrix makepattern def
/EmptyPattern <<
/PatternType 1
/PaintProc { pop }
/BBox [ 0 0 10 10 ] /XStep 5 /YStep 5
/PaintType 2 /TilingType 1
>> matrix makepattern def
/ColorfromHSBP {
4 1 roll gsave sethsbcolor currentrgbcolor grestore
4 -1 roll 4 array astore
} bind def
/setcolorp {
[ /Pattern [ /DeviceRGB ] ] setcolorspace
aload pop setcolor
} bind def
% PART 4 - extents
%: string -> extents
/stringextents {
gsave
newpath 0 0 moveto
true charpath pathbbox 2Vectors Rectfromcorners
currentpoint exch pop 1 index y sub % depth
exch w+h 2 index sub 3 -1 roll % width height depth
0 0 5 2 roll 5 packedarray
grestore
} bind def
/depth { 4 get } bind def
% PART 5 - bindcurrent and helpers
% copies array recursively
% <array> -> <new array>
/deepcopy {
dup xcheck exch
dup length array copy
dup length 1 sub 0 exch 1 exch { % for % a i
2 copy 2 copy get dup type
dup /arraytype eq exch /packedarraytype eq or % a i a i e ?
{ % ifelse
deepcopy put
}
{
pop pop pop
} ifelse
pop
} for
exch { cvx } if
} bind def
% recursively replaces elements in <array> found in <dict>
% <array> <dict> -> -
/replaceall {
1 index length 1 sub 0 1 3 -1 roll { % for 0 1 length-1
3 copy 3 -1 roll exch % a d i d a i
get % a d i d e
2 copy known % a d i d e ?
% ifelse
{ % a d i d e
get % a d i v
3 index 3 1 roll % a d a i v
put
} % else
{ % a d i d e
dup type /arraytype eq % a d i d e ?
{ exch replaceall }
{ pop pop } ifelse
pop
} ifelse % a d
} for
pop pop
} bind def
% bind names existing in currentdict
% proc -> proc
/bindcurrent {
deepcopy dup currentdict replaceall
} bind def
--
[toc] | [prev] | [next] | [standalone]
| From | Markus Triska <triska@metalevel.at> |
|---|---|
| Date | 2016-10-25 20:52 +0200 |
| Message-ID | <m2h980dzwr.fsf@metalevel.at> |
| In reply to | #2921 |
Lawrence D’Oliveiro <lawrencedo99@gmail.com> writes:
> Would anybody like to try doing this in PostScript? It would take at
> least twice as much work.
The way I approached the task in PostScript was to first think about how
I would eventually like to describe the layout within PostScript.
Then, I added the necessary definitions so that I could describe the
whole graph (100 nodes) like this:
/instrs {
{r r r r r r r r r r r r r r r r
d
l l l l l l l l l l l l l l
d
r r r r r r r r r r r r r r r
d
l l l l l l l l l l l l l l
d
r r r r r r r r r r r r r
d
l l l l l l l l l l l l l l l l
u r u l u u u } } def
You can download the whole source from:
https://www.metalevel.at/postscript/cyclegraph.ps
It's about 80 lines of PostScript. This general approach has served me
very well also for other graphs, and makes it easy to try variations
using only your keyboard and editing facilities of Emacs.
> And it still wouldn’t be interactive.
That's true, it is not interactive.
When I program in PostScript, it feels a bit like handling plasticine:
It is very simple and uniform, and you can mold it quite freely. When I
see your Python code, it feels a bit like playing with an action figure:
I understand it can be appealing to some, and it may feature a few cool
gizmos, but it feels more rigid and inflexible, and less uniform.
All the best,
Markus
[toc] | [prev] | [next] | [standalone]
Page 2 of 3 — ← Prev page 1 [2] 3 Next page →
Back to top | Article view | comp.lang.postscript
csiph-web