W3cubDocs

/Nim

Module basic2d

Basic 2d support with vectors, points, matrices and some basic utilities. Vectors are implemented as direction vectors, ie. when transformed with a matrix the translation part of matrix is ignored. Operators + , - , * , / , += , -= , *= and /= are implemented for vectors and scalars.

Quick start example:

# Create a matrix which first rotates, then scales and at last translates

var m:Matrix2d=rotate(DEG90) & scale(2.0) & move(100.0,200.0)

# Create a 2d point at (100,0) and a vector (5,2)

var pt:Point2d=point2d(100.0,0.0)

var vec:Vector2d=vector2d(5.0,2.0)


pt &= m # transforms pt in place

var pt2:Point2d=pt & m #concatenates pt with m and returns a new point

var vec2:Vector2d=vec & m #concatenates vec with m and returns a new vector
implements binary operators +, -, * and / for vectorsimplements binary operators +, -, * and / for vectorsimplements binary operators +, -, * and / for vectorsimplements binary operators +, -, * and / for vectorsimplements inplace binary operators +=, -=, /= and *= for vectorsimplements inplace binary operators +=, -=, /= and *= for vectorsimplements inplace binary operators +=, -=, /= and *= for vectorsimplements inplace binary operators +=, -=, /= and *= for vectors

Imports

math, strutils

Types

Matrix2d = object
  ax*, ay*, bx*, by*, tx*, ty*: float
Implements a row major 2d matrix, which means transformations are applied the order they are concatenated. The rightmost column of the 3x3 matrix is left out since normally not used for geometric transformations in 2d.
Point2d = object
  x*, y*: float
Implements a non-homogeneous 2d point stored as an x coordinate and an y coordinate.
Vector2d = object
  x*, y*: float
Implements a 2d direction vector stored as an x coordinate and an y coordinate. Direction vector means, that when transforming a vector with a matrix, the translational part of the matrix is ignored.

Lets

IDMATRIX: Matrix2d = matrix2d(1.0, 0.0, 0.0, 1.0, 0.0, 0.0)
Quick access to an identity matrix
ORIGO: Point2d = point2d(0.0, 0.0)
Quick access to point (0,0)
XAXIS: Vector2d = vector2d(1.0, 0.0)
Quick access to an 2d x-axis unit vector
YAXIS: Vector2d = vector2d(0.0, 1.0)
Quick access to an 2d y-axis unit vector

Consts

DEG360 = 6.283185307179586
360 degrees in radians.
DEG270 = 4.71238898038469
270 degrees in radians.
DEG180 = 3.141592653589793
180 degrees in radians.
DEG90 = 1.570796326794897
90 degrees in radians.
DEG60 = 1.047197551196598
60 degrees in radians.
DEG45 = 0.7853981633974483
45 degrees in radians.
DEG30 = 0.5235987755982988
30 degrees in radians.
DEG15 = 0.2617993877991494
15 degrees in radians.

Procs

proc setElements(t: var Matrix2d; ax, ay, bx, by, tx, ty: float) {.inline, raises: [],
    tags: [].}
