-
Notifications
You must be signed in to change notification settings - Fork 0
/
Function.lua
144 lines (114 loc) · 3.15 KB
/
Function.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
local Function = {}
-----------------------------------------------
--[[ Auxiliary functions ]]--
-----------------------------------------------
local function distance(P, Q)
local dx = P.x - Q.x
local dy = P.y - Q.y
return math.sqrt( dx ^ 2 + dy ^ 2 )
end
local function evaluate(expression)
return load("return " .. expression)()
end
local function treat_expression(pretty_exp)
local math_exp
math_exp = pretty_exp:gsub("sin", "math.sin")
math_exp = math_exp:gsub("cos", "math.cos")
math_exp = math_exp:gsub("tan", "math.tan")
math_exp = math_exp:gsub("sqrt", "math.sqrt")
math_exp = math_exp:gsub("abs", "math.abs")
math_exp = math_exp:gsub("exp", "math.exp")
math_exp = math_exp:gsub("ln", "math.log")
math_exp = math_exp:gsub("log", "math.log10")
math_exp = math_exp:gsub("pow", "math.pow")
math_exp = math_exp:gsub("PI", "math.pi")
return math_exp
end
local function is_number(n)
if n ~= 1/0 and n ~= -1/0 and n == n and n ~= nil then
return true
end
return false
end
local function apply_to_self(self, value)
local exp = self.mathExp:gsub("x", value)
return evaluate(exp)
end
local function translate_graph(graph, vector)
local new_graph = {}
for i = 1, #graph do
new_graph[i] =
{
x = graph[i].x + vector.x,
y = graph[i].y + vector.y
}
end
return new_graph
end
local function scale_graph(graph, factor)
local new_graph = {}
setmetatable(new_graph, { __add = translate_graph })
for i = 1, #graph do
new_graph[i] =
{
x = graph[i].x * factor,
y = graph[i].y * -factor
}
end
return new_graph
end
-----------------------------------------------
--[[ Class Methods ]]--
-----------------------------------------------
Function.New = function (pretty_exp, mode)
local o = {}
setmetatable(o, { __index = Function, __call = apply_to_self })
o.prettyExp = pretty_exp or "x"
o.mode = mode or "cartesian"
o.mathExp = treat_expression(pretty_exp)
return o
end
-----------------------------------------------
--[[ Object Methods ]]--
-----------------------------------------------
Function.computeCartesianGraph = function (self)
for i, xi in pairs(self.domain) do
local P = { x = xi, y = self(xi) }
self.graph[i] = P
end
end
Function.computePolarGraph = function (self)
for _, theta in pairs(self.domain) do
local ro = self(theta)
local P = { x = ro*math.cos(theta), y = ro*math.sin(theta) }
table.insert(self.graph, P)
end
end
Function.computeGraph = function (self)
self.graph = {}
setmetatable(self.graph, { __mul = scale_graph })
if self.mode == "cartesian" then
self:computeCartesianGraph()
elseif self.mode == "polar" then
self:computePolarGraph()
end
end
Function.computeCOM = function (self)
local Sxdl, Sydl, L = 0, 0, 0
local graph = self.graph
local n = #graph - 1
for i = 1, n do
local P = graph[i]
local Q = graph[i + 1]
if is_number(P.y) and is_number(Q.y) then
local dLi = distance(P, Q)
local xmi = (P.x + Q.x) / 2
local ymi = (P.y + Q.y) / 2
L = L + dLi
Sxdl = Sxdl + (xmi * dLi)
Sydl = Sydl + (ymi * dLi)
end
end
self.com = { x = Sxdl/L, y = Sydl/L }
end
return Function