summary refs log tree commit diff stats
path: root/lib/pure/basic2d.nim
diff options
context:
space:
mode:
Diffstat (limited to 'lib/pure/basic2d.nim')
-rw-r--r--lib/pure/basic2d.nim234
1 files changed, 117 insertions, 117 deletions
diff --git a/lib/pure/basic2d.nim b/lib/pure/basic2d.nim
index 1392fdeba..ad8f8653d 100644
--- a/lib/pure/basic2d.nim
+++ b/lib/pure/basic2d.nim
@@ -13,26 +13,26 @@ import strutils
 
 ## 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. 
+## 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 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
 
 
@@ -64,12 +64,12 @@ type
       ## not used for geometric transformations in 2d.
       ax*,ay*,bx*,by*,tx*,ty*:float
     Point2d* = object
-      ## Implements a non-homogeneous 2d point stored as 
+      ## Implements a non-homogeneous 2d point stored as
       ## an `x` coordinate and an `y` coordinate.
       x*,y*:float
-    Vector2d* = object 
-      ## Implements a 2d **direction vector** stored as 
-      ## an `x` coordinate and an `y` coordinate. Direction vector means, 
+    Vector2d* = object
+      ## 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.
       x*,y*:float
@@ -78,7 +78,7 @@ type
 
 # Some forward declarations...
 proc matrix2d*(ax,ay,bx,by,tx,ty:float):Matrix2d {.noInit.}
-  ## Creates a new matrix. 
+  ## Creates a new matrix.
   ## `ax`,`ay` is the local x axis
   ## `bx`,`by` is the local y axis
   ## `tx`,`ty` is the translation
@@ -99,7 +99,7 @@ let
   YAXIS*:Vector2d=vector2d(0.0,1.0)
     ## Quick acces to an 2d y-axis unit vector
 
-  
+
 # ***************************************
 #     Private utils
 # ***************************************
@@ -114,13 +114,13 @@ proc safeArccos(v:float):float=
   return arccos(clamp(v,-1.0,1.0))
 
 
-template makeBinOpVector(s:expr)= 
+template makeBinOpVector(s:expr)=
   ## implements binary operators + , - , * and / for vectors
   proc s*(a,b:Vector2d):Vector2d {.inline,noInit.} = vector2d(s(a.x,b.x),s(a.y,b.y))
   proc s*(a:Vector2d,b:float):Vector2d {.inline,noInit.}  = vector2d(s(a.x,b),s(a.y,b))
   proc s*(a:float,b:Vector2d):Vector2d {.inline,noInit.}  = vector2d(s(a,b.x),s(a,b.y))
-  
-template makeBinOpAssignVector(s:expr)= 
+
+template makeBinOpAssignVector(s:expr)=
   ## implements inplace binary operators += , -= , /= and *= for vectors
   proc s*(a:var Vector2d,b:Vector2d) {.inline.} = s(a.x,b.x) ; s(a.y,b.y)
   proc s*(a:var Vector2d,b:float) {.inline.} = s(a.x,b) ; s(a.y,b)
@@ -144,7 +144,7 @@ proc matrix2d*(ax,ay,bx,by,tx,ty:float):Matrix2d =
 
 proc `&`*(a,b:Matrix2d):Matrix2d {.noInit.} = #concatenate matrices
   ## Concatenates matrices returning a new matrix.
-  
+
   # | a.AX a.AY 0 |   | b.AX b.AY 0 |
   # | a.BX a.BY 0 | * | b.BX b.BY 0 |
   # | a.TX a.TY 1 |   | b.TX b.TY 1 |
@@ -153,7 +153,7 @@ proc `&`*(a,b:Matrix2d):Matrix2d {.noInit.} = #concatenate matrices
     a.ax * b.ay + a.ay * b.by,
     a.bx * b.ax + a.by * b.bx,
     a.bx * b.ay + a.by * b.by,
