Re: [SPAM: 6.600] Re: [pygame] Re: removing 'experimental' notice from pygame.math

2018-03-19 Thread René Dudfield
I'll merge this in now. Consider it stable(ish).


Re: [SPAM: 6.600] Re: [pygame] Re: removing 'experimental' notice from pygame.math

2018-03-15 Thread René Dudfield
Hi,

here is a PR for Vector changes from our discussion here (and elsewhere).
https://github.com/pygame/pygame/pull/416


   - Tests and fixes for keyword arguments with Vector2 Vector3
   - Tests for Vector2, and Vector3 scalar constructors like GLSL.
   Vector3(1) -> Vector3(1, 1, 1)
   - missing an element is an error now, no zero default. Vector3(1, 2),
   and Vector3(x=1, y=2)  fails.
   - Added magnitude to Vector types, which is an alias for length.
   - pygame.math require import (no missing module).
   - pygame.Vector2 pygame.Vector3 available.
   - Not in pygame.locals for now, to avoid possible breakage with common
   Vector2/Vector3 names.


The one breakage is for when people were doing:
  - Vector2(1), which used to give Vector2(1, 0), and now gives Vector2(1,
1).
  - Vector3(1), which used to give Vector3(1, 0, 0), or Vector3(1,2) which
used to give Vector3(1,2,0).


This should be the last of the changes to the Vector stuff for now to be
released in 1.9.4.
Other things can be added later without breaking backwards compatibility.


ciao,


On Sun, Mar 4, 2018 at 1:32 AM, Greg Ewing 
wrote:

> Russell Jones wrote:
>
>> IDK about physics, but AIUI, Z points from side to side, Y points down
>> and X points diagonally; it's Λ that points up.
>>
>
> Only if your computer screen is oriented vertically.
> If you're using a tablet in your lap, Λ points forward
> and Y points backwards.
>
> So obviously the code should interrogate the orientation
> sensor of the device it's running on, if it has one, to
> figure out the correct naming of the unit vector constants.
>
> --
> Greg
>
>


Re: [SPAM: 6.600] Re: [pygame] Re: removing 'experimental' notice from pygame.math

2018-03-03 Thread Greg Ewing

Russell Jones wrote:
IDK about physics, but AIUI, Z points from side to side, Y points down 
and X points diagonally; it's Λ that points up.


Only if your computer screen is oriented vertically.
If you're using a tablet in your lap, Λ points forward
and Y points backwards.

So obviously the code should interrogate the orientation
sensor of the device it's running on, if it has one, to
figure out the correct naming of the unit vector constants.

--
Greg



Re: [SPAM: 6.600] Re: [pygame] Re: removing 'experimental' notice from pygame.math

2018-03-03 Thread Russell Jones
IDK about physics, but AIUI, Z points from side to side, Y points down and
X points diagonally; it's Λ that points up.

(sorry)

Russell

On 1 March 2018 at 08:43, Greg Ewing  wrote:

> Daniel Pope wrote:
>
> Y points up in real physics?
>>
>
> No, no, no. Z points up in real physics!
>
> --
> Greg
>


Re: [SPAM: 5.011] Re: [SPAM: 6.600] Re: [pygame] Re: removing 'experimental' notice from pygame.math

2018-03-02 Thread Greg Ewing

René Dudfield wrote:

So it might be nice to return the length(magnitude) there?


BTW, I don't really like the name "length" for a function
that returns the magnitude of an arbitrary vector. It only
makes sense for vectors representing a physical distance;
it's nonsense for anything else (velocity, acceleration,
electric field, etc.)

--
Greg


Re: [SPAM: 6.600] Re: [pygame] Re: removing 'experimental' notice from pygame.math

2018-03-02 Thread René Dudfield
Having normalize_ip return the old length would be a bit weird.
Yeah, another name like 'normalize_ip_return_length' But maybe longer ;)
speed = direction.length_normalize_ip()


Re: [SPAM: 6.600] Re: [pygame] Re: removing 'experimental' notice from pygame.math

2018-03-02 Thread René Dudfield
What is UP for rock climbers hanging upside down,
when they are chatting on their phone,
which points towards the horizon,
whilst they live in Australia? ;)

( @Ian... give in to the temptation... )




Thanks Victor, those are some good notes.
And I guess some of them will take some time to figure out how to handle
them nicely.


1) Ok, right. I'll add that to the list.
http://www.pymunk.org/en/latest/_modules/pymunk/vec2d.html#Vec2d.normalize_return_length

That's useful because...
when you want to keep the length (as a speed),
but normalize the vector to be used just as a direction.

This would be like normalize_ip in the pygame vector.
  http://www.pygame.org/docs/ref/math.html#pygame.math.Vector2.normalize_ip

'normalize_ip' currently returns None.
So it might be nice to return the length(magnitude) there?

'normalize` returns a copy of the vector.



