[wxPython] DrawXList and CVS frustration

First the good news. I have a working version of DrawLineList and
DrawPointList that I was hoping to distribute for comment this weekend. My
experiments indicate that using DrawXList is about 10x faster than the
equivalent loop in Python. The syntax I used is:

dc.DrawPointList(seqOfPoints, [None | wxPen | listOfwxPens])
dc.DrawLineList(seqOfPoints1,seqOfPoints2, [None | wxPen | listOfwxPens])

The pen argument defaults to None. I'm still not convinced that allowing a
single wxPen argument is a good idea -- It adds no functionality and it
seems to add more room for mistakes. It was easy to add though and someone
else really wanted it so it's in the patch for the moment.

The bad news is that at this point I don't even know what version of
wxPython the patch is against. I was trying to make a patch against the
current CVS, but I can't get current CVS to compile. The first problem I run
into is that wxWindows is missing msw/setup.h. I copied one from an older
version I had lying around, and wxWindows compiled, but the wxPython would
not compile. In the process I made the patch against a few different
versions and got myself all confusified.

I'm out of time now and I don't know if I'll have time to get back to this
in the next couple of weeks (I'm off to the bottom of the Grand Canyon,
among other places, where net access is hard to come by to say the least.)
So, I'm just going to throw the patch out there: if someone is inclined to
put in the time to get it to compile on their system, that'd be great.
Please send me your thoughts if you do. Otherwise I'll get back to this when
I get back and try to put together a more useful patch.

-tim

wxdrawlist.patch (5.04 KB)

First the good news. I have a working version of DrawLineList and
DrawPointList that I was hoping to distribute for comment this weekend. My
experiments indicate that using DrawXList is about 10x faster than the
equivalent loop in Python. The syntax I used is:

dc.DrawPointList(seqOfPoints, [None | wxPen | listOfwxPens])
dc.DrawLineList(seqOfPoints1,seqOfPoints2, [None | wxPen | listOfwxPens])

The pen argument defaults to None. I'm still not convinced that allowing a
single wxPen argument is a good idea -- It adds no functionality and it
seems to add more room for mistakes. It was easy to add though and someone
else really wanted it so it's in the patch for the moment.

Tim,

Your patch didn't include the chages that actually implemented these
methods, only the helpers.

···

--
Robin Dunn
Software Craftsman
robin@AllDunn.com Java give you jitters?
http://wxPython.org Relax with wxPython!

Hi Robin,

[SNIP broken patch]

Tim,

Your patch didn't include the chages that actually implemented these
methods, only the helpers.

Sorry!

Ack. I've got not time to do this right at the moment, so I completely
understand if you just ignore this till I get some time to deal with in a
couple of weeks, but if your in a hurry the missing stuff is in the
definition of wxDC in gdi.i and is:

%addmethods {
  PyObject* _DrawPointList(int PCOUNT, wxPoint* points, int LCOUNT, wxPen**
choices) {
   for (int i = 0; i < PCOUNT; i++) {
    if (i < LCOUNT) {
     self->SetPen(*choices[i]);
    }
    self->DrawPoint(points[i]);
   }
   Py_INCREF(Py_None);
   return Py_None;
  }
  PyObject* _DrawLineList(int PCOUNT, wxPoint* points, int PCOUNT2, wxPoint*
points2, int LCOUNT, wxPen** choices) {
   for (int i = 0; i < PCOUNT && i < PCOUNT2; i++) {
    if (i < LCOUNT) {
     self->SetPen(*choices[i]);
    }
    self->DrawLine(points[i], points2[i]);
   }
   Py_INCREF(Py_None);
   return Py_None;
  }
}

    %pragma(python) addtoclass = "
    def DrawPointList(self, points, pens=None):
        if pens is None:
           pens =
        elif isinstance(pens, wxPen):
           pens = [pens]
        elif len(pens) != len(points):
           raise ValueError('points and pens must have same length')
        return self._DrawPointList(points, pens)

    def DrawLineList(self, points1, points2, pens=None):
        if pens is None:
           pens =
        elif isinstance(pens, wxPen):
           pens = [pens]
        elif len(pens) != len(points1):
           raise ValueError('points and pens must have same length')
        if len(points1) != len(points2):
           raise ValueError('points1 and points2 must have same length')
        return self._DrawLineList(points1, points2, pens)
"

I hope that's the only thing missing!

-tim

First the good news. I have a working version of DrawLineList and
DrawPointList that I was hoping to distribute for comment this weekend. My
experiments indicate that using DrawXList is about 10x faster than the
equivalent loop in Python. The syntax I used is:

dc.DrawPointList(seqOfPoints, [None | wxPen | listOfwxPens])
dc.DrawLineList(seqOfPoints1,seqOfPoints2, [None | wxPen | listOfwxPens])

