Snippet Vectors

krainert

Member
See below for version 5.0.

JASS:
library Vectors

//********************************************************************************************************************************
//* Vectors
//*  
//*  ABOUT
//*   Author:   krainert
//*   Version:  4.0
//*   
//*  DESCRIPTION
//*   This library provides two vector classes:
//*   - Vector2D representing a two-dimensional vector
//*   - Vector3D representing a three-dimensional vector
//*   Note: All angles are in radians
//*   
//*  CLASSES
//*   ======== Vector2D ========
//*    -- Description
//*     Represents a two-dimensional vector
//*    -- Static methods
//*     static Vector2D create(Vector2D v)                                      - instantiates a new two-dimensional vector as a clone of v
//*     static Vector2D createXY(real x, real y)                                - instantiates a new two-dimensional vector with x coordinate x and y coordinate y
//*     static Vector2D createDM(real d, real m)                                - instantiates a new two-dimensional vector with direction d and magnitude m
//*     static Vector2D createNull()                                            - instantiates a new two-dimensional vector with x and y coordinates 0
//*    -- Methods
//*     Vector2D clone()                                                        - returns a new clone of this vector
//*     real     getX()                                                         - returns the x coordinate of this vector
//*     real     getY()                                                         - returns the y coordinate of this vector
//*     real     getDir()                                                       - returns the direction of this vector
//*     real     getMag()                                                       - returns the magnitude of this vector
//*     Vector2D setX(real x)                                                   - sets the x coordinate of this vector to x and returns the result
//*     Vector2D setY(real y)                                                   - sets the y coordinate of this vector to y and returns the result
//*     Vector2D setDir(real d)                                                 - sets the direction of this vector to d and returns the result
//*     Vector2D setMag(real m)                                                 - sets the magnitude of this vector to m and returns the result
//*     real     dotProduct(Vector2D v)                                         - returns the dot product of this vector and v
//*     real     angle(Vector2D v)                                              - returns the angle between this vector and v
//*     Vector2D unit()                                                         - sets the magnitude of this vector to 1 and returns the result
//*     Vector2D flip()                                                         - sets the x coordinate of this vector to its previous y coordinate and the y coordinate of this vector to its previous x coordinate and returns the result
//*     Vector2D invert()                                                       - sets the x coordinate of this vector to the inverse of its previous x coordinate and the y coordinate of this vector to the inverse of its previous y coordinate and returns the result
//*     Vector2D scale(real s)                                                  - scales this vector by an amount equal to s and returns the result
//*     Vector2D add(Vector2D v)                                                - adds v to this vector and returns the vector
//*     Vector2D sub(Vector2D v)                                                - subtracts v from this vector and returns the result
//*     Vector2D addXY(real x, real y)                                          - adds a vector with x coordinate x and y coordinate y to this vector and returns the result
//*     Vector2D subXY(real x, real y)                                          - subtracts a vector with x coordinate x and y coordinate y from this vector and returns the result
//*     Vector2D addDM(real d, real m)                                          - adds a vector with direction d and magnitude m to this vector and returns the result
//*     Vector2D subDM(real d, real m)                                          - subtracts a vector with direction d and magnitude m from this vector and returns the result
//*   ======== Vector3D ========
//*    -- Description
//*     Represents a three-dimensional vector
//*    -- Static methods
//*     static Vector3D create(Vector3D v)                                      - instantiates a new three-dimensional vector as a clone of v
//*     static Vector3D createXYZ(real x, real y, real z)                       - instantiates a new three-dimensional vector with x coordinate x, y coordinate y, and z coordinate z
//*     static Vector3D createNull()                                            - instantiates a new three-dimensional vector with x, y, and z coordinates 0
//*     static Vector3D createTerrainNormal(real x, real y, real sampleRadius)  - instantiates a new three-dimensional vector representing the normal of the terrain at the location with x coordinate x and y coordinate y with sample radius sampleRadius
//*    -- Methods
//*     Vector3D clone()                                                        - returns a new clone of this vector
//*     real     getX()                                                         - returns the x coordinate of this vector
//*     real     getY()                                                         - returns the y coordinate of this vector
//*     real     getZ()                                                         - returns the z coordinate of this vector
//*     real     getMag()                                                       - returns the magnitude of this vector
//*     Vector3D setX(real x)                                                   - sets the x coordinate of this vector to x and returns the result
//*     Vector3D setY(real y)                                                   - sets the y coordinate of this vector to y and returns the result
//*     Vector3D setZ(real z)                                                   - sets the z coordinate of this vector to z and returns the result
//*     Vector3D setMag(real m)                                                 - sets the magnitude of this vector to m and returns the result
//*     real     dotProduct(Vector3D v)                                         - returns the dot product of this vector and v
//*     real     tripleProductScalar(Vector3D v1, Vector3D v2)                  - returns the tripple scalar product of this vector, v1, and v2
//*     real     angle(Vector3D v)                                              - returns the angle between this vector and v
//*     Vector3D crossProduct(Vector3D v)                                       - sets this vector to the cross product of it and v and returns the result
//*     Vector3D tripleProductVector(Vector3D v1, Vector3D v2)                  - sets this vector to the tripple scalar product of it, v1, and v2 and returns the result
//*     Vector3D projectionVector(Vector3D dir)                                 - sets this vector to the projection of it onto dir and returns the result
//*     Vector3D projectionPlane(Vector3D normal)                               - sets this vector to the projection of it onto the plane with normal vector normal and returns the result
//*     Vector3D unit()                                                         - sets the magnitude of this vector to 1 and returns the result
//*     Vector3D invert()                                                       - sets the x coordinate of this vector to the inverse of its previous x coordinate, the y coordinate of this vector to the inverse of its previous y coordinate, and the z coordinate of this vector to the inverse of its previous z coordinate and returns the result
//*     Vector3D scale(real s)                                                  - scales this vector by an amount equal to s and returns the result
//*     Vector3D rotate(Vector3D axis, real angle)                              - rotates this vector around an axis through axis by an amount equal to angle and returns the result
//*     Vector3D add(Vector3D v)                                                - adds v to this vector and returns the result
//*     Vector3D sub(Vector3D v)                                                - subtracts v from this vector and returns the result
//*     Vector3D addXYZ(real x, real y, real z)                                 - adds a vector with x coordinate x, y coordinate y, and z coordinate z to this vector and returns the result
//*     Vector3D subXYZ(real x, real y, real z)                                 - subtracts a vector with x coordinate x, y coordinate y, and z coordinate z from this vector and returns the result
//*     
//*  CHANGELOG
//*   1.0  2011-07-08  Original release
//*   2.0  2011-07-13  vector redesigned and renamed to Vector2D
//*                    Vector3D added
//*   2.1  2011-07-17  modDir, modMag, and accumulative operations added to Vector2D
//*   2.2  2011-08-04  setMag added to Vector3D
//*                    crossProduct, tripleProductScalar, tripleProductVector, projectionVector, projectionPlane, rotate, mRotate, and static createTerrainNormal added to Vector3D
//*                    Note: the implementations of the above methods were inspired by Anitarf's Vector library
//*                    setMag optimized in Vector2D
//*                    Operator < overloaded for Vector2D: returns true if the magnitude of this vector is lower than the magnitude of the other vector, false otherwise
//*                    Operator < overloaded for Vector3D: returns true if the magnitude of this vector is lower than the magnitude of the other vector, false otherwise
//*                    Operator == overloaded for Vector2D: returns true if the x and y coordinates of this vector are equal to the x and y coordinates of the other vector respectively, false otherwise
//*                    Operator == overloaded for Vector3D: returns true if the x, y, and z coordinates of this vector are equal to the x, y, and z coordinates of the other vector respectively, false otherwise
//*   2.3  2011-08-05  getMag, getDir, setMag, setDir, addXY, subXY, mAddXY, and mSubXY in Vector2D relocated to prevent trigger evaluation
//*                    getMag, setMag, addXYZ, subXYZ, mAddXYZ, and mSubXYZ in Vector3D relocated to prevent trigger evaluation
//*   3.0  2011-10-24  Extensive API modifications and reductions
//*   4.0  2011-10-31  crossProduct, trippleProductVector, projectionVector, and projectionPlane in Vector3D changed into mutators
//*                    Miscellaneous corrections
//*   
//********************************************************************************************************************************