-    a.tx * b.ax + a.ty * b.bx + b.tx, 
+    a.tx * b.ax + a.ty * b.bx + b.tx,
     a.tx * b.ay + a.ty * b.by + b.ty)
 
 
@@ -169,13 +169,13 @@ proc stretch*(sx,sy:float):Matrix2d {.noInit.} =
   ## Returns new a stretch matrix, which is a
   ## scale matrix with non uniform scale in x and y.
   result.setElements(sx,0,0,sy,0,0)
-    
+
 proc stretch*(sx,sy:float,org:Point2d):Matrix2d {.noInit.} =
   ## Returns a new stretch matrix, which is a
   ## scale matrix with non uniform scale in x and y.
   ## `org` is used as stretch origin.
   result.setElements(sx,0,0,sy,org.x-sx*org.x,org.y-sy*org.y)
-    
+
 proc move*(dx,dy:float):Matrix2d {.noInit.} =
   ## Returns a new translation matrix.
   result.setElements(1,0,0,1,dx,dy)
@@ -187,7 +187,7 @@ proc move*(v:Vector2d):Matrix2d {.noInit.} =
 proc rotate*(rad:float):Matrix2d {.noInit.} =
   ## Returns a new rotation matrix, which
   ## represents a rotation by `rad` radians
-  let 
+  let
     s=sin(rad)
     c=cos(rad)
   result.setElements(c,s,-s,c,0,0)
@@ -200,7 +200,7 @@ proc rotate*(rad:float,org:Point2d):Matrix2d {.noInit.} =
     s=sin(rad)
     c=cos(rad)
   result.setElements(c,s,-s,c,org.x+s*org.y-c*org.x,org.y-c*org.y-s*org.x)
-  
+
 proc mirror*(v:Vector2d):Matrix2d {.noInit.} =
   ## Returns a new mirror matrix, mirroring
   ## around the line that passes through origo and
@@ -211,7 +211,7 @@ proc mirror*(v:Vector2d):Matrix2d {.noInit.} =
     nd=1.0/(sqx+sqy) #used to normalize invector
     xy2=v.x*v.y*2.0*nd
     sqd=nd*(sqx-sqy)
-    
+
   if nd==Inf or nd==NegInf:
     return IDMATRIX #mirroring around a zero vector is arbitrary=>just use identity
 
@@ -230,7 +230,7 @@ proc mirror*(org:Point2d,v:Vector2d):Matrix2d {.noInit.} =
     nd=1.0/(sqx+sqy) #used to normalize invector
     xy2=v.x*v.y*2.0*nd
     sqd=nd*(sqx-sqy)
-    
+
   if nd==Inf or nd==NegInf:
     return IDMATRIX #mirroring around a zero vector is arbitrary=>just use identity
 
@@ -238,47 +238,47 @@ proc mirror*(org:Point2d,v:Vector2d):Matrix2d {.noInit.} =
     sqd,xy2,
     xy2,-sqd,
     org.x-org.y*xy2-org.x*sqd,org.y-org.x*xy2+org.y*sqd)
-  
+
 
 
 proc skew*(xskew,yskew:float):Matrix2d {.noInit.} =
-  ## Returns a new skew matrix, which has its 
+  ## 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
   result.setElements(cos(yskew),sin(yskew),-sin(xskew),cos(xskew),0,0)
-  
+
 
 proc `$`* (t:Matrix2d):string {.noInit.} =
   ## Returns a string representation of the matrix
   return rtos(t.ax) & "," & rtos(t.ay) &
-    "," & rtos(t.bx) & "," & rtos(t.by) & 
+    "," & rtos(t.bx) & "," & rtos(t.by) &
     "," & rtos(t.tx) & "," & rtos(t.ty)
 
 proc isUniform*(t:Matrix2d,tol=1.0e-6):bool=
-  ## Checks if the transform is uniform, that is 
+  ## 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 
+  ## `tol` is used as tolerance for both equal length comparison
   ## and perp. comparison.
