diff options
-rw-r--r-- | lib/pure/basic2d.nim | 40 | ||||
-rw-r--r-- | lib/pure/basic3d.nim | 59 |
2 files changed, 59 insertions, 40 deletions
diff --git a/lib/pure/basic2d.nim b/lib/pure/basic2d.nim index 08313c9d3..f8391a368 100644 --- a/lib/pure/basic2d.nim +++ b/lib/pure/basic2d.nim @@ -131,7 +131,7 @@ template makeBinOpAssignVector(s:expr)= # *************************************** proc setElements*(t:var TMatrix2d,ax,ay,bx,by,tx,ty:float) {.inline.}= - ## Sets arbitrary elements in an exisitng matrix. + ## Sets arbitrary elements in an existing matrix. t.ax=ax t.ay=ay t.bx=bx @@ -220,7 +220,7 @@ proc mirror*(v:TVector2d):TMatrix2d {.noInit.} = xy2,-sqd, 0.0,0.0) -proc mirror*(v:TVector2d,org:TPoint2d):TMatrix2d {.noInit.} = +proc mirror*(org:TPoint2d,v:TVector2d):TMatrix2d {.noInit.} = ## Returns a new mirror matrix, mirroring ## around the line that passes through `org` and ## has the direction of `v` @@ -270,6 +270,7 @@ proc isUniform*(t:TMatrix2d,tol=1.0e-6):bool= proc determinant*(t:TMatrix2d):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 @@ -413,8 +414,8 @@ proc `&=`*(v:var TVector2d,m:TMatrix2d) {.inline.}= proc tryNormalize*(v:var TVector2d):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 false is - ## returned, otherwise true is returned. + ## 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 @@ -452,7 +453,7 @@ proc transformNorm*(v:var TVector2d,t:TMatrix2d)= v.x = newx proc transformInv*(v:var TVector2d,t:TMatrix2d)= - ## Applies inverse of a transformation `m` to `v` in place. + ## 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 @@ -521,7 +522,7 @@ proc stretch*(v:var TVector2d,facx,facy:float){.inline.}= v.x*=facx v.y*=facy -proc mirror*(v:var TVector2d,mirrvec:TVector2d){.inline.}= +proc mirror*(v:var TVector2d,mirrvec:TVector2d)= ## Mirrors vector `v` using `mirrvec` as mirror direction. let sqx=mirrvec.x*mirrvec.x @@ -561,7 +562,7 @@ proc dot*(v1,v2:TVector2d):float= proc cross*(v1,v2:TVector2d):float= ## Computes the cross product of two vectors, also called - ## the 'perpendicualar dot product' in 2d. Returns 0.0 if the vectors + ## the 'perpendicular dot product' in 2d. Returns 0.0 if the vectors ## are parallel. return v1.x*v2.y-v1.y*v2.x @@ -575,7 +576,8 @@ proc `=~` *(v1,v2:TVector2d):bool= equals(v1,v2) proc angleTo*(v1,v2:TVector2d):float= - ## Returns the smallest of the two possible angles between `v1` and `v2` in radians. + ## Returns the smallest of the two possible angles + ## between `v1` and `v2` in radians. var nv1=v1 nv2=v2 @@ -585,7 +587,7 @@ proc angleTo*(v1,v2:TVector2d):float= proc angleCCW*(v1,v2:TVector2d):float= ## Returns the counter clockwise plane angle from `v1` to `v2`, - ## in range 0-PI + ## in range 0 - 2*PI let a=v1.angleTo(v2) if v1.cross(v2)>=0.0: return a @@ -593,7 +595,7 @@ proc angleCCW*(v1,v2:TVector2d):float= proc angleCW*(v1,v2:TVector2d):float= ## Returns the clockwise plane angle from `v1` to `v2`, - ## in range 0-PI + ## in range 0 - 2*PI let a=v1.angleTo(v2) if v1.cross(v2)<=0.0: return a @@ -609,7 +611,7 @@ proc turnAngle*(v1,v2:TVector2d):float= proc bisect*(v1,v2:TVector2d):TVector2d {.noInit.}= ## Computes the bisector between v1 and v2 as a normalized vector. - ## If one of the input vectors has zero length, a normalized verison + ## 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. var @@ -651,13 +653,13 @@ proc point2d*(x,y:float):TPoint2d = result.y=y proc sqrDist*(a,b:TPoint2d):float= - ## Computes the squared distance between `a`and `b` + ## 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:TPoint2d):float {.inline.}= - ## Computes the absolute distance between `a`and `b` + ## Computes the absolute distance between `a` and `b` result=sqrt(sqrDist(a,b)) proc angle*(a,b:TPoint2d):float= @@ -759,7 +761,8 @@ proc rotate*(p:var TPoint2d,rad:float)= p.x=newx proc rotate*(p:var TPoint2d,rad:float,org:TPoint2d)= - ## Rotates a point in place `rad` radians around another point `org` + ## Rotates a point in place `rad` radians using `org` as + ## center of rotation. let c=cos(rad) s=sin(rad) @@ -778,12 +781,14 @@ proc scale*(p:var TPoint2d,fac:float,org:TPoint2d){.inline.}= p.y=(p.y - org.y) * fac + org.y proc stretch*(p:var TPoint2d,facx,facy:float){.inline.}= - ## Scales a point in place non uniformly `facx` and `facy` times with world origo as origin. + ## 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 TPoint2d,facx,facy:float,org:TPoint2d){.inline.}= - ## Scales the point in place non uniformly `facx` and `facy` times with `org` as origin. + ## 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 @@ -809,7 +814,8 @@ proc area*(a,b,c:TPoint2d):float= return abs(sgnArea(a,b,c)) proc closestPoint*(p:TPoint2d,pts:varargs[TPoint2d]):TPoint2d= - ## Returns a point selected from `pts`, that has the closest euclidean distance to `p` + ## 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 diff --git a/lib/pure/basic3d.nim b/lib/pure/basic3d.nim index fc4c62663..74494ae5f 100644 --- a/lib/pure/basic3d.nim +++ b/lib/pure/basic3d.nim @@ -17,7 +17,8 @@ import times ## the translation part of matrix is ignored. The coordinate system used is ## right handed, because its compatible with 2d coordinate system (rotation around ## zaxis equals 2d rotation). -## Operators `+` , `-` , `*` , `/` , `+=` , `-=` , `*=` and `/=` are implemented for vectors and scalars. +## Operators `+` , `-` , `*` , `/` , `+=` , `-=` , `*=` and `/=` are implemented +## for vectors and scalars. ## ## ## Quick start example: @@ -37,7 +38,7 @@ import times ## ## var pt2:TPoint3d=pt & m #concatenates pt with m and returns a new point ## -## var vec2:TVector3d=vec & m #concatenates vec with m and returns a new vector +## var vec2:TVector3d=vec & m #concatenates vec with m and returns a new vector @@ -69,6 +70,7 @@ proc matrix3d*(ax,ay,az,aw,bx,by,bz,bw,cx,cy,cz,cw,tx,ty,tz,tw:float):TMatrix3d ## Creates a new 4x4 3d transformation matrix. ## `ax` , `ay` , `az` is the local x axis. ## `bx` , `by` , `bz` is the local y axis. + ## `cx` , `cy` , `cz` is the local z axis. ## `tx` , `ty` , `tz` is the translation. proc vector3d*(x,y,z:float):TVector3d {.noInit,inline.} ## Returns a new 3d vector (`x`,`y`,`z`) @@ -114,14 +116,19 @@ proc safeArccos(v:float):float= template makeBinOpVector(s:expr)= ## implements binary operators + , - , * and / for vectors - proc s*(a,b:TVector3d):TVector3d {.inline,noInit.} = vector3d(s(a.x,b.x),s(a.y,b.y),s(a.z,b.z)) - proc s*(a:TVector3d,b:float):TVector3d {.inline,noInit.} = vector3d(s(a.x,b),s(a.y,b),s(a.z,b)) - proc s*(a:float,b:TVector3d):TVector3d {.inline,noInit.} = vector3d(s(a,b.x),s(a,b.y),s(a,b.z)) + proc s*(a,b:TVector3d):TVector3d {.inline,noInit.} = + vector3d(s(a.x,b.x),s(a.y,b.y),s(a.z,b.z)) + proc s*(a:TVector3d,b:float):TVector3d {.inline,noInit.} = + vector3d(s(a.x,b),s(a.y,b),s(a.z,b)) + proc s*(a:float,b:TVector3d):TVector3d {.inline,noInit.} = + vector3d(s(a,b.x),s(a,b.y),s(a,b.z)) template makeBinOpAssignVector(s:expr)= ## implements inplace binary operators += , -= , /= and *= for vectors - proc s*(a:var TVector3d,b:TVector3d) {.inline.} = s(a.x,b.x) ; s(a.y,b.y) ; s(a.z,b.z) - proc s*(a:var TVector3d,b:float) {.inline.} = s(a.x,b) ; s(a.y,b) ; s(a.z,b) + proc s*(a:var TVector3d,b:TVector3d) {.inline.} = + s(a.x,b.x) ; s(a.y,b.y) ; s(a.z,b.z) + proc s*(a:var TVector3d,b:float) {.inline.} = + s(a.x,b) ; s(a.y,b) ; s(a.z,b) @@ -235,7 +242,7 @@ proc rotate*(angle:float,axis:TVector3d):TMatrix3d {.noInit.}= uwomc+vsi, vwomc-usi, w2+(1.0-w2)*cs, 0.0, 0.0,0.0,0.0,1.0) -proc rotate*(angle:float,axis:TVector3d,org:TPoint3d):TMatrix3d {.noInit.}= +proc rotate*(angle:float,org:TPoint3d,axis:TVector3d):TMatrix3d {.noInit.}= ## Creates a rotation matrix that rotates `angle` radians over ## `axis`, which passes through `org`. @@ -319,7 +326,10 @@ proc isUniform*(m:TMatrix3d,tol=1.0e-6):bool= ## and perpendicular comparison. #dot product=0 means perpendicular coord. system, check xaxis vs yaxis and xaxis vs zaxis - if abs(m.ax*m.bx+m.ay*m.by+m.az*m.bz)<=tol and abs(m.ax*m.cx+m.ay*m.cy+m.az*m.cz)<=tol: + if abs(m.ax*m.bx+m.ay*m.by+m.az*m.bz)<=tol and # x vs y + abs(m.ax*m.cx+m.ay*m.cy+m.az*m.cz)<=tol and #x vs z + abs(m.bx*m.cx+m.by*m.cy+m.bz*m.cz)<=tol: #y vs z + #subtract squared lengths of axes to check if uniform scaling: let sqxlen=(m.ax*m.ax+m.ay*m.ay+m.az*m.az) @@ -355,7 +365,7 @@ proc mirror*(planeperp:TVector3d):TMatrix3d {.noInit.}= 0,0,0,1) -proc mirror*(planeperp:TVector3d,org:TPoint3d):TMatrix3d {.noInit.}= +proc mirror*(org:TPoint3d,planeperp:TVector3d):TMatrix3d {.noInit.}= ## Creates a matrix that mirrors over the plane that has `planeperp` as normal, ## and passes through `org`. `planeperp` does not need to be normalized. @@ -393,7 +403,8 @@ proc mirror*(planeperp:TVector3d,org:TPoint3d):TMatrix3d {.noInit.}= proc determinant*(m:TMatrix3d):float= ## Computes the determinant of matrix `m`. - # This computation is gotten from ratsimp(optimize(determinant(m))) in maxima CAS + # This computation is gotten from ratsimp(optimize(determinant(m))) + # in maxima CAS let O1=m.cx*m.tw-m.cw*m.tx O2=m.cy*m.tw-m.cw*m.ty @@ -537,7 +548,7 @@ proc len*(v:TVector3d):float= proc `len=`*(v:var TVector3d,newlen:float) {.noInit.} = ## Sets the length of the vector, keeping its direction. - ## If the vector has zero length before chenging it's length, + ## If the vector has zero length before changing it's length, ## an arbitrary vector of the requested length is returned. let fac=newlen/v.len @@ -702,8 +713,7 @@ proc stretch*(v:var TVector3d,sx,sy,sz:float)= proc mirror*(v:var TVector3d,planeperp:TVector3d)= ## Computes the mirrored vector of `v` over the plane - ## that has `planeperp` as normal direction. This is the - ## same as reflecting the vector `v` on the plane. + ## that has `planeperp` as normal direction. ## `planeperp` does not need to be normalized. var n=planeperp @@ -750,7 +760,8 @@ proc cross*(v1,v2:TVector3d):TVector3d {.inline.}= ## Computes the cross product of two vectors. ## The result is a vector which is perpendicular ## to the plane of `v1` and `v2`, which means - ## cross(xaxis,yaxis)=zaxis + ## cross(xaxis,yaxis)=zaxis. The magnitude of the result is + ## zero if the vectors are colinear. result.x = (v1.y * v2.z) - (v2.y * v1.z) result.y = (v1.z * v2.x) - (v2.z * v1.x) result.z = (v1.x * v2.y) - (v2.x * v1.y) @@ -798,16 +809,16 @@ proc arbitraryAxis*(norm:TVector3d):TMatrix3d {.noInit.}= 0.0,0.0,0.0,1.0) proc bisect*(v1,v2:TVector3d):TVector3d {.noInit.}= - ## Computes the bisector between v1 and v2 as a normalized vector - ## If one of the input vectors has zero length, a normalized verison + ## 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. + ## an arbitrary normalized vector `v1`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 + # zero length vector equals arbitrary vector, just change + # magnitude to one to avoid zero division if vmag1==0.0: if vmag2==0: #both are zero length return any normalized vector return XAXIS @@ -943,7 +954,7 @@ proc rotate*(p:var TPoint3d,rad:float,axis:TVector3d)= p.y=v.y p.z=v.z -proc rotate*(p:var TPoint3d,angle:float,axis:TVector3d,org:TPoint3d)= +proc rotate*(p:var TPoint3d,angle:float,org:TPoint3d,axis:TVector3d)= ## Rotates point `p` in place `rad` radians about an axis ## passing through `org` @@ -994,13 +1005,15 @@ proc scale*(p:var TPoint3d,fac:float,org:TPoint3d){.inline.}= p.z=(p.z - org.z) * fac + org.z proc stretch*(p:var TPoint3d,facx,facy,facz:float){.inline.}= - ## Scales a point in place non uniformly `facx` and `facy` times with world origo as origin. + ## Scales a point in place non uniformly `facx` , `facy` , `facz` times + ## with world origo as origin. p.x*=facx p.y*=facy p.z*=facz proc stretch*(p:var TPoint3d,facx,facy,facz:float,org:TPoint3d){.inline.}= - ## Scales the point in place non uniformly `facx` and `facy` times with `org` as origin. + ## Scales the point in place non uniformly `facx` , `facy` , `facz` times + ## with `org` as origin. p.x=(p.x - org.x) * facx + org.x p.y=(p.y - org.y) * facy + org.y p.z=(p.z - org.z) * facz + org.z |