2) scaling back up from 0 does indeed seem hard.
Would it need to be only after it was scaled down?
Perhaps adding the last value would be useful.
But then, there are many ways a vector can come to be at zero.

3) perhaps some assumption could be used about screen->world coordinates
could be baked in.

Or some property of the vector,
vec2(0, 1).asGL??? -> vec2(0, -1)

Swizzle convention?
vec2(0, 1).xY -> vec2(0, -1)

Not sure really.

draw.circle says,
  "Give me the coordinates in pygame screen coordinates? Please." -> (0, 1)



4) oh yes, draw functions. Very good point.

Automatic rounding in the draw functions seem a good idea.
I'll include drawing a circle in my example I'm writing,
and perhaps modernise circle drawing first.

What would a pygame.draw.vector2 look like? draw.vector3?



5) I didn't try benchmarking with pypy.
I expect they'll have similar performance to other pygame C types like Rect.

Not sure if they have optimized keyword arguments(METH_KEYWORDS),
 as much as they have METH_NOARGS and METH_VARARGS.

I'm going to the pypy sprint in Leysin, and should get a benchmark ready by
then.





On Thu, Mar 1, 2018 at 10:17 AM, Ian Mallett  wrote:

> On Thu, Mar 1, 2018 at 1:43 AM, Greg Ewing 
> wrote:
>
>> No, no, no. Z points up in real physics!
>
>
> Oh, and I expect "j" is the imaginary unit, "Σ"s can be omitted, gravity
> is exactly 10 m/s, without the square, and anyway one can drop units
> whenever one feels like it?
> ( Must. Resist. Temptation. To. Rant. . . )
>


Re: [SPAM: 6.600] Re: [pygame] Re: removing 'experimental' notice from pygame.math

2018-03-01 Thread Ian Mallett
On Thu, Mar 1, 2018 at 1:43 AM, Greg Ewing 
wrote:

> No, no, no. Z points up in real physics!


Oh, and I expect "j" is the imaginary unit, "Σ"s can be omitted, gravity is
exactly 10 m/s, without the square, and anyway one can drop units whenever
one feels like it?
( Must. Resist. Temptation. To. Rant. . . )


Re: [SPAM: 6.600] Re: [pygame] Re: removing 'experimental' notice from pygame.math

2018-03-01 Thread Greg Ewing

Daniel Pope wrote:


Y points up in real physics?


No, no, no. Z points up in real physics!

--
Greg


Re: [pygame] Re: removing 'experimental' notice from pygame.math

2018-02-28 Thread Daniel Pope
> As René pointed out in most of the Pymunk examples Y is converted so that
positive Y points up to keep examples consistent and close to "real"
physics.

Y points up in real physics?

This is making my head hurt; I need to go lie -Y. 

On Wed, 28 Feb 2018, 22:52 Victor Blomqvist,  wrote:

> Hi,
>
> René sent an email asking if I had any input (as the author of pymunk), so
> here I am. In general I think it seems like a very well versed vector
> library in the making :)
>
> A couple of comments:
> 1. A function that normalizes and returns the length before normalizing in
> one call can be useful and be a little bit faster than doing two calls. In
> the pymunk.vec2d class its called normalize_return_length.
>
> 2. A user asked me why a vector cant be scaled up again after it has been
> scaled down to 0 (which is not supported in the pymunk.vec2d class or
> pygame.math). It would be a very useful feature and also beginner friendly.
> However, I dont see a way to do it in a good way so I havent implemented
> anything.
>
> 3. As René pointed out in most of the Pymunk examples Y is converted so
> that positive Y points up to keep examples consistent and close to "real"
> physics. Would be nice if pygame could handle it easily, maybe something
> you could set in the beginning of you code? But Im not sure if it fits here
> :)
>
> 4. In many cases Pygame methods expect an integer, such as position in
> pygame.draw.circle(). Since Vector2 seems to be a float either some
> automatic rounding or a method Vector2.int_tuple or similar would be
> convenient?
>
> 5. You already do some benchmarking, did you try Pypy?
>
> /Victor
>
>
>
> On Tue, Feb 27, 2018 at 10:55 PM, Ian Mallett  wrote:
>
>> ​(Skims discussion)
>>
>> For e.g. `abs(Vector2(2,-1).elementwise())`, my (C++) library instead
>> handles this as `abs(Vec2(2,-1))`, returning another `Vec2`. In C++, if you
>> weren't expecting that, you get a compile error on whatever happens next,
>> whereas in Python you'll get a `TypeError`, so it's well-defined.
>>
>> If you want the vector's length, I use a function, but perhaps it's more
>> pythonic to use a method: `Vec2(2,-1).getLength()`, or
>> `Vec2(2,-1).getLengthSq()`.
>>
>> If your vector represents a complex number and you're wondering why
>> `abs(...)` shouldn't return a complex modulus, then I ask why you aren't
>> using the built-in `complex`, which is designed for this.
>>
>> Ian
>>
>
>


