Current File : //usr/share/texlive/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/deprecated/Vector.lua |
-- Copyright 2012 by Till Tantau
--
-- This file may be distributed an/or modified
--
-- 1. under the LaTeX Project Public License and/or
-- 2. under the GNU Public License
--
-- See the file doc/generic/pgf/licenses/LICENSE for more information
-- @release $Header$
--- Vector class
--
-- This class augments a normal array so that:
--
-- 1) Several functions like "plus" or "normalize" become available.
-- 2) You can access the ".x" and ".y" fields to get the fields [1] and [2].
local Vector = {}
-- Namespace:
local lib = require "pgf.gd.lib"
lib.Vector = Vector
-- Class setup
Vector.__index =
function (t, k)
if k == "x" then
return rawget(t,1)
elseif k == "y" then
return rawget(t,2)
else
return rawget(Vector,k)
end
end
Vector.__newindex =
function (t, k, v)
if k == "x" then
rawset(t,1,v)
elseif k == "y" then
rawset(t,2,v)
else
rawset(t,k,v)
end
end
--- Creates a new vector with \meta{n} values using an optional \meta{fill\_function}.
--
-- @param n The number of elements of the vector. (If omitted, then 2.)
-- @param fill_function Optional function that takes a number between 1 and \meta{n}
-- and is expected to return a value for the corresponding element
-- of the vector. If omitted, all elements of the vector will
-- be initialized with 0.
--
-- @return A newly-allocated vector with \meta{n} elements.
--
function Vector.new(n, fill_function)
-- create vector
local vector = { }
setmetatable(vector, Vector)
local n = n or 2
if type(n) == 'table' then
for k,v in pairs(n) do
vector[k] = v
end
else
-- fill vector elements with values
if not fill_function then
for i = 1,n do
rawset(vector,i,0)
end
else
for i = 1,n do
rawset(vector,i,fill_function(i))
end
end
end
return vector
end
--- Creates a copy of the vector that holds the same elements as the original.
--
-- @return A newly-allocated copy of the vector holding exactly the same elements.
--
function Vector:copy()
return Vector.new(#self, function (n) return self[n] end)
end
--- Performs a vector addition and returns the result in a new vector.
--
-- @param other The vector to add.
--
-- @return A new vector with the result of the addition.
--
function Vector:plus(other)
assert(#self == #other)
return Vector.new(#self, function (n) return self[n] + other[n] end)
end
--- Subtracts two vectors and returns the result in a new vector.
--
-- @param other Vector to subtract.
--
-- @return A new vector with the result of the subtraction.
--
function Vector:minus(other)
assert(#self == #other)
return Vector.new(#self, function (n) return self[n] - other[n] end)
end
--- Divides a vector by a scalar value and returns the result in a new vector.
--
-- @param scalar Scalar value to divide the vector by.
--
-- @return A new vector with the result of the division.
--
function Vector:dividedByScalar(scalar)
return Vector.new(#self, function (n) return self[n] / scalar end)
end
--- Multiplies a vector by a scalar value and returns the result in a new vector.
--
-- @param scalar Scalar value to multiply the vector with.
--
-- @return A new vector with the result of the multiplication.
--
function Vector:timesScalar(scalar)
return Vector.new(#self, function (n) return self[n] * scalar end)
end
--- Performs the dot product of two vectors and returns the result in a new vector.
--
-- @param other Vector to perform the dot product with.
--
-- @return A new vector with the result of the dot product.
--
function Vector:dotProduct(other)
assert(#self == #other)
local product = 0
for n = 1,#self do
product = product + self[n] * other[n]
end
return product
end
--- Computes the Euclidean norm of the vector.
--
-- @return The Euclidean norm of the vector.
--
function Vector:norm()
return math.sqrt(self:dotProduct(self))
end
--- Normalizes the vector and returns the result in a new vector.
--
-- @return Normalized version of the original vector.
--
function Vector:normalized()
local norm = self:norm()
if norm == 0 then
return Vector.new(#self)
else
return self:dividedByScalar(self:norm())
end
end
--- Updates the values of the vector in-place.
--
-- @param update_function A function that is called for each element of the
-- vector. The elements are replaced by the values
-- returned from this function.
--
function Vector:update(update_function)
for i=1,#self do
self[i] = update_function(self[i])
end
end
--- Limits all elements of the vector in-place.
--
-- @param limit_function A function that is called for each index/element
-- pair. It is supposed to return minimum and maximum
-- values for the element. The element is then clamped
-- to these values.
--
function Vector:limit(limit_function)
for i=1,#self do
local min, max = limit_function(i, self[i])
self[i] = math.max(min, math.min(max, value))
end
end
--- Tests whether all elements of two vectors are the same
--
-- @param other The other vector
--
-- @return true or false
--
function Vector:equals(other)
if #self ~= #other then
return false
end
for n = 1, #self do
if self[n] ~= other[n] then
return false
end
end
return true
end
function Vector:__tostring()
return '(' .. table.concat(self, ', ') .. ')'
end
-- Done
return Vector