globals
    private constant integer MAX_2D = 8191
    private constant integer MAX_3D = 8191
endglobals

struct Vector2D[MAX_2D]
    private real x
    private real y
    
    static method create takes thistype v returns thistype
        local thistype r = .allocate()
        set r.x = v.x
        set r.y = v.y
        return r
    endmethod
    
    static method createXY takes real x, real y returns thistype
        local thistype r = .allocate()
        set r.x = x
        set r.y = y
        return r
    endmethod
    
    static method createDM takes real d, real m returns thistype
        local thistype r = .allocate()
        set r.x = Cos(d)*m
        set r.y = Sin(d)*m
        return r
    endmethod
    
    static method createNull takes nothing returns thistype
        local thistype r = .allocate()
        set r.x = 0
        set r.y = 0
        return r
    endmethod
    
    method onDestroy takes nothing returns nothing
    endmethod
    
    method clone takes nothing returns thistype
        local thistype r = .allocate()
        set r.x = .x
        set r.y = .y
        return r
    endmethod
    
    method getX takes nothing returns real
        return .x
    endmethod
    
    method getY takes nothing returns real
        return .y
    endmethod
    
    method getDir takes nothing returns real
        return Atan2(.y, .x)
    endmethod
    
    method getMag takes nothing returns real
        return SquareRoot(.x*.x+.y*.y)
    endmethod
    
    method setX takes real x returns thistype
        set .x = x
        return this
    endmethod
    
    method setY takes real y returns thistype
        set .y = y
        return this
    endmethod
    
    method setDir takes real d returns thistype
        local real m = .getMag()
        set .x = Cos(d)*m
        set .y = Sin(d)*m
        return this
    endmethod
    
    method setMag takes real m returns thistype
        local real f = m/.getMag()
        set .x = f*.x
        set .y = f*.y
        return this
    endmethod
    
    method dotProduct takes thistype v returns real
        return .x*v.x+.y*v.y
    endmethod
    
    method angle takes thistype v returns real
        return Acos(.dotProduct(v)/(.getMag()*v.getMag()))
    endmethod
    
    method unit takes nothing returns thistype
        local real m = .getMag()
        set .x = .x/m
        set .y = .y/m
        return this
    endmethod
    
    method flip takes nothing returns thistype
        local real x = .x
        set .x = .y
        set .y = x
        return this
    endmethod
    
    method invert takes nothing returns thistype
        set .x = -.x
        set .y = -.y
        return this
    endmethod
    
    method scale takes real s returns thistype
        set .x = s*.x
        set .y = s*.y
        return this
    endmethod
    
    method add takes thistype v returns thistype
        set .x = .x+v.x
        set .y = .y+v.y
        return this
    endmethod
    
    method sub takes thistype v returns thistype
        set .x = .x-v.x
        set .y = .y-v.y
        return this
    endmethod
    
    method addXY takes real x, real y returns thistype
        set .x = .x+x
        set .y = .y+y
        return this
    endmethod
    
    method subXY takes real x, real y returns thistype
        set .x = .x-x
        set .y = .y-y
        return this
    endmethod
    
    method addDM takes real d, real m returns thistype
        set .x = .x+Cos(d)*m
        set .y = .y+Sin(d)*m
        return this
    endmethod
    
    method subDM takes real d, real m returns thistype
        set .x = .x-Cos(d)*m
        set .y = .y-Sin(d)*m
        return this
    endmethod
endstruct