Re: [pygame] Re: removing 'experimental' notice from pygame.math

2018-02-28 Thread Victor Blomqvist
Hi,

René sent an email asking if I had any input (as the author of pymunk), so
here I am. In general I think it seems like a very well versed vector
library in the making :)

A couple of comments:
1. A function that normalizes and returns the length before normalizing in
one call can be useful and be a little bit faster than doing two calls. In
the pymunk.vec2d class its called normalize_return_length.

2. A user asked me why a vector cant be scaled up again after it has been
scaled down to 0 (which is not supported in the pymunk.vec2d class or
pygame.math). It would be a very useful feature and also beginner friendly.
However, I dont see a way to do it in a good way so I havent implemented
anything.

3. As René pointed out in most of the Pymunk examples Y is converted so
that positive Y points up to keep examples consistent and close to "real"
physics. Would be nice if pygame could handle it easily, maybe something
you could set in the beginning of you code? But Im not sure if it fits here
:)

4. In many cases Pygame methods expect an integer, such as position in
pygame.draw.circle(). Since Vector2 seems to be a float either some
automatic rounding or a method Vector2.int_tuple or similar would be
convenient?

5. You already do some benchmarking, did you try Pypy?

/Victor



On Tue, Feb 27, 2018 at 10:55 PM, Ian Mallett  wrote:

> ​(Skims discussion)
>
> For e.g. `abs(Vector2(2,-1).elementwise())`, my (C++) library instead
> handles this as `abs(Vec2(2,-1))`, returning another `Vec2`. In C++, if you
> weren't expecting that, you get a compile error on whatever happens next,
> whereas in Python you'll get a `TypeError`, so it's well-defined.
>
> If you want the vector's length, I use a function, but perhaps it's more
> pythonic to use a method: `Vec2(2,-1).getLength()`, or
> `Vec2(2,-1).getLengthSq()`.
>
> If your vector represents a complex number and you're wondering why
> `abs(...)` shouldn't return a complex modulus, then I ask why you aren't
> using the built-in `complex`, which is designed for this.
>
> Ian
>


Re: [pygame] Re: removing 'experimental' notice from pygame.math

2018-02-27 Thread Daniel Pope
> Vector2(x=0, y=0) -> Vector(0, 0)

If rgba and uvst are swizzle attributes, are they also accepted as kwargs?

> However, I feel this single scalar is hard to make
a mistake with accidentally passing in the wrong thing?

I don't think so. I think it could easily happen accidentally, while
refactoring.

On Tue, 27 Feb 2018, 18:19 René Dudfield,  wrote:

> Some good points. Thanks, I appreciate the discussion.
>
>
> On Tue, Feb 27, 2018 at 3:51 PM, Daniel Pope  wrote:
>
>> > Single scalar constructor should Vector2(1) == Vector2(1, 1)
>>
>> This is the kind of situation where I'd follow PEP20: "In the face of
>> ambiguity, refuse the temptation to guess." There's an obvious pitfall if
>> you expected to pass a tuple and you instead pass a scalar or the wrong
>> length tuple - it silently succeeds but constructs the wrong Vector.
>> Perhaps raise a TypeError?
>>
>>
> At the moment Vector2/3 uses keyword arguments.
> Vector2() -> Vector(0, 0)
> ​Vector2(x=0, y=0) -> Vector(0, 0)
> Vector2(1) -> Vector(1, 0)
>
> I'm beginning to think keyword arguments are wrong for this.
> Would maybe prefer to raise a TypeError as you suggest,
>   or follow GLSL behaviour and allow single scalar, error for the others.
>
> These should raise an error for sure?
>   Vector3(1, 1) # oops, I meant to type three 1s.
>   Vector3(some2d_I_thought_was_a_3d) #oops, the incoming value is of a
> different size.
>
> However, I feel this single scalar is hard to make
> a mistake with accidentally passing in the wrong thing?
>   Vector(1)
>
> Keyword arguments are also pretty useless for readability with Vector2/3.
> Because you know it's a 3 element container.
>   Vector3(x=0, y=0, z=0) VS
>   Vector3(0,0,0)
>
> It's fairly common to init vec2/vec3 in GLSL with a single number.
> Eyeballing a few scripts, maybe 10% of usage is single scalar constructor.
> And to be able to have fairly good compatibility with code from shadertoy
> might be nice.
>
>
>
>
>
> > Lower dimensional to higher dimension contructors should work:
>> > Vector3(1, Vector2(2, 3)) == Vector3(1, 2, 3)
>>
>> We don't need this because we have star args:
>>
>> Vector3(1, *Vector2(2, 3))
>>
>
> Yeah, good point.
>
> There is this error message for this case at least:
> >>> Vector3(1, (1,2))
> ValueError: Vector3 must be initialized with 3 real numbers or a
> sequence of 3 real numbers
>
> I don't think the "Lower dimensional to higher dimension constructors
> should work" bit is that important.
> It's not super common in GLSL code I've seen in the wild anyway.
>
> And as you say, we have * notation for this.
>
>
>
>
>
>
> *Some more benchmarking.*
>
> Some timing on python 3.6 (with PyArg_ParseTupleAndKeywords which supports
> keyword arguments).
> Note v3.xyz is the fastest constructor. See below with just
> PyArg_ParseTuple (no speed improvement).
>
>
> v3 = Vector3(0)
>
> %timeit v3.xyz
>
> 1000 loops, best of 3: *83.3 ns per loop*
>
> %timeit Vector3()
> 1000 loops, best of 3: 131 ns per loop
>
> %timeit Vector3(0)
> 100 loops, best of 3: 199 ns per loop
>
> %timeit Vector3(0, 0, 0)
> 100 loops, best of 3: 269 ns per loop
>
> %timeit Vector3(x=0, y=0, z=0)
> 100 loops, best of 3: 426 ns per loop
>
> %timeit Rect((0, 0, 0, 0))
> 1000 loops, best of 3: 184 ns per loop
>
> from numpy import array
> %timeit array((0,0,0))
> 100 loops, best of 3: *919 ns* per loop
>
> assert id(v3) != id(v3.xyz), ".xyz makes a copy"
>
> %timeit (0,0,0)
> 1 loops, best of 3: *14.9 ns* per loop
>
> somevec= (1, 2)
>
> %timeit Vector3(1, *somevec)
> 100 loops, best of 3: 333 ns per loop
>
> %timeit anothervec=v3.xyz;anothervec.xyz = (1, 2, 3)
> 100 loops, best of 3: 221 ns per loop
>
>
>
>
>
> *Now timing with PyArg_ParseTuple.*
> Interestingly, in 3.6 PyArg_ParseTupleAndKeywords and PyArg_ParseTuple
> are the same speed (on this mac laptop anyway).
>
> %timeit Vector3(0)
> 100 loops, best of 3: 198 ns per loop
>
> %timeit Vector3(0, 0, 0)
> 100 loops, best of 3: 276 ns per loop
>
>
> Exactly the same timing as PyArg_ParseTupleAndKeywords pretty much.
>
>
> And now for something kind of funny...
>
> In [11]: from dis import dis
>
> In [12]: def a():
> ...: Vector3(0,0,0)
> ...:
>
> In [13]: def b():
> ...: v3.xyz
> ...:
>
> In [14]: dis(a)
>   2   0 LOAD_GLOBAL  0 (Vector3)
>   2 LOAD_CONST   1 (0)
>   4 LOAD_CONST   1 (0)
>   6 LOAD_CONST   1 (0)
>   8 CALL_FUNCTION3
>  10 POP_TOP
>  12 LOAD_CONST   0 (None)
>  14 RETURN_VALUE
>
> In [15]: dis(b)
>   2   0 LOAD_GLOBAL  0 (v3)
>   2 LOAD_ATTR1 (xyz)
>   4 POP_TOP
>   6 LOAD_CONST   0 (None)
>   8 RETURN_VALUE
>
> An ugly hack would be to
>   avoid those byte code 

Re: [pygame] Re: removing 'experimental' notice from pygame.math

2018-02-27 Thread Daniel Pope
> We want to go two left? This is sort of nice.
> >>> velocity + Vector3.left * 2

Christening a particular axis or Vector as "left" had all kinds of
problems. Which way is up? +y, like a graph? -y, like Surface coordinates?
Is it a left-handed or right-handed coordinate system?

On Tue, 27 Feb 2018, 21:56 Ian Mallett,  wrote:

> ​(Skims discussion)
>
> For e.g. `abs(Vector2(2,-1).elementwise())`, my (C++) library instead
> handles this as `abs(Vec2(2,-1))`, returning another `Vec2`. In C++, if you
> weren't expecting that, you get a compile error on whatever happens next,
> whereas in Python you'll get a `TypeError`, so it's well-defined.
>
> If you want the vector's length, I use a function, but perhaps it's more
> pythonic to use a method: `Vec2(2,-1).getLength()`, or
> `Vec2(2,-1).getLengthSq()`.
>
> If your vector represents a complex number and you're wondering why
> `abs(...)` shouldn't return a complex modulus, then I ask why you aren't
> using the built-in `complex`, which is designed for this.
>
> Ian
>


Re: [pygame] Re: removing 'experimental' notice from pygame.math

2018-02-27 Thread Ian Mallett
​(Skims discussion)

For e.g. `abs(Vector2(2,-1).elementwise())`, my (C++) library instead
handles this as `abs(Vec2(2,-1))`, returning another `Vec2`. In C++, if you
weren't expecting that, you get a compile error on whatever happens next,
whereas in Python you'll get a `TypeError`, so it's well-defined.