For DrawLineList does having the two paralell sequences of points make sense
to everybody or would a sequence of (x1, y1, x2, y2) tuples be more
intuitive and useful?

···

--
Robin Dunn
Software Craftsman
robin@AllDunn.com Java give you jitters?
http://wxPython.org Relax with wxPython!

> dc.DrawPointList(seqOfPoints, [None | wxPen | listOfwxPens])
> dc.DrawLineList(seqOfPoints1,seqOfPoints2, [None | wxPen |
listOfwxPens])
>

For DrawLineList does having the two paralell sequences of points
make sense
to everybody or would a sequence of (x1, y1, x2, y2) tuples be more
intuitive and useful?

Two separate sequences doesn't make sense to me. I would rather have a
single list. I'm not thrilled with having a separate pen list. [None |
wxPen] makes sense where None just means use the default pen. If a list of
pens is going to be supported, then the pen should be part of the list (x1,
y1, x2, y2, wxPen). Of course, other methods would need the same support for
the brush.

ka

For DrawLineList does having the two paralell sequences of points make

sense

to everybody or would a sequence of (x1, y1, x2, y2) tuples be more
intuitive and useful?

That's a good question. I waffled back and forth a few times and then
decided that the former had the virtue (from an implementation point of
view) of not requiring a new helper function. So, not having a preference I
tried the easier of the two. Actually I also considered a sequence of (pt1,
pt2). Mirroring the docs would argue for what you propose above so I suppose
that's probably best. I guess I'll look into writing an appropriate helper.

Two separate sequences doesn't make sense to me. I would rather have a
single list.

Fair enough. I'm leaning that way myself at the moment.

I'm not thrilled with having a separate pen list. [None |
wxPen] makes sense where None just means use the default pen. If a list of
pens is going to be supported, then the pen should be part of the list

(x1,

y1, x2, y2, wxPen).

This makes no sense to me. Supplying a single pen argument adds no
functionality that you can't do just as fast using:

wxDC.SetPen(pen)
wxDC.DrawLineList(points)

In fact I'm very tempted to rip out the single pen option. On the other
hand, allowing a pen list allows this:

for i in range(len(points)):
   wxDC.SetPen(pens[i])
   wxDC.DrawLine(*points[i])

as wxDC.DrawLineList(points, pens) which is about 10x faster.

The final suggestion that the points and the pen combined into a single list
would be very bad for those of us that use Numeric to manipulate out points.
Any speed gain I could expect from using DrawPointList would probably be
negated by having to recombine the points and pens matrices. I think it
would also complicate the implementation somewhat, but I'm not sure on that
front.

Note that regardless of what happens with the pen list, the plan has always
been that you can omit it and nothing will happen, so you don't have to use
it...

Of course, other methods would need the same support for
the brush.

That would be the plan.

-tim

···

From: "Robin Dunn" <robin@alldunn.com>
From: "Kevin Altis":

I'm not thrilled with having a separate pen list. [None |
wxPen] makes sense where None just means use the default pen. If a list of
pens is going to be supported, then the pen should be part of the list

(x1,

y1, x2, y2, wxPen). Of course, other methods would need the same support

for

the brush.

That would increase the complexity by a couple orders of magnitude.

···

--
Robin Dunn
Software Craftsman
robin@AllDunn.com Java give you jitters?
http://wxPython.org Relax with wxPython!

Hi Robin,

Are C++ templates legal in helpers.cpp? I've been thinking for some time
that it would be nice to generalize all the LIST_helper functions to accepts
generic sequences, and if more helpers are needed for DrawXList, this might
be the time to do it.

-tim

> pens is going to be supported, then the pen should be part of the list
(x1,
> y1, x2, y2, wxPen).

This makes no sense to me. Supplying a single pen argument adds no
functionality that you can't do just as fast using:

Okay, now I'm confused. I thought that part of this exercise was that
DrawPointList and DrawLineList doesn't in fact draw a list of lines, but
rather makes some sort of polygon? I need to go back and try this, but am
running off to dinner, so I'll do it later. If DrawLineList does the "right
thing" then I agree my suggestion above is stupid as is the none option for
the pen. Your solution below is better.

wxDC.SetPen(pen)
wxDC.DrawLineList(points)

In fact I'm very tempted to rip out the single pen option. On the other
hand, allowing a pen list allows this:

for i in range(len(points)):
   wxDC.SetPen(pens[i])
   wxDC.DrawLine(*points[i])

as wxDC.DrawLineList(points, pens) which is about 10x faster.

ka

Okay, now I'm confused. I thought that part of this exercise was that
DrawPointList and DrawLineList doesn't in fact draw a list of lines, but
rather makes some sort of polygon? I need to go back and try this, but am
running off to dinner, so I'll do it later. If DrawLineList does the

"right

thing" then I agree my suggestion above is stupid as is the none option