struct Vector3D[MAX_3D]
    private static location loc = Location(0., 0.)
    private real x
    private real y
    private real z
    
    static method create takes thistype v returns thistype
        local thistype r = .allocate()
        set r.x = v.x
        set r.y = v.y
        set r.z = v.z
        return r
    endmethod
    
    static method createXYZ takes real x, real y, real z returns thistype
        local thistype r = .allocate()
        set r.x = x
        set r.y = y
        set r.z = z
        return r
    endmethod
    
    static method createNull takes nothing returns thistype
        local thistype r = .allocate()
        set r.x = 0
        set r.y = 0
        set r.z = 0
        return r
    endmethod
    
    static method createTerrainNormal takes real x, real y, real sampleRadius returns thistype
        local thistype v = .allocate()
        local real zx
        local real zy
        call MoveLocation(.loc, x-sampleRadius, y)
        set zx = GetLocationZ(.loc)
        call MoveLocation(.loc, x+sampleRadius, y)
        set zx = zx-GetLocationZ(.loc)
        call MoveLocation(.loc, x, y-sampleRadius)
        set zy = GetLocationZ(.loc)
        call MoveLocation(.loc, x, y+sampleRadius)
        set zy = zy-GetLocationZ(.loc)
        set sampleRadius = 2*sampleRadius
        set v.x = zx*sampleRadius
        set v.y = zy*sampleRadius
        set v.z = sampleRadius*sampleRadius
        return v
    endmethod
    
    method onDestroy takes nothing returns nothing
    endmethod
    
    method clone takes nothing returns thistype
        local thistype r = .allocate()
        set r.x = .x
        set r.y = .y
        set r.z = .z
        return r
    endmethod
    
    method getX takes nothing returns real
        return .x
    endmethod
    
    method getY takes nothing returns real
        return .y
    endmethod
    
    method getZ takes nothing returns real
        return .z
    endmethod
    
    method getMag takes nothing returns real
        return SquareRoot(.x*.x+.y*.y+.z*.z)
    endmethod
    
    method setX takes real x returns thistype
        set .x = x
        return this
    endmethod
    
    method setY takes real y returns thistype
        set .y = y
        return this
    endmethod
    
    method setZ takes real z returns thistype
        set .z = z
        return this
    endmethod
    
    method setMag takes real m returns thistype
        local real f = m/.getMag()
        set .x = f*.x
        set .y = f*.y
        set .z = f*.z
        return this
    endmethod
    
    method dotProduct takes thistype v returns real
        return .x*v.x+.y*v.y+.z*v.z
    endmethod
    
    method tripleProductScalar takes thistype v1, thistype v2 returns real
        return (.y*v1.z - .z*v1.y)*v2.x + (.z*v1.x - .x*v1.z)*v2.y + (.x*v1.y - .y*v1.x)*v2.z
    endmethod
    
    method angle takes thistype v returns real
        return Acos(.dotProduct(v)/(.getMag()*v.getMag()))
    endmethod
    
    method crossProduct takes thistype v returns thistype
        local real x = .y*v.z - .z*v.y
        local real y = .z*v.x - .x*v.z
        set .z       = .x*v.y - .y*v.x
        set .x = x
        set .y = y
        return this
    endmethod
    
    method tripleProductVector takes thistype v1, thistype v2 returns thistype
        local real x = .y*v1.z - .z*v1.y
        local real y = .z*v1.x - .x*v1.z
        local real z = .x*v1.y - .y*v1.x
        set .x = y*v2.z - z*v2.y
        set .y = z*v2.x - x*v2.z
        set .z = x*v2.y - y*v2.x
        return this
    endmethod
    
    method projectionVector takes thistype dir returns thistype
        local real l = (.x*dir.x + .y*dir.y + .z*dir.z) / (dir.x*dir.x + dir.y*dir.y + dir.z*dir.z)
        set .x = dir.x*l
        set .y = dir.y*l
        set .z = dir.z*l
        return this
    endmethod
    
    method projectionPlane takes thistype normal returns thistype
        local real l = (.x*normal.x + .y*normal.y + .z*normal.z) / (normal.x*normal.x + normal.y*normal.y + normal.z*normal.z)
        set .x = .x - normal.x*l
        set .y = .y - normal.y*l
        set .z = .z - normal.z*l
        return this
    endmethod
    
    method unit takes nothing returns thistype
        local real m = .getMag()
        set .x = .x/m
        set .y = .y/m
        set .z = .z/m
        return this
    endmethod
    
    method invert takes nothing returns thistype
        set .x = -.x
        set .y = -.y
        set .z = -.z
        return this
    endmethod
    
    method scale takes real s returns thistype
        set .x = s*.x
        set .y = s*.y
        set .z = s*.z
        return this
    endmethod
    
    method rotate takes thistype axis, real angle returns thistype
        local real xx
        local real xy
        local real xz
        local real yx
        local real yy
        local real yz
        local real zx
        local real zy
        local real zz
        local real al = axis.x*axis.x + axis.y*axis.y + axis.z*axis.z
        local real f = (this.x*axis.x + this.y*axis.y + this.z*axis.z) / al
        local real c = Cos(angle)
        local real s = Sin(angle)
        set zx = axis.x*f
        set zy = axis.y*f
        set zz = axis.z*f
        set xx = this.x-zx
        set xy = this.y-zy
        set xz = this.z-zz
        set al = SquareRoot(al)
        set yx = (axis.y*xz - axis.z*xy) / al
        set yy = (axis.z*xx - axis.x*xz) / al
        set yz = (axis.x*xy - axis.y*xx) / al
        set .x = xx*c + yx*s + zx
        set .y = xy*c + yy*s + zy
        set .z = xz*c + yz*s + zz
        return this
    endmethod
    
    method add takes thistype v returns thistype
        set .x = .x+v.x
        set .y = .y+v.y
        set .z = .z+v.z
        return this
    endmethod
    
    method sub takes thistype v returns thistype
        set .x = .x-v.x
        set .y = .y-v.y
        set .z = .z-v.z
        return this
    endmethod
    
    method addXYZ takes real x, real y, real z returns thistype
        set .x = .x+x
        set .y = .y+y
        set .z = .z+z
        return this
    endmethod
    
    method subXYZ takes real x, real y, real z returns thistype
        set .x = .x-x
        set .y = .y-y
        set .z = .z-z
        return this
    endmethod