If you want the vector's length, I use a function, but perhaps it's more
pythonic to use a method: `Vec2(2,-1).getLength()`, or
`Vec2(2,-1).getLengthSq()`.

If your vector represents a complex number and you're wondering why
`abs(...)` shouldn't return a complex modulus, then I ask why you aren't
using the built-in `complex`, which is designed for this.

Ian


Re: [pygame] Re: removing 'experimental' notice from pygame.math

2018-02-27 Thread René Dudfield
Some static constructors could be useful.

up, down, left, right
forward, back
zero, one, two, ...

>>> velocity = Vector3(1, 2, 3)

We want to go two left? This is sort of nice.
>>> velocity + Vector3.left * 2


>>> Vector3.left


>>> Vector3.right


>>> Vector3.up


They are unit vectors (length 1) in a particular direction.

Plus a few other useful constants.
>>> Vector3.one


etc.



​If I remove PyArg_ParseTuple entirely...
%timeit Vector3()
1000 loops, best of 3: 104 ns per loop

(I guess it'd be around 84ns as a static attribute lookup which constructs
a new vector).

So these special constructors, as well as being readable would be faster.

It'd still be quicker to declare them as variables, and make them immutable.
vec3_left = Vector3(-1, 0, 0)
%timeit vec3_left
1000 loops, best of 3: 24 ns per loop


Note below, how the 'vec3_left' variable is lots quicker.

%timeit velocity + Vector3(-1, 0, 0) * 2
100 loops, best of 3: 451 ns per loop

%timeit velocity + vec3_left * 2
1000 loops, best of 3: 184 ns per loop

We make a pretend Vector3 with a left variable to see how quick it is.
In [27]: class Vector3:
...: pass
...:

In [28]: Vector3.left = vec3_left

%timeit Vector3.vector_left
1000 loops, best of 3: 44.1 ns per loop

In [29]: %timeit velocity + Vector3.left * 2
100 loops, best of 3: 214 ns per loop

So it seems making some immutable vectors would be useful for a 10.2x -
18.8x speedup.
Without immutable vectors, 5.3x speedup.



Plus, I think they'd be more readable, and perhaps instructive.


Re: [pygame] Re: removing 'experimental' notice from pygame.math

2018-02-27 Thread René Dudfield
Some good points. Thanks, I appreciate the discussion.


On Tue, Feb 27, 2018 at 3:51 PM, Daniel Pope  wrote:

> > Single scalar constructor should Vector2(1) == Vector2(1, 1)
>
> This is the kind of situation where I'd follow PEP20: "In the face of
> ambiguity, refuse the temptation to guess." There's an obvious pitfall if
> you expected to pass a tuple and you instead pass a scalar or the wrong
> length tuple - it silently succeeds but constructs the wrong Vector.
> Perhaps raise a TypeError?
>
>
At the moment Vector2/3 uses keyword arguments.
Vector2() -> Vector(0, 0)
​Vector2(x=0, y=0) -> Vector(0, 0)
Vector2(1) -> Vector(1, 0)

I'm beginning to think keyword arguments are wrong for this.
Would maybe prefer to raise a TypeError as you suggest,
  or follow GLSL behaviour and allow single scalar, error for the others.

These should raise an error for sure?
  Vector3(1, 1) # oops, I meant to type three 1s.
  Vector3(some2d_I_thought_was_a_3d) #oops, the incoming value is of a
different size.

However, I feel this single scalar is hard to make
a mistake with accidentally passing in the wrong thing?
  Vector(1)

Keyword arguments are also pretty useless for readability with Vector2/3.
Because you know it's a 3 element container.
  Vector3(x=0, y=0, z=0) VS
  Vector3(0,0,0)

It's fairly common to init vec2/vec3 in GLSL with a single number.
Eyeballing a few scripts, maybe 10% of usage is single scalar constructor.
And to be able to have fairly good compatibility with code from shadertoy
might be nice.





> Lower dimensional to higher dimension contructors should work:
> > Vector3(1, Vector2(2, 3)) == Vector3(1, 2, 3)
>
> We don't need this because we have star args:
>
> Vector3(1, *Vector2(2, 3))
>

Yeah, good point.

There is this error message for this case at least:
>>> Vector3(1, (1,2))
ValueError: Vector3 must be initialized with 3 real numbers or a
sequence of 3 real numbers

I don't think the "Lower dimensional to higher dimension constructors
should work" bit is that important.
It's not super common in GLSL code I've seen in the wild anyway.

And as you say, we have * notation for this.






*Some more benchmarking.*

Some timing on python 3.6 (with PyArg_ParseTupleAndKeywords which supports
keyword arguments).
Note v3.xyz is the fastest constructor. See below with just
PyArg_ParseTuple (no speed improvement).


v3 = Vector3(0)

%timeit v3.xyz
1000 loops, best of 3: *83.3 ns per loop*

%timeit Vector3()
1000 loops, best of 3: 131 ns per loop