Sets arbitrary elements in an existing matrix.
proc matrix2d(ax, ay, bx, by, tx, ty: float): Matrix2d {.noInit, raises: [], tags: [].}
Creates a new matrix. ax,`ay` is the local x axis bx,`by` is the local y axis tx,`ty` is the translation
proc `&`(a, b: Matrix2d): Matrix2d {.noInit, raises: [], tags: [].}
Concatenates matrices returning a new matrix.
proc scale(s: float): Matrix2d {.noInit, raises: [], tags: [].}
Returns a new scale matrix.
proc scale(s: float; org: Point2d): Matrix2d {.noInit, raises: [], tags: [].}
Returns a new scale matrix using, org as scale origin.
proc stretch(sx, sy: float): Matrix2d {.noInit, raises: [], tags: [].}
Returns new a stretch matrix, which is a scale matrix with non uniform scale in x and y.
proc stretch(sx, sy: float; org: Point2d): Matrix2d {.noInit, raises: [], tags: [].}
Returns a new stretch matrix, which is a scale matrix with non uniform scale in x and y. org is used as stretch origin.
proc move(dx, dy: float): Matrix2d {.noInit, raises: [], tags: [].}
Returns a new translation matrix.
proc move(v: Vector2d): Matrix2d {.noInit, raises: [], tags: [].}
Returns a new translation matrix from a vector.
proc rotate(rad: float): Matrix2d {.noInit, raises: [], tags: [].}
Returns a new rotation matrix, which represents a rotation by rad radians
proc rotate(rad: float; org: Point2d): Matrix2d {.noInit, raises: [], tags: [].}
Returns a new rotation matrix, which represents a rotation by rad radians around the origin org
proc mirror(v: Vector2d): Matrix2d {.noInit, raises: [], tags: [].}
Returns a new mirror matrix, mirroring around the line that passes through origo and has the direction of v
proc mirror(org: Point2d; v: Vector2d): Matrix2d {.noInit, raises: [], tags: [].}
Returns a new mirror matrix, mirroring around the line that passes through org and has the direction of v
proc skew(xskew, yskew: float): Matrix2d {.noInit, raises: [], tags: [].}
Returns a new skew matrix, which has its x axis rotated xskew radians from the local x axis, and y axis rotated yskew radians from the local y axis
proc `$`(t: Matrix2d): string {.noInit, raises: [], tags: [].}
Returns a string representation of the matrix
proc isUniform(t: Matrix2d; tol = 1e-006): bool {.raises: [], tags: [].}
Checks if the transform is uniform, that is perpendicular axes of equal length, which means (for example) it cannot transform a circle into an ellipse. tol is used as tolerance for both equal length comparison and perp. comparison.
proc determinant(t: Matrix2d): float {.raises: [], tags: [].}
Computes the determinant of the matrix.
proc isMirroring(m: Matrix2d): bool {.raises: [], tags: [].}
Checks if the m is a mirroring matrix, which means it will reverse direction of a curve transformed with it
proc inverse(m: Matrix2d): Matrix2d {.noInit, raises: [DivByZeroError], tags: [].}
Returns a new matrix, which is the inverse of the matrix If the matrix is not invertible (determinant=0), an EDivByZero will be raised.
proc equals(m1: Matrix2d; m2: Matrix2d; tol = 1e-006): bool {.raises: [], tags: [].}
Checks if all elements of m1`and `m2 is equal within a given tolerance tol.
proc `=~`(m1, m2: Matrix2d): bool {.raises: [], tags: [].}
Checks if m1`and `m2 is approximately equal, using a tolerance of 1e-6.
proc isIdentity(m: Matrix2d; tol = 1e-006): bool {.raises: [], tags: [].}
Checks is a matrix is approximately an identity matrix, using tol as tolerance for each element.
proc apply(m: Matrix2d; x, y: var float; translate = false) {.raises: [], tags: [].}
Applies transformation m onto x,`y`, optionally using the translation part of the matrix.
proc vector2d(x, y: float): Vector2d {.noInit, inline, raises: [], tags: [].}
Returns a new vector (x,`y`)
proc polarVector2d(ang: float; len: float): Vector2d {.noInit, raises: [], tags: [].}
Returns a new vector with angle ang and magnitude len
proc slopeVector2d(slope: float; len: float): Vector2d {.noInit, raises: [], tags: [].}
Returns a new vector having slope (dy/dx) given by slope, and a magnitude of len
proc len(v: Vector2d): float {.inline, raises: [], tags: [].}
Returns the length of the vector.
proc len=(v: var Vector2d; newlen: float) {.noInit, raises: [], tags: [].}
Sets the length of the vector, keeping its angle.
proc sqrLen(v: Vector2d): float {.inline, raises: [], tags: [].}
Computes the squared length of the vector, which is faster than computing the absolute length.
proc angle(v: Vector2d): float {.raises: [], tags: [].}
Returns the angle of the vector. (The counter clockwise plane angle between posetive x axis and v)
proc `$`(v: Vector2d): string {.raises: [], tags: [].}
String representation of v
proc `&`(v: Vector2d; m: Matrix2d): Vector2d {.noInit, raises: [], tags: [].}
Concatenate vector v with a transformation matrix. Transforming a vector ignores the translational part of the matrix.
proc `&=`(v: var Vector2d; m: Matrix2d) {.inline, raises: [], tags: [].}
Applies transformation m onto v in place. Transforming a vector ignores the translational part of the matrix.
proc tryNormalize(v: var Vector2d): bool {.raises: [], tags: [].}
Modifies v to have a length of 1.0, keeping its angle. If v has zero length (and thus no angle), it is left unmodified and false is returned, otherwise true is returned.
proc normalize(v: var Vector2d) {.inline, raises: [DivByZeroError], tags: [].}
Modifies v to have a length of 1.0, keeping its angle. If v has zero length, an EDivByZero will be raised.
proc transformNorm(v: var Vector2d; t: Matrix2d) {.raises: [DivByZeroError], tags: [].}
Applies a normal direction transformation t onto v in place. The resulting vector is not normalized. Transforming a vector ignores the translational part of the matrix. If the matrix is not invertible (determinant=0), an EDivByZero will be raised.
proc transformInv(v: var Vector2d; t: Matrix2d) {.raises: [DivByZeroError], tags: [].}
Applies inverse of a transformation t to v in place. This is faster than creating an inverse matrix and apply() it. Transforming a vector ignores the translational part of the matrix. If the matrix is not invertible (determinant=0), an EDivByZero will be raised.
proc transformNormInv(v: var Vector2d; t: Matrix2d) {.raises: [], tags: [].}
Applies an inverse normal direction transformation t onto v in place. This is faster than creating an inverse matrix and transformNorm(...) it. Transforming a vector ignores the translational part of the matrix.
proc rotate90(v: var Vector2d) {.inline, raises: [], tags: [].}
Quickly rotates vector v 90 degrees counter clockwise, without using any trigonometrics.
proc rotate180(v: var Vector2d) {.inline, raises: [], tags: [].}
Quickly rotates vector v 180 degrees counter clockwise, without using any trigonometrics.
proc rotate270(v: var Vector2d) {.inline, raises: [], tags: [].}
Quickly rotates vector v 270 degrees counter clockwise, without using any trigonometrics.
proc rotate(v: var Vector2d; rad: float) {.raises: [], tags: [].}
Rotates vector v rad radians in place.
proc scale(v: var Vector2d; fac: float) {.inline, raises: [], tags: [].}
Scales vector v rad radians in place.
proc stretch(v: var Vector2d; facx, facy: float) {.inline, raises: [], tags: [].}
Stretches vector v facx times horizontally, and facy times vertically.
proc mirror(v: var Vector2d; mirrvec: Vector2d) {.raises: [], tags: [].}
Mirrors vector v using mirrvec as mirror direction.
proc `-`(v: Vector2d): Vector2d {.raises: [], tags: [].}
Negates a vector
proc `+`(a122589, b122591: Vector2d): Vector2d {.inline, noInit, raises: [], tags: [].}
proc `+`(a122593: Vector2d; b122595: float): Vector2d {.inline, noInit, raises: [],
    tags: [].}