for

the pen. Your solution below is better.

Ah, now I understand. No, DrawLineList just draws a list of lines not a
polygon. DrawLines and/or DrawPolygon already does what you're thinking of.

-tim

···

From: "Kevin Altis" <altis@semi-retired.com>

Sorry, I meant that wxPython DrawLines doesn't allow you to draw
(x1,y1,x2,y2), (x3,y3,x4,y4), etc. I thought that is what we were shooting
for and something similar for Points, Rects, etc. I'm mostly interested in
drawing a bunch of points or lines or rects or polygons, etc. using a single
pen, since that is the most common case I can think of.

I think you're on the right track.

ka

···

-----Original Message-----
From: wxpython-users-admin@lists.wxwindows.org
[mailto:wxpython-users-admin@lists.wxwindows.org]On Behalf Of Kevin
Altis
Sent: Monday, October 15, 2001 6:53 PM
To: wxpython-users@lists.wxwindows.org
Subject: RE: [wxPython] DrawXList and CVS frustration

> > pens is going to be supported, then the pen should be part of the list
> (x1,
> > y1, x2, y2, wxPen).
>
> This makes no sense to me. Supplying a single pen argument adds no
> functionality that you can't do just as fast using:

Okay, now I'm confused. I thought that part of this exercise was that
DrawPointList and DrawLineList doesn't in fact draw a list of lines, but
rather makes some sort of polygon? I need to go back and try this, but am
running off to dinner, so I'll do it later. If DrawLineList does
the "right
thing" then I agree my suggestion above is stupid as is the none
option for
the pen. Your solution below is better.

> wxDC.SetPen(pen)
> wxDC.DrawLineList(points)
>
> In fact I'm very tempted to rip out the single pen option. On the other
> hand, allowing a pen list allows this:
>
> for i in range(len(points)):
> wxDC.SetPen(pens[i])
> wxDC.DrawLine(*points[i])
>
> as wxDC.DrawLineList(points, pens) which is about 10x faster.

ka

_______________________________________________
wxpython-users mailing list
wxpython-users@lists.wxwindows.org
http://lists.wxwindows.org/mailman/listinfo/wxpython-users

Are C++ templates legal in helpers.cpp? I've been thinking for some time
that it would be nice to generalize all the LIST_helper functions to

accepts

generic sequences, and if more helpers are needed for DrawXList, this

might

be the time to do it.

It would be nice to be able to use them, but I'm going to have to say that
they are illegal. They are not allowed in wxWIndows code and although I
don't have to strictly follow those guildlines it is already hard enough to
build wxPython on some platforms/compilers so I don't want to make it any
more difficult.

···

--
Robin Dunn
Software Craftsman
robin@AllDunn.com Java give you jitters?
http://wxPython.org Relax with wxPython!

It is probably a good idea to disallow the templates for something as
general as wxPython. My current project exports a large number of templated
objects and functions to Python and, though the design works very well for
my specific problem, it does make it difficult to compile and debug at
times. We actually have some custom build tools to make it all work easily,
but they are very specific to the application.

Karl

Karl MacMillan
Computer Music Department
Peabody Institute of Johns Hopkins University
karlmac@peabody.jhu.edu | 410-659-4440
mambo.peabody.jhu.edu/~karlmac

···

-----Original Message-----
From: wxpython-users-admin@lists.wxwindows.org
[mailto:wxpython-users-admin@lists.wxwindows.org]On Behalf Of Robin Dunn
Sent: Tuesday, October 16, 2001 12:05 AM
To: wxpython-users@lists.wxwindows.org
Subject: Re: [wxPython] DrawXList: helpers

Are C++ templates legal in helpers.cpp? I've been thinking for some time
that it would be nice to generalize all the LIST_helper functions to

accepts

generic sequences, and if more helpers are needed for DrawXList, this

might

be the time to do it.

It would be nice to be able to use them, but I'm going to have to say that
they are illegal. They are not allowed in wxWIndows code and although I
don't have to strictly follow those guildlines it is already hard enough to
build wxPython on some platforms/compilers so I don't want to make it any
more difficult.

--
Robin Dunn
Software Craftsman
robin@AllDunn.com Java give you jitters?
http://wxPython.org Relax with wxPython!

_______________________________________________
wxpython-users mailing list
wxpython-users@lists.wxwindows.org
http://lists.wxwindows.org/mailman/listinfo/wxpython-users

Robin Dunn wrote:

For DrawLineList does having the two parallel sequences of points make sense
to everybody or would a sequence of (x1, y1, x2, y2) tuples be more
intuitive and useful?

I think the sequence of 4-tuples would make the most sense, as it
parallels what the exisiting DrawLine() takes. All the Draw*List methods
should take a sequence of the same input that the regular Draw* methods
do. As Tim is working on this, I'm sure it's already in there, but it
should take a NX4 NumPy array as well.

