Planar logo

Table Of Contents

Previous topic

Planar Overview

Next topic

Vector Objects

This Page

Usage Guide

Importing Classes

Generally you will want to import classes directly from the top-level planar package, or simply import the package itself:

from planar import Vec2
v = Vec2(5, 4)

or:

import planar
v = planar.Vec2(5, 4)

Doing this will give you the most efficient implementation available of each class where the program is being run. It will provide the native-code implementation where available, falling back to the pure-Python reference implementation if necessary. This insulates your program from the particulars of the run-time environment.

If desired, you can import a particular implementation directly from the planar package. The Python implementations can be imported from the planar.py module:

from planar.py import Vec2 # Python implementation

The C implementations of all planar objects can be imported from the planar.c module:

from planar.c import Vec2 # C implementation

Generally, however, it is best to simply import things directly from the planar package. Relying on the vagaries of either implementation in your application is not recommended.

Also, you should avoid mixing usage of Python and C implementations of planar classes in a single app (see below for details why). If you simply import them from the planar package directly, you won’t have to worry about this.

Implementation Differences

In general, the Python and C implementations of each class should be virtually identical from the application’s standpoint. Efforts have been made to ensure this is true. However, practical considerations mean there are some subtle differences that you should be aware of. Applications should not rely on these implementation details for correct operation:

  • Python implementations may be based on highly general base-classes (e.g., tuple) whereas the C implementations are not. You should not rely on specific base-classes, except where documented here, and you should not rely on any specific inherited behavior that is not documented. For instance, the Python Vec2 implementation derives from tuple, thus it supports operations like slicing, in and count(), whereas the C implementation does not.
  • Exception message strings will vary according to implementation. As with Python itself, exception messages are not considered part of the canonical API, and applications should not rely on their content.
  • Some C APIs may not support keyword arguments, whereas all Python APIs do. For example planar.Vec2(x=1, y=2) will work with the Python implementation, but not the C implementation. All APIs with optional arguments support both positional and keyword arguments. For example: planar.Vec2.polar(angle=45, length=10) is fully supported by both.

Note

Use of positional arguments is often optimized and significantly faster in the C implementations.

  • Instances of C-implemented classes do not have instance dictionaries, whereas all Python implementations do. In Python, they are often used for caching property values for repeated access. In C they are omitted for efficiency. This means that application code should not assign arbitrary attributes onto planar instances. If you need such functionality, you should subclass the planar class within your application. Such subclasses, will always have an instance dict regardless of the base-class implementation.
  • Hashable objects, such as Vec2 may not hash to the same value in their C and Python implementations. This is because the Python hash method is often derived from the generic tuple hash method, whereas the C hash method is a less-general, more efficient hash. In practical terms this means you cannot put cvector.Vec2, and vector.Vec2 instances into the same dict or set with satisfactory results.
  • Like tuples, and floats, among others, planar object instances may be pooled and recycled for efficiency. You should not rely on the results of the is operator between planar objects.

If you run across other implementation differences than the above, let us know. They are either a bug or they should be documented.

Angles

Being a geometry library, planar has some apis that involve angles. Angles in planar are always specified in degrees with zero degrees being parallel to the ascending x-axis. Larger angles are counter-clockwise in direction from smaller angles. Thus 90 ° is parallel to the ascending y-axis.

You might wonder why planar, being a mathematically-minded library, would use degrees for angles instead of using the more mathematically pure radians. There are a few important reasons for this design decision:

  • planar is a library made by and made for software engineers, not mathematicians. Degrees are simply easier to reason about and construct values for intuitively for non-mathematicians.
  • The library is intended to represent and manipulate shapes that may eventually be drawn using a graphics library, such as OpenGL. OpenGL represents angles in degrees, so it makes sense to do the same here for consistency.
  • Radians represent angles in terms of π, a transcendental number. The value of π cannot be represented exactly using floating-point numbers. This means that the values of common angles, such as 30 °, 45 °, 60 °, 90 °, 180 °, and 270 °, also cannot be represented exactly in floating-point radian values. This adversely affects the precision of rotation operations by common angles, particularly rotation by multiples of 90 °. The use of degrees allows planar to behave better in these common cases.