proc `+`(a122597: float; b122599: Vector2d): Vector2d {.inline, noInit, raises: [],
    tags: [].}
proc `-`(a122610, b122612: Vector2d): Vector2d {.inline, noInit, raises: [], tags: [].}
proc `-`(a122614: Vector2d; b122616: float): Vector2d {.inline, noInit, raises: [],
    tags: [].}
proc `-`(a122618: float; b122620: Vector2d): Vector2d {.inline, noInit, raises: [],
    tags: [].}
proc `*`(a122631, b122633: Vector2d): Vector2d {.inline, noInit, raises: [], tags: [].}
proc `*`(a122635: Vector2d; b122637: float): Vector2d {.inline, noInit, raises: [],
    tags: [].}
proc `*`(a122639: float; b122641: Vector2d): Vector2d {.inline, noInit, raises: [],
    tags: [].}
proc `/`(a122652, b122654: Vector2d): Vector2d {.inline, noInit, raises: [], tags: [].}
proc `/`(a122656: Vector2d; b122658: float): Vector2d {.inline, noInit, raises: [],
    tags: [].}
proc `/`(a122660: float; b122662: Vector2d): Vector2d {.inline, noInit, raises: [],
    tags: [].}
proc `+=`(a122673: var Vector2d; b122675: Vector2d) {.inline, raises: [], tags: [].}
proc `+=`(a122677: var Vector2d; b122679: float) {.inline, raises: [], tags: [].}
proc `-=`(a122727: var Vector2d; b122729: Vector2d) {.inline, raises: [], tags: [].}
proc `-=`(a122731: var Vector2d; b122733: float) {.inline, raises: [], tags: [].}
proc `*=`(a122781: var Vector2d; b122783: Vector2d) {.inline, raises: [], tags: [].}
proc `*=`(a122785: var Vector2d; b122787: float) {.inline, raises: [], tags: [].}
proc `/=`(a122835: var Vector2d; b122837: Vector2d) {.inline, raises: [], tags: [].}
proc `/=`(a122839: var Vector2d; b122841: float) {.inline, raises: [], tags: [].}
proc dot(v1, v2: Vector2d): float {.raises: [], tags: [].}
Computes the dot product of two vectors. Returns 0.0 if the vectors are perpendicular.
proc cross(v1, v2: Vector2d): float {.raises: [], tags: [].}
Computes the cross product of two vectors, also called the 'perpendicular dot product' in 2d. Returns 0.0 if the vectors are parallel.
proc equals(v1, v2: Vector2d; tol = 1e-006): bool {.raises: [], tags: [].}
Checks if two vectors approximately equals with a tolerance.
proc `=~`(v1, v2: Vector2d): bool {.raises: [], tags: [].}
Checks if two vectors approximately equals with a hardcoded tolerance 1e-6
proc angleTo(v1, v2: Vector2d): float {.raises: [], tags: [].}
Returns the smallest of the two possible angles between v1 and v2 in radians.
proc angleCCW(v1, v2: Vector2d): float {.raises: [], tags: [].}
Returns the counter clockwise plane angle from v1 to v2, in range 0 - 2*PI
proc angleCW(v1, v2: Vector2d): float {.raises: [], tags: [].}
Returns the clockwise plane angle from v1 to v2, in range 0 - 2*PI
proc turnAngle(v1, v2: Vector2d): float {.raises: [], tags: [].}
Returns the amount v1 should be rotated (in radians) to equal v2, in range -PI to PI
proc bisect(v1, v2: Vector2d): Vector2d {.noInit, raises: [], tags: [].}
Computes the bisector between v1 and v2 as a normalized vector. If one of the input vectors has zero length, a normalized version of the other is returned. If both input vectors has zero length, an arbitrary normalized vector is returned.
proc point2d(x, y: float): Point2d {.noInit, inline, raises: [], tags: [].}
Returns a new point (x,`y`)
proc sqrDist(a, b: Point2d): float {.raises: [], tags: [].}
Computes the squared distance between a and b
proc dist(a, b: Point2d): float {.inline, raises: [], tags: [].}
Computes the absolute distance between a and b
proc angle(a, b: Point2d): float {.raises: [], tags: [].}
Computes the angle of the vector b-a
proc `$`(p: Point2d): string {.raises: [], tags: [].}
String representation of p
proc `&`(p: Point2d; t: Matrix2d): Point2d {.noInit, inline, raises: [], tags: [].}
Concatenates a point p with a transform t, resulting in a new, transformed point.
proc `&=`(p: var Point2d; t: Matrix2d) {.inline, raises: [], tags: [].}
Applies transformation t onto p in place.
proc transformInv(p: var Point2d; t: Matrix2d) {.inline, raises: [DivByZeroError],
    tags: [].}