By the way, is there any real reason for DrawLine() to exist at all,
rather than using DrawLines() with just two points??

Tim Hochberg wrote:

> I'm not thrilled with having a separate pen list. [None |
> wxPen] makes sense where None just means use the default pen. If a list of
> pens is going to be supported, then the pen should be part of the list
(x1,
> y1, x2, y2, wxPen).

This makes no sense to me. Supplying a single pen argument adds no
functionality that you can't do just as fast using:

wxDC.SetPen(pen)
wxDC.DrawLineList(points)
In fact I'm very tempted to rip out the single pen option.

Quite true. I'm the one that argued for the single pen option. I still
think is a good idea, just tho keep the API clean, To me , it kindo of
mirrors the ideas of array broadcasting in NumPy, and other Array
oriented languages. For example, A*B works for A an array and B either
an Array of the same shape, or a scalar. If B is a scalar, it is
broadcast over all the elements of A (Broadcasting works on higher rank
arrays in very nifty ways, but that's not the point). Anyway, with my
background in MATLAB and NumPy, I tend to like this interace. It's also
a little more object oriented way to think about drawing: I want to draw
a given object (in this case a line, or set of lines with a given pen).
The current syntax is really a mirror of how a drawing process works:
set the pen, set the brush, draw the object. I'd rather be hidden from
those mechanics. Of course, the whole way DCs work is already set, and
I've written a more object oriented wrapper around them anyway, so there
may be little point in adding this small feature.

Actually, for real consistancy, a singleton sequence might be better
than a pen itself [pen], rather than pen. Hmmm..

That was a long-winded way to say: I'd like to have the single pen
option, but it's no big deal. He who writes the code, make the decision,
so go ahead and do what you want, Tim.

On the other hand, allowing a pen list allows this:

for i in range(len(points)):
   wxDC.SetPen(pens[i])
   wxDC.DrawLine(*points[i])

as wxDC.DrawLineList(points, pens) which is about 10x faster.

That, of course, is really the whole point of the exercise. While I,
too, most frequently want to draw a bunch of lines and points in a
single pen, The same is not true for rectangles and polygons, which I am
more likely to want in different colors, etc.

The final suggestion that the points and the pen combined into a single list
would be very bad for those of us that use Numeric to manipulate out points.

Exactly. While it is more object-oriented to think of a sequence of
objects, each object having all it's properties together, for
performance reasons, keeping the sequence of coordinates separate from
the other properties is crucial. You can manipulate all the coordinates
as a package. Even in C, there is always the choice between an array of
structs, and a struct of arrays.

Robin Dunn wrote:

the pen should be part of the list

(x1, y1, x2, y2, wxPen).
That would increase the complexity by a couple orders of magnitude.

Another good reason to keep them separate. If that's not enough, we want
the option of using a single pen (either by passing it in, or pre
setting it), so we can't go this route.

Tim Hochberg wrote:

Ah, now I understand. No, DrawLineList just draws a list of lines not a
polygon. DrawLines and/or DrawPolygon already does what you're thinking of.

right, which is exactly why it should be called DrawPolyline, because
that's what it does. And DrawPolylineList() (or DrawLinesList() ) will
draw a list of polylines. The point of this is twofold:

1) to have a cleaner syntax to draw a bunch of object (I always feel
like I'm writting clunky code when I write a for loop to do exactly the
same thing to each item in a list)

2) to have a faster way to draw a bunch of objects. This is perhaps the
stronger motivator. Without the speed issue, you culd wite this in
Python (and I have)

Kevin Altis wrote:

Sorry, I meant that wxPython DrawLines doesn't allow you to draw
(x1,y1,x2,y2), (x3,y3,x4,y4), etc.

That's because it draws a single Polyline....(x1,y1),(x2,y2),(x3,y3),
....

I'm mostly interested in
drawing a bunch of points or lines or rects or polygons, etc. using a single
pen, since that is the most common case I can think of.

It's the most common case for me two (at least for points and lines),
but while we are at it, being able to have them use different pens is a
very nice feature too.

I think you're on the right track.

So do I.

Kevin, did you try out my Python prototype of all this? Except for a few
details of the syntax, Tim is doing the same thing, but in C++.

Tim and Robin, thanks for putting your time into this, I, at least am
really going to appreciate it.

-Chris

···

--
Christopher Barker,
Ph.D.
ChrisHBarker@home.net --- --- ---
http://members.home.net/barkerlohmann ---@@ -----@@ -----@@
                                   ------@@@ ------@@@ ------@@@
Oil Spill Modeling ------ @ ------ @ ------ @
Water Resources Engineering ------- --------- --------
Coastal and Fluvial Hydrodynamics --------------------------------------
------------------------------------------------------------------------