-  
+
   #dot product=0 means perpendicular coord. system:
-  if abs(t.ax*t.bx+t.ay*t.by)<=tol:   
+  if abs(t.ax*t.bx+t.ay*t.by)<=tol:
     #subtract squared lengths of axes to check if uniform scaling:
     if abs((t.ax*t.ax+t.ay*t.ay)-(t.bx*t.bx+t.by*t.by))<=tol:
       return true
   return false
-    
+
 proc determinant*(t:Matrix2d):float=
   ## Computes the determinant of the matrix.
-  
+
   #NOTE: equivalent with perp.dot product for two 2d vectors
-  return t.ax*t.by-t.bx*t.ay  
+  return t.ax*t.by-t.bx*t.ay
 
 proc isMirroring* (m:Matrix2d):bool=
   ## Checks if the `m` is a mirroring matrix,
   ## which means it will reverse direction of a curve transformed with it
   return m.determinant<0.0
-  
+
 proc inverse*(m:Matrix2d):Matrix2d {.noInit.} =
   ## Returns a new matrix, which is the inverse of the matrix
   ## If the matrix is not invertible (determinant=0), an EDivByZero
@@ -286,7 +286,7 @@ proc inverse*(m:Matrix2d):Matrix2d {.noInit.} =
   let d=m.determinant
   if d==0.0:
     raise newException(DivByZeroError,"Cannot invert a zero determinant matrix")