Applies the inverse of transformation t onto p in place. If the matrix is not invertable (determinant=0) , EDivByZero will be raised.
proc `+`(p: Point2d; v: Vector2d): Point2d {.noInit, inline, raises: [], tags: [].}
Adds a vector v to a point p, resulting in a new point.
proc `+=`(p: var Point2d; v: Vector2d) {.noInit, inline, raises: [], tags: [].}
Adds a vector v to a point p in place.
proc `-`(p: Point2d; v: Vector2d): Point2d {.noInit, inline, raises: [], tags: [].}
Subtracts a vector v from a point p, resulting in a new point.
proc `-`(p1, p2: Point2d): Vector2d {.noInit, inline, raises: [], tags: [].}
Subtracts p2`from `p1 resulting in a difference vector.
proc `-=`(p: var Point2d; v: Vector2d) {.noInit, inline, raises: [], tags: [].}
Subtracts a vector v from a point p in place.
proc `=~`(p1, p2: Point2d): bool {.inline, raises: [], tags: [].}
Checks if two vectors approximately equals with a hardcoded tolerance 1e-6
proc polar(p: Point2d; ang, dist: float): Point2d {.noInit, raises: [], tags: [].}
Returns a point with a given angle and distance away from p
proc rotate(p: var Point2d; rad: float) {.raises: [], tags: [].}
Rotates a point in place rad radians around origo.
proc rotate(p: var Point2d; rad: float; org: Point2d) {.raises: [], tags: [].}
Rotates a point in place rad radians using org as center of rotation.
proc scale(p: var Point2d; fac: float) {.inline, raises: [], tags: [].}
Scales a point in place fac times with world origo as origin.
proc scale(p: var Point2d; fac: float; org: Point2d) {.inline, raises: [], tags: [].}
Scales the point in place fac times with org as origin.
proc stretch(p: var Point2d; facx, facy: float) {.inline, raises: [], tags: [].}
Scales a point in place non uniformly facx and facy times with world origo as origin.
proc stretch(p: var Point2d; facx, facy: float; org: Point2d) {.inline, raises: [], tags: [].}
Scales the point in place non uniformly facx and facy times with org as origin.
proc move(p: var Point2d; dx, dy: float) {.inline, raises: [], tags: [].}
Translates a point dx, dy in place.
proc move(p: var Point2d; v: Vector2d) {.inline, raises: [], tags: [].}
Translates a point with vector v in place.
proc sgnArea(a, b, c: Point2d): float {.raises: [], tags: [].}
Computes the signed area of the triangle thru points a,`b` and c result>0.0 for counter clockwise triangle result<0.0 for clockwise triangle This is commonly used to determinate side of a point with respect to a line.
proc area(a, b, c: Point2d): float {.raises: [], tags: [].}
Computes the area of the triangle thru points a,`b` and c
proc closestPoint(p: Point2d; pts: varargs[Point2d]): Point2d {.raises: [], tags: [].}
Returns a point selected from pts, that has the closest euclidean distance to p
proc normAngle(ang: float): float {.raises: [], tags: [].}
Returns an angle in radians, that is equal to ang, but in the range 0 to <2*PI
proc degToRad(deg: float): float {.inline, raises: [], tags: [].}
converts deg degrees to radians
proc radToDeg(rad: float): float {.inline, raises: [], tags: [].}
converts rad radians to degrees

© 2006–2017 Andreas Rumpf
Licensed under the MIT License.
https://nim-lang.org/docs/basic2d.html