%timeit Vector3(0)
100 loops, best of 3: 199 ns per loop

%timeit Vector3(0, 0, 0)
100 loops, best of 3: 269 ns per loop

%timeit Vector3(x=0, y=0, z=0)
100 loops, best of 3: 426 ns per loop

%timeit Rect((0, 0, 0, 0))
1000 loops, best of 3: 184 ns per loop

from numpy import array
%timeit array((0,0,0))
100 loops, best of 3: *919 ns* per loop

assert id(v3) != id(v3.xyz), ".xyz makes a copy"

%timeit (0,0,0)
1 loops, best of 3: *14.9 ns* per loop

somevec= (1, 2)

%timeit Vector3(1, *somevec)
100 loops, best of 3: 333 ns per loop

%timeit anothervec=v3.xyz;anothervec.xyz = (1, 2, 3)
100 loops, best of 3: 221 ns per loop





*Now timing with PyArg_ParseTuple.*
Interestingly, in 3.6 PyArg_ParseTupleAndKeywords and PyArg_ParseTuple
are the same speed (on this mac laptop anyway).

%timeit Vector3(0)
100 loops, best of 3: 198 ns per loop

%timeit Vector3(0, 0, 0)
100 loops, best of 3: 276 ns per loop


Exactly the same timing as PyArg_ParseTupleAndKeywords pretty much.


And now for something kind of funny...

In [11]: from dis import dis

In [12]: def a():
...: Vector3(0,0,0)
...:

In [13]: def b():
...: v3.xyz
...:

In [14]: dis(a)
  2   0 LOAD_GLOBAL  0 (Vector3)
  2 LOAD_CONST   1 (0)
  4 LOAD_CONST   1 (0)
  6 LOAD_CONST   1 (0)
  8 CALL_FUNCTION3
 10 POP_TOP
 12 LOAD_CONST   0 (None)
 14 RETURN_VALUE

In [15]: dis(b)
  2   0 LOAD_GLOBAL  0 (v3)
  2 LOAD_ATTR1 (xyz)
  4 POP_TOP
  6 LOAD_CONST   0 (None)
  8 RETURN_VALUE

An ugly hack would be to
  avoid those byte code ops,
  and avoid PyArg_ParseTupleX in CALL_FUNCTION...

And encode numbers in a swizzle-ish attribute.
  Vector3.xyz_1234234235__23423__333 -> Vector3(1234234235, 23423, 333)

Haha... pretty ridiculous. Not a good idea for readability.
But interesting how you can abuse the attribute getter.


It's sort of unfair that tuple construction gets a 18x faster constructor
over extension types in CPython.
But anyway. 3.4x to 11x faster construction than numpy arrays is nice.


Re: [pygame] Re: removing 'experimental' notice from pygame.math

2018-02-27 Thread Daniel Pope
> Single scalar constructor should Vector2(1) == Vector2(1, 1)

This is the kind of situation where I'd follow PEP20: "In the face of
ambiguity, refuse the temptation to guess." There's an obvious pitfall if
you expected to pass a tuple and you instead pass a scalar or the wrong
length tuple - it silently succeeds but constructs the wrong Vector.
Perhaps raise a TypeError?

> Lower dimensional to higher dimension contructors should work:
> Vector3(1, Vector2(2, 3)) == Vector3(1, 2, 3)

We don't need this because we have star args:

Vector3(1, *Vector2(2, 3))


Re: [pygame] Re: removing 'experimental' notice from pygame.math

2018-02-27 Thread René Dudfield
I've done a much larger review and testing.
Comparing it to different vector implementations,
and looking at how it inter-operates with pygame and OpenGL APIs.

TLDR; these things need to be fixed:
- scalar construction is buggy.
- One naming improvement I'd like help with is .elementwise() ? I think
it's too long.
- float('NaN') and float('inf') behaviour is not tested.
- Construction from Color, and Rect needs to be defined.

There's other useful functionality that could be added later I think.

I'll finish off the narrative documentation and example program,
and then await feedback before the Experimental notice is lifted.
This process has already uncovered a bunch of things that
are missing, so I expect more to pop up.

IMHO, it's already one of the best vector2/vector3 implementations in
python.
And I like that people will be able to use their knowledge of this API with
GLSL (a bit).



*A) GLSL shadling language vectors*

https://en.wikibooks.org/wiki/GLSL_Programming/Vector_and_Matrix_Operations#Components
https://www.khronos.org/registry/OpenGL/specs/gl/GLSLangSpec.4.60.pdf

Here's what I've found missing/different.

1) Single scalar constructor should
Vector2(1) == Vector2(1, 1)
   # currently it makes Vector2(1, 0)

2) Lower dimensional to higher dimension contructors should work:
Vector3(1, Vector2(2, 3)) == Vector3(1, 2, 3)

3) the GLSL documentation uses "component wise", whereas we use
elementwise()
  Additionally, I think elementwise() is quite long, and should probably be
