[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

Re: [pygame] API draft for vector type



Any reason to not follow the pep-8 naming convention for methods, i.e.:

v.get_distance_to()

instead of:

v.getDistanceTo()

or maybe even (the get seems a little superfluous):

v.distanceto()

Other pygame modules seem to use the pep-8 convention, would be a shame to break the nice consistency.

-Casey

On Apr 27, 2009, at 3:59 PM, Lorenz Quack wrote:

Hello,

I am interested in the inclusion of a vector and matrix types into pygame as suggested here [4]. In this email I want to propose a API for a vector module.

I will for brevity only present the API for the types in three dimensions.
The APIs for two or four dimensions should look analog.

Also I enumerated every API for easier reference in discussions.
Alternatives are denoted by lexical items (e.g. a) or b))
At the end I put together a small comparison to existing implementations.

This is only a suggestion to spark discussion and provoke feedback. So throw
in your 2 cents.

sincerely yours
//Lorenz


PS: If this turns out to be of any value I will put something similar together for matrix types and quaternions.




******************
* API draft v1.0 *
******************

In the following I will use the notation:
  v, v1, v2, ... are vectors
  s, s1, s2, ... are objects implementing the sequences
                 protocol (list, tuple, the proposed vector)
  a, a1, a2, ... are scalars (int, float)


§ 1 Vector type
################

1.1 Class name and constructor
==============================
1.1.1  a) Vector3
      b) Vector3d
1.1.2 V(a1, a2, a3)# initialize x, y and z with a1, a2 and a3 respectivly 1.1.3 V(s) # initialize x, y and z with s[0], s[1] and s[2] respectivly
1.1.4  V()          # initialize x, y and z with zeros


1.2 numerical behavior
======================
1.2.1.1  v1 + s -> v3
1.2.1.2  s + v1 -> v3
1.2.1.3  v += s
1.2.2.1  v1 - s -> v3
1.2.2.2  s - v1 -> v3
1.2.2.3  v -= s
1.2.3.1  v1 * a -> v3
1.2.3.2  a * v1 -> v3
1.2.3.3  v *= a
1.2.4.1  v1 / a -> v3
1.2.4.2  v /= a
1.2.5.1  v1 // a -> v3
1.2.5.2  v //= a
1.2.6.1  v1 % a -> v3
1.2.6.2  v %= a

1.2.7.1  v * s -> a      # dot/scalar/inner product
1.2.7.2  s * v -> a      # dot/scalar/inner product

1.2.8.1  +v1 -> v2       # returns a new vector
1.2.8.2  -v1 -> v2


1.3 sequence behavior
=====================
1.3.1    len(v) -> 3       # fixed length
1.3.2.1  v[0] -> a         # 0-based indexing
1.3.2.2  v[0] = a


1.4 attributes
==============
1.4.0    "x", "y", "z" (and "w" for 4th dimension)
        "_epsilon" for comparison operations
1.4.1.1  v.x -> a
1.4.1.2  v.x = a


1.5 methods
===========
1.5.1    v.dot(s) -> a     # dot/scalar/inner product
1.5.2    v.cross(s) -> v   # cross/vector product
        # in 2 dimensions this returns v.x * s[1] - v.y * s[0]
        # this is not defined in 4 dimensions
1.5.3    v.outer(s) -> m   # outer product yielding a matrix
1.5.4.1  v.isNormalized() -> bool
1.5.4.2  v.normalize() -> None    # normalizes inplace
1.5.4.3  v1.normalized() -> v2    # returns normalized vector
1.5.5.1  v1.rotate(s1[, a]) -> None
        # rotates around s1 by angle a. if a isn't given it
        # rotates around s1 by the magnitude of s1
        # this is an inplace operation
1.5.5.2  v1.rotated(s1[, a]) -> v2
# same as 1.5.6 but returns a new vector and leaves v1 untouched
1.5.6.1  v1.rotateX(a) -> None
        # rotates v1 around the x-axis by the angle a
1.5.6.2  v1.rotatedX(a) -> v2
# same as 1.5.6.1 but returns a new vector and leaves v1 untouched
1.5.6.3  # implement 1.5.6.1 and 2 also for Y and Z
1.5.7    v1.reflect(s) -> v2
        # reflects the vector of a surface with surface normal s
1.5.8    a) v1.interpolate(s, a) -> generator of vectors
        b) v1.slerp(s, a) -> generator of vectors
        # the distance between "v1" and "s" divided in "a" steps