endstruct

endlibrary


VUnit:

JASS:
library VectorsVUnit initializer ini requires Vectors, VUnit

private function vector2D_createNull takes VUnitSuite suite returns nothing
    local Vector2D v = Vector2D.createNull()
    call suite.assertRealEquals(0., v.getX(), .001, "x")
    call suite.assertRealEquals(0., v.getY(), .001, "y")
    call v.destroy()
endfunction

private function vector2D_createXY takes VUnitSuite suite returns nothing
    local Vector2D v = Vector2D.createXY(3., 7.)
    call suite.assertRealEquals(3., v.getX(), .001, "x")
    call suite.assertRealEquals(7., v.getY(), .001, "y")
    call v.destroy()
endfunction

private function vector2D_create takes VUnitSuite suite returns nothing
    local Vector2D v1 = Vector2D.createXY(3., 7.)
    local Vector2D v2 = Vector2D.create(v1)
    call suite.assertRealEquals(3., v2.getX(), .001, "x")
    call suite.assertRealEquals(7., v2.getY(), .001, "y")
    call v2.destroy()
    call v2.destroy()
endfunction

private function vector2D_createDM takes VUnitSuite suite returns nothing
    local Vector2D v = Vector2D.createDM(.5*3.1416, 2.)
    call suite.assertRealEquals(0., v.getX(), .001, "x")
    call suite.assertRealEquals(2., v.getY(), .001, "y")
    call v.destroy()
endfunction

private function vector2D_getDir takes VUnitSuite suite returns nothing
    local Vector2D v = Vector2D.createXY(-3., 3.)
    call suite.assertRealEquals(.75*3.1416, v.getDir(), .001, "dir")
    call v.destroy()
endfunction

private function vector2D_getMag takes VUnitSuite suite returns nothing
    local Vector2D v = Vector2D.createXY(3., -4.)
    call suite.assertRealEquals(5., v.getMag(), .001, "mag")
    call v.destroy()
endfunction

private function vector2D_setDir takes VUnitSuite suite returns nothing
    local Vector2D v = Vector2D.createXY(0., 4.2426)
    call v.setDir(-.75*3.1416)
    call suite.assertRealEquals(-3., v.getX(), .001, "x")
    call suite.assertRealEquals(-3., v.getY(), .001, "y")
    call v.destroy()
endfunction

private function vector2D_setMag takes VUnitSuite suite returns nothing
    local Vector2D v = Vector2D.createXY(4., 3.)
    call v.setMag(15.)
    call suite.assertRealEquals(12., v.getX(), .001, "x")
    call suite.assertRealEquals(9., v.getY(), .001, "y")
    call v.destroy()
endfunction

private function vector2D_dotProduct takes VUnitSuite suite returns nothing
    local Vector2D v1 = Vector2D.createXY(2., 2.5)
    local Vector2D v2 = Vector2D.createXY(5., 3.)
    call suite.assertRealEquals(17.5, v1.dotProduct(v2), .001, "dotProduct")
    call v1.destroy()
    call v2.destroy()
endfunction

private function vector2D_angle takes VUnitSuite suite returns nothing
    local Vector2D v1 = Vector2D.createXY(1., 1.)
    local Vector2D v2 = Vector2D.createXY(-27., 27.)
    call suite.assertRealEquals(.5*3.1416, v1.angle(v2), .001, "angle")
    call v1.destroy()
    call v2.destroy()
endfunction

private function vector2D_unit takes VUnitSuite suite returns nothing
    local Vector2D v = Vector2D.createXY(4., 3.)
    call v.unit()
    call suite.assertRealEquals(4./5., v.getX(), .001, "x")
    call suite.assertRealEquals(3./5., v.getY(), .001, "y")
    call v.destroy()
endfunction

private function vector2D_flip takes VUnitSuite suite returns nothing
    local Vector2D v = Vector2D.createXY(123., 321.)
    call v.flip()
    call suite.assertRealEquals(321., v.getX(), .001, "x")
    call suite.assertRealEquals(123., v.getY(), .001, "y")
    call v.destroy()
endfunction

private function vector2D_invert takes VUnitSuite suite returns nothing
    local Vector2D v = Vector2D.createXY(42., -24.)
    call v.invert()
    call suite.assertRealEquals(-42., v.getX(), .001, "x")
    call suite.assertRealEquals(24., v.getY(), .001, "y")
    call v.destroy()
endfunction

private function vector2D_scale takes VUnitSuite suite returns nothing
    local Vector2D v = Vector2D.createXY(-42., 24.)
    call v.scale(-.25)
    call suite.assertRealEquals(10.5, v.getX(), .001, "x")
    call suite.assertRealEquals(-6., v.getY(), .001, "y")
    call v.destroy()
endfunction

private function vector2D_add takes VUnitSuite suite returns nothing
    local Vector2D v1 = Vector2D.createXY(12.101, 34.123)
    local Vector2D v2 = Vector2D.createXY(56.303, -78.22)
    call v1.add(v2)
    call suite.assertRealEquals(68.404, v1.getX(), .001, "x")
    call suite.assertRealEquals(-44.097, v1.getY(), .001, "y")
    call v1.destroy()
    call v2.destroy()
endfunction

private function vector2D_sub takes VUnitSuite suite returns nothing
    local Vector2D v1 = Vector2D.createXY(342.23, -54.2)
    local Vector2D v2 = Vector2D.createXY(-948.3, 84.)
    call v1.sub(v2)
    call suite.assertRealEquals(1290.53, v1.getX(), .001, "x")
    call suite.assertRealEquals(-138.2, v1.getY(), .001, "y")
    call v1.destroy()
    call v2.destroy()
