-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit e3fc602
Showing
6 changed files
with
171 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
.DS_Store | ||
*.swp | ||
.gitignore.swp | ||
bin/ | ||
__/ | ||
doc/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
version = "0.1" | ||
license = "GPL" | ||
package = "sci" | ||
title = "Scientific and Mathematical Functions" | ||
date = "10 August 2015" | ||
authors = "Gilberto Camara" | ||
contact = "[email protected]" | ||
content = "Implements useful mathematical functions" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
if not isLoaded("sci") then | ||
import("sci") | ||
end | ||
|
||
if not isLoaded("sysdyn") then | ||
import("sysdyn") | ||
end | ||
|
||
|
||
-- relation btw | ||
waterSurface = Spline { | ||
points = { {x = 0, y = 0}, {x = 1000, y = 24.7}, | ||
{x = 2000, y = 35.3}, {x = 3000, y = 48.6}, | ||
{x = 4000, y = 54.3}, {x = 5000, y = 57.2}, | ||
{x = 6000, y = 61.6}, {x = 7000, y = 66.0}, | ||
{x = 8000, y = 69.9} }, | ||
steps = 1 | ||
} | ||
|
||
spline = SysDynModel { | ||
data = 0.0, | ||
surface = 0.0, | ||
finalTime = 80, | ||
|
||
changes = function (model, time) | ||
model.surface = waterSurface:value (100*time) | ||
model.data = waterSurface:value (1000*math.floor (time/10)) | ||
end, | ||
|
||
graphics = { timeseries = { {"surface", "data"}}} | ||
} | ||
|
||
spline:execute() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
files = { | ||
"Spline.lua" | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
|
||
local buildSpline = function (self) | ||
-- build a Catmull-Roll spline | ||
local points = self.points | ||
local steps = self.steps or 10 | ||
|
||
local values = {} | ||
|
||
local px = nil | ||
local py = nil | ||
|
||
if #points < 3 then | ||
return points | ||
end | ||
local count = #points - 1 | ||
local p0, p1, p2, p3, x, y | ||
|
||
for i = 1, count do | ||
if i == 1 then | ||
p0, p1, p2, p3 = points[i], points[i], points[i + 1], points[i + 2] | ||
elseif i == count then | ||
p0, p1, p2, p3 = points[#points - 2], points[#points - 1], points[#points], points[#points] | ||
else | ||
p0, p1, p2, p3 = points[i - 1], points[i], points[i + 1], points[i + 2] | ||
end | ||
-- interpolate "step" new points btw two data points | ||
for t = 0, 1, 1 / steps do | ||
local x = 0.5 * ( ( 2 * p1.x ) + ( p2.x - p0.x ) * t + ( 2 * p0.x - 5 * p1.x + 4 * p2.x - p3.x ) * t * t + ( 3 * p1.x - p0.x - 3 * p2.x + p3.x ) * t * t * t ) | ||
local y = 0.5 * ( ( 2 * p1.y ) + ( p2.y - p0.y ) * t + ( 2 * p0.y - 5 * p1.y + 4 * p2.y - p3.y ) * t * t + ( 3 * p1.y - p0.y - 3 * p2.y + p3.y ) * t * t * t ) | ||
|
||
--prevent duplicate entries | ||
if (next (values) == nil) then -- table is empty, insert first point | ||
table.insert(values, { x = x , y = y }) | ||
else if (values[#values].x ~= x and values[#values].y ~= y) then | ||
table.insert(values, { x = x , y = y }) | ||
end | ||
end | ||
end | ||
end | ||
|
||
return values | ||
end | ||
|
||
Spline_ = { | ||
type_ = "Spline", | ||
--- Returns the value of the spline for a given value. | ||
-- @arg t A number value. | ||
-- @usage spline:value(5) | ||
value = function(self, t) | ||
local iStart, iEnd, iMid = 1, #self.values, 0 | ||
local found = false | ||
|
||
verify(self.values[iEnd].x >= t, " values outside range - last value is smaller that requested") | ||
verify(self.values[iStart].x <= t, " values outside range - first value is bigger than requested") | ||
|
||
while not found do | ||
iMid = math.floor((iStart+iEnd)/2) | ||
if self.values[iMid].x == t then | ||
return self.values[iMid].y | ||
else if self.values[iMid].x < t then | ||
if self.values[iMid+1].x < t then | ||
iStart = iMid | ||
else | ||
found = true | ||
local w = ( t - self.values[iMid].x) / (self.values[iMid +1].x - self.values[iMid].x) | ||
return (1 - w)*self.values[iMid].y + w*self.values[iMid +1].y | ||
end | ||
else -- self.values[iMid].x > t | ||
iEnd = iMid | ||
end | ||
end | ||
end | ||
end | ||
} | ||
|
||
metaTableSpline_ = {__index = Spline_} | ||
|
||
--- Build a Catmull-Roll spline from a set of points and returns interpolated value. | ||
-- @arg argv.points the set of x-ordered points in format { { x = x0, y = y0 }, { x = x1, y = y1 }, ....} | ||
-- @arg argv.steps how many points to interpolate btw two data points. Default is 10. | ||
-- @usage spl = Spline {points = { { x = x0, y = y0 },, ....}, steps = 10} | ||
function Spline(argv) | ||
mandatoryTableArgument(argv, "points", "table") | ||
defaultTableValue(argv, "steps", 10) | ||
|
||
setmetatable(argv, metaTableSpline_) | ||
|
||
argv.values = buildSpline(argv) | ||
|
||
return argv | ||
end | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
-- Test file for Spline.lua | ||
-- Author: Gilberto Camara | ||
|
||
return{ | ||
Spline = function(unitTest) | ||
local waterSurface = Spline { | ||
points = { {x = 0, y = 0}, {x = 1000, y = 24.7}, | ||
{x = 2000, y = 35.3}, {x = 3000, y = 48.6}, | ||
{x = 4000, y = 54.3}, {x = 5000, y = 57.2}, | ||
{x = 6000, y = 61.6}, {x = 7000, y = 66.0}, | ||
{x = 8000, y = 69.9} } | ||
} | ||
|
||
unitTest:assertType(waterSurface, "Spline") | ||
end, | ||
value = function(unitTest) | ||
local waterSurface = Spline { | ||
points = { {x = 0, y = 0}, {x = 1000, y = 24.7}, | ||
{x = 2000, y = 35.3}, {x = 3000, y = 48.6}, | ||
{x = 4000, y = 54.3}, {x = 5000, y = 57.2}, | ||
{x = 6000, y = 61.6}, {x = 7000, y = 66.0}, | ||
{x = 8000, y = 69.9} } | ||
} | ||
|
||
unitTest:assertEquals(waterSurface:value(1500), 30.7125, 0.0001) | ||
end, | ||
} | ||
|