1.5.9    v.getAngleTo(s) -> a
        # returns the angle between v and s
1.5.10.1 v.getDistanceTo(s) -> a
        # returns the distance between v and s
1.5.10.2 v.getDistance2To(s) -> a
        # returns the squared distance between v and s


1.6 properties
==============
1.6.1.1  v.length -> a # gets the magnitude/length of the vector
1.6.1.2  v.length = a
        # sets the length of the vector while preserving its direction
1.6.2.1  a) v.lengthSquared -> a
        b) v.length2 -> a
# gets the squared length of the vector. same as v.dot(v) or v * v
1.6.2.1  a) v.lengthSquared = a
        b) v.length2 = a
# sets the squared length of the vector. preserving its direction
# the following only have meaning in 3 dimensions
1.6.3.1 v.r -> a # returns the "r" coordiante of sherical coordinates
                  # this is the same as the "length" property
1.6.3.2  v.r = a
1.6.4.1 v.phi -> a # returns the "phi" coordiante of spherical coordiantes
1.6.4.2  v.phi = a
1.6.5.1 v.theta -> a # returns the "theta" coordiante of spherical coordiantes
1.6.5.2  v.theta = a


1.7 comparison operations
=========================
1.7.0 the "==" and "!=" and "bool" operater compare the differences against the attribute v._epsilon. this way the user can adjust the accuracy.
1.7.1.1  v == s -> bool
        # true if all component differ at most by v._epsilon
1.7.1.2  s == v -> bool
1.7.2.1  v != s -> bool
        # true unless all component differ at most by v._epsilon
1.7.2.2  s != v -> bool
1.7.3    bool(v) -> bool
        # returns true if any component is larger than v._epsilon
        # formerly known as v.__nonzero__


1.8 misc
======================
1.8.1  support iter protocol
1.8.2  str(v) -> "[x, y, z]"
1.8.3  repr(v) -> "Vec<x, y, z>"
1.8.4  support pickle protocol


1.10 open questions (in no particular order)
============================================
1.10.1  a) use radians for all angles
       b) use degrees for all angles
1.10.2  what about slicing?
1.10.3  what about swizzling?
1.10.4  do we need int or complex vectors?
1.10.5  what about negative indices in the sequence protocol?
1.10.6  is there need for explicit row- and column-vectors?





Contrast to existing implementations
####################################

There are of course already existing implementations of vector types. In
particular I want to take a look at pyeuclid [1], vectypes [2] and
3DVectorClass [3]. In this chapter I want to compare them and point out their similarities and differences. This isn't a full review but I tried to find out and describe the most important differences. If your favorite implementation is missing from this comparison feel free to contribute your
own analysis.  Disclaimer: I never used any of these.

numerical behaviour:
* __add__ and __sub__:
  vectypes doesn't interact with other sequence types.
    e.g. "vec2() + [3, 4]" would not work.
* __mul__ with other vectors
  pyeuclid doesn't support multiplication with anything but numbers
    e.g. "Vector2() * Vector2()" would not work
  vectypes and 3DVectorClass do elementwise multiplication
    e.g. "vec2(1,2) * vec2(3,4) == vec(1*3, 2*4)"
  this proposal preforms a dot product
    e.g. "V(1,2) * V(3,4) == 1*3 + 2*4"
* __div__
pyeuclid and this proposal only support division by (int, long, float)
  vectypes and 3DVectorClass also do implicit elementwise division
  same for __floordiv__ and __mod__
* __abs__
  pyeuclid returns the magnitude.
  3DVectorType returns vec3d(abs(x), abs(y), abs(z))
vectypes and this proposal don't implement __abs__ to avoid confusion

other differences:
* from the mentioned packages only pyeuclid optionally supports swizzleing
* pyeuclid has a method "magnitude" instead of "length"
* vectypes uses functions at a module level rather than instance methods.
* vectypes has a method refract
* pyeuclid has seperate geometry classes like "point", "line", "ray" and
  "lineSegment"
* only 3DVectorClass and this proposal have built-in methods of
  the "rotate"-family


#################################################
[1] http://partiallydisassembled.net/euclid.html
[2] http://code.google.com/p/vectypes/
[3] http://pygame.org/wiki/3DVectorClass
[4] http://pygame.org/wiki/gsoc2009ideas#Math%20for%20pygame%20(vectors,%20matrix,%20etc.)