-    
+
   result.setElements(
     m.by/d,-m.ay/d,
     -m.bx/d,m.ax/d,
@@ -296,14 +296,14 @@ proc inverse*(m:Matrix2d):Matrix2d {.noInit.} =
 proc equals*(m1:Matrix2d,m2:Matrix2d,tol=1.0e-6):bool=
   ## Checks if all elements of `m1`and `m2` is equal within
   ## a given tolerance `tol`.
-  return 
+  return
     abs(m1.ax-m2.ax)<=tol and
     abs(m1.ay-m2.ay)<=tol and
     abs(m1.bx-m2.bx)<=tol and
     abs(m1.by-m2.by)<=tol and
     abs(m1.tx-m2.tx)<=tol and
     abs(m1.ty-m2.ty)<=tol
-    
+
 proc `=~`*(m1,m2:Matrix2d):bool=
   ## Checks if `m1`and `m2` is approximately equal, using a
   ## tolerance of 1e-6.
@@ -350,16 +350,16 @@ proc slopeVector2d*(slope:float,len:float):Vector2d {.noInit.} =
 proc len*(v:Vector2d):float {.inline.}=
   ## Returns the length of the vector.
   sqrt(v.x*v.x+v.y*v.y)
-  
+
 proc `len=`*(v:var Vector2d,newlen:float) {.noInit.} =
   ## Sets the length of the vector, keeping its angle.
   let fac=newlen/v.len
-  
+
   if newlen==0.0:
     v.x=0.0
     v.y=0.0
     return
-  
+
   if fac==Inf or fac==NegInf:
     #to short for float accuracy
     #do as good as possible:
@@ -368,30 +368,30 @@ proc `len=`*(v:var Vector2d,newlen:float) {.noInit.} =
   else:
     v.x*=fac
     v.y*=fac
-  
+
 proc sqrLen*(v:Vector2d):float {.inline.}=
   ## Computes the squared length of the vector, which is
   ## faster than computing the absolute length.
   v.x*v.x+v.y*v.y
-  
+
 proc angle*(v:Vector2d):float=
-  ## Returns the angle of the vector. 
+  ## Returns the angle of the vector.
   ## (The counter clockwise plane angle between posetive x axis and `v`)
   result=arctan2(v.y,v.x)
   if result<0.0: result+=DEG360
-  
+
 proc `$` *(v:Vector2d):string=
   ## String representation of `v`
   result=rtos(v.x)
   result.add(",")
   result.add(rtos(v.y))
-  
-  
+
+
 proc `&` *(v:Vector2d,m:Matrix2d):Vector2d {.noInit.} =
   ## Concatenate vector `v` with a transformation matrix.
   ## Transforming a vector ignores the translational part
   ## of the matrix.
-  
+
   #             | AX AY 0 |
   # | X Y 1 | * | BX BY 0 |
   #             | 0  0  1 |
@@ -403,7 +403,7 @@ proc `&=`*(v:var Vector2d,m:Matrix2d) {.inline.}=
   ## Applies transformation `m` onto `v` in place.
   ## Transforming a vector ignores the translational part
   ## of the matrix.
-  
+
   #             | AX AY 0 |
   # | X Y 1 | * | BX BY 0 |
   #             | 0  0  1 |
@@ -412,31 +412,31 @@ proc `&=`*(v:var Vector2d,m:Matrix2d) {.inline.}=
   v.x=newx
 
 
-proc tryNormalize*(v:var Vector2d):bool= 
+proc tryNormalize*(v:var Vector2d):bool=
   ## 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 
+  ## If `v` has zero length (and thus no angle), it is left unmodified and
   ## false is returned, otherwise true is returned.
 
   let mag=v.len
 
   if mag==0.0:
     return false
-  
+
   v.x/=mag
   v.y/=mag
   return true
 
 
-proc normalize*(v:var Vector2d) {.inline.}= 
+proc normalize*(v:var Vector2d) {.inline.}=
   ## Modifies `v` to have a length of 1.0, keeping its angle.
   ## If  `v` has zero length, an EDivByZero will be raised.
   if not tryNormalize(v):
     raise newException(DivByZeroError,"Cannot normalize zero length vector")
-  
+
 proc transformNorm*(v:var Vector2d,t:Matrix2d)=
   ## 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 
+  ## 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.
 
   # transforming a normal is done by transforming
@@ -469,16 +469,16 @@ proc transformInv*(v:var Vector2d,t:Matrix2d)=
 
 proc transformNormInv*(v:var Vector2d,t:Matrix2d)=
   ## 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 
+  ## This is faster than creating an inverse
+  ## matrix and transformNorm(...) it. Transforming a vector ignores the
   ## translational part of the matrix.
 
   # normal inverse transform is done by transforming
   # by the inverse of the transpose of the inverse of the org. matrix
   # which is equivalent with transforming with the transpose.
   #             | | | AX AY 0 |^-1|^T|^-1                | AX BX 0 |
-  # | X Y 1 | * | | | BX BY 0 |   |  |    =  | X Y 1 | * | AY BY 0 | 
-  #             | | | 0  0  1 |   |  |                   | 0  0  1 | 
+  # | X Y 1 | * | | | BX BY 0 |   |  |    =  | X Y 1 | * | AY BY 0 |
+  #             | | | 0  0  1 |   |  |                   | 0  0  1 |
   # This can be heavily reduced to:
   let newx=t.ay*v.y+t.ax*v.x
   v.y=t.by*v.y+t.bx*v.x
@@ -489,19 +489,19 @@ proc rotate90*(v:var Vector2d) {.inline.}=
   ## without using any trigonometrics.
   swap(v.x,v.y)
   v.x= -v.x
-  
+
 proc rotate180*(v:var Vector2d){.inline.}=
   ## Quickly rotates vector `v` 180 degrees counter clockwise,
   ## without using any trigonometrics.
   v.x= -v.x
   v.y= -v.y
-  
+
 proc rotate270*(v:var Vector2d) {.inline.}=
   ## Quickly rotates vector `v` 270 degrees counter clockwise,
   ## without using any trigonometrics.
   swap(v.x,v.y)
   v.y= -v.y
-  
+
 proc rotate*(v:var Vector2d,rad:float) =
   ## Rotates vector `v` `rad` radians in place.
   let
@@ -510,18 +510,18 @@ proc rotate*(v:var Vector2d,rad:float) =
     newx=c*v.x-s*v.y
   v.y=c*v.y+s*v.x
   v.x=newx
-  
+
 proc scale*(v:var Vector2d,fac:float){.inline.}=
   ## Scales vector `v` `rad` radians in place.
   v.x*=fac
   v.y*=fac
-  
+
 proc stretch*(v:var Vector2d,facx,facy:float){.inline.}=
   ## Stretches vector `v` `facx` times horizontally,
   ## and `facy` times vertically.
   v.x*=facx
   v.y*=facy
-  
+
 proc mirror*(v:var Vector2d,mirrvec:Vector2d)=
   ## Mirrors vector `v` using `mirrvec` as mirror direction.
   let
@@ -530,20 +530,20 @@ proc mirror*(v:var Vector2d,mirrvec:Vector2d)=
     nd=1.0/(sqx+sqy) #used to normalize invector
     xy2=mirrvec.x*mirrvec.y*2.0*nd
     sqd=nd*(sqx-sqy)
-    
+
   if nd==Inf or nd==NegInf:
     return #mirroring around a zero vector is arbitrary=>keep as is is fastest
-  
+
   let newx=xy2*v.y+sqd*v.x
   v.y=v.x*xy2-sqd*v.y
   v.x=newx
-    
- 
+
+
 proc `-` *(v:Vector2d):Vector2d=
   ## Negates a vector
   result.x= -v.x
   result.y= -v.y
-    
+
 # declare templated binary operators
 makeBinOpVector(`+`)
 makeBinOpVector(`-`)
@@ -556,27 +556,27 @@ makeBinOpAssignVector(`/=`)
 
 
 proc dot*(v1,v2:Vector2d):float=
-  ## Computes the dot product of two vectors. 
+  ## Computes the dot product of two vectors.
   ## Returns 0.0 if the vectors are perpendicular.
   return v1.x*v2.x+v1.y*v2.y
-  
+
 proc cross*(v1,v2:Vector2d):float=
   ## Computes the cross product of two vectors, also called
   ## the 'perpendicular dot product' in 2d. Returns 0.0 if the vectors
   ## are parallel.
   return v1.x*v2.y-v1.y*v2.x
-  
+
 proc equals*(v1,v2:Vector2d,tol=1.0e-6):bool=
   ## Checks if two vectors approximately equals with a tolerance.
   return abs(v2.x-v1.x)<=tol and abs(v2.y-v1.y)<=tol
-  
+
 proc `=~` *(v1,v2:Vector2d):bool=
-  ## Checks if two vectors approximately equals with a 
+  ## Checks if two vectors approximately equals with a
   ## hardcoded tolerance 1e-6
   equals(v1,v2)
-  
+
 proc angleTo*(v1,v2:Vector2d):float=
-  ## Returns the smallest of the two possible angles 
+  ## Returns the smallest of the two possible angles
   ## between `v1` and `v2` in radians.
   var
     nv1=v1
@@ -584,7 +584,7 @@ proc angleTo*(v1,v2:Vector2d):float=
   if not nv1.tryNormalize or not nv2.tryNormalize:
     return 0.0 # zero length vector has zero angle to any other vector
   return safeArccos(dot(nv1,nv2))
-  
+
 proc angleCCW*(v1,v2:Vector2d):float=
   ## Returns the counter clockwise plane angle from `v1` to `v2`,
   ## in range 0 - 2*PI
@@ -592,7 +592,7 @@ proc angleCCW*(v1,v2:Vector2d):float=
   if v1.cross(v2)>=0.0:
     return a
   return DEG360-a
-  
+
 proc angleCW*(v1,v2:Vector2d):float=
   ## Returns the clockwise plane angle from `v1` to `v2`,
   ## in range 0 - 2*PI
@@ -612,32 +612,32 @@ proc turnAngle*(v1,v2:Vector2d):float=
 proc bisect*(v1,v2:Vector2d):Vector2d {.noInit.}=
   ## 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, 
+  ## of the other is returned. If both input vectors has zero length,
   ## an arbitrary normalized vector is returned.
   var
     vmag1=v1.len
     vmag2=v2.len
-    
+
   # zero length vector equals arbitrary vector, just change to magnitude to one to
   # avoid zero division
-  if vmag1==0.0: 
+  if vmag1==0.0:
     if vmag2==0: #both are zero length return any normalized vector
       return XAXIS
     vmag1=1.0
-  if vmag2==0.0: vmag2=1.0    
-    
+  if vmag2==0.0: vmag2=1.0
+
   let
     x1=v1.x/vmag1
     y1=v1.y/vmag1
     x2=v2.x/vmag2
     y2=v2.y/vmag2
-    
+
   result.x=(x1 + x2) * 0.5
   result.y=(y1 + y2) * 0.5
-  
+
   if not result.tryNormalize():
     # This can happen if vectors are colinear. In this special case
-    # there are actually two bisectors, we select just 
+    # there are actually two bisectors, we select just
     # one of them (x1,y1 rotated 90 degrees ccw).
     result.x = -y1
     result.y = x1
@@ -651,13 +651,13 @@ proc bisect*(v1,v2:Vector2d):Vector2d {.noInit.}=
 proc point2d*(x,y:float):Point2d =
   result.x=x
   result.y=y
-  
+
 proc sqrDist*(a,b:Point2d):float=
   ## Computes the squared distance between `a` and `b`
   let dx=b.x-a.x
   let dy=b.y-a.y
   result=dx*dx+dy*dy
-  
+
 proc dist*(a,b:Point2d):float {.inline.}=
   ## Computes the absolute distance between `a` and `b`
   result=sqrt(sqrDist(a,b))
@@ -675,11 +675,11 @@ proc `$` *(p:Point2d):string=
   result=rtos(p.x)
   result.add(",")
   result.add(rtos(p.y))
-  
+
 proc `&`*(p:Point2d,t:Matrix2d):Point2d {.noInit,inline.} =
   ## Concatenates a point `p` with a transform `t`,
   ## resulting in a new, transformed point.
-  
+
   #             | AX AY 0 |
   # | X Y 1 | * | BX BY 0 |
   #             | TX TY 1 |
@@ -697,21 +697,21 @@ proc transformInv*(p:var Point2d,t:Matrix2d){.inline.}=
   ## Applies the inverse of transformation `t` onto `p` in place.
   ## If the matrix is not invertable (determinant=0) , EDivByZero will
   ## be raised.
-  
+
   #             | AX AY 0 | ^-1
   # | X Y 1 | * | BX BY 0 |
   #             | TX TY 1 |
   let d=t.determinant
   if d==0.0:
     raise newException(DivByZeroError,"Cannot invert a zero determinant matrix")
-  let 
+  let
     newx= (t.bx*t.ty-t.by*t.tx+p.x*t.by-p.y*t.bx)/d
   p.y = -(t.ax*t.ty-t.ay*t.tx+p.x*t.ay-p.y*t.ax)/d
   p.x=newx
-  
-  
+
+
 proc `+`*(p:Point2d,v:Vector2d):Point2d {.noInit,inline.} =
-  ## Adds a vector `v` to a point `p`, resulting 
+  ## Adds a vector `v` to a point `p`, resulting
   ## in a new point.
   result.x=p.x+v.x
   result.y=p.y+v.y
@@ -722,7 +722,7 @@ proc `+=`*(p:var Point2d,v:Vector2d) {.noInit,inline.} =
   p.y+=v.y
 
 proc `-`*(p:Point2d,v:Vector2d):Point2d {.noInit,inline.} =
-  ## Subtracts a vector `v` from a point `p`, resulting 
+  ## Subtracts a vector `v` from a point `p`, resulting
   ## in a new point.
   result.x=p.x-v.x
   result.y=p.y-v.y
@@ -736,13 +736,13 @@ proc `-=`*(p:var Point2d,v:Vector2d) {.noInit,inline.} =
   ## Subtracts a vector `v` from a point `p` in place.
   p.x-=v.x
   p.y-=v.y
-  
+
 proc equals(p1,p2:Point2d,tol=1.0e-6):bool {.inline.}=
   ## Checks if two points approximately equals with a tolerance.
   return abs(p2.x-p1.x)<=tol and abs(p2.y-p1.y)<=tol
 
 proc `=~`*(p1,p2:Point2d):bool {.inline.}=
-  ## Checks if two vectors approximately equals with a 
+  ## Checks if two vectors approximately equals with a
   ## hardcoded tolerance 1e-6
   equals(p1,p2)
 
@@ -759,7 +759,7 @@ proc rotate*(p:var Point2d,rad:float)=
     newx=p.x*c-p.y*s
   p.y=p.y*c+p.x*s
   p.x=newx
-    
+
 proc rotate*(p:var Point2d,rad:float,org:Point2d)=
   ## Rotates a point in place `rad` radians using `org` as
   ## center of rotation.
@@ -769,25 +769,25 @@ proc rotate*(p:var Point2d,rad:float,org:Point2d)=
     newx=(p.x - org.x) * c - (p.y - org.y) * s + org.x
   p.y=(p.y - org.y) * c + (p.x - org.x) * s + org.y
   p.x=newx
-  
+
 proc scale*(p:var Point2d,fac:float) {.inline.}=
   ## Scales a point in place `fac` times with world origo as origin.
   p.x*=fac
   p.y*=fac
-  
+
 proc scale*(p:var Point2d,fac:float,org:Point2d){.inline.}=
   ## Scales the point in place `fac` times with `org` as origin.
   p.x=(p.x - org.x) * fac + org.x
   p.y=(p.y - org.y) * fac + org.y
 
 proc stretch*(p:var Point2d,facx,facy:float){.inline.}=
-  ## Scales a point in place non uniformly `facx` and `facy` times with 
+  ## Scales a point in place non uniformly `facx` and `facy` times with
   ## world origo as origin.
   p.x*=facx
   p.y*=facy
 
 proc stretch*(p:var Point2d,facx,facy:float,org:Point2d){.inline.}=
-  ## Scales the point in place non uniformly `facx` and `facy` times with 
+  ## Scales the point in place non uniformly `facx` and `facy` times with
   ## `org` as origin.
   p.x=(p.x - org.x) * facx + org.x
   p.y=(p.y - org.y) * facy + org.y
@@ -814,21 +814,21 @@ proc area*(a,b,c:Point2d):float=
   return abs(sgnArea(a,b,c))
 
 proc closestPoint*(p:Point2d,pts:varargs[Point2d]):Point2d=
-  ## Returns a point selected from `pts`, that has the closest 
+  ## Returns a point selected from `pts`, that has the closest
   ## euclidean distance to `p`
   assert(pts.len>0) # must have at least one point
-  
-  var 
+
+  var
     bestidx=0
     bestdist=p.sqrDist(pts[0])
     curdist:float
-    
+
   for idx in 1..high(pts):
     curdist=p.sqrDist(pts[idx])
     if curdist<bestdist:
       bestidx=idx
       bestdist=curdist
-  
+
   result=pts[bestidx]
 
 
@@ -843,7 +843,7 @@ proc normAngle*(ang:float):float=
     return ang
 
   return ang mod DEG360
-  
+
 proc degToRad*(deg:float):float {.inline.}=
   ## converts `deg` degrees to radians
   deg / RAD2DEGCONST
@@ -852,4 +852,4 @@ proc radToDeg*(rad:float):float {.inline.}=
   ## converts `rad` radians to degrees
   rad * RAD2DEGCONST
 
-  
+