endfunction

private function vector2D_addXY takes VUnitSuite suite returns nothing
    local Vector2D v = Vector2D.createXY(12.101, 34.123)
    call v.addXY(56.303, -78.22)
    call suite.assertRealEquals(68.404, v.getX(), .001, "x")
    call suite.assertRealEquals(-44.097, v.getY(), .001, "y")
    call v.destroy()
endfunction

private function vector2D_subXY takes VUnitSuite suite returns nothing
    local Vector2D v = Vector2D.createXY(342.23, -54.2)
    call v.subXY(-948.3, 84.)
    call suite.assertRealEquals(1290.53, v.getX(), .001, "x")
    call suite.assertRealEquals(-138.2, v.getY(), .001, "y")
    call v.destroy()
endfunction

private function vector2D_addDM takes VUnitSuite suite returns nothing
    local Vector2D v = Vector2D.createXY(4, -3)
    call v.addDM(.75*3.1416, 2.8284)
    call suite.assertRealEquals(2, v.getX(), .001, "x")
    call suite.assertRealEquals(-1, v.getY(), .001, "y")
    call v.destroy()
endfunction

private function vector2D_subDM takes VUnitSuite suite returns nothing
    local Vector2D v = Vector2D.createXY(4, -3)
    call v.subDM(.75*3.1416, 2.8284)
    call suite.assertRealEquals(6, v.getX(), .001, "x")
    call suite.assertRealEquals(-5, v.getY(), .001, "y")
    call v.destroy()
endfunction

private function vector3D_createNull takes VUnitSuite suite returns nothing
    local Vector3D v = Vector3D.createNull()
    call suite.assertRealEquals(0., v.getX(), .001, "x")
    call suite.assertRealEquals(0., v.getY(), .001, "y")
    call suite.assertRealEquals(0., v.getZ(), .001, "z")
    call v.destroy()
endfunction

private function vector3D_createXYZ takes VUnitSuite suite returns nothing
    local Vector3D v = Vector3D.createXYZ(3., 7., 4.)
    call suite.assertRealEquals(3., v.getX(), .001, "x")
    call suite.assertRealEquals(7., v.getY(), .001, "y")
    call suite.assertRealEquals(4., v.getZ(), .001, "z")
    call v.destroy()
endfunction

private function vector3D_create takes VUnitSuite suite returns nothing
    local Vector3D v1 = Vector3D.createXYZ(3., 7., 4.)
    local Vector3D v2 = Vector3D.create(v1)
    call suite.assertRealEquals(3., v2.getX(), .001, "x")
    call suite.assertRealEquals(7., v2.getY(), .001, "y")
    call suite.assertRealEquals(4., v2.getZ(), .001, "z")
    call v1.destroy()
    call v2.destroy()
endfunction

private function vector3D_getMag takes VUnitSuite suite returns nothing
    local Vector3D v = Vector3D.createXYZ(1.2, 23., 3.1)
    call suite.assertRealEquals(23.2390, v.getMag(), .001, "mag")
    call v.destroy()
endfunction

private function vector3D_setMag takes VUnitSuite suite returns nothing
    local Vector3D v = Vector3D.createXYZ(12., 23., 3.4)
    call v.setMag(39.19020924)
    call suite.assertRealEquals(18., v.getX(), .01*18., "x")
    call suite.assertRealEquals(34.5, v.getY(), .01*34.5, "y")
    call suite.assertRealEquals(5.1, v.getZ(), .01*5.1, "z")
    call v.destroy()
endfunction

private function vector3D_dotProduct takes VUnitSuite suite returns nothing
    local Vector3D v1 = Vector3D.createXYZ(2., 2.5, 4.)
    local Vector3D v2 = Vector3D.createXYZ(5., 3., 1.23)
    call suite.assertRealEquals(22.42, v1.dotProduct(v2), .001, "dotProduct")
    call v1.destroy()
    call v2.destroy()
endfunction

private function vector3D_tripleProductScalar takes VUnitSuite suite returns nothing
    local Vector3D v1 = Vector3D.createXYZ(2., 2.5, 4.)
    local Vector3D v2 = Vector3D.createXYZ(5., 3., 1.23)
    local Vector3D v3 = Vector3D.createXYZ(12.34, 23.45, -432.1)
    call suite.assertRealEquals(3109.8285, v1.tripleProductScalar(v2, v3), .01*3109.8285, "trippleProductScalar")
    call v1.destroy()
    call v2.destroy()
    call v3.destroy()
endfunction

private function vector3D_angle takes VUnitSuite suite returns nothing
    local Vector3D v1 = Vector3D.createXYZ(2., 2.5, 4.)
    local Vector3D v2 = Vector3D.createXYZ(5., 3., 1.23)
    call suite.assertRealEquals(0.746151, v1.angle(v2), .01*0.123221, "angle")
    call v1.destroy()
    call v2.destroy()
endfunction

private function vector3D_crossProduct takes VUnitSuite suite returns nothing
    local Vector3D v1 = Vector3D.createXYZ(2., 2.5, 4.)
    local Vector3D v2 = Vector3D.createXYZ(5., 3., 1.23)
    call v1.crossProduct(v2)
    call suite.assertRealEquals(-8.925, v1.getX(), .01*8.925, "x")
    call suite.assertRealEquals(17.54, v1.getY(), .01*17.54, "y")
    call suite.assertRealEquals(-6.5, v1.getZ(), .01*6.5, "z")
    call v1.destroy()
    call v2.destroy()
endfunction

private function vector3D_tripleProductVector takes VUnitSuite suite returns nothing
    local Vector3D v1 = Vector3D.createXYZ(2., 2.5, 4.)
    local Vector3D v2 = Vector3D.createXYZ(5., 3., 1.23)
    local Vector3D v3 = Vector3D.createXYZ(12.34, 23.45, -432.1)
    call v1.tripleProductVector(v2, v3)
    call suite.assertRealEquals(-7426.61, v1.getX(), .01*7426.61, "x")
    call suite.assertRealEquals(-3936.7, v1.getY(), .01*3936.7, "y")
    call suite.assertRealEquals(-425.735, v1.getZ(), .01*425.735, "z")
    call v1.destroy()
    call v2.destroy()
    call v3.destroy()