a property.
  A shorter name here would be nice.


4) Missing functions:
abs
abs(Vector2(2,-1).elementwise()) works.
sign
floor
trunc
round
roundEven
ceil
fract
mod
modf
min
max
clamp
mix
step
smoothstep

faceForward are missing
... more


Section 8.3, Common Functions
https://www.khronos.org/registry/OpenGL/specs/gl/GLSLangSpec.4.30.pdf

The functions operate component wise.
Vector2(1, 3).min(Vector2(4, -2)) == Vector2(1, -2)

We have min() and max() in python, but unfortunately they use some weird
magic, and not a dunder magic method.

"Classes that act like numbers"
http://www.diveintopython3.net/special-method-names.html#acts-like-number
  __floor__
  __ceil__
  __trunc__

5) swizzling only there with xyzw

Seems like rgba, and stpq should be available.

{x, y, z, w} Useful when accessing vectors that represent points or normals
{r, g, b, a} Useful when accessing vectors that represent colors
{s, t, p, q} Useful when accessing vectors that represent texture
coordinates

Perhaps vec3.rgb would return a pygame.Color




*B) Compared to the CookBook 2d vector class...*
https://www.pygame.org/wiki/2DVectorClass


missing:
get_angle()
perpendicular
http://mathworld.wolfram.com/PerpendicularVector.html
perpendicular_normal
projection (not in here, but the inverse is the rejection)
https://en.wikipedia.org/wiki/Vector_projection



*C) Compred to box2d vec2*
https://github.com/pybox2d/pypybox2d/blob/master/pypybox2d/src/vec2module.c

missing:
contains() isn't there, but you can do:
  2 in v2
clamp
min
max



*D) pyeuclid*

rotate_around(axis, theta)
https://github.com/ezag/pyeuclid/blob/master/euclid.py#L565
copy()
Rect, and Surface have this in pygame too
Vector2(Vector2(1,2)) work however.



*E) planar*

https://pythonhosted.org/planar/vectorref.html
almost_equals

https://pythonhosted.org/planar/vectorref.html#planar.Vec2.almost_equals
Should be called isclose like python3.5+ math.isclose
https://docs.python.org/3/library/math.html#math.isclose
scaled_to
https://pythonhosted.org/planar/vectorref.html#planar.Vec2.scaled_to
perpendicular
clamped




*Extras*
Additional functionality not done is the buffer stuff. Which is commented
out in math.c
I guess the purpose is to allow a Vector2/3 to act with it's storage coming
in
an array. This would be super useful if you allocated a big array and wanted
to act on one element easily. Again, I think this could come later without
harming
backwards compatibility.

There is partial support in the code for a Vector4.
There's nothing done for 2x2, 3x3 or 4x4 matrix.
Which are all quite useful in games (and in GLSL).
These can all come later without harming backwards compatibility.


*Existing pygame APIs.*

There are some differences between Vector3 and Rect and Color types.

Vectors allow some niceties which people might come to expect from Rect and
Color.
v2[:] = (3,4)
v2.xy = (3,4)
Vector3(0) -> Vector3(0, 0, 0)

Also, Rect has methods like copy() which are missing in Vector3.

Passing a color into pygame gives a very strange result.
>>> Vector2(pygame.Color(2,3,4, 111))


I think Vector3(Color('red')) should work to give you Vector(1, 0, 0).
And Vector3(Color(255, 255, 255)) should give you Vector3(1, 1, 1).

Or maybe 

Re: [pygame] Re: removing 'experimental' notice from pygame.math

2018-02-27 Thread René Dudfield
I won't move pygame.math.Vector2/3 into pygame or pygame.locals namespace
for now.
That's potentially breaking things which already have their own Vector2/3.
This type of API change will wait for pygame 2.

Narrative documentation is missing, and I'm working on that now.


Re: [pygame] Re: removing 'experimental' notice from pygame.math

2018-02-25 Thread René Dudfield
I fixed a bunch of compiler warnings, added a test for lerp(), and tweaked
the documentation.

Note that the pickle stuff isn't working under pypy.


Re: [pygame] Re: removing 'experimental' notice from pygame.math

2018-02-25 Thread Daniel Pope
Indeed, getting the attribute returns a float so the attribute should be
settable as a float for consistency.

If users are familiar with GLSL[1], they might be surprised that the type
of vectors returned by swizzle attribute access is not a vector:

>>> from pygame.math import Vector3, enable_swizzling
>>> enable_swizzling()
>>> Vector3()

>>> v = Vector3(1, 2, 3)

>>> v.xy
(1.0, 2.0)
>>> type(v.xy)


[1]
https://en.wikibooks.org/wiki/GLSL_Programming/Vector_and_Matrix_Operations#Components


On Sun, 25 Feb 2018 at 09:38 René Dudfield  wrote:

> Hi,
>
> that's a good point.
>
> TLDR; I think it should be on by default too. There's still a couple of
> issues with doing that.
>
>
> It should have _no_ cost in almost all cases for attribute access. Because
> it first tries normal attribute access.
> See: https://github.com/pygame/pygame/blob/master/src/math.c#L1517
>
> I guess the reason is it's off by default is because it was implemented
> later on, and to leave it on in a buggy state caused issues.
>
> Not a big concern, but turning it on by default will perhaps have annoying
> compatibility issues for people using an old pygame.
> If they forget to turn it on.
>
> There's two test failures once I changed to be enabled by default:
>
> >>> import pygame.math
> >>> v = pygame.math.Vector2(1,2)
> >>> v.x = 3
> Traceback (most recent call last):
>   File "", line 1, in 
> TypeError: a sequence is expected
> >>> pygame.math.disable_swizzling()
> >>> v.x = 3
> >>> v
> 
>
> These are to do with assignment to a variable.
> https://github.com/pygame/pygame/pull/403
>
>
>
>
> On Sat, Feb 24, 2018 at 7:23 PM, Daniel Pope  wrote:
>
>> Does the Swizzling have a cost if you're not using it? If not I'd be
>> tempted to say it should always be on.
>>
>>
>> On Sat, 24 Feb 2018, 18:00 René Dudfield,  wrote:
>>
>>> Hey hey,
>>>
>>> I noticed the pygame.math vectors couldn't be pickled/unpickled.
>>>
>>> So that has been added here:
>>> https://github.com/pygame/pygame/pull/403
>>>
>>> Could someone please review?
>>>
>>>
>>> cheers,
>>>
>>>
>>>
>>> On Sat, Feb 24, 2018 at 10:30 AM, René Dudfield 
>>> wrote:
>>>
 Hello,

 I'm going to remove the experimental notice from pygame.math in the
 docs.
 https://www.pygame.org/docs/ref/math.html

 It seems fine to me, and I guess no one has plans to change it?


 best regards,

>>>
>>>
>


Re: [pygame] Re: removing 'experimental' notice from pygame.math

2018-02-25 Thread René Dudfield
Hi,

that's a good point.

TLDR; I think it should be on by default too. There's still a couple of
issues with doing that.


It should have _no_ cost in almost all cases for attribute access. Because
it first tries normal attribute access.
See: https://github.com/pygame/pygame/blob/master/src/math.c#L1517

I guess the reason is it's off by default is because it was implemented
later on, and to leave it on in a buggy state caused issues.

Not a big concern, but turning it on by default will perhaps have annoying
compatibility issues for people using an old pygame.
If they forget to turn it on.

There's two test failures once I changed to be enabled by default:

>>> import pygame.math
>>> v = pygame.math.Vector2(1,2)
>>> v.x = 3
Traceback (most recent call last):
  File "", line 1, in 
TypeError: a sequence is expected
>>> pygame.math.disable_swizzling()
>>> v.x = 3
>>> v


These are to do with assignment to a variable.
https://github.com/pygame/pygame/pull/403




On Sat, Feb 24, 2018 at 7:23 PM, Daniel Pope  wrote:

> Does the Swizzling have a cost if you're not using it? If not I'd be
> tempted to say it should always be on.
>
>
> On Sat, 24 Feb 2018, 18:00 René Dudfield,  wrote:
>
>> Hey hey,
>>
>> I noticed the pygame.math vectors couldn't be pickled/unpickled.
>>
>> So that has been added here:
>> https://github.com/pygame/pygame/pull/403
>>
>> Could someone please review?
>>
>>
>> cheers,
>>
>>
>>
>> On Sat, Feb 24, 2018 at 10:30 AM, René Dudfield  wrote:
>>
>>> Hello,
>>>
>>> I'm going to remove the experimental notice from pygame.math in the docs.
>>> https://www.pygame.org/docs/ref/math.html
>>>
>>> It seems fine to me, and I guess no one has plans to change it?
>>>
>>>
>>> best regards,
>>>
>>
>>


Re: [pygame] Re: removing 'experimental' notice from pygame.math

2018-02-24 Thread Daniel Pope
Does the Swizzling have a cost if you're not using it? If not I'd be
tempted to say it should always be on.

On Sat, 24 Feb 2018, 18:00 René Dudfield,  wrote:

> Hey hey,
>
> I noticed the pygame.math vectors couldn't be pickled/unpickled.
>
> So that has been added here:
> https://github.com/pygame/pygame/pull/403
>
> Could someone please review?
>
>
> cheers,
>
>
>
> On Sat, Feb 24, 2018 at 10:30 AM, René Dudfield  wrote:
>
>> Hello,
>>
>> I'm going to remove the experimental notice from pygame.math in the docs.
>> https://www.pygame.org/docs/ref/math.html
>>
>> It seems fine to me, and I guess no one has plans to change it?
>>
>>
>> best regards,
>>
>
>