diff options
Diffstat (limited to 'lib/pure/basic2d.nim')
-rw-r--r-- | lib/pure/basic2d.nim | 234 |
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 - + |