endfunction

private function vector3D_projectionVector takes VUnitSuite suite returns nothing
    local Vector3D v = Vector3D.createXYZ(2., 2.5, 4.)
    local Vector3D dir = Vector3D.createXYZ(5., 3., 1.23)
    call v.projectionVector(dir)
    call suite.assertRealEquals(3.156598158, v.getX(), .01*3.156598158, "x")
    call suite.assertRealEquals(1.893958895, v.getY(), .01*1.893958895, "y")
    call suite.assertRealEquals(.776523147, v.getZ(), .01*.776523147, "z")
    call v.destroy()
    call dir.destroy()
endfunction

private function vector3D_projectionPlane takes VUnitSuite suite returns nothing
    local Vector3D v = Vector3D.createXYZ(1., -3.5, 3.)
    local Vector3D normal = Vector3D.createXYZ(1.5, 2.5, -1.)
    call v.projectionPlane(normal)
    call suite.assertRealEquals(2.618421053, v.getX(), .01*2.618421053, "x")
    call suite.assertRealEquals(-.802631579, v.getY(), .01*.802631579, "y")
    call suite.assertRealEquals(1.921052632, v.getZ(), .01*1.921052632, "z")
    call v.destroy()
    call normal.destroy()
endfunction

private function vector3D_unit takes VUnitSuite suite returns nothing
    local Vector3D v = Vector3D.createXYZ(4., 3., 5.)
    call v.unit()
    call suite.assertRealEquals(4./7.0711, v.getX(), .001, "x")
    call suite.assertRealEquals(3./7.0711, v.getY(), .001, "y")
    call suite.assertRealEquals(5./7.0711, v.getZ(), .001, "z")
    call v.destroy()
endfunction

private function vector3D_invert takes VUnitSuite suite returns nothing
    local Vector3D v = Vector3D.createXYZ(42., -24., 2.3)
    call v.invert()
    call suite.assertRealEquals(-42., v.getX(), .001, "x")
    call suite.assertRealEquals(24., v.getY(), .001, "y")
    call suite.assertRealEquals(-2.3, v.getZ(), .001, "z")
    call v.destroy()
endfunction

private function vector3D_scale takes VUnitSuite suite returns nothing
    local Vector3D v = Vector3D.createXYZ(-42., 24., 1.5)
    call v.scale(-.25)
    call suite.assertRealEquals(10.5, v.getX(), .001, "x")
    call suite.assertRealEquals(-6., v.getY(), .001, "y")
    call suite.assertRealEquals(-.375, v.getZ(), .001, "z")
    call v.destroy()
endfunction

private function vector3D_rotate takes VUnitSuite suite returns nothing
    local Vector3D v = Vector3D.createXYZ(1.5, 2., -2.5)
    local Vector3D axis = Vector3D.createXYZ(0., 0., 123.)
    call v.rotate(axis, .5*3.1416)
    call suite.assertRealEquals(-2., v.getX(), .001, "x")
    call suite.assertRealEquals(1.5, v.getY(), .001, "y")
    call suite.assertRealEquals(-2.5, v.getZ(), .001, "z")
    call v.destroy()
    call axis.destroy()
endfunction

private function vector3D_add takes VUnitSuite suite returns nothing
    local Vector3D v1 = Vector3D.createXYZ(12.101, 34.123, .123)
    local Vector3D v2 = Vector3D.createXYZ(56.303, -78.22, .321)
    call v1.add(v2)
    call suite.assertRealEquals(68.404, v1.getX(), .001, "x")
    call suite.assertRealEquals(-44.097, v1.getY(), .001, "y")
    call suite.assertRealEquals(.444, v1.getZ(), .001, "z")
    call v1.destroy()
    call v2.destroy()
endfunction

private function vector3D_sub takes VUnitSuite suite returns nothing
    local Vector3D v1 = Vector3D.createXYZ(342.23, -54.2, .123)
    local Vector3D v2 = Vector3D.createXYZ(-948.3, 84., .321)
    call v1.sub(v2)
    call suite.assertRealEquals(1290.53, v1.getX(), .001, "x")
    call suite.assertRealEquals(-138.2, v1.getY(), .001, "y")
    call suite.assertRealEquals(-.198, v1.getZ(), .001, "z")
    call v1.destroy()
    call v2.destroy()
endfunction

private function vector3D_addXYZ takes VUnitSuite suite returns nothing
    local Vector3D v = Vector3D.createXYZ(12.101, 34.123, .123)
    call v.addXYZ(56.303, -78.22, .321)
    call suite.assertRealEquals(68.404, v.getX(), .001, "x")
    call suite.assertRealEquals(-44.097, v.getY(), .001, "y")
    call suite.assertRealEquals(.444, v.getZ(), .001, "z")
    call v.destroy()
endfunction

private function vector3D_subXYZ takes VUnitSuite suite returns nothing
    local Vector3D v = Vector3D.createXYZ(342.23, -54.2, .123)
    call v.subXYZ(-948.3, 84., .321)
    call suite.assertRealEquals(1290.53, v.getX(), .001, "x")
    call suite.assertRealEquals(-138.2, v.getY(), .001, "y")
    call suite.assertRealEquals(-.198, v.getZ(), .001, "z")
    call v.destroy()
endfunction

