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:TMatrix2d=rotate(DEG90) & scale(2.0) & move(100.0,200.0)
# Create a 2d point at (100,0) and a vector (5,2)
var pt:TPoint2d=point2d(100.0,0.0)
var vec:TVector2d=vector2d(5.0,2.0)
pt &= m # transforms pt in place
var pt2:TPoint2d=pt & m #concatenates pt with m and returns a new point
var vec2:TVector2d=vec & m #concatenates vec with m and returns a new vector
Types
TMatrix2d = 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. Source
TPoint2d = object x*, y*: float
- Implements a non-homegeneous 2d point stored as an x coordinate and an y coordinate. Source
TVector2d = 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. Source
Lets
IDMATRIX: TMatrix2d = matrix2d(1.0, 0.0, 0.0, 1.0, 0.0, 0.0)
- Quick access to an identity matrix Source
ORIGO: TPoint2d = point2d(0.0, 0.0)
- Quick acces to point (0,0) Source
XAXIS: TVector2d = vector2d(1.0, 0.0)
- Quick acces to an 2d x-axis unit vector Source
YAXIS: TVector2d = vector2d(0.0, 1.0)
- Quick acces to an 2d y-axis unit vector Source
Consts
DEG360 = 6.283185307179586
- 360 degrees in radians. Source
DEG270 = 4.71238898038469
- 270 degrees in radians. Source
DEG180 = 3.141592653589793
- 180 degrees in radians. Source
DEG90 = 1.570796326794897
- 90 degrees in radians. Source
DEG60 = 1.047197551196598
- 60 degrees in radians. Source
DEG45 = 0.7853981633974483
- 45 degrees in radians. Source
DEG30 = 0.5235987755982988
- 30 degrees in radians. Source
DEG15 = 0.2617993877991494
- 15 degrees in radians. Source
Procs
proc setElements(t: var TMatrix2d; ax, ay, bx, by, tx, ty: float) {.inline, raises: [], tags: [].}
- Sets arbitrary elements in an existing matrix. Source
proc matrix2d(ax, ay, bx, by, tx, ty: float): TMatrix2d {.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 Source
proc `&`(a, b: TMatrix2d): TMatrix2d {.noInit, raises: [], tags: [].}
- Concatenates matrices returning a new matrix. Source
proc scale(s: float): TMatrix2d {.noInit, raises: [], tags: [].}
- Returns a new scale matrix. Source
proc scale(s: float; org: TPoint2d): TMatrix2d {.noInit, raises: [], tags: [].}
- Returns a new scale matrix using, org as scale origin. Source
proc stretch(sx, sy: float): TMatrix2d {.noInit, raises: [], tags: [].}
- Returns new a stretch matrix, which is a scale matrix with non uniform scale in x and y. Source
proc stretch(sx, sy: float; org: TPoint2d): TMatrix2d {.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. Source
proc move(dx, dy: float): TMatrix2d {.noInit, raises: [], tags: [].}
- Returns a new translation matrix. Source
proc move(v: TVector2d): TMatrix2d {.noInit, raises: [], tags: [].}
- Returns a new translation matrix from a vector. Source
proc rotate(rad: float): TMatrix2d {.noInit, raises: [], tags: [].}
- Returns a new rotation matrix, which represents a rotation by rad radians Source
proc rotate(rad: float; org: TPoint2d): TMatrix2d {.noInit, raises: [], tags: [].}
- Returns a new rotation matrix, which represents a rotation by rad radians around the origin org Source
proc mirror(v: TVector2d): TMatrix2d {.noInit, raises: [], tags: [].}
- Returns a new mirror matrix, mirroring around the line that passes through origo and has the direction of v Source
proc mirror(org: TPoint2d; v: TVector2d): TMatrix2d {.noInit, raises: [], tags: [].}
- Returns a new mirror matrix, mirroring around the line that passes through org and has the direction of v Source
proc skew(xskew, yskew: float): TMatrix2d {.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 Source
proc `$`(t: TMatrix2d): string {.noInit, raises: [], tags: [].}
- Returns a string representation of the matrix Source
proc isUniform(t: TMatrix2d; tol = 1e-06): 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. Source
proc determinant(t: TMatrix2d): float {.raises: [], tags: [].}
- Computes the determinant of the matrix. Source
proc isMirroring(m: TMatrix2d): bool {.raises: [], tags: [].}
- Checks if the m is a mirroring matrix, which means it will reverse direction of a curve transformed with it Source
proc inverse(m: TMatrix2d): TMatrix2d {.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. Source
proc equals(m1: TMatrix2d; m2: TMatrix2d; tol = 1e-06): bool {.raises: [], tags: [].}
- Checks if all elements of m1`and `m2 is equal within a given tolerance tol. Source
proc `=~`(m1, m2: TMatrix2d): bool {.raises: [], tags: [].}
- Checks if m1`and `m2 is approximately equal, using a tolerance of 1e-6. Source
proc isIdentity(m: TMatrix2d; tol = 1e-06): bool {.raises: [], tags: [].}
- Checks is a matrix is approximately an identity matrix, using tol as tolerance for each element. Source
proc apply(m: TMatrix2d; x, y: var float; translate = false) {.raises: [], tags: [].}
- Applies transformation m onto x,`y`, optionally using the translation part of the matrix. Source
proc vector2d(x, y: float): TVector2d {.noInit, inline, raises: [], tags: [].}
- Returns a new vector (x,`y`) Source
proc polarVector2d(ang: float; len: float): TVector2d {.noInit, raises: [], tags: [].}
- Returns a new vector with angle ang and magnitude len Source
proc slopeVector2d(slope: float; len: float): TVector2d {.noInit, raises: [], tags: [].}
- Returns a new vector having slope (dy/dx) given by slope, and a magnitude of len Source
proc len(v: TVector2d): float {.inline, raises: [], tags: [].}
- Returns the length of the vector. Source
proc len=(v: var TVector2d; newlen: float) {.noInit, raises: [], tags: [].}
- Sets the length of the vector, keeping its angle. Source
proc sqrLen(v: TVector2d): float {.inline, raises: [], tags: [].}
- Computes the squared length of the vector, which is faster than computing the absolute length. Source
proc angle(v: TVector2d): float {.raises: [], tags: [].}
- Returns the angle of the vector. (The counter clockwise plane angle between posetive x axis and v) Source
proc `$`(v: TVector2d): string {.raises: [], tags: [].}
- String representation of v Source
proc `&`(v: TVector2d; m: TMatrix2d): TVector2d {.noInit, raises: [], tags: [].}
- Concatenate vector v with a transformation matrix. Transforming a vector ignores the translational part of the matrix. Source
proc `&=`(v: var TVector2d; m: TMatrix2d) {.inline, raises: [], tags: [].}
- Applies transformation m onto v in place. Transforming a vector ignores the translational part of the matrix. Source
proc tryNormalize(v: var TVector2d): 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. Source
proc normalize(v: var TVector2d) {.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. Source
proc transformNorm(v: var TVector2d; t: TMatrix2d) {.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. Source
proc transformInv(v: var TVector2d; t: TMatrix2d) {.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. Source
proc transformNormInv(v: var TVector2d; t: TMatrix2d) {.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. Source
proc rotate90(v: var TVector2d) {.inline, raises: [], tags: [].}
- Quickly rotates vector v 90 degrees counter clockwise, without using any trigonometrics. Source
proc rotate180(v: var TVector2d) {.inline, raises: [], tags: [].}
- Quickly rotates vector v 180 degrees counter clockwise, without using any trigonometrics. Source
proc rotate270(v: var TVector2d) {.inline, raises: [], tags: [].}
- Quickly rotates vector v 270 degrees counter clockwise, without using any trigonometrics. Source
proc rotate(v: var TVector2d; rad: float) {.raises: [], tags: [].}
- Rotates vector v rad radians in place. Source
proc scale(v: var TVector2d; fac: float) {.inline, raises: [], tags: [].}
- Scales vector v rad radians in place. Source
proc stretch(v: var TVector2d; facx, facy: float) {.inline, raises: [], tags: [].}
- Stretches vector v facx times horizontally, and facy times vertically. Source
proc mirror(v: var TVector2d; mirrvec: TVector2d) {.raises: [], tags: [].}
- Mirrors vector v using mirrvec as mirror direction. Source
proc `-`(v: TVector2d): TVector2d {.raises: [], tags: [].}
- Negates a vector Source
proc `+`(a, b: TVector2d): TVector2d {.inline, noInit, raises: [], tags: [].}
- Source
proc `+`(a: TVector2d; b: float): TVector2d {.inline, noInit, raises: [], tags: [].}
- Source
proc `+`(a: float; b: TVector2d): TVector2d {.inline, noInit, raises: [], tags: [].}
- Source
proc `-`(a, b: TVector2d): TVector2d {.inline, noInit, raises: [], tags: [].}
- Source
proc `-`(a: TVector2d; b: float): TVector2d {.inline, noInit, raises: [], tags: [].}
- Source
proc `-`(a: float; b: TVector2d): TVector2d {.inline, noInit, raises: [], tags: [].}
- Source
proc `*`(a, b: TVector2d): TVector2d {.inline, noInit, raises: [], tags: [].}
- Source
proc `*`(a: TVector2d; b: float): TVector2d {.inline, noInit, raises: [], tags: [].}
- Source
proc `*`(a: float; b: TVector2d): TVector2d {.inline, noInit, raises: [], tags: [].}
- Source
proc `/`(a, b: TVector2d): TVector2d {.inline, noInit, raises: [], tags: [].}
- Source
proc `/`(a: TVector2d; b: float): TVector2d {.inline, noInit, raises: [], tags: [].}
- Source
proc `/`(a: float; b: TVector2d): TVector2d {.inline, noInit, raises: [], tags: [].}
- Source
proc `+=`(a: var TVector2d; b: TVector2d) {.inline, raises: [], tags: [].}
- Source
proc `+=`(a: var TVector2d; b: float) {.inline, raises: [], tags: [].}
- Source
proc `-=`(a: var TVector2d; b: TVector2d) {.inline, raises: [], tags: [].}
- Source
proc `-=`(a: var TVector2d; b: float) {.inline, raises: [], tags: [].}
- Source
proc `*=`(a: var TVector2d; b: TVector2d) {.inline, raises: [], tags: [].}
- Source
proc `*=`(a: var TVector2d; b: float) {.inline, raises: [], tags: [].}
- Source
proc `/=`(a: var TVector2d; b: TVector2d) {.inline, raises: [], tags: [].}
- Source
proc `/=`(a: var TVector2d; b: float) {.inline, raises: [], tags: [].}
- Source
proc dot(v1, v2: TVector2d): float {.raises: [], tags: [].}
- Computes the dot product of two vectors. Returns 0.0 if the vectors are perpendicular. Source
proc cross(v1, v2: TVector2d): 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. Source
proc equals(v1, v2: TVector2d; tol = 1e-06): bool {.raises: [], tags: [].}
- Checks if two vectors approximately equals with a tolerance. Source
proc `=~`(v1, v2: TVector2d): bool {.raises: [], tags: [].}
- Checks if two vectors approximately equals with a hardcoded tolerance 1e-6 Source
proc angleTo(v1, v2: TVector2d): float {.raises: [], tags: [].}
- Returns the smallest of the two possible angles between v1 and v2 in radians. Source
proc angleCCW(v1, v2: TVector2d): float {.raises: [], tags: [].}
- Returns the counter clockwise plane angle from v1 to v2, in range 0 - 2*PI Source
proc angleCW(v1, v2: TVector2d): float {.raises: [], tags: [].}
- Returns the clockwise plane angle from v1 to v2, in range 0 - 2*PI Source
proc turnAngle(v1, v2: TVector2d): float {.raises: [], tags: [].}
- Returns the amount v1 should be rotated (in radians) to equal v2, in range -PI to PI Source
proc bisect(v1, v2: TVector2d): TVector2d {.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. Source
proc point2d(x, y: float): TPoint2d {.noInit, inline, raises: [], tags: [].}
- Returns a new point (x,`y`) Source
proc sqrDist(a, b: TPoint2d): float {.raises: [], tags: [].}
- Computes the squared distance between a and b Source
proc dist(a, b: TPoint2d): float {.inline, raises: [], tags: [].}
- Computes the absolute distance between a and b Source
proc angle(a, b: TPoint2d): float {.raises: [], tags: [].}
- Computes the angle of the vector b-a Source
proc `$`(p: TPoint2d): string {.raises: [], tags: [].}
- String representation of p Source
proc `&`(p: TPoint2d; t: TMatrix2d): TPoint2d {.noInit, inline, raises: [], tags: [].}
- Concatenates a point p with a transform t, resulting in a new, transformed point. Source
proc `&=`(p: var TPoint2d; t: TMatrix2d) {.inline, raises: [], tags: [].}
- Applies transformation t onto p in place. Source
proc transformInv(p: var TPoint2d; t: TMatrix2d) {.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. Source
proc `+`(p: TPoint2d; v: TVector2d): TPoint2d {.noInit, inline, raises: [], tags: [].}
- Adds a vector v to a point p, resulting in a new point. Source
proc `+=`(p: var TPoint2d; v: TVector2d) {.noInit, inline, raises: [], tags: [].}
- Adds a vector v to a point p in place. Source
proc `-`(p: TPoint2d; v: TVector2d): TPoint2d {.noInit, inline, raises: [], tags: [].}
- Subtracts a vector v from a point p, resulting in a new point. Source
proc `-`(p1, p2: TPoint2d): TVector2d {.noInit, inline, raises: [], tags: [].}
- Subtracts p2`from `p1 resulting in a difference vector. Source
proc `-=`(p: var TPoint2d; v: TVector2d) {.noInit, inline, raises: [], tags: [].}
- Subtracts a vector v from a point p in place. Source
proc `=~`(p1, p2: TPoint2d): bool {.inline, raises: [], tags: [].}
- Checks if two vectors approximately equals with a hardcoded tolerance 1e-6 Source
proc polar(p: TPoint2d; ang, dist: float): TPoint2d {.noInit, raises: [], tags: [].}
- Returns a point with a given angle and distance away from p Source
proc rotate(p: var TPoint2d; rad: float) {.raises: [], tags: [].}
- Rotates a point in place rad radians around origo. Source
proc rotate(p: var TPoint2d; rad: float; org: TPoint2d) {.raises: [], tags: [].}
- Rotates a point in place rad radians using org as center of rotation. Source
proc scale(p: var TPoint2d; fac: float) {.inline, raises: [], tags: [].}
- Scales a point in place fac times with world origo as origin. Source
proc scale(p: var TPoint2d; fac: float; org: TPoint2d) {.inline, raises: [], tags: [].}
- Scales the point in place fac times with org as origin. Source
proc stretch(p: var TPoint2d; facx, facy: float) {.inline, raises: [], tags: [].}
- Scales a point in place non uniformly facx and facy times with world origo as origin. Source
proc stretch(p: var TPoint2d; facx, facy: float; org: TPoint2d) {.inline, raises: [], tags: [].}
- Scales the point in place non uniformly facx and facy times with org as origin. Source
proc move(p: var TPoint2d; dx, dy: float) {.inline, raises: [], tags: [].}
- Translates a point dx, dy in place. Source
proc move(p: var TPoint2d; v: TVector2d) {.inline, raises: [], tags: [].}
- Translates a point with vector v in place. Source
proc sgnArea(a, b, c: TPoint2d): 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. Source
proc area(a, b, c: TPoint2d): float {.raises: [], tags: [].}
- Computes the area of the triangle thru points a,`b` and c Source
proc closestPoint(p: TPoint2d; pts: varargs[TPoint2d]): TPoint2d {.raises: [], tags: [].}
- Returns a point selected from pts, that has the closest euclidean distance to p Source
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 Source
proc degToRad(deg: float): float {.inline, raises: [], tags: [].}
- converts deg degrees to radians Source
proc radToDeg(rad: float): float {.inline, raises: [], tags: [].}
- converts rad radians to degrees Source