private function ini takes nothing returns nothing
    //suites
    local VUnitSuite vector2D = VUnitSuite.create("Vector2D")
    local VUnitSuite vector3D = VUnitSuite.create("Vector3D")
    //Vector2D
    call vector2D.addTest(vector2D_createNull, "createNull")
    call vector2D.addTest(vector2D_createXY, "createXY")
    call vector2D.addTest(vector2D_create, "create")
    call vector2D.addTest(vector2D_createDM, "createDM")
    call vector2D.addTest(vector2D_getDir, "getDir")
    call vector2D.addTest(vector2D_getMag, "getMag")
    call vector2D.addTest(vector2D_setDir, "setDir")
    call vector2D.addTest(vector2D_setMag, "setMag")
    call vector2D.addTest(vector2D_dotProduct, "dotProduct")
    call vector2D.addTest(vector2D_angle, "angle")
    call vector2D.addTest(vector2D_unit, "unit")
    call vector2D.addTest(vector2D_flip, "flip")
    call vector2D.addTest(vector2D_invert, "invert")
    call vector2D.addTest(vector2D_scale, "scale")
    call vector2D.addTest(vector2D_add, "add")
    call vector2D.addTest(vector2D_sub, "sub")
    call vector2D.addTest(vector2D_addXY, "addXY")
    call vector2D.addTest(vector2D_subXY, "subXY")
    call vector2D.addTest(vector2D_addDM, "addDM")
    call vector2D.addTest(vector2D_subDM, "subDM")
    //Vector3D
    call vector3D.addTest(vector3D_createNull, "createNull")
    call vector3D.addTest(vector3D_createXYZ, "createXYZ")
    call vector3D.addTest(vector3D_create, "create")
    call vector3D.addTest(vector3D_getMag, "getMag")
    call vector3D.addTest(vector3D_setMag, "setMag")
    call vector3D.addTest(vector3D_dotProduct, "dotProduct")
    call vector3D.addTest(vector3D_tripleProductScalar, "tripleProductScalar")
    call vector3D.addTest(vector3D_angle, "angle")
    call vector3D.addTest(vector3D_crossProduct, "crossProduct")
    call vector3D.addTest(vector3D_tripleProductVector, "tripleProductVector")
    call vector3D.addTest(vector3D_projectionVector, "projectionVector")
    call vector3D.addTest(vector3D_projectionPlane, "projectionPlane")
    call vector3D.addTest(vector3D_unit, "unit")
    call vector3D.addTest(vector3D_invert, "invert")
    call vector3D.addTest(vector3D_scale, "scale")
    call vector3D.addTest(vector3D_rotate, "rotate")
    call vector3D.addTest(vector3D_add, "add")
    call vector3D.addTest(vector3D_sub, "sub")
    call vector3D.addTest(vector3D_addXYZ, "addXYZ")
    call vector3D.addTest(vector3D_subXYZ, "subXYZ")
    //run
    call TriggerSleepAction(0)
    call vector2D.run()
    call vector3D.run()
    call vector2D.destroy()
    call vector3D.destroy()
endfunction

endlibrary


http://krainert.com/content/vectors/
 
You're missing operations like cross product and rotations. Also, you're missing stuff like checking if 2 vectors are perpendicular and finding a perpendicular vector.

It's good that you included unit vectors =D.



Also, Vector 2D and Vector 3D should be separate resources. It doesn't make sense to include both in the same lib... they are different structures. It's like creating a Tree library and including lots and lots of trees ;\.
 

krainert

Member
Frankly I have no idea how to calculate cross products, rotations, and perpendicularity, but if you'll supply a formula I'll stuff it into the code.

Regarding the unification of Vector2D and Vector3D into the same library it's due to their tight relations; there are several methods converting from one to the other, and splitting up the library would probably result in some pretty messy code.
 

NoobImbaPro

You can change this now in User CP.
I think vectors don't help you that much, unless you don't know maths :p


"http://en.wikipedia.org/wiki/Pythagoras_theorem"
And this is the theorem of theorems, and you should know how to calculate these kind of stuff
 

krainert

Member
I probably won't spend time on some of the more advanced functions, but you're free to contribute.
EDIT: NoobImbaPro, why wouldn't vectors be useful to one with skills in math?
Also EDIT: It should be pretty easy to expand the classes as they are now, and I don't need fancy stuff like cross product for what I'm building now - hence why I hesitate to spend time on implementing it at present.
 

NoobImbaPro

You can change this now in User CP.
If I know maths well, I just won't need your snippet, I don't say that this snippet is awful or something similar but I mean it will help few
Or everything I say above is totally wrong by taking for granted that programmers don't know math.

If I know maths (geometry + algebra) I know how to make them, and do it faster than writing your functions.
You organize them well, as If I make a mistake to know what part of it is wrong rather than searching many lines.
But you just cut off the knowledge, as most now will use your functions rather than getting on the procedure that will train their minds.
That's all, but don't give up, keep in mind that guys/gals need advanced things, the easy ones do not grant attention.

EDIT: I understand you, it may be helpful to refresh your knowledge but there is the word "but" yet.
 

Bribe

vJass errors are legion
JASS:
//
    method operator [] takes integer key returns real
        if key == 0 then
            return x
        elseif key == 1 then
            return y
        else
            return z
        endif
    endmethod
    
    method operator []= takes integer key, real value returns nothing
        if key == 0 then
            set .x = value
        elseif key == 1 then
            set .y = value
        else
            set .z = value
        endif
    endmethod


These methods couldn't be more useless. Not only are they harder to read
than this.x, this.y or this.z, they would be slower and also add bulk to the
script because they are non-inlining methods.
 

krainert

Member
NoobImbaPro: Apparently we differ greatly in our approach to software architecture :)

Bribe: I agree, but someone requested the functionality, and I figured I might as well implement it.
 

NoobImbaPro

You can change this now in User CP.
I know man All I wanted to say is that you should implement advanced stuff.


Also check this out:
JASS:
method operator [] takes integer key returns real
    if key == 0 then
        return x
    else
        return y
    endif
endmethod
    
method operator []= takes integer key, real value returns nothing
    if key == 0 then
        set .x = value
    else
        set .y = value
    endif
endmethod

//kill above operators

//Better?
set MyLocalVector.x = 15
//Than:
set MyLocalVector[0]=15
//Why you put the variable key?
 

Bribe

vJass errors are legion
I'm not sure why someone would request something so useless, but it's not
worth implementing.
 

krainert

Member
In the response to the operator overriding issue...

Here are some potential arguments against implementing (for removing) them:
- (Saves space)
- (Prevents the use of less efficient code)

And some potential arguments for implementing (against removing) them:
- Response: Space saved is negligible and virtually irrelevant
- Response: A user aiming at highly efficient code should investigate the library to find the best possible method anyway, and a user unable to realize the ineffectiveness of using the overridden operators most likely will not have been able to produce fast code in the first place
- Principal: A vector is an array, and thus it should follow the example of array access and mutation
- Pragmatic: One might hypothetically need to perform calculations on which coordinate to access or mutate, and in those cases the built-in operators could save some time and effort
- Pragmatic: One might previously have used simple arrays and then moved on to use a vector library due to a need of built-in functionality in which case the ability to quickly and superficially perform the conversion without immediately replacing every index with variables might ease the process

Based on the above, removing the functionality will result in an insignificantly minor decrease in space requirements at an undecidable cost. Hence, I choose to leave it.

With regard to the issue of implementing more advanced functionality: I may have a look at it once my schedule allows it. Most likely I will simply run through Anitarf's library and build my methods based on his (thanks, Anitarf :)).
 

Bribe

vJass errors are legion
In structs, you need to use top-to-bottom parsing to avoid trigger evaluations.

JASS:
method a...
    call .b() //Bad! Creates a trigger evaluation
method b...
 

krainert

Member
Version 3.0

Vectors updated to 3.0.
The API has changed almost entirely so the easiest thing to do is probably consider this a whole new library.
Perhaps most notably, all accessor methods for basic operations (e.g. unit, scale, add, sub) have been removed, and the "m" prefix on corresponding mutator methods have been omitted so that, for example, unit now mutates the vector into a unit vector with the same direction. All of these new mutator methods return the result of the operation.
Why this change? Because vJass does not feature automated garbage collection, and using non-primitive accessor methods yields considerable amounts of objects for later cleanup. Consequently, the previous accessor methods resulted in excessive amounts of tedious manual object maintenance and destruction.
Note that advanced properties (e.g. crossProduct, trippleScalarProduct, projectionVector) are still implemented as accessor methods.
Accumulative operations and operator overloading have been removed; the former were hardly standard vector functionality and can easily be achieved using the new API anyway, and the latter was of little use and either somewhat counter-intuitive or technically inefficient.
Note that several other changes have been introduced in the library but omitted in this summary.
 

Sgqvur

FullOfUltimateTruthsAndEt ernalPrinciples, i.e shi
Can someone explain to me this method

JASS:
    static method createTerrainNormal takes real x, real y, real sampleRadius returns Vector3D
        local Vector3D v = Vector3D.allocate()
        local real zx
        local real zy
        local location loc = Location(0.0, 0.0)
        call MoveLocation(loc, x-sampleRadius, y)
        set zx = GetLocationZ(loc)
        call MoveLocation(loc, x+sampleRadius, y)
        set zx = zx-GetLocationZ(loc)
        call MoveLocation(loc, x, y-sampleRadius)
        set zy = GetLocationZ(loc)
        call MoveLocation(loc, x, y+sampleRadius)
        set zy = zy-GetLocationZ(loc)
        set sampleRadius = 2*sampleRadius
        set v.x = zx*sampleRadius
        set v.y = zy*sampleRadius
        set v.z = sampleRadius*sampleRadius
        return v
    endmethod


Is this the same thing as calculating a "surface normal"? Why isn't the resultant vector normalized? What's with the v.z = sampleRadius*sampleRadius? =)
 
General chit-chat
Help Users
  • No one is chatting at the moment.
  • Ghan Ghan:
    Test!
  • tom_mai78101 tom_mai78101:
    I must be in a test server.
  • tom_mai78101 tom_mai78101:
    Nice, Twitter tweets embedding now works
  • Wizard Wizard:
    Yup.
  • Ghan Ghan:
    Excellent.
  • Ghan Ghan:
    @tom_mai78101 Hello there.
  • Ghan Ghan:
    Tagging works in the chat too.
  • tom_mai78101 tom_mai78101:
    @Ghan Missed it.
  • Wizard Wizard:
    Still fixing things here and there. Added widgets to the portal, will make it match the ones here on the forum index tomorrow.
  • Ghan Ghan:
    The venerable World Editor Tutorials site has been converted to HTTPS at last.
  • jonas jonas:
    cool
  • jonas jonas:
    and I can even edit my messages, nice
  • seph ir oth seph ir oth:
    GENERAL CHIT CHAT, YOU ARE A BOLD ONE
  • Ghan Ghan:
    Hello there
  • The Helper The Helper:
    this new chatbox is great and the forum software update is great too
    +1
  • The Helper The Helper:
    upgrade has fixed forum registration spam problem
  • tom_mai78101 tom_mai78101:
    Something tells me we might be able to customize the chatbox a bit, considering that there's a gap under every message.
  • Wizard Wizard:
    Going to deploy a fix soon, just had to take some time for myself this weekend.
  • Varine Varine:
    Unbelievable. Time for yourself? How dare you!
  • Wizard Wizard:
    xD
  • tom_mai78101 tom_mai78101:
    Hm, it is now harder to type anything on an Android phone. Pressing Backspace or Enter keys will dismiss the Android keyboard for some reasons.
  • tom_mai78101 tom_mai78101:
    Just noticed there's a delay of at least 2 minutes before each post. Guess I can't post Headline News quickly as I used to.
  • tom_mai78101 tom_mai78101:
    As far as I can tell, there are definitely things I need to get accustomed to first.
  • Varine Varine:
    FCC is cracking down recently

    Staff online

    • Ghan
      Administrator - Servers are fun

    Members online

    Affiliates

    Hive Workshop
    Top