switching from breezefield to windfield because of the documentation
This commit is contained in:
68
deps/breezefield/collider.lua
vendored
68
deps/breezefield/collider.lua
vendored
@@ -1,68 +0,0 @@
|
||||
-- a Collider object, wrapping shape, body, and fixtue
|
||||
local set_funcs, lp, lg, COLLIDER_TYPES = unpack(require("deps.breezefield.utils")) -- it me who put deps.breezefield
|
||||
|
||||
local Collider = {}
|
||||
Collider.__index = Collider
|
||||
|
||||
|
||||
|
||||
function Collider.new(world, collider_type, ...)
|
||||
-- deprecated
|
||||
return world:newCollider(collider_type, {...})
|
||||
end
|
||||
|
||||
function Collider:draw_type()
|
||||
if self.collider_type == 'Edge' or self.collider_type == 'Chain' then
|
||||
return 'line'
|
||||
end
|
||||
return self.collider_type:lower()
|
||||
end
|
||||
|
||||
function Collider:__draw__()
|
||||
self._draw_type = self._draw_type or self:draw_type()
|
||||
local args
|
||||
if self._draw_type == 'line' then
|
||||
args = {self:getSpatialIdentity()}
|
||||
else
|
||||
args = {'line', self:getSpatialIdentity()}
|
||||
end
|
||||
love.graphics[self:draw_type()](unpack(args))
|
||||
end
|
||||
|
||||
function Collider:draw()
|
||||
self:__draw__()
|
||||
end
|
||||
|
||||
|
||||
function Collider:destroy()
|
||||
self._world.colliders[self] = nil
|
||||
self.fixture:setUserData(nil)
|
||||
self.fixture:destroy()
|
||||
self.body:destroy()
|
||||
end
|
||||
|
||||
function Collider:getSpatialIdentity()
|
||||
if self.collider_type == 'Circle' then
|
||||
return self:getX(), self:getY(), self:getRadius()
|
||||
else
|
||||
return self:getWorldPoints(self:getPoints())
|
||||
end
|
||||
end
|
||||
|
||||
function Collider:collider_contacts()
|
||||
local contacts = self:getContacts()
|
||||
local colliders = {}
|
||||
for i, contact in ipairs(contacts) do
|
||||
if contact:isTouching() then
|
||||
local f1, f2 = contact:getFixtures()
|
||||
if f1 == self.fixture then
|
||||
colliders[#colliders+1] = f2:getUserData()
|
||||
else
|
||||
colliders[#colliders+1] = f1:getUserData()
|
||||
end
|
||||
end
|
||||
end
|
||||
return colliders
|
||||
end
|
||||
|
||||
return Collider
|
||||
24
deps/breezefield/init.lua
vendored
24
deps/breezefield/init.lua
vendored
@@ -1,24 +0,0 @@
|
||||
-- breezefield: init.lua
|
||||
--[[
|
||||
implements Collider and World objects
|
||||
Collider wraps the basic functionality of shape, fixture, and body
|
||||
World wraps world, and provides automatic drawing simplified collisions
|
||||
]]--
|
||||
|
||||
|
||||
|
||||
local bf = {}
|
||||
|
||||
local BASE = (...) .. "."
|
||||
local Collider = require(BASE .. 'collider')
|
||||
local World = require(BASE .. 'world')
|
||||
|
||||
|
||||
function bf.newWorld(...)
|
||||
return bf.World:new(...)
|
||||
end
|
||||
|
||||
bf.Collider = Collider
|
||||
bf.World = World
|
||||
|
||||
return bf
|
||||
32
deps/breezefield/utils.lua
vendored
32
deps/breezefield/utils.lua
vendored
@@ -1,32 +0,0 @@
|
||||
-- function used for both
|
||||
local function set_funcs(mainobject, subobject)
|
||||
-- this function assigns functions of a subobject to a primary object
|
||||
--[[
|
||||
mainobject: the table to which to assign the functions
|
||||
subobject: the table whose functions to assign
|
||||
no output
|
||||
--]]
|
||||
for k, v in pairs(subobject.__index) do
|
||||
if k ~= '__gc' and k ~= '__eq' and k ~= '__index'
|
||||
and k ~= '__tostring' and k ~= 'destroy' and k ~= 'type'
|
||||
and k ~= 'typeOf'and k ~= 'getUserData' and k ~= 'setUserData' then
|
||||
mainobject[k] = function(mainobject, ...)
|
||||
return v(subobject, ...)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local COLLIDER_TYPES = {
|
||||
CIRCLE = "Circle",
|
||||
CIRC = "Circle",
|
||||
RECTANGLE = "Rectangle",
|
||||
RECT = "Rectangle",
|
||||
POLYGON = "Polygon",
|
||||
POLY = "Polygon",
|
||||
EDGE = 'Edge',
|
||||
CHAIN = 'Chain'
|
||||
}
|
||||
|
||||
|
||||
return {set_funcs, love.physics, love.graphics, COLLIDER_TYPES}
|
||||
238
deps/breezefield/world.lua
vendored
238
deps/breezefield/world.lua
vendored
@@ -1,238 +0,0 @@
|
||||
-- breezefield: World.lua
|
||||
--[[
|
||||
World: has access to all the functions of love.physics.world
|
||||
additionally stores all Collider objects assigned to it in
|
||||
self.colliders (as key-value pairs)
|
||||
can draw all its Colliders
|
||||
by default, calls :collide on any colliders in it for postSolve
|
||||
or for beginContact if the colliders are sensors
|
||||
--]]
|
||||
-- TODO make updating work from here too
|
||||
-- TODO: update test and tutorial
|
||||
local Collider = require('deps.breezefield.collider') -- it me who put deps.breezefield
|
||||
local set_funcs, lp, lg, COLLIDER_TYPES = unpack(require("deps.breezefield.utils")) -- it me who put deps.breezefield
|
||||
|
||||
|
||||
local World = {}
|
||||
World.__index = World
|
||||
function World:new(...)
|
||||
-- create a new physics world
|
||||
--[[
|
||||
inputs: (same as love.physics.newWorld)
|
||||
xg: float, gravity in x direction
|
||||
yg: float, gravity in y direction
|
||||
sleep: boolean, whether bodies can sleep
|
||||
outputs:
|
||||
w: bf.World, the created world
|
||||
]]--
|
||||
|
||||
local w = {}
|
||||
setmetatable(w, self)
|
||||
w._world = lp.newWorld(...)
|
||||
set_funcs(w, w._world)
|
||||
w.update = nil -- to use our custom update
|
||||
w.colliders = {}
|
||||
|
||||
-- some functions defined here to use w without being passed it
|
||||
|
||||
function w.collide(obja, objb, coll_type, ...)
|
||||
-- collision event for two Colliders
|
||||
local function run_coll(obj1, obj2, ...)
|
||||
if obj1[coll_type] ~= nil then
|
||||
local e = obj1[coll_type](obj1, obj2, ...)
|
||||
if type(e) == 'function' then
|
||||
w.collide_events[#w.collide_events+1] = e
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if obja ~= nil and objb ~= nil then
|
||||
run_coll(obja, objb, ...)
|
||||
run_coll(objb, obja, ...)
|
||||
end
|
||||
end
|
||||
|
||||
function w.enter(a, b, ...)
|
||||
return w.collision(a, b, 'enter', ...)
|
||||
end
|
||||
function w.exit(a, b, ...)
|
||||
return w.collision(a, b, 'exit', ...)
|
||||
end
|
||||
function w.preSolve(a, b, ...)
|
||||
return w.collision(a, b, 'preSolve', ...)
|
||||
end
|
||||
function w.postSolve(a, b, ...)
|
||||
return w.collision(a, b, 'postSolve', ...)
|
||||
end
|
||||
|
||||
function w.collision(a, b, ...)
|
||||
-- objects that hit one another can have collide methods
|
||||
-- by default used as postSolve callback
|
||||
local obja = a:getUserData(a)
|
||||
local objb = b:getUserData(b)
|
||||
w.collide(obja, objb, ...)
|
||||
end
|
||||
|
||||
w:setCallbacks(w.enter, w.exit, w.preSolve, w.postSolve)
|
||||
w.collide_events = {}
|
||||
return w
|
||||
end
|
||||
|
||||
|
||||
function World:draw(alpha, draw_over)
|
||||
-- draw the world
|
||||
--[[
|
||||
alpha: sets the alpha of the drawing, defaults to 1
|
||||
draw_over: draws the collision objects shapes even if their
|
||||
.draw method is overwritten
|
||||
--]]
|
||||
local color = {love.graphics.getColor()}
|
||||
for _, c in pairs(self.colliders) do
|
||||
love.graphics.setColor(1, 1, 1, alpha or 1)
|
||||
c:draw(alpha)
|
||||
if draw_over then
|
||||
love.graphics.setColor(1, 1, 1, alpha or 1)
|
||||
c:__draw__()
|
||||
end
|
||||
end
|
||||
love.graphics.setColor(color)
|
||||
end
|
||||
|
||||
function World:queryRectangleArea(x1, y1, x2, y2)
|
||||
-- query a bounding-box aligned area for colliders
|
||||
--[[
|
||||
inputs:
|
||||
x1, y1, x2, y2: floats, the x and y coordinates of two points
|
||||
outputs:
|
||||
colls: table, all colliders in bounding box
|
||||
--]]
|
||||
|
||||
local colls = {}
|
||||
local callback = function(fixture)
|
||||
table.insert(colls, fixture:getUserData())
|
||||
return true
|
||||
end
|
||||
self:queryBoundingBox(x1, y1, x2, y2, callback)
|
||||
return colls
|
||||
end
|
||||
|
||||
local function check_vertices(vertices)
|
||||
if #vertices % 2 ~= 0 then
|
||||
error('vertices must be a multiple of 2')
|
||||
elseif #vertices < 4 then
|
||||
error('must have at least 2 vertices with x and y each')
|
||||
end
|
||||
end
|
||||
|
||||
local function query_region(world, coll_type, args)
|
||||
local collider = world:newCollider(coll_type, args)
|
||||
collider:setSensor(true)
|
||||
world:update(0)
|
||||
local colls = collider:collider_contacts(collider)
|
||||
collider:destroy()
|
||||
return colls
|
||||
end
|
||||
|
||||
function World:queryPolygonArea(...)
|
||||
-- query an area enclosed by the lines connecting a series of points
|
||||
--[[
|
||||
inputs:
|
||||
x1, y1, x2, y2, ... floats, the x and y positions defining polygon
|
||||
outputs:
|
||||
colls: table, all Colliders intersecting the area
|
||||
--]]
|
||||
local vertices = {...}
|
||||
if type(vertices[1]) == 'table' then
|
||||
vertices = vertices[1]
|
||||
end
|
||||
check_vertices(vertices)
|
||||
return query_region(self, 'Polygon', vertices)
|
||||
end
|
||||
|
||||
function World:queryCircleArea(x, y, r)
|
||||
-- get all colliders in a circle are
|
||||
--[[
|
||||
inputs:
|
||||
x, y, r: floats, x, y and radius of circle
|
||||
outputs:
|
||||
colls: table: colliders in area
|
||||
]]--
|
||||
return query_region(self, 'Circle', {x, y, r})
|
||||
end
|
||||
|
||||
function World:queryEdgeArea(...)
|
||||
-- get all colliders along a (series of) line(s)
|
||||
--[[
|
||||
inputs:
|
||||
x1, y1, x2, y2, ... floats, the x and y positions defining lines
|
||||
outpts:
|
||||
colls: table: colliders intersecting these lines
|
||||
--]]
|
||||
local vertices = {...}
|
||||
if type(vertices[1]) == 'table' then
|
||||
vertices = vertices[1]
|
||||
end
|
||||
check_vertices(vertices)
|
||||
return query_region(self, 'Edge', vertices)
|
||||
end
|
||||
|
||||
|
||||
function World:update(dt)
|
||||
-- update physics world
|
||||
self._world:update(dt)
|
||||
for i, v in pairs(self.collide_events) do
|
||||
v()
|
||||
self.collide_events[i] = nil
|
||||
end
|
||||
end
|
||||
|
||||
--[[
|
||||
create a new collider in this world
|
||||
|
||||
args:
|
||||
collider_type (string): the type of the collider (not case seinsitive). any of:
|
||||
circle, rectangle, polygon, edge, chain.
|
||||
shape_arguments (table): arguments required to instantiate shape.
|
||||
circle: {x, y, radius}
|
||||
rectangle: {x, y, width height}
|
||||
polygon/edge/chain: {x1, y1, x2, y2, ...}
|
||||
table_to_use (optional, table): table to generate as the collider
|
||||
]]--
|
||||
function World:newCollider(collider_type, shape_arguments, table_to_use)
|
||||
|
||||
local o = table_to_use or {}
|
||||
setmetatable(o, Collider)
|
||||
-- note that you will need to set static vs dynamic later
|
||||
local _collider_type = COLLIDER_TYPES[collider_type:upper()]
|
||||
assert(_collider_type ~= nil, "unknown collider type: "..collider_type)
|
||||
collider_type = _collider_type
|
||||
if collider_type == 'Circle' then
|
||||
local x, y, r = unpack(shape_arguments)
|
||||
o.body = lp.newBody(self._world, x, y, "dynamic")
|
||||
o.shape = lp.newCircleShape(r)
|
||||
elseif collider_type == "Rectangle" then
|
||||
local x, y, w, h = unpack(shape_arguments)
|
||||
o.body = lp.newBody(self._world, x, y, "dynamic")
|
||||
o.shape = lp.newRectangleShape(w, h)
|
||||
collider_type = "Polygon"
|
||||
else
|
||||
o.body = lp.newBody(self._world, 0, 0, "dynamic")
|
||||
o.shape = lp['new'..collider_type..'Shape'](unpack(shape_arguments))
|
||||
end
|
||||
|
||||
o.collider_type = collider_type
|
||||
|
||||
o.fixture = lp.newFixture(o.body, o.shape, 1)
|
||||
o.fixture:setUserData(o)
|
||||
|
||||
set_funcs(o, o.body)
|
||||
set_funcs(o, o.shape)
|
||||
set_funcs(o, o.fixture)
|
||||
|
||||
-- index by self for now
|
||||
o._world = self
|
||||
self.colliders[o] = o
|
||||
return o
|
||||
end
|
||||
|
||||
return World
|
||||
929
deps/windfield/init.lua
vendored
Normal file
929
deps/windfield/init.lua
vendored
Normal file
@@ -0,0 +1,929 @@
|
||||
--[[
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2018 SSYGEN
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
]]--
|
||||
|
||||
local path = ... .. '.'
|
||||
local wf = {}
|
||||
wf.Math = require(path .. 'mlib.mlib')
|
||||
|
||||
World = {}
|
||||
World.__index = World
|
||||
|
||||
function wf.newWorld(xg, yg, sleep)
|
||||
local world = wf.World.new(wf, xg, yg, sleep)
|
||||
|
||||
world.box2d_world:setCallbacks(world.collisionOnEnter, world.collisionOnExit, world.collisionPre, world.collisionPost)
|
||||
world:collisionClear()
|
||||
world:addCollisionClass('Default')
|
||||
|
||||
-- Points all box2d_world functions to this wf.World object
|
||||
-- This means that the user can call world:setGravity for instance without having to say world.box2d_world:setGravity
|
||||
for k, v in pairs(world.box2d_world.__index) do
|
||||
if k ~= '__gc' and k ~= '__eq' and k ~= '__index' and k ~= '__tostring' and k ~= 'update' and k ~= 'destroy' and k ~= 'type' and k ~= 'typeOf' then
|
||||
world[k] = function(self, ...)
|
||||
return v(self.box2d_world, ...)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return world
|
||||
end
|
||||
|
||||
function World.new(wf, xg, yg, sleep)
|
||||
local self = {}
|
||||
local settings = settings or {}
|
||||
self.wf = wf
|
||||
|
||||
self.draw_query_for_n_frames = 10
|
||||
self.query_debug_drawing_enabled = false
|
||||
self.explicit_collision_events = false
|
||||
self.collision_classes = {}
|
||||
self.masks = {}
|
||||
self.is_sensor_memo = {}
|
||||
self.query_debug_draw = {}
|
||||
|
||||
love.physics.setMeter(32)
|
||||
self.box2d_world = love.physics.newWorld(xg, yg, sleep)
|
||||
|
||||
return setmetatable(self, World)
|
||||
end
|
||||
|
||||
function World:update(dt)
|
||||
self:collisionEventsClear()
|
||||
self.box2d_world:update(dt)
|
||||
end
|
||||
|
||||
function World:draw(alpha)
|
||||
-- get the current color values to reapply
|
||||
local r, g, b, a = love.graphics.getColor()
|
||||
-- alpha value is optional
|
||||
alpha = alpha or 255
|
||||
-- Colliders debug
|
||||
love.graphics.setColor(222, 222, 222, alpha)
|
||||
local bodies = self.box2d_world:getBodies()
|
||||
for _, body in ipairs(bodies) do
|
||||
local fixtures = body:getFixtures()
|
||||
for _, fixture in ipairs(fixtures) do
|
||||
if fixture:getShape():type() == 'PolygonShape' then
|
||||
love.graphics.polygon('line', body:getWorldPoints(fixture:getShape():getPoints()))
|
||||
elseif fixture:getShape():type() == 'EdgeShape' or fixture:getShape():type() == 'ChainShape' then
|
||||
local points = {body:getWorldPoints(fixture:getShape():getPoints())}
|
||||
for i = 1, #points, 2 do
|
||||
if i < #points-2 then love.graphics.line(points[i], points[i+1], points[i+2], points[i+3]) end
|
||||
end
|
||||
elseif fixture:getShape():type() == 'CircleShape' then
|
||||
local body_x, body_y = body:getPosition()
|
||||
local shape_x, shape_y = fixture:getShape():getPoint()
|
||||
local r = fixture:getShape():getRadius()
|
||||
love.graphics.circle('line', body_x + shape_x, body_y + shape_y, r, 360)
|
||||
end
|
||||
end
|
||||
end
|
||||
love.graphics.setColor(255, 255, 255, alpha)
|
||||
|
||||
-- Joint debug
|
||||
love.graphics.setColor(222, 128, 64, alpha)
|
||||
local joints = self.box2d_world:getJoints()
|
||||
for _, joint in ipairs(joints) do
|
||||
local x1, y1, x2, y2 = joint:getAnchors()
|
||||
if x1 and y1 then love.graphics.circle('line', x1, y1, 4) end
|
||||
if x2 and y2 then love.graphics.circle('line', x2, y2, 4) end
|
||||
end
|
||||
love.graphics.setColor(255, 255, 255, alpha)
|
||||
|
||||
-- Query debug
|
||||
love.graphics.setColor(64, 64, 222, alpha)
|
||||
for _, query_draw in ipairs(self.query_debug_draw) do
|
||||
query_draw.frames = query_draw.frames - 1
|
||||
if query_draw.type == 'circle' then
|
||||
love.graphics.circle('line', query_draw.x, query_draw.y, query_draw.r)
|
||||
elseif query_draw.type == 'rectangle' then
|
||||
love.graphics.rectangle('line', query_draw.x, query_draw.y, query_draw.w, query_draw.h)
|
||||
elseif query_draw.type == 'line' then
|
||||
love.graphics.line(query_draw.x1, query_draw.y1, query_draw.x2, query_draw.y2)
|
||||
elseif query_draw.type == 'polygon' then
|
||||
local triangles = love.math.triangulate(query_draw.vertices)
|
||||
for _, triangle in ipairs(triangles) do love.graphics.polygon('line', triangle) end
|
||||
end
|
||||
end
|
||||
for i = #self.query_debug_draw, 1, -1 do
|
||||
if self.query_debug_draw[i].frames <= 0 then
|
||||
table.remove(self.query_debug_draw, i)
|
||||
end
|
||||
end
|
||||
love.graphics.setColor(r, g, b, a)
|
||||
end
|
||||
|
||||
function World:setQueryDebugDrawing(value)
|
||||
self.query_debug_drawing_enabled = value
|
||||
end
|
||||
|
||||
function World:setExplicitCollisionEvents(value)
|
||||
self.explicit_collision_events = value
|
||||
end
|
||||
|
||||
function World:addCollisionClass(collision_class_name, collision_class)
|
||||
if self.collision_classes[collision_class_name] then error('Collision class ' .. collision_class_name .. ' already exists.') end
|
||||
|
||||
if self.explicit_collision_events then
|
||||
self.collision_classes[collision_class_name] = collision_class or {}
|
||||
else
|
||||
self.collision_classes[collision_class_name] = collision_class or {}
|
||||
self.collision_classes[collision_class_name].enter = {}
|
||||
self.collision_classes[collision_class_name].exit = {}
|
||||
self.collision_classes[collision_class_name].pre = {}
|
||||
self.collision_classes[collision_class_name].post = {}
|
||||
for c_class_name, _ in pairs(self.collision_classes) do
|
||||
table.insert(self.collision_classes[collision_class_name].enter, c_class_name)
|
||||
table.insert(self.collision_classes[collision_class_name].exit, c_class_name)
|
||||
table.insert(self.collision_classes[collision_class_name].pre, c_class_name)
|
||||
table.insert(self.collision_classes[collision_class_name].post, c_class_name)
|
||||
end
|
||||
for c_class_name, _ in pairs(self.collision_classes) do
|
||||
table.insert(self.collision_classes[c_class_name].enter, collision_class_name)
|
||||
table.insert(self.collision_classes[c_class_name].exit, collision_class_name)
|
||||
table.insert(self.collision_classes[c_class_name].pre, collision_class_name)
|
||||
table.insert(self.collision_classes[c_class_name].post, collision_class_name)
|
||||
end
|
||||
end
|
||||
|
||||
self:collisionClassesSet()
|
||||
end
|
||||
|
||||
function World:collisionClassesSet()
|
||||
self:generateCategoriesMasks()
|
||||
|
||||
self:collisionClear()
|
||||
local collision_table = self:getCollisionCallbacksTable()
|
||||
for collision_class_name, collision_list in pairs(collision_table) do
|
||||
for _, collision_info in ipairs(collision_list) do
|
||||
if collision_info.type == 'enter' then self:addCollisionEnter(collision_class_name, collision_info.other) end
|
||||
if collision_info.type == 'exit' then self:addCollisionExit(collision_class_name, collision_info.other) end
|
||||
if collision_info.type == 'pre' then self:addCollisionPre(collision_class_name, collision_info.other) end
|
||||
if collision_info.type == 'post' then self:addCollisionPost(collision_class_name, collision_info.other) end
|
||||
end
|
||||
end
|
||||
|
||||
self:collisionEventsClear()
|
||||
end
|
||||
|
||||
function World:collisionClear()
|
||||
self.collisions = {}
|
||||
self.collisions.on_enter = {}
|
||||
self.collisions.on_enter.sensor = {}
|
||||
self.collisions.on_enter.non_sensor = {}
|
||||
self.collisions.on_exit = {}
|
||||
self.collisions.on_exit.sensor = {}
|
||||
self.collisions.on_exit.non_sensor = {}
|
||||
self.collisions.pre = {}
|
||||
self.collisions.pre.sensor = {}
|
||||
self.collisions.pre.non_sensor = {}
|
||||
self.collisions.post = {}
|
||||
self.collisions.post.sensor = {}
|
||||
self.collisions.post.non_sensor = {}
|
||||
end
|
||||
|
||||
function World:collisionEventsClear()
|
||||
local bodies = self.box2d_world:getBodies()
|
||||
for _, body in ipairs(bodies) do
|
||||
local collider = body:getFixtures()[1]:getUserData()
|
||||
collider:collisionEventsClear()
|
||||
end
|
||||
end
|
||||
|
||||
function World:addCollisionEnter(type1, type2)
|
||||
if not self:isCollisionBetweenSensors(type1, type2) then
|
||||
table.insert(self.collisions.on_enter.non_sensor, {type1 = type1, type2 = type2})
|
||||
else table.insert(self.collisions.on_enter.sensor, {type1 = type1, type2 = type2}) end
|
||||
end
|
||||
|
||||
function World:addCollisionExit(type1, type2)
|
||||
if not self:isCollisionBetweenSensors(type1, type2) then
|
||||
table.insert(self.collisions.on_exit.non_sensor, {type1 = type1, type2 = type2})
|
||||
else table.insert(self.collisions.on_exit.sensor, {type1 = type1, type2 = type2}) end
|
||||
end
|
||||
|
||||
function World:addCollisionPre(type1, type2)
|
||||
if not self:isCollisionBetweenSensors(type1, type2) then
|
||||
table.insert(self.collisions.pre.non_sensor, {type1 = type1, type2 = type2})
|
||||
else table.insert(self.collisions.pre.sensor, {type1 = type1, type2 = type2}) end
|
||||
end
|
||||
|
||||
function World:addCollisionPost(type1, type2)
|
||||
if not self:isCollisionBetweenSensors(type1, type2) then
|
||||
table.insert(self.collisions.post.non_sensor, {type1 = type1, type2 = type2})
|
||||
else table.insert(self.collisions.post.sensor, {type1 = type1, type2 = type2}) end
|
||||
end
|
||||
|
||||
function World:doesType1IgnoreType2(type1, type2)
|
||||
local collision_ignores = {}
|
||||
for collision_class_name, collision_class in pairs(self.collision_classes) do
|
||||
collision_ignores[collision_class_name] = collision_class.ignores or {}
|
||||
end
|
||||
local all = {}
|
||||
for collision_class_name, _ in pairs(collision_ignores) do
|
||||
table.insert(all, collision_class_name)
|
||||
end
|
||||
local ignored_types = {}
|
||||
for _, collision_class_type in ipairs(collision_ignores[type1]) do
|
||||
if collision_class_type == 'All' then
|
||||
for _, collision_class_name in ipairs(all) do
|
||||
table.insert(ignored_types, collision_class_name)
|
||||
end
|
||||
else table.insert(ignored_types, collision_class_type) end
|
||||
end
|
||||
for key, _ in pairs(collision_ignores[type1]) do
|
||||
if key == 'except' then
|
||||
for _, except_type in ipairs(collision_ignores[type1].except) do
|
||||
for i = #ignored_types, 1, -1 do
|
||||
if ignored_types[i] == except_type then table.remove(ignored_types, i) end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
for _, ignored_type in ipairs(ignored_types) do
|
||||
if ignored_type == type2 then return true end
|
||||
end
|
||||
end
|
||||
|
||||
function World:isCollisionBetweenSensors(type1, type2)
|
||||
if not self.is_sensor_memo[type1] then self.is_sensor_memo[type1] = {} end
|
||||
if not self.is_sensor_memo[type1][type2] then self.is_sensor_memo[type1][type2] = (self:doesType1IgnoreType2(type1, type2) or self:doesType1IgnoreType2(type2, type1)) end
|
||||
if self.is_sensor_memo[type1][type2] then return true
|
||||
else return false end
|
||||
end
|
||||
|
||||
-- https://love2d.org/forums/viewtopic.php?f=4&t=75441
|
||||
function World:generateCategoriesMasks()
|
||||
local collision_ignores = {}
|
||||
for collision_class_name, collision_class in pairs(self.collision_classes) do
|
||||
collision_ignores[collision_class_name] = collision_class.ignores or {}
|
||||
end
|
||||
local incoming = {}
|
||||
local expanded = {}
|
||||
local all = {}
|
||||
for object_type, _ in pairs(collision_ignores) do
|
||||
incoming[object_type] = {}
|
||||
expanded[object_type] = {}
|
||||
table.insert(all, object_type)
|
||||
end
|
||||
for object_type, ignore_list in pairs(collision_ignores) do
|
||||
for key, ignored_type in pairs(ignore_list) do
|
||||
if ignored_type == 'All' then
|
||||
for _, all_object_type in ipairs(all) do
|
||||
table.insert(incoming[all_object_type], object_type)
|
||||
table.insert(expanded[object_type], all_object_type)
|
||||
end
|
||||
elseif type(ignored_type) == 'string' then
|
||||
if ignored_type ~= 'All' then
|
||||
table.insert(incoming[ignored_type], object_type)
|
||||
table.insert(expanded[object_type], ignored_type)
|
||||
end
|
||||
end
|
||||
if key == 'except' then
|
||||
for _, except_ignored_type in ipairs(ignored_type) do
|
||||
for i, v in ipairs(incoming[except_ignored_type]) do
|
||||
if v == object_type then
|
||||
table.remove(incoming[except_ignored_type], i)
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
for _, except_ignored_type in ipairs(ignored_type) do
|
||||
for i, v in ipairs(expanded[object_type]) do
|
||||
if v == except_ignored_type then
|
||||
table.remove(expanded[object_type], i)
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
local edge_groups = {}
|
||||
for k, v in pairs(incoming) do
|
||||
table.sort(v, function(a, b) return string.lower(a) < string.lower(b) end)
|
||||
end
|
||||
local i = 0
|
||||
for k, v in pairs(incoming) do
|
||||
local str = ""
|
||||
for _, c in ipairs(v) do
|
||||
str = str .. c
|
||||
end
|
||||
if not edge_groups[str] then i = i + 1; edge_groups[str] = {n = i} end
|
||||
table.insert(edge_groups[str], k)
|
||||
end
|
||||
local categories = {}
|
||||
for k, _ in pairs(collision_ignores) do
|
||||
categories[k] = {}
|
||||
end
|
||||
for k, v in pairs(edge_groups) do
|
||||
for i, c in ipairs(v) do
|
||||
categories[c] = v.n
|
||||
end
|
||||
end
|
||||
for k, v in pairs(expanded) do
|
||||
local category = {categories[k]}
|
||||
local current_masks = {}
|
||||
for _, c in ipairs(v) do
|
||||
table.insert(current_masks, categories[c])
|
||||
end
|
||||
self.masks[k] = {categories = category, masks = current_masks}
|
||||
end
|
||||
end
|
||||
|
||||
function World:getCollisionCallbacksTable()
|
||||
local collision_table = {}
|
||||
for collision_class_name, collision_class in pairs(self.collision_classes) do
|
||||
collision_table[collision_class_name] = {}
|
||||
for _, v in ipairs(collision_class.enter or {}) do table.insert(collision_table[collision_class_name], {type = 'enter', other = v}) end
|
||||
for _, v in ipairs(collision_class.exit or {}) do table.insert(collision_table[collision_class_name], {type = 'exit', other = v}) end
|
||||
for _, v in ipairs(collision_class.pre or {}) do table.insert(collision_table[collision_class_name], {type = 'pre', other = v}) end
|
||||
for _, v in ipairs(collision_class.post or {}) do table.insert(collision_table[collision_class_name], {type = 'post', other = v}) end
|
||||
end
|
||||
return collision_table
|
||||
end
|
||||
|
||||
local function collEnsure(collision_class_name1, a, collision_class_name2, b)
|
||||
if a.collision_class == collision_class_name2 and b.collision_class == collision_class_name1 then return b, a
|
||||
else return a, b end
|
||||
end
|
||||
|
||||
local function collIf(collision_class_name1, collision_class_name2, a, b)
|
||||
if (a.collision_class == collision_class_name1 and b.collision_class == collision_class_name2) or
|
||||
(a.collision_class == collision_class_name2 and b.collision_class == collision_class_name1) then
|
||||
return true
|
||||
else return false end
|
||||
end
|
||||
|
||||
function World.collisionOnEnter(fixture_a, fixture_b, contact)
|
||||
local a, b = fixture_a:getUserData(), fixture_b:getUserData()
|
||||
|
||||
if fixture_a:isSensor() and fixture_b:isSensor() then
|
||||
if a and b then
|
||||
for _, collision in ipairs(a.world.collisions.on_enter.sensor) do
|
||||
if collIf(collision.type1, collision.type2, a, b) then
|
||||
a, b = collEnsure(collision.type1, a, collision.type2, b)
|
||||
table.insert(a.collision_events[collision.type2], {collision_type = 'enter', collider_1 = a, collider_2 = b, contact = contact})
|
||||
if collision.type1 == collision.type2 then
|
||||
table.insert(b.collision_events[collision.type1], {collision_type = 'enter', collider_1 = b, collider_2 = a, contact = contact})
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
elseif not (fixture_a:isSensor() or fixture_b:isSensor()) then
|
||||
if a and b then
|
||||
for _, collision in ipairs(a.world.collisions.on_enter.non_sensor) do
|
||||
if collIf(collision.type1, collision.type2, a, b) then
|
||||
a, b = collEnsure(collision.type1, a, collision.type2, b)
|
||||
table.insert(a.collision_events[collision.type2], {collision_type = 'enter', collider_1 = a, collider_2 = b, contact = contact})
|
||||
if collision.type1 == collision.type2 then
|
||||
table.insert(b.collision_events[collision.type1], {collision_type = 'enter', collider_1 = b, collider_2 = a, contact = contact})
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function World.collisionOnExit(fixture_a, fixture_b, contact)
|
||||
local a, b = fixture_a:getUserData(), fixture_b:getUserData()
|
||||
|
||||
if fixture_a:isSensor() and fixture_b:isSensor() then
|
||||
if a and b then
|
||||
for _, collision in ipairs(a.world.collisions.on_exit.sensor) do
|
||||
if collIf(collision.type1, collision.type2, a, b) then
|
||||
a, b = collEnsure(collision.type1, a, collision.type2, b)
|
||||
table.insert(a.collision_events[collision.type2], {collision_type = 'exit', collider_1 = a, collider_2 = b, contact = contact})
|
||||
if collision.type1 == collision.type2 then
|
||||
table.insert(b.collision_events[collision.type1], {collision_type = 'exit', collider_1 = b, collider_2 = a, contact = contact})
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
elseif not (fixture_a:isSensor() or fixture_b:isSensor()) then
|
||||
if a and b then
|
||||
for _, collision in ipairs(a.world.collisions.on_exit.non_sensor) do
|
||||
if collIf(collision.type1, collision.type2, a, b) then
|
||||
a, b = collEnsure(collision.type1, a, collision.type2, b)
|
||||
table.insert(a.collision_events[collision.type2], {collision_type = 'exit', collider_1 = a, collider_2 = b, contact = contact})
|
||||
if collision.type1 == collision.type2 then
|
||||
table.insert(b.collision_events[collision.type1], {collision_type = 'exit', collider_1 = b, collider_2 = a, contact = contact})
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function World.collisionPre(fixture_a, fixture_b, contact)
|
||||
local a, b = fixture_a:getUserData(), fixture_b:getUserData()
|
||||
|
||||
if fixture_a:isSensor() and fixture_b:isSensor() then
|
||||
if a and b then
|
||||
for _, collision in ipairs(a.world.collisions.pre.sensor) do
|
||||
if collIf(collision.type1, collision.type2, a, b) then
|
||||
a, b = collEnsure(collision.type1, a, collision.type2, b)
|
||||
a:preSolve(b, contact)
|
||||
if collision.type1 == collision.type2 then
|
||||
b:preSolve(a, contact)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
elseif not (fixture_a:isSensor() or fixture_b:isSensor()) then
|
||||
if a and b then
|
||||
for _, collision in ipairs(a.world.collisions.pre.non_sensor) do
|
||||
if collIf(collision.type1, collision.type2, a, b) then
|
||||
a, b = collEnsure(collision.type1, a, collision.type2, b)
|
||||
a:preSolve(b, contact)
|
||||
if collision.type1 == collision.type2 then
|
||||
b:preSolve(a, contact)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function World.collisionPost(fixture_a, fixture_b, contact, ni1, ti1, ni2, ti2)
|
||||
local a, b = fixture_a:getUserData(), fixture_b:getUserData()
|
||||
|
||||
if fixture_a:isSensor() and fixture_b:isSensor() then
|
||||
if a and b then
|
||||
for _, collision in ipairs(a.world.collisions.post.sensor) do
|
||||
if collIf(collision.type1, collision.type2, a, b) then
|
||||
a, b = collEnsure(collision.type1, a, collision.type2, b)
|
||||
a:postSolve(b, contact, ni1, ti1, ni2, ti2)
|
||||
if collision.type1 == collision.type2 then
|
||||
b:postSolve(a, contact, ni1, ti1, ni2, ti2)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
elseif not (fixture_a:isSensor() or fixture_b:isSensor()) then
|
||||
if a and b then
|
||||
for _, collision in ipairs(a.world.collisions.post.non_sensor) do
|
||||
if collIf(collision.type1, collision.type2, a, b) then
|
||||
a, b = collEnsure(collision.type1, a, collision.type2, b)
|
||||
a:postSolve(b, contact, ni1, ti1, ni2, ti2)
|
||||
if collision.type1 == collision.type2 then
|
||||
b:postSolve(a, contact, ni1, ti1, ni2, ti2)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function World:newCircleCollider(x, y, r, settings)
|
||||
return self.wf.Collider.new(self, 'Circle', x, y, r, settings)
|
||||
end
|
||||
|
||||
function World:newRectangleCollider(x, y, w, h, settings)
|
||||
return self.wf.Collider.new(self, 'Rectangle', x, y, w, h, settings)
|
||||
end
|
||||
|
||||
function World:newBSGRectangleCollider(x, y, w, h, corner_cut_size, settings)
|
||||
return self.wf.Collider.new(self, 'BSGRectangle', x, y, w, h, corner_cut_size, settings)
|
||||
end
|
||||
|
||||
function World:newPolygonCollider(vertices, settings)
|
||||
return self.wf.Collider.new(self, 'Polygon', vertices, settings)
|
||||
end
|
||||
|
||||
function World:newLineCollider(x1, y1, x2, y2, settings)
|
||||
return self.wf.Collider.new(self, 'Line', x1, y1, x2, y2, settings)
|
||||
end
|
||||
|
||||
function World:newChainCollider(vertices, loop, settings)
|
||||
return self.wf.Collider.new(self, 'Chain', vertices, loop, settings)
|
||||
end
|
||||
|
||||
-- Internal AABB box2d query used before going for more specific and precise computations.
|
||||
function World:_queryBoundingBox(x1, y1, x2, y2)
|
||||
local colliders = {}
|
||||
local callback = function(fixture)
|
||||
if not fixture:isSensor() then table.insert(colliders, fixture:getUserData()) end
|
||||
return true
|
||||
end
|
||||
self.box2d_world:queryBoundingBox(x1, y1, x2, y2, callback)
|
||||
return colliders
|
||||
end
|
||||
|
||||
function World:collisionClassInCollisionClassesList(collision_class, collision_classes)
|
||||
if collision_classes[1] == 'All' then
|
||||
local all_collision_classes = {}
|
||||
for class, _ in pairs(self.collision_classes) do
|
||||
table.insert(all_collision_classes, class)
|
||||
end
|
||||
if collision_classes.except then
|
||||
for _, except in ipairs(collision_classes.except) do
|
||||
for i, class in ipairs(all_collision_classes) do
|
||||
if class == except then
|
||||
table.remove(all_collision_classes, i)
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
for _, class in ipairs(all_collision_classes) do
|
||||
if class == collision_class then return true end
|
||||
end
|
||||
else
|
||||
for _, class in ipairs(collision_classes) do
|
||||
if class == collision_class then return true end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function World:queryCircleArea(x, y, radius, collision_class_names)
|
||||
if not collision_class_names then collision_class_names = {'All'} end
|
||||
if self.query_debug_drawing_enabled then table.insert(self.query_debug_draw, {type = 'circle', x = x, y = y, r = radius, frames = self.draw_query_for_n_frames}) end
|
||||
|
||||
local colliders = self:_queryBoundingBox(x-radius, y-radius, x+radius, y+radius)
|
||||
local outs = {}
|
||||
for _, collider in ipairs(colliders) do
|
||||
if self:collisionClassInCollisionClassesList(collider.collision_class, collision_class_names) then
|
||||
for _, fixture in ipairs(collider.body:getFixtures()) do
|
||||
if self.wf.Math.polygon.getCircleIntersection(x, y, radius, {collider.body:getWorldPoints(fixture:getShape():getPoints())}) then
|
||||
table.insert(outs, collider)
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
return outs
|
||||
end
|
||||
|
||||
function World:queryRectangleArea(x, y, w, h, collision_class_names)
|
||||
if not collision_class_names then collision_class_names = {'All'} end
|
||||
if self.query_debug_drawing_enabled then table.insert(self.query_debug_draw, {type = 'rectangle', x = x, y = y, w = w, h = h, frames = self.draw_query_for_n_frames}) end
|
||||
|
||||
local colliders = self:_queryBoundingBox(x, y, x+w, y+h)
|
||||
local outs = {}
|
||||
for _, collider in ipairs(colliders) do
|
||||
if self:collisionClassInCollisionClassesList(collider.collision_class, collision_class_names) then
|
||||
for _, fixture in ipairs(collider.body:getFixtures()) do
|
||||
if self.wf.Math.polygon.isPolygonInside({x, y, x+w, y, x+w, y+h, x, y+h}, {collider.body:getWorldPoints(fixture:getShape():getPoints())}) then
|
||||
table.insert(outs, collider)
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
return outs
|
||||
end
|
||||
|
||||
function World:queryPolygonArea(vertices, collision_class_names)
|
||||
if not collision_class_names then collision_class_names = {'All'} end
|
||||
if self.query_debug_drawing_enabled then table.insert(self.query_debug_draw, {type = 'polygon', vertices = vertices, frames = self.draw_query_for_n_frames}) end
|
||||
|
||||
local cx, cy = self.wf.Math.polygon.getCentroid(vertices)
|
||||
local d_max = 0
|
||||
for i = 1, #vertices, 2 do
|
||||
local d = self.wf.Math.line.getLength(cx, cy, vertices[i], vertices[i+1])
|
||||
if d > d_max then d_max = d end
|
||||
end
|
||||
local colliders = self:_queryBoundingBox(cx-d_max, cy-d_max, cx+d_max, cy+d_max)
|
||||
local outs = {}
|
||||
for _, collider in ipairs(colliders) do
|
||||
if self:collisionClassInCollisionClassesList(collider.collision_class, collision_class_names) then
|
||||
for _, fixture in ipairs(collider.body:getFixtures()) do
|
||||
if self.wf.Math.polygon.isPolygonInside(vertices, {collider.body:getWorldPoints(fixture:getShape():getPoints())}) then
|
||||
table.insert(outs, collider)
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
return outs
|
||||
end
|
||||
|
||||
function World:queryLine(x1, y1, x2, y2, collision_class_names)
|
||||
if not collision_class_names then collision_class_names = {'All'} end
|
||||
if self.query_debug_drawing_enabled then
|
||||
table.insert(self.query_debug_draw, {type = 'line', x1 = x1, y1 = y1, x2 = x2, y2 = y2, frames = self.draw_query_for_n_frames})
|
||||
end
|
||||
|
||||
local colliders = {}
|
||||
local callback = function(fixture, ...)
|
||||
if not fixture:isSensor() then table.insert(colliders, fixture:getUserData()) end
|
||||
return 1
|
||||
end
|
||||
self.box2d_world:rayCast(x1, y1, x2, y2, callback)
|
||||
|
||||
local outs = {}
|
||||
for _, collider in ipairs(colliders) do
|
||||
if self:collisionClassInCollisionClassesList(collider.collision_class, collision_class_names) then
|
||||
table.insert(outs, collider)
|
||||
end
|
||||
end
|
||||
return outs
|
||||
end
|
||||
|
||||
function World:addJoint(joint_type, ...)
|
||||
local args = {...}
|
||||
if args[1].body then args[1] = args[1].body end
|
||||
if type(args[2]) == "table" and args[2].body then args[2] = args[2].body end
|
||||
local joint = love.physics['new' .. joint_type](unpack(args))
|
||||
return joint
|
||||
end
|
||||
|
||||
function World:removeJoint(joint)
|
||||
joint:destroy()
|
||||
end
|
||||
|
||||
function World:destroy()
|
||||
local bodies = self.box2d_world:getBodies()
|
||||
for _, body in ipairs(bodies) do
|
||||
local collider = body:getFixtures()[1]:getUserData()
|
||||
collider:destroy()
|
||||
end
|
||||
local joints = self.box2d_world:getJoints()
|
||||
for _, joint in ipairs(joints) do joint:destroy() end
|
||||
self.box2d_world:destroy()
|
||||
self.box2d_world = nil
|
||||
end
|
||||
|
||||
|
||||
|
||||
local Collider = {}
|
||||
Collider.__index = Collider
|
||||
|
||||
local generator = love.math.newRandomGenerator(os.time())
|
||||
local function UUID()
|
||||
local fn = function(x)
|
||||
local r = generator:random(16) - 1
|
||||
r = (x == "x") and (r + 1) or (r % 4) + 9
|
||||
return ("0123456789abcdef"):sub(r, r)
|
||||
end
|
||||
return (("xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx"):gsub("[xy]", fn))
|
||||
end
|
||||
|
||||
function Collider.new(world, collider_type, ...)
|
||||
local self = {}
|
||||
self.id = UUID()
|
||||
self.world = world
|
||||
self.type = collider_type
|
||||
self.object = nil
|
||||
|
||||
self.shapes = {}
|
||||
self.fixtures = {}
|
||||
self.sensors = {}
|
||||
|
||||
self.collision_events = {}
|
||||
self.collision_stay = {}
|
||||
self.enter_collision_data = {}
|
||||
self.exit_collision_data = {}
|
||||
self.stay_collision_data = {}
|
||||
|
||||
local args = {...}
|
||||
local shape, fixture
|
||||
if self.type == 'Circle' then
|
||||
self.collision_class = (args[4] and args[4].collision_class) or 'Default'
|
||||
self.body = love.physics.newBody(self.world.box2d_world, args[1], args[2], (args[4] and args[4].body_type) or 'dynamic')
|
||||
shape = love.physics.newCircleShape(args[3])
|
||||
|
||||
elseif self.type == 'Rectangle' then
|
||||
self.collision_class = (args[5] and args[5].collision_class) or 'Default'
|
||||
self.body = love.physics.newBody(self.world.box2d_world, args[1] + args[3]/2, args[2] + args[4]/2, (args[5] and args[5].body_type) or 'dynamic')
|
||||
shape = love.physics.newRectangleShape(args[3], args[4])
|
||||
|
||||
elseif self.type == 'BSGRectangle' then
|
||||
self.collision_class = (args[6] and args[6].collision_class) or 'Default'
|
||||
self.body = love.physics.newBody(self.world.box2d_world, args[1] + args[3]/2, args[2] + args[4]/2, (args[6] and args[6].body_type) or 'dynamic')
|
||||
local w, h, s = args[3], args[4], args[5]
|
||||
shape = love.physics.newPolygonShape({
|
||||
-w/2, -h/2 + s, -w/2 + s, -h/2,
|
||||
w/2 - s, -h/2, w/2, -h/2 + s,
|
||||
w/2, h/2 - s, w/2 - s, h/2,
|
||||
-w/2 + s, h/2, -w/2, h/2 - s
|
||||
})
|
||||
|
||||
elseif self.type == 'Polygon' then
|
||||
self.collision_class = (args[2] and args[2].collision_class) or 'Default'
|
||||
self.body = love.physics.newBody(self.world.box2d_world, 0, 0, (args[2] and args[2].body_type) or 'dynamic')
|
||||
shape = love.physics.newPolygonShape(unpack(args[1]))
|
||||
|
||||
elseif self.type == 'Line' then
|
||||
self.collision_class = (args[5] and args[5].collision_class) or 'Default'
|
||||
self.body = love.physics.newBody(self.world.box2d_world, 0, 0, (args[5] and args[5].body_type) or 'dynamic')
|
||||
shape = love.physics.newEdgeShape(args[1], args[2], args[3], args[4])
|
||||
|
||||
elseif self.type == 'Chain' then
|
||||
self.collision_class = (args[3] and args[3].collision_class) or 'Default'
|
||||
self.body = love.physics.newBody(self.world.box2d_world, 0, 0, (args[3] and args[3].body_type) or 'dynamic')
|
||||
shape = love.physics.newChainShape(args[1], unpack(args[2]))
|
||||
end
|
||||
|
||||
-- Define collision classes and attach them to fixture and sensor
|
||||
fixture = love.physics.newFixture(self.body, shape)
|
||||
if self.world.masks[self.collision_class] then
|
||||
fixture:setCategory(unpack(self.world.masks[self.collision_class].categories))
|
||||
fixture:setMask(unpack(self.world.masks[self.collision_class].masks))
|
||||
end
|
||||
fixture:setUserData(self)
|
||||
local sensor = love.physics.newFixture(self.body, shape)
|
||||
sensor:setSensor(true)
|
||||
sensor:setUserData(self)
|
||||
|
||||
self.shapes['main'] = shape
|
||||
self.fixtures['main'] = fixture
|
||||
self.sensors['main'] = sensor
|
||||
self.shape = shape
|
||||
self.fixture = fixture
|
||||
|
||||
self.preSolve = function() end
|
||||
self.postSolve = function() end
|
||||
|
||||
-- Points all body, fixture and shape functions to this wf.Collider object
|
||||
-- This means that the user can call collider:setLinearVelocity for instance without having to say collider.body:setLinearVelocity
|
||||
for k, v in pairs(self.body.__index) do
|
||||
if k ~= '__gc' and k ~= '__eq' and k ~= '__index' and k ~= '__tostring' and k ~= 'destroy' and k ~= 'type' and k ~= 'typeOf' then
|
||||
self[k] = function(self, ...)
|
||||
return v(self.body, ...)
|
||||
end
|
||||
end
|
||||
end
|
||||
for k, v in pairs(self.fixture.__index) do
|
||||
if k ~= '__gc' and k ~= '__eq' and k ~= '__index' and k ~= '__tostring' and k ~= 'destroy' and k ~= 'type' and k ~= 'typeOf' then
|
||||
self[k] = function(self, ...)
|
||||
return v(self.fixture, ...)
|
||||
end
|
||||
end
|
||||
end
|
||||
for k, v in pairs(self.shape.__index) do
|
||||
if k ~= '__gc' and k ~= '__eq' and k ~= '__index' and k ~= '__tostring' and k ~= 'destroy' and k ~= 'type' and k ~= 'typeOf' then
|
||||
self[k] = function(self, ...)
|
||||
return v(self.shape, ...)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return setmetatable(self, Collider)
|
||||
end
|
||||
|
||||
function Collider:collisionEventsClear()
|
||||
self.collision_events = {}
|
||||
for other, _ in pairs(self.world.collision_classes) do
|
||||
self.collision_events[other] = {}
|
||||
end
|
||||
end
|
||||
|
||||
function Collider:setCollisionClass(collision_class_name)
|
||||
if not self.world.collision_classes[collision_class_name] then error("Collision class " .. collision_class_name .. " doesn't exist.") end
|
||||
self.collision_class = collision_class_name
|
||||
for _, fixture in pairs(self.fixtures) do
|
||||
if self.world.masks[collision_class_name] then
|
||||
fixture:setCategory(unpack(self.world.masks[collision_class_name].categories))
|
||||
fixture:setMask(unpack(self.world.masks[collision_class_name].masks))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function Collider:enter(other_collision_class_name)
|
||||
local events = self.collision_events[other_collision_class_name]
|
||||
if events and #events >= 1 then
|
||||
for _, e in ipairs(events) do
|
||||
if e.collision_type == 'enter' then
|
||||
if not self.collision_stay[other_collision_class_name] then self.collision_stay[other_collision_class_name] = {} end
|
||||
table.insert(self.collision_stay[other_collision_class_name], {collider = e.collider_2, contact = e.contact})
|
||||
self.enter_collision_data[other_collision_class_name] = {collider = e.collider_2, contact = e.contact}
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function Collider:getEnterCollisionData(other_collision_class_name)
|
||||
return self.enter_collision_data[other_collision_class_name]
|
||||
end
|
||||
|
||||
function Collider:exit(other_collision_class_name)
|
||||
local events = self.collision_events[other_collision_class_name]
|
||||
if events and #events >= 1 then
|
||||
for _, e in ipairs(events) do
|
||||
if e.collision_type == 'exit' then
|
||||
if self.collision_stay[other_collision_class_name] then
|
||||
for i = #self.collision_stay[other_collision_class_name], 1, -1 do
|
||||
local collision_stay = self.collision_stay[other_collision_class_name][i]
|
||||
if collision_stay.collider.id == e.collider_2.id then table.remove(self.collision_stay[other_collision_class_name], i) end
|
||||
end
|
||||
end
|
||||
self.exit_collision_data[other_collision_class_name] = {collider = e.collider_2, contact = e.contact}
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function Collider:getExitCollisionData(other_collision_class_name)
|
||||
return self.exit_collision_data[other_collision_class_name]
|
||||
end
|
||||
|
||||
function Collider:stay(other_collision_class_name)
|
||||
if self.collision_stay[other_collision_class_name] then
|
||||
if #self.collision_stay[other_collision_class_name] >= 1 then
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function Collider:getStayCollisionData(other_collision_class_name)
|
||||
return self.collision_stay[other_collision_class_name]
|
||||
end
|
||||
|
||||
function Collider:setPreSolve(callback)
|
||||
self.preSolve = callback
|
||||
end
|
||||
|
||||
function Collider:setPostSolve(callback)
|
||||
self.postSolve = callback
|
||||
end
|
||||
|
||||
function Collider:setObject(object)
|
||||
self.object = object
|
||||
end
|
||||
|
||||
function Collider:getObject()
|
||||
return self.object
|
||||
end
|
||||
|
||||
function Collider:addShape(shape_name, shape_type, ...)
|
||||
if self.shapes[shape_name] or self.fixtures[shape_name] then error("Shape/fixture " .. shape_name .. " already exists.") end
|
||||
local args = {...}
|
||||
local shape = love.physics['new' .. shape_type](unpack(args))
|
||||
local fixture = love.physics.newFixture(self.body, shape)
|
||||
if self.world.masks[self.collision_class] then
|
||||
fixture:setCategory(unpack(self.world.masks[self.collision_class].categories))
|
||||
fixture:setMask(unpack(self.world.masks[self.collision_class].masks))
|
||||
end
|
||||
fixture:setUserData(self)
|
||||
local sensor = love.physics.newFixture(self.body, shape)
|
||||
sensor:setSensor(true)
|
||||
sensor:setUserData(self)
|
||||
|
||||
self.shapes[shape_name] = shape
|
||||
self.fixtures[shape_name] = fixture
|
||||
self.sensors[shape_name] = sensor
|
||||
end
|
||||
|
||||
function Collider:removeShape(shape_name)
|
||||
if not self.shapes[shape_name] then return end
|
||||
self.shapes[shape_name] = nil
|
||||
self.fixtures[shape_name]:setUserData(nil)
|
||||
self.fixtures[shape_name]:destroy()
|
||||
self.fixtures[shape_name] = nil
|
||||
self.sensors[shape_name]:setUserData(nil)
|
||||
self.sensors[shape_name]:destroy()
|
||||
self.sensors[shape_name] = nil
|
||||
end
|
||||
|
||||
function Collider:destroy()
|
||||
self.collision_stay = nil
|
||||
self.enter_collision_data = nil
|
||||
self.exit_collision_data = nil
|
||||
self:collisionEventsClear()
|
||||
|
||||
self:setObject(nil)
|
||||
for name, _ in pairs(self.fixtures) do
|
||||
self.shapes[name] = nil
|
||||
self.fixtures[name]:setUserData(nil)
|
||||
self.fixtures[name] = nil
|
||||
self.sensors[name]:setUserData(nil)
|
||||
self.sensors[name] = nil
|
||||
end
|
||||
self.body:destroy()
|
||||
self.body = nil
|
||||
end
|
||||
|
||||
wf.World = World
|
||||
wf.Collider = Collider
|
||||
|
||||
return wf
|
||||
|
||||
568
deps/windfield/mlib/Changes.txt
vendored
Normal file
568
deps/windfield/mlib/Changes.txt
vendored
Normal file
@@ -0,0 +1,568 @@
|
||||
0.11.0
|
||||
====
|
||||
Added:
|
||||
----
|
||||
- mlib.vec2 component
|
||||
|
||||
To-Do:
|
||||
----
|
||||
- Update README.md
|
||||
- Update spec.lua
|
||||
- Fix tabbing
|
||||
|
||||
0.10.1
|
||||
====
|
||||
Added:
|
||||
----
|
||||
- Point category
|
||||
- point.rotate
|
||||
- point.scale
|
||||
- point.polarToCartesian
|
||||
- point.cartesianToPolar
|
||||
|
||||
Changed:
|
||||
----
|
||||
- math.getPercent now returns decimals (instead of percentages) since those are more common to use.
|
||||
|
||||
To-Do:
|
||||
----
|
||||
- Determine if isCompletelyInsideFunctions should return true with tangents.
|
||||
- Check argument order for logicality and consistency.
|
||||
- Add error checking.
|
||||
- Make sure to see if any aliases were missed. (e.g. isSegmentInside)
|
||||
- Clean up and correct README (add "Home" link, etc.)
|
||||
|
||||
0.10.0
|
||||
====
|
||||
Added:
|
||||
----
|
||||
|
||||
Changed:
|
||||
----
|
||||
- mlib.line.segment is now mlib.segment.
|
||||
- mlib.line.getIntercept has been renamed to mlib.line.getYIntercept
|
||||
- mlib.line.getYIntercept now returns the x-coordinate for vertical lines instead of false.
|
||||
- mlib.line.getYIntercept now returns the value `isVertical` as the second return value.
|
||||
- mlib.line.getPerpendicularBisector is now mlib.segment.getPerpendicularBisector.
|
||||
|
||||
Fixed:
|
||||
----
|
||||
- mlib.line.getIntersection now should handle vertical slopes better.
|
||||
- mlib.line.getClosestPoint now uses local function checkFuzzy for checking horizontal lines.
|
||||
- Fixed possible bug in mlib.line.getSegmentIntersection and vertical lines.
|
||||
- mlib.segment.getIntersection now uses fuzzy checking for parallel lines.
|
||||
- mlib.math.round is now much more efficient.
|
||||
- Removed some useless code from mlib.polygon.isSegmentInside.
|
||||
|
||||
To-Do:
|
||||
----
|
||||
- Determine if isCompletelyInsideFunctions should return true with tangents.
|
||||
- Check argument order for logicality and consistency.
|
||||
- Improve speed.
|
||||
- Add error checking.
|
||||
- Make sure to see if any aliases were missed. (e.g. isSegmentInside)
|
||||
- Implement mlib.shapes again(?)
|
||||
- Clean up and correct README (add "Home" link, etc.)
|
||||
|
||||
0.9.4
|
||||
====
|
||||
Added:
|
||||
----
|
||||
|
||||
Changed:
|
||||
----
|
||||
- mlib.line.getDistance is now slightly faster.
|
||||
- Made code much easier to debug by using new utility `cycle`.
|
||||
- Added new utility.
|
||||
- Various other minor changes.
|
||||
|
||||
Removed:
|
||||
----
|
||||
- Unused local utility function copy
|
||||
|
||||
To-Do
|
||||
----
|
||||
- Determine if isCompletelyInsideFunctions should return true with tangents.
|
||||
- Make argument order more logical.
|
||||
- Improve speed and error checking.
|
||||
- Make sure to see if any aliases were missed. (e.g. isSegmentInside)
|
||||
- Implement mlib.shapes again(?)
|
||||
- Clean up README (add "Home" link, etc.)
|
||||
|
||||
0.9.3
|
||||
====
|
||||
Added:
|
||||
----
|
||||
- milb.circle.isCircleCompletelyInside
|
||||
- mlib.circle.isPolygonCompletelyInside
|
||||
- milb.circle.isSegmentCompletelyInside
|
||||
- mlib.polygon.isCircleCompletelyInside
|
||||
- mlib.polygon.isPolygonCompletelyInside
|
||||
- mlib.polygon.isSegmentCompletelyInside
|
||||
|
||||
- ALIASES -
|
||||
- mlib.circle.getPolygonIntersection
|
||||
- mlib.circle.isCircleInsidePolygon
|
||||
- mlib.circle.isCircleCompletelyInsidePolygon
|
||||
- milb.line.getCircleIntersection
|
||||
- milb.line.getPolygonIntersection
|
||||
- milb.line.getLineIntersection
|
||||
- mlib.line.segment.getCircleIntersection
|
||||
- mlib.line.segment.getPolygonIntersection
|
||||
- mlib.line.segment.getLineIntersection
|
||||
- mlib.line.segment.getSegmentIntersection
|
||||
- mlib.line.segment.isSegmentCompletelyInsideCircle
|
||||
- mlib.line.segment.isSegmentCompletelyInsidePolygon
|
||||
- mlib.polygon.isCircleCompletelyOver
|
||||
|
||||
Changed:
|
||||
----
|
||||
- mlib.circle.getCircleIntersection now returns 'inside' instead of 'intersection' if the point has not intersections but is within the circle.
|
||||
- Fixed problem involving mlib.circle.getSegmentIntersection
|
||||
|
||||
- README.md now has more information on how to run specs and other minor improvements.
|
||||
- Fixed some commenting on explanation of derivation of mlib.line.getIntersection.
|
||||
- Updated the example to use the current version of mlib.
|
||||
- Made/Changed some comments in the example main.lua.
|
||||
|
||||
Removed:
|
||||
----
|
||||
|
||||
To-Do
|
||||
----
|
||||
- Make examples file on github (examples/shapes/main.lua, etc.) not just one line.
|
||||
- Determine if isCompletelyInsideFunctions should return true with tangents.
|
||||
- Make argument order more logical.
|
||||
- Make sure to see if any aliases were missed. (e.g. isSegmentInside)
|
||||
- Update spec links in README
|
||||
|
||||
0.9.2
|
||||
====
|
||||
Added:
|
||||
----
|
||||
|
||||
Changed:
|
||||
----
|
||||
- mlib.polygon.getPolygonIntersection now does not create duplicate local table.
|
||||
- mlib.line.getPerpendicularSlope now does not create a global variable.
|
||||
- mlib.math.getSummation now allows the error to go through instead of returning false if the stop value is not a number.
|
||||
|
||||
- Changed any instance of the term "userdata" with "input"
|
||||
|
||||
Removed:
|
||||
----
|
||||
|
||||
0.9.1
|
||||
====
|
||||
Added:
|
||||
----
|
||||
- Added mlib.statistics.getCentralTendency
|
||||
- Added mlib.statistics.getDispersion
|
||||
- Added mlib.statistics.getStandardDeviation
|
||||
- Added mlib.statistics.getVariation
|
||||
- Added mlib.statistics.getVariationRatio
|
||||
|
||||
Removed:
|
||||
----
|
||||
|
||||
Changed:
|
||||
----
|
||||
- FIX: mlib.polygon.checkPoint now handles vertices better.
|
||||
|
||||
|
||||
To-Do
|
||||
----
|
||||
- Add more functions.
|
||||
|
||||
0.9.0
|
||||
====
|
||||
Added:
|
||||
----
|
||||
- mlib.line.getDistance as an alias for mlib.line.getLength.
|
||||
- mlib.line.checkPoint
|
||||
- Internal documentation.
|
||||
|
||||
Removed:
|
||||
----
|
||||
- mlib.circle.isPointInCircle is replaced with mlib.circle.checkPoint
|
||||
- mlib.circle.checkPoint is replaced with mlib.circle.isPointOnCircle
|
||||
- Variation of mlib.circle.getLineIntersection( cx, cy, radius, slope, intercept ) is no longer supported, as it can cause errors with vertical lines.
|
||||
|
||||
Changed:
|
||||
----
|
||||
- CHANGE: mlib.line.getIntersection now returns true for colinear lines.
|
||||
- CHANGE: mlib.line.getIntersection now returns true if the line are collinear.
|
||||
- CHANGE: mlib.line.getIntersection now returns true if vertical lines are collinear.
|
||||
- CHANGE: mlib.line.getSegmentIntersection now returns true if the line and segment are collinear.
|
||||
- CHANGE: Changed the order of mlib.line.segment.checkPoint arguments.
|
||||
- NAME: mlib.polygon.lineIntersects is now mlib.polygon.getLineIntersection
|
||||
- NAME: mlib.polygon.lineSegmentIntersects is now mlib.polygon.getSegmentIntersection
|
||||
- NAME: mlib.polygon.isLineSegmentInside is now mlib.polygon.isSegmentInside
|
||||
- NAME: mlib.polygon.polygonIntersects is now mlib.polygon.getPolygonIntersection
|
||||
- CHANGED: mlib.circle.checkPoint now takes arguments ( px, py, cx, cy, radius ).
|
||||
- CHANGED: mlib.circle.isPointOnCircle now takes arguments ( px, py, cx, cy, radius ).
|
||||
- NAME: mlib.polygon.circleIntersects is now mlib.polygon.getCircleIntersection
|
||||
- NAME: mlib.circle.isLineSecant is now mlib.circle.getLineIntersection
|
||||
- NAME: mlib.circle.isSegmentSecant is now mlib.circle.getSegmentIntersection
|
||||
- NAME: mlib.circle.circlesIntersects is now mlib.circle.getCircleIntersection
|
||||
- CHANGE: Added types 'tangent' and 'intersection' to mlib.circle.getCircleIntersection.
|
||||
- NAME: mlib.math.getRootsOfQuadratic is now mlib.math.getQuadraticRoots
|
||||
- CHANGE: mlib.math.getRoot now only returns the positive, since it there is not always negatives.
|
||||
- NAME: mlib.math.getPercent is now mlib.math.getPercentage
|
||||
|
||||
- Cleaned up code (added comments, spaced lines, etc.)
|
||||
- Made syntax that uses camelCase instead of CamelCase.
|
||||
- Match style of more programmers.
|
||||
- Easier to type.
|
||||
- Moved to semantic numbering.
|
||||
- Made any returns strings lower-case.
|
||||
- Updated specs for missing functions.
|
||||
|
||||
To-Do
|
||||
----
|
||||
- Update readme.
|
||||
- Add mlib.statistics.getStandardDeviation
|
||||
- Add mlib.statistics.getMeasuresOfCentralTendency
|
||||
- Add mlib.statistics.getMeasuresOfDispersion
|
||||
|
||||
1.1.0.2
|
||||
====
|
||||
Added:
|
||||
----
|
||||
- MLib.Polygon.IsPolygonInside
|
||||
|
||||
Removed:
|
||||
----
|
||||
- Removed all MLib.Shape:
|
||||
- Was very slow.
|
||||
- Could not define custom callbacks.
|
||||
- Allow for flexibility.
|
||||
|
||||
Changed:
|
||||
----
|
||||
- Switched MLib.Line.GetIntersection back to the old way
|
||||
- MLib.Line.GetSegmentIntersection now returns 4 values if the lines are parallel.
|
||||
|
||||
TODO:
|
||||
- Make it so that MLib.Shape objects can use ':' syntax for other functions (i.e. MLib.Line.GetLength for Line objects, etc.)
|
||||
- Intuitive error messages.
|
||||
|
||||
|
||||
1.1.0.1
|
||||
====
|
||||
Added:
|
||||
----
|
||||
|
||||
Removed:
|
||||
----
|
||||
|
||||
Changed:
|
||||
- MLib.Line.GetIntersection now returns true, instead of two points.
|
||||
|
||||
----
|
||||
|
||||
Fixed:
|
||||
----
|
||||
- MLib.Line.GetIntersection now handles vertical lines: returns true if they collide, false otherwise.
|
||||
- MLib.Polygon.LineIntersects now also handles verticals.
|
||||
|
||||
TODO:
|
||||
- Fix
|
||||
- MLib.Shape Table can't have metatables.
|
||||
|
||||
1.1.0.0
|
||||
====
|
||||
Added:
|
||||
----
|
||||
- MLib.Polygon.IsCircleInside
|
||||
- MLib.Polygon.LineSegmentIntersects
|
||||
- MLib.Polygon.IsLineSegmentInside
|
||||
- MLib.Statistics.GetFrequency
|
||||
- MLib.Math.Factorial
|
||||
- MLib.Math.SystemOfEquations
|
||||
|
||||
Removed:
|
||||
----
|
||||
|
||||
Changed:
|
||||
----
|
||||
- MLib.Polygon.LineIntersects is now MLib.Polygon.LineSegmentIntersects.
|
||||
- Put Word-wrap on Changes.txt
|
||||
|
||||
Fixed:
|
||||
----
|
||||
- Problems with numberous MLib.Polygon and MLib.Circle problems.
|
||||
|
||||
TODO:
|
||||
- Fix
|
||||
- MLib.Shape Table can't have metatables.
|
||||
|
||||
1.0.0.3
|
||||
====
|
||||
Added:
|
||||
----
|
||||
|
||||
Removed:
|
||||
----
|
||||
|
||||
Changed:
|
||||
----
|
||||
|
||||
Fixed:
|
||||
----
|
||||
- README.md
|
||||
|
||||
TODO:
|
||||
- Add:
|
||||
- Frequency
|
||||
- Binomial Probability
|
||||
- Standard Deviation
|
||||
- Conditional Probability
|
||||
|
||||
1.0.0.2
|
||||
====
|
||||
Added:
|
||||
----
|
||||
|
||||
Removed:
|
||||
----
|
||||
- Ability to use a direction for Math.GetAngle's 5th argument instead of having a third point. See Fixed for more.
|
||||
|
||||
Changed:
|
||||
----
|
||||
- Changed README.md for clarity and consistency.
|
||||
- Updated spec.lua
|
||||
- See Fixed for more.
|
||||
|
||||
Fixed:
|
||||
----
|
||||
- Circle.IsSegmentSecant now properly accounts for chords actually being chords, and not secants.
|
||||
- Circle.CircleIntersects now can return 'Colinear' or 'Equal' if the circles have same x and y but different radii (Colinear) or are exactly the same (Equal).
|
||||
- Statistics.GetMode now returns a table with the modes, and the second argument as the number of times they appear.
|
||||
- Math.GetRoot now returns the negative number as a second argument.
|
||||
- Math.GetPercentOfChange now works for 0 to 0 (previously false).
|
||||
- Math.GetAngle now takes only three points and no direction option.
|
||||
- Typos in Shape.CheckCollisions and Shape.Remove.
|
||||
- Fixed nil problems in Shape.CheckCollisions.
|
||||
- Improved readablility and DRYness of Shape.CheckCollisions.
|
||||
- Bugs in Shape.Remove and Shape.CheckCollisions regarding passing tables as arguments.
|
||||
|
||||
TODO:
|
||||
- Add:
|
||||
- Frequency
|
||||
- Binomial Probability
|
||||
- Standard Deviation
|
||||
- Conditional Probability
|
||||
|
||||
1.0.0.1
|
||||
====
|
||||
Added:
|
||||
----
|
||||
|
||||
Removed:
|
||||
----
|
||||
|
||||
Changed:
|
||||
----
|
||||
- Changes.txt now expanded to include short excertps from all previous commits.
|
||||
- Changed release number from 3.0.0 to 1.0.0.1
|
||||
- Math.Round now can round to decimal places as the second argument.
|
||||
- Commented unnecessary call of Segment.CheckPoint in Polygon.LineIntersects.
|
||||
- Polygon.LineIntersects now returns where the lines intersect.
|
||||
- false if not intersection.
|
||||
- A table with all of the intersections { { px, py } }
|
||||
- Same with Polygon.PolygonIntersects, Polygon.CircleIntersects,
|
||||
|
||||
Fixed:
|
||||
----
|
||||
- Error with GetSlope being called incorrectly.
|
||||
- README.md Line.GetPerpendicularSlope misdirection.
|
||||
- Same with Line.GetPerpendicularBisector, Line.Segment.GetIntersection, Circle.IsLineSecant, Circle.IsSegmentSecant, Statistics.GetMean, Median, Mode, and Range, and Shape:Remove, and fixed the naming for Shape:CheckCollisions and Shape:Remove.
|
||||
- Clarified README.md
|
||||
- Made util SortWithReferences local.
|
||||
- Errors caused by local functions.
|
||||
|
||||
TODO:
|
||||
- Add:
|
||||
- Frequency
|
||||
- Binomial Probability
|
||||
- Standard Deviation
|
||||
- Conditional Probability
|
||||
|
||||
3.0.0
|
||||
-----
|
||||
ADDED:
|
||||
- Added function GetSignedArea.
|
||||
REMOVED:
|
||||
- Removed drawing functions.
|
||||
- Removed MLib.Line.Functions entirely.
|
||||
CHANGED:
|
||||
- Changed all the names to CamelCase.
|
||||
- Changed module name to MLib.
|
||||
- Changed return order of GetPerpendicualrBisector from Slope, Midpoint to Midpoint, Slope.
|
||||
- Changed returned string of MLib.circle.isLineSecant to be upper-case.
|
||||
- Changed IsPrime to accept only one number at a time.
|
||||
- Changed NewShape's type to Capitals.
|
||||
|
||||
Related to code:
|
||||
- Added more accuarate comments.
|
||||
- Made code more DRY.
|
||||
- Made code monkey-patchable and saved space (by declaring all functions as local values then inserted them into a large table.
|
||||
|
||||
TODO:
|
||||
- Make LineIntersectsPolygon return where intersection occurs.
|
||||
- Ditto with PolygonIntersectsPolygon.
|
||||
- Add:
|
||||
- Frequency
|
||||
- Binomial Probability
|
||||
- Standard Deviation
|
||||
- Conditional Probability
|
||||
|
||||
|
||||
Not as accurately maintained before 2.0.2
|
||||
-----------------------------------------
|
||||
|
||||
2.0.2
|
||||
-----
|
||||
- Cleaned up code, mostly.
|
||||
|
||||
2.0.1
|
||||
-----
|
||||
- Bug fixes, mlib.shape:remove & demos added.
|
||||
|
||||
2.0.0
|
||||
-----
|
||||
- Added mlib.shape and various bug fixes.
|
||||
|
||||
2.0.0
|
||||
-----
|
||||
- Made mlib.shape and made numberous bug fixes.
|
||||
|
||||
1.9.4
|
||||
-----
|
||||
- Made mlib.math.prime faster and removed ability to test multiple numbers at once. Thanks Robin!
|
||||
|
||||
1.9.3
|
||||
-----
|
||||
- Fixed polygon.area and polygon.centroid
|
||||
|
||||
1.9.2
|
||||
-----
|
||||
- Updated to LOVE 0.9.0.
|
||||
|
||||
1.9.1
|
||||
-----
|
||||
- Made mlib.line.closestPoint able to take either two points on the slope or the slope and intercept.
|
||||
|
||||
1.9.0
|
||||
-----
|
||||
- Added mlib.lineSegmentIntersects (no affiliation with previous one (changed to mlib.line.segment.intersect)) and mlib.line.closestPoint
|
||||
|
||||
1.8.3
|
||||
-----
|
||||
- Changed naming mechanism to be more organized.
|
||||
|
||||
1.8.2
|
||||
-----
|
||||
- "Fixed" mlib.lineSegmentsIntersect AGAIN!!!! :x
|
||||
|
||||
1.8.1
|
||||
-----
|
||||
- Removed a print statement.
|
||||
|
||||
1.8.0
|
||||
-----
|
||||
- mlib.pointInPolygon added
|
||||
|
||||
1.7.5
|
||||
-----
|
||||
- mlib.lineSegmentsIntersect vertical lines fixed again. This time for real. I promise... or hope, at least... :P
|
||||
|
||||
1.7.4
|
||||
-----
|
||||
- mlib.lineSegmentsIntersect vertical parallels fixed
|
||||
|
||||
1.7.3
|
||||
-----
|
||||
- mlib.lineSegmentsIntersect parallels fixed
|
||||
|
||||
1.7.2
|
||||
-----
|
||||
- mlib.lineSegmentsIntersect now handles vertical lines
|
||||
|
||||
1.7.1
|
||||
-----
|
||||
- mlib.lineSegmentsIntersect now returns the two places in between where the line segments begin to intersect.
|
||||
|
||||
1.7.0
|
||||
-----
|
||||
- Added mlib.circlesIntersect, mlib.pointOnLineSegment, mlib.linesIntersect, and mlib.lineSegmentsIntersect
|
||||
|
||||
1.6.1
|
||||
-----
|
||||
- Employed usage of summations for mlib.getPolygonArea and mlib.getPolygonCentroid and removed area as an argument for mlib.getPolygonCentroid.
|
||||
|
||||
1.6.0
|
||||
-----
|
||||
- Added several functions.
|
||||
|
||||
1.5.0
|
||||
-----
|
||||
- Made lots of changes to syntax to make it easier to use (hopefully). I also put out specs.
|
||||
|
||||
1.4.1
|
||||
-----
|
||||
- Localized mlib. Thanks, Yonaba!
|
||||
|
||||
1.4.0
|
||||
-----
|
||||
- Added mlib.getPolygonCentroid (gets the midpoint of a non-self-intersecting polygons)
|
||||
|
||||
1.3.2
|
||||
-----
|
||||
- Made mlib.getPrime take tables as arguments, so you can check all the values of a table.
|
||||
|
||||
1.3.1
|
||||
-----
|
||||
- Changed name method to mlib.getPolygonArea
|
||||
|
||||
1.3.0
|
||||
-----
|
||||
- Added mlib.get_polygon_area and removed mlib.get_convex_area and mlib.get_triangle_area since they are repetitive.
|
||||
|
||||
1.2.2
|
||||
-----
|
||||
- Made functions return faster, functions that previously returned tables now return multiple arguments.
|
||||
|
||||
1.2.1
|
||||
-----
|
||||
- Localized functions, made tables acceptable as arguments, refined function speed, mlib.get_mode now returns number most repeated as well as how many times.
|
||||
|
||||
1.2.0
|
||||
-----
|
||||
- Added mlib.get_angle
|
||||
|
||||
1.1.0
|
||||
-----
|
||||
- Added mlib.get_convex_area
|
||||
|
||||
1.0.4
|
||||
-----
|
||||
- Fixed get_mode to handle bimodials.
|
||||
|
||||
1.0.3
|
||||
-----
|
||||
- Prime Checker optimized (hopefully final update on this.)
|
||||
|
||||
1.0.2
|
||||
-----
|
||||
- Prime checker now works! (At least to 1000. I haven't tested any
|
||||
further)
|
||||
|
||||
1.0.1
|
||||
-----
|
||||
- 'Fixed' the prime checker
|
||||
|
||||
1.0.0
|
||||
-----
|
||||
- Initial release
|
||||
17
deps/windfield/mlib/LICENSE.md
vendored
Normal file
17
deps/windfield/mlib/LICENSE.md
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
Copyright (c) 2015 Davis Claiborne
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgement in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
890
deps/windfield/mlib/README.md
vendored
Normal file
890
deps/windfield/mlib/README.md
vendored
Normal file
@@ -0,0 +1,890 @@
|
||||
MLib
|
||||
====
|
||||
|
||||
__MLib__ is a math and shape-intersection detection library written in Lua. It's aim is to be __robust__ and __easy to use__.
|
||||
|
||||
__NOTE:__
|
||||
- I am (slowly) working on completely rewriting this in order to be easier to use and less bug-prone. You can check out the progress [here](../../tree/dev).
|
||||
- I am currently slowing development of MLib while moving over to helping with [CPML](https://github.com/excessive/cpml). To discuss this, please comment [here](../../issues/12).
|
||||
|
||||
If you are looking for a library that handles updating/collision responses for you, take a look at [hxdx](https://github.com/adonaac/hxdx). It uses MLib functions as well as Box2d to handle physics calculations.
|
||||
|
||||
## Downloading
|
||||
You can download the latest __stable__ version of MLib by downloading the latest [release](../../releases/).
|
||||
You can download the latest __working__ version of MLib by downloading the latest [commit](../../commits/master/). Documentation will __only__ be updated upon releases, not upon commits.
|
||||
|
||||
## Implementing
|
||||
To use MLib, simply place [mlib.lua](mlib.lua) inside the desired folder in your project. Then use the `require 'path.to.mlib'` to use any of the functions.
|
||||
|
||||
## Examples
|
||||
If you don't have [LÖVE](https://love2d.org/) installed, you can download the .zip of the demo from the [Executables](Examples/Executables) folder and extract and run the .exe that way.
|
||||
You can see some examples of the code in action [here](Examples).
|
||||
All examples are done using the *awesome* engine of [LÖVE](https://love2d.org/).
|
||||
To run them properly, download the [.love file](Examples/LOVE) and install LÖVE to your computer.
|
||||
After that, make sure you set .love files to open with "love.exe".
|
||||
For more, see [here](https://love2d.org/).
|
||||
|
||||
## When should I use MLib?
|
||||
- If you need to know exactly where two objects intersect.
|
||||
- If you need general mathematical equations to be done.
|
||||
- If you need very precise details about point intersections.
|
||||
|
||||
## When should I __not__ use MLib?
|
||||
- All of the objects in a platformer, or other game, for instance, should not be registered with MLib. Only ones that need very specific information.
|
||||
- When you don't need precise information/odd shapes.
|
||||
|
||||
## Specs
|
||||
#### For Windows
|
||||
If you run Windows and have Telescope in `%USERPROFILE%\Documents\GitHub` (you can also manually change the path in [test.bat](test.bat)) you can simply run [test.bat](test.bat) and it will display the results, and then clean up after it's finished.
|
||||
|
||||
#### Default
|
||||
Alternatively, you can find the tests [here](spec.lua). Keep in mind that you may need to change certain semantics to suit your OS.
|
||||
You can run them via [Telescope](https://github.com/norman/telescope/) and type the following command in the command-line of the root folder:
|
||||
```
|
||||
tsc -f specs.lua
|
||||
```
|
||||
If that does not work, you made need to put a link to Lua inside of the folder for `telescope` and run the following command:
|
||||
```
|
||||
lua tsc -f specs.lua
|
||||
```
|
||||
If you encounter further errors, try to run the command line as an administrator (usually located in `C:\Windows\System32\`), then right-click on `cmd.exe` and select `Run as administrator`, then do
|
||||
```
|
||||
cd C:\Path\to\telescope\
|
||||
```
|
||||
And __then__ run one of the above commands. If none of those work, just take my word for it that all the tests pass and look at this picture.
|
||||

|
||||
|
||||
## Functions
|
||||
- [mlib.line](#mlibline)
|
||||
- [mlib.line.checkPoint](#mliblinecheckpoint)
|
||||
- [mlib.line.getClosestPoint](#mliblinegetclosestpoint)
|
||||
- [mlib.line.getYIntercept](#mliblinegetintercept)
|
||||
- [mlib.line.getIntersection](#mliblinegetintersection)
|
||||
- [mlib.line.getLength](#mliblinegetlength)
|
||||
- [mlib.line.getMidpoint](#mliblinegetmidpoint)
|
||||
- [mlib.line.getPerpendicularSlope](#mliblinegetperpendicularslope)
|
||||
- [mlib.line.getSegmentIntersection](#mliblinegetsegmentintersection)
|
||||
- [mlib.line.getSlope](#mliblinegetslope)
|
||||
- [mlib.segment](#mlibsegment)
|
||||
- [mlib.segment.checkPoint](#mlibsegmentcheckpoint)
|
||||
- [mlib.segment.getPerpendicularBisector](#mlibsegmentgetperpendicularbisector)
|
||||
- [mlib.segment.getIntersection](#mlibsegmentgetintersection)
|
||||
- [mlib.polygon](#mlibpolygon)
|
||||
- [mlib.polygon.checkPoint](#mlibpolygoncheckpoint)
|
||||
- [mlib.polygon.getCentroid](#mlibpolygongetcentroid)
|
||||
- [mlib.polygon.getCircleIntersection](#mlibpolygongetcircleintersection)
|
||||
- [mlib.polygon.getLineIntersection](#mlibpolygongetlineintersection)
|
||||
- [mlib.polygon.getPolygonArea](#mlibpolygongetpolygonarea)
|
||||
- [mlib.polygon.getPolygonIntersection](#mlibpolygongetpolygonintersection)
|
||||
- [mlib.polygon.getSegmentIntersection](#mlibpolygongetsegmentintersection)
|
||||
- [mlib.polygon.getSignedPolygonArea](#mlibpolygongetsignedpolygonarea)
|
||||
- [mlib.polygon.getTriangleHeight](#mlibpolygongettriangleheight)
|
||||
- [mlib.polygon.isCircleInside](#mlibpolygoniscircleinside)
|
||||
- [mlib.polygon.isCircleCompletelyInside](#mlibpolygoniscirclecompletelyinside)
|
||||
- [mlib.polygon.isPolygonInside](#mlibpolygonispolygoninside)
|
||||
- [mlib.polygon.isPolygonCompletelyInside](#mlibpolygonispolygoncompletelyinside)
|
||||
- [mlib.polygon.isSegmentInside](#mlibpolygonissegmentinside)
|
||||
- [mlib.polygon.isSegmentCompletelyInside](#mlibpolygonissegmentcompletelyinside)
|
||||
- [mlib.circle](#mlibcircle)
|
||||
- [mlib.circle.checkPoint](#mlibcirclecheckpoint)
|
||||
- [mlib.circle.getArea](#mlibcirclegetarea)
|
||||
- [mlib.circle.getCircleIntersection](#mlibcirclegetcircleintersection)
|
||||
- [mlib.circle.getCircumference](#mlibcirclegetcircumference)
|
||||
- [mlib.circle.getLineIntersection](#mlibcirclegetlineintersection)
|
||||
- [mlib.circle.getSegmentIntersection](#mlibcirclegetsegmentintersection)
|
||||
- [mlib.circle.isCircleCompletelyInside](#mlibcircleiscirclecompletelyinside)
|
||||
- [mlib.circle.isCircleCompletelyInsidePolygon](#mlibcircleiscirclecompletelyinsidepolygon)
|
||||
- [mlib.circle.isPointOnCircle](#mlibcircleispointoncircle)
|
||||
- [mlib.circle.isPolygonCompletelyInside](#mlibcircleispolygoncompletelyinside)
|
||||
- [mlib.statistics](#mlibstatistics)
|
||||
- [mlib.statistics.getCentralTendency](#mlibstatisticsgetcentraltendency)
|
||||
- [mlib.statistics.getDispersion](#mlibstatisticsgetdispersion)
|
||||
- [mlib.statistics.getMean](#mlibstatisticsgetmean)
|
||||
- [mlib.statistics.getMedian](#mlibstatisticsgetmedian)
|
||||
- [mlib.statistics.getMode](#mlibstatisticsgetmode)
|
||||
- [mlib.statistics.getRange](#mlibstatisticsgetrange)
|
||||
- [mlib.statistics.getStandardDeviation](#mlibstatisticsgetstandarddeviation)
|
||||
- [mlib.statistics.getVariance](#mlibstatisticsgetvariance)
|
||||
- [mlib.statistics.getVariationRatio](#mlibstatisticsgetvariationratio)
|
||||
- [mlib.math](#mlibmath)
|
||||
- [mlib.math.getAngle](#mlibmathgetangle)
|
||||
- [mlib.math.getPercentage](#mlibmathgetpercentage)
|
||||
- [mlib.math.getPercentOfChange](#mlibmathgetpercentofchange)
|
||||
- [mlib.math.getQuadraticRoots](#mlibmathgetquadraticroots)
|
||||
- [mlib.math.getRoot](#mlibmathgetroot)
|
||||
- [mlib.math.getSummation](#mlibmathgetsummation)
|
||||
- [mlib.math.isPrime](#mlibmathisprime)
|
||||
- [mlib.math.round](#mlibmathround)
|
||||
- [Aliases](#aliases)
|
||||
|
||||
#### mlib.line
|
||||
- Deals with linear aspects, such as slope and length.
|
||||
|
||||
##### mlib.line.checkPoint
|
||||
- Checks if a point lies on a line.
|
||||
- Synopsis:
|
||||
- `onPoint = mlib.line.checkPoint( px, px, x1, y1, x2, y2 )`
|
||||
- Arguments:
|
||||
- `px`, `py`: Numbers. The x and y coordinates of the point being tested.
|
||||
- `x1`, `y1`, `x2`, `y2`: Numbers. Two x and y coordinates of the line being tested.
|
||||
- Returns:
|
||||
- `onPoint`: Boolean.
|
||||
- `true` if the point is on the line.
|
||||
- `false` if it does not.
|
||||
- Notes:
|
||||
- You cannot use the format `mlib.line.checkPoint( px, px, slope, intercept )` because this would lead to errors on vertical lines.
|
||||
|
||||
##### mlib.line.getClosestPoint
|
||||
- Gives the closest point to a line.
|
||||
- Synopses:
|
||||
- `cx, cy = mlib.line.getClosestPoint( px, py, x1, y1, x2, y2 )`
|
||||
- `cx, cy = mlib.line.getClosestPoint( px, py, slope, intercept )`
|
||||
- Arguments:
|
||||
- `x`, `y`: Numbers. The x and y coordinates of the point.
|
||||
- `x1`, `y1`, `x2`, `y2`: Numbers. Two x and y coordinates on the line.
|
||||
- `slope`, `intercept`:
|
||||
- Numbers. The slope and y-intercept of the line.
|
||||
- Booleans (`false`). The slope and y-intercept of a vertical line.
|
||||
- Returns:
|
||||
- `cx`, `cy`: Numbers. The closest points that lie on the line to the point.
|
||||
|
||||
##### mlib.line.getYIntercept
|
||||
- Gives y-intercept of the line.
|
||||
- Synopses:
|
||||
- `intercept, isVertical = mlib.line.getYIntercept( x1, y1, x2, y2 )`
|
||||
- `intercept, isVertical = mlib.line.getYIntercept( x1, y1, slope )`
|
||||
- Arguments:
|
||||
- `x1`, `y1`, `x2`, `y2`: Numbers. Two x and y coordinates that lie on the line.
|
||||
- `slope`:
|
||||
- Number. The slope of the line.
|
||||
- Returns:
|
||||
- `intercept`:
|
||||
- Number. The y-intercept of the line.
|
||||
- Number. The `x1` coordinate of the line if the line is vertical.
|
||||
- `isVertical`:
|
||||
- Boolean. `true` if the line is vertical, `false` if the line is not vertical.
|
||||
|
||||
##### mlib.line.getIntersection
|
||||
- Gives the intersection of two lines.
|
||||
- Synopses:
|
||||
- `x, y = mlib.line.getIntersection( x1, y1, x2, y2, x3, y3, x4, y4 )`
|
||||
- `x, y = mlib.line.getIntersection( slope1, intercept1, x3, y3, x4, y4 )`
|
||||
- `x, y = mlib.line.getIntersection( slope1, intercept1, slope2, intercept2 )`
|
||||
- Arguments:
|
||||
- `x1`, `y1`, `x2`, `y2`: Numbers. Two x and y coordinates that lie on the first line.
|
||||
- `x3`, `y3`, `x4`, `y4`: Numbers. Two x and y coordinates that lie on the second line.
|
||||
- `slope1`, `intercept1`:
|
||||
- Numbers. The slope and y-intercept of the first line.
|
||||
- Booleans (`false`). The slope and y-intercept of the first line (if the first line is vertical).
|
||||
- `slope2`, `intercept2`:
|
||||
- Numbers. The slope and y-intercept of the second line.
|
||||
- Booleans (`false`). The slope and y-intercept of the second line (if the second line is vertical).
|
||||
- Returns:
|
||||
- `x`, `y`:
|
||||
- Numbers. The x and y coordinate where the lines intersect.
|
||||
- Boolean:
|
||||
- `true`, `nil`: The lines are collinear.
|
||||
- `false`, `nil`: The lines are parallel and __not__ collinear.
|
||||
|
||||
##### mlib.line.getLength
|
||||
- Gives the distance between two points.
|
||||
- Synopsis:
|
||||
- `length = mlib.line.getLength( x1, y1, x2, y2 )
|
||||
- Arguments:
|
||||
- `x1`, `y1`, `x2`, `y2`: Numbers. Two x and y coordinates.
|
||||
- Returns:
|
||||
- `length`: Number. The distance between the two points.
|
||||
|
||||
##### mlib.line.getMidpoint
|
||||
- Gives the midpoint of two points.
|
||||
- Synopsis:
|
||||
- `x, y = mlib.line.getMidpoint( x1, y1, x2, y2 )`
|
||||
- Arguments:
|
||||
- `x1`, `y1`, `x2`, `y2`: Numbers. Two x and y coordinates.
|
||||
- Returns:
|
||||
- `x`, `y`: Numbers. The midpoint x and y coordinates.
|
||||
|
||||
##### mlib.line.getPerpendicularSlope
|
||||
- Gives the perpendicular slope of a line.
|
||||
- Synopses:
|
||||
- `perpSlope = mlib.line.getPerpendicularSlope( x1, y1, x2, y2 )`
|
||||
- `perpSlope = mlib.line.getPerpendicularSlope( slope )`
|
||||
- Arguments:
|
||||
- `x1`, `y1`, `x2`, `y2`: Numbers. Two x and y coordinates.
|
||||
- `slope`: Number. The slope of the line.
|
||||
- Returns:
|
||||
- `perpSlope`:
|
||||
- Number. The perpendicular slope of the line.
|
||||
- Boolean (`false`). The perpendicular slope of the line (if the original line was horizontal).
|
||||
|
||||
##### mlib.line.getSegmentIntersection
|
||||
- Gives the intersection of a line segment and a line.
|
||||
- Synopses:
|
||||
- `x1, y1, x2, y2 = mlib.line.getSegmentIntersection( x1, y1, x2, y2, x3, y3, x4, y4 )`
|
||||
- `x1, y1, x2, y2 = mlib.line.getSegmentIntersection( x1, y1, x2, y2, slope, intercept )`
|
||||
- Arguments:
|
||||
- `x1`, `y1`, `x2`, `y2`: Numbers. Two x and y coordinates that lie on the line segment.
|
||||
- `x3`, `y3`, `x4`, `y4`: Numbers. Two x and y coordinates that lie on the line.
|
||||
- `slope`, `intercept`:
|
||||
- Numbers. The slope and y-intercept of the the line.
|
||||
- Booleans (`false`). The slope and y-intercept of the line (if the line is vertical).
|
||||
- Returns:
|
||||
- `x1`, `y1`, `x2`, `y2`:
|
||||
- Number, Number, Number, Number.
|
||||
- The points of the line segment if the line and segment are collinear.
|
||||
- Number, Number, Boolean (`nil`), Boolean (`nil`).
|
||||
- The coordinate of intersection if the line and segment intersect and are not collinear.
|
||||
- Boolean (`false`), Boolean (`nil`), Boolean (`nil`),
|
||||
- Boolean (`nil`). If the line and segment don't intersect.
|
||||
|
||||
##### mlib.line.getSlope
|
||||
- Gives the slope of a line.
|
||||
- Synopsis:
|
||||
- `slope = mlib.line.getSlope( x1, y1, x2, y2 )
|
||||
- Arguments:
|
||||
- `x1`, `y1`, `x2`, `y2`: Numbers. Two x and y coordinates.
|
||||
- Returns:
|
||||
- `slope`:
|
||||
- Number. The slope of the line.
|
||||
- Boolean (`false`). The slope of the line (if the line is vertical).
|
||||
|
||||
#### mlib.segment
|
||||
- Deals with line segments.
|
||||
|
||||
##### mlib.segment.checkPoint
|
||||
- Checks if a point lies on a line segment.
|
||||
- Synopsis:
|
||||
- `onSegment = mlib.segment.checkPoint( px, py, x1 y1, x2, y2 )`
|
||||
- Arguments:
|
||||
- `px`, `py`: Numbers. The x and y coordinates of the point being checked.
|
||||
- `x1`, `y1`, `x2`, `y2`: Numbers. Two x and y coordinates.
|
||||
- Returns:
|
||||
- `onSegment`: Boolean.
|
||||
- `true` if the point lies on the line segment.
|
||||
- `false` if the point does not lie on the line segment.
|
||||
|
||||
##### mlib.segment.getPerpendicularBisector
|
||||
- Gives the perpendicular bisector of a line.
|
||||
- Synopsis:
|
||||
- `x, y, slope = mlib.segment.getPerpendicularBisector( x1, y1, x2, y2 )`
|
||||
- Arguments:
|
||||
- `x1`, `y1`, `x2`, `y2`: Numbers. Two x and y coordinates.
|
||||
- Returns:
|
||||
- `x`, `y`: Numbers. The midpoint of the line.
|
||||
- `slope`:
|
||||
- Number. The perpendicular slope of the line.
|
||||
- Boolean (`false`). The perpendicular slope of the line (if the original line was horizontal).
|
||||
|
||||
##### mlib.segment.getIntersection
|
||||
- Checks if two line segments intersect.
|
||||
- Synopsis:
|
||||
- `cx1, cy1, cx2, cy2 = mlib.segment.getIntersection( x1, y1, x2, y2, x3, y3 x4, y4 )`
|
||||
- Arguments:
|
||||
- `x1`, `y1`, `x2`, `y2`: Numbers. Two x and y coordinates of the first line segment.
|
||||
- `x3`, `y3`, `x4`, `y4`: Numbers. Two x and y coordinates of the second line segment.
|
||||
- Returns:
|
||||
- `cx1`, `cy1`, `cx2`, `cy2`:
|
||||
- Number, Number, Number, Number.
|
||||
- The points of the resulting intersection if the line segments are collinear.
|
||||
- Number, Number, Boolean (`nil`), Boolean (`nil`).
|
||||
- The point of the resulting intersection if the line segments are not collinear.
|
||||
- Boolean (`false`), Boolean (`nil`), Boolean (`nil`) , Boolean (`nil`).
|
||||
- If the line segments don't intersect.
|
||||
|
||||
#### mlib.polygon
|
||||
- Handles aspects involving polygons.
|
||||
|
||||
##### mlib.polygon.checkPoint
|
||||
- Checks if a point is inside of a polygon.
|
||||
- Synopses:
|
||||
- `inPolygon = mlib.polygon.checkPoint( px, py, vertices )`
|
||||
- `inPolygon = mlib.polygon.checkPoint( px, py, ... )`
|
||||
- Arguments:
|
||||
- `px`, `py`: Numbers. The x and y coordinate of the point being checked.
|
||||
- `vertices`: Table. The vertices of the polygon in the format `{ x1, y1, x2, y2, x3, y3, ... }`
|
||||
- `...`: Numbers. The x and y coordinates of the polygon. (Same as using `unpack( vertices )`)
|
||||
- Returns:
|
||||
- `inPolygon`: Boolean.
|
||||
- `true` if the point is inside the polygon.
|
||||
- `false` if the point is not inside the polygon.
|
||||
|
||||
##### mlib.polygon.getCentroid
|
||||
- Returns the centroid of the polygon.
|
||||
- Synopses:
|
||||
- `cx, cy = mlib.polygon.getCentroid( vertices )`
|
||||
- `cx, cy = mlib.polygon.getCentroid( ... )`
|
||||
- Arguments:
|
||||
- `vertices`: Table. The vertices of the polygon in the format `{ x1, y1, x2, y2, x3, y3, ... }`
|
||||
- `...`: Numbers. The x and y coordinates of the polygon. (Same as using `unpack( vertices )`)
|
||||
- Returns:
|
||||
- `cx`, `cy`: Numbers. The x and y coordinates of the centroid.
|
||||
|
||||
##### mlib.polygon.getCircleIntersection
|
||||
- Returns the coordinates of where a circle intersects a polygon.
|
||||
- Synopses:
|
||||
- `intersections = mlib.polygon.getCircleIntersection( cx, cy, radius, vertices )`
|
||||
- `intersections = mlib.polygon.getCircleIntersection( cx, cy, radius, ... )
|
||||
- Arguments:
|
||||
- `cx`, `cy`: Number. The coordinates of the center of the circle.
|
||||
- `radius`: Number. The radius of the circle.
|
||||
- `vertices`: Table. The vertices of the polygon in the format `{ x1, y1, x2, y2, x3, y3, ... }`
|
||||
- `...`: Numbers. The x and y coordinates of the polygon. (Same as using `unpack( vertices )`)
|
||||
- Returns:
|
||||
- `intersections`: Table. Contains the intersections and type.
|
||||
- Example:
|
||||
```lua
|
||||
local tab = _.polygon.getCircleIntersection( 5, 5, 1, 4, 4, 6, 4, 6, 6, 4, 6 )
|
||||
for i = 1, # tab do
|
||||
print( i .. ':', unpack( tab[i] ) )
|
||||
end
|
||||
-- 1: tangent 5 4
|
||||
-- 2: tangent 6 5
|
||||
-- 3: tangent 5 6
|
||||
-- 4: tagnent 4 5
|
||||
```
|
||||
- For more see [mlib.circle.getSegmentIntersection](#mlibcirclegetsegmentintersection) or the [specs](spec.lua# L676)
|
||||
|
||||
##### mlib.polygon.getLineIntersection
|
||||
- Returns the coordinates of where a line intersects a polygon.
|
||||
- Synopses:
|
||||
- `intersections = mlib.polygon.getLineIntersection( x1, y1, x2, y2, vertices )`
|
||||
- `intersections = mlib.polygon.getLineIntersection( x1, y1, x2, y2, ... )
|
||||
- Arguments:
|
||||
- `x1`, `y1`, `x2`, `y2`: Numbers. Two x and y coordinates.
|
||||
- `vertices`: Table. The vertices of the polygon in the format `{ x1, y1, x2, y2, x3, y3, ... }`
|
||||
- `...`: Numbers. The x and y coordinates of the polygon. (Same as using `unpack( vertices )`)
|
||||
- Returns:
|
||||
- `intersections`: Table. Contains the intersections.
|
||||
- Notes:
|
||||
- With collinear lines, they are actually broken up. i.e. `{ 0, 4, 0, 0 }` would become `{ 0, 4 }, { 0, 0 }`.
|
||||
|
||||
##### mlib.polygon.getPolygonArea
|
||||
- Gives the area of a polygon.
|
||||
- Synopses:
|
||||
- `area = mlib.polygon.getArea( vertices )`
|
||||
- `area = mlib.polygon.getArea( ... )
|
||||
- Arguments:
|
||||
- `vertices`: Table. The vertices of the polygon in the format `{ x1, y1, x2, y2, x3, y3, ... }`
|
||||
- `...`: Numbers. The x and y coordinates of the polygon. (Same as using `unpack( vertices )`)
|
||||
- Returns:
|
||||
- `area`: Number. The area of the polygon.
|
||||
|
||||
##### mlib.polygon.getPolygonIntersection
|
||||
- Gives the intersection of two polygons.
|
||||
- Synopsis:
|
||||
- `intersections = mlib.polygon.getPolygonIntersections( polygon1, polygon2 )`
|
||||
- Arguments:
|
||||
- `polygon1`: Table. The vertices of the first polygon in the format `{ x1, y1, x2, y2, x3, y3, ... }`
|
||||
- `polygon2`: Table. The vertices of the second polygon in the format `{ x1, y1, x2, y2, x3, y3, ... }`
|
||||
- Returns:
|
||||
- `intersections`: Table. A table of the points of intersection.
|
||||
|
||||
##### mlib.polygon.getSegmentIntersection
|
||||
- Returns the coordinates of where a line segmeing intersects a polygon.
|
||||
- Synopses:
|
||||
- `intersections = mlib.polygon.getSegmentIntersection( x1, y1, x2, y2, vertices )`
|
||||
- `intersections = mlib.polygon.getSegmentIntersection( x1, y1, x2, y2, ... )
|
||||
- Arguments:
|
||||
- `x1`, `y1`, `x2`, `y2`: Numbers. Two x and y coordinates.
|
||||
- `vertices`: Table. The vertices of the polygon in the format `{ x1, y1, x2, y2, x3, y3, ... }`
|
||||
- `...`: Numbers. The x and y coordinates of the polygon. (Same as using `unpack( vertices )`)
|
||||
- Returns:
|
||||
- `intersections`: Table. Contains the intersections.
|
||||
- Notes:
|
||||
- With collinear line segments, they are __not__ broken up. See the [specs](spec.lua# L508) for more.
|
||||
|
||||
##### mlib.polygon.getSignedPolygonArea
|
||||
- Gets the signed area of the polygon. If the points are ordered counter-clockwise the area is positive. If the points are ordered clockwise the number is negative.
|
||||
- Synopses:
|
||||
- `area = mlib.polygon.getLineIntersection( vertices )`
|
||||
- `area = mlib.polygon.getLineIntersection( ... )
|
||||
- Arguments:
|
||||
- `vertices`: Table. The vertices of the polygon in the format `{ x1, y1, x2, y2, x3, y3, ... }`
|
||||
- `...`: Numbers. The x and y coordinates of the polygon. (Same as using `unpack( vertices )`)
|
||||
- Returns:
|
||||
- `area`: Number. The __signed__ area of the polygon. If the points are ordered counter-clockwise the area is positive. If the points are ordered clockwise the number is negative.
|
||||
|
||||
##### mlib.polygon.getTriangleHeight
|
||||
- Gives the height of a triangle.
|
||||
- Synopses:
|
||||
- `height = mlib.polygon.getTriangleHeigh( base, x1, y1, x2, y2, x3, y3 )`
|
||||
- `height = mlib.polygon.getTriangleHeight( base, area )`
|
||||
- Arguments:
|
||||
- `base`: Number. The length of the base of the triangle.
|
||||
- `x1`, `y1`, `x2`, `y2`, `x3`, `y3`: Numbers. The x and y coordinates of the triangle.
|
||||
- `area`: Number. The regular area of the triangle. __Not__ the signed area.
|
||||
- Returns:
|
||||
- `height`: Number. The height of the triangle.
|
||||
|
||||
##### mlib.polygon.isCircleInside
|
||||
- Checks if a circle is inside the polygon.
|
||||
- Synopses:
|
||||
- `inPolygon = mlib.polygon.isCircleInside( cx, cy, radius, vertices )`
|
||||
- `inPolygon = mlib.polygon.isCircleInside( cx, cy, radius, ... )`
|
||||
- Arguments:
|
||||
- `cx`, `cy`: Numbers. The x and y coordinates for the center of the circle.
|
||||
- `radius`: Number. The radius of the circle.
|
||||
- `vertices`: Table. The vertices of the polygon in the format `{ x1, y1, x2, y2, x3, y3, ... }`
|
||||
- `...`: Numbers. The x and y coordinates of the polygon. (Same as using `unpack( vertices )`)
|
||||
- Returns:
|
||||
- `inPolygon`: Boolean.
|
||||
- `true` if the circle is inside the polygon.
|
||||
- `false` if the circle is not inside the polygon.
|
||||
- Notes:
|
||||
- Only returns true if the center of the circle is inside the circle.
|
||||
|
||||
##### mlib.polygon.isCircleCompletelyInside
|
||||
- Checks if a circle is completely inside the polygon.
|
||||
- Synopses:
|
||||
- `inPolygon = mlib.polygon.isCircleCompletelyInside( cx, cy, radius, vertices )`
|
||||
- `inPolygon = mlib.polygon.isCircleCompletelyInside( cx, cy, radius, ... )`
|
||||
- Arguments:
|
||||
- `cx`, `cy`: Numbers. The x and y coordinates for the center of the circle.
|
||||
- `radius`: Number. The radius of the circle.
|
||||
- `vertices`: Table. The vertices of the polygon in the format `{ x1, y1, x2, y2, x3, y3, ... }`
|
||||
- `...`: Numbers. The x and y coordinates of the polygon. (Same as using `unpack( vertices )`)
|
||||
- Returns:
|
||||
- `inPolygon`: Boolean.
|
||||
- `true` if the circle is __completely__ inside the polygon.
|
||||
- `false` if the circle is not inside the polygon.
|
||||
|
||||
##### mlib.polygon.isPolygonInside
|
||||
- Checks if a polygon is inside a polygon.
|
||||
- Synopsis:
|
||||
- `inPolygon = mlib.polygon.isPolygonInside( polygon1, polygon2 )`
|
||||
- Arguments:
|
||||
- `polygon1`: Table. The vertices of the first polygon in the format `{ x1, y1, x2, y2, x3, y3, ... }`
|
||||
- `polygon2`: Table. The vertices of the second polygon in the format `{ x1, y1, x2, y2, x3, y3, ... }`
|
||||
- Returns:
|
||||
- `inPolygon`: Boolean.
|
||||
- `true` if the `polygon2` is inside of `polygon1`.
|
||||
- `false` if `polygon2` is not inside of `polygon2`.
|
||||
- Notes:
|
||||
- Returns true as long as any of the line segments of `polygon2` are inside of the `polygon1`.
|
||||
|
||||
##### mlib.polygon.isPolygonCompletelyInside
|
||||
- Checks if a polygon is completely inside a polygon.
|
||||
- Synopsis:
|
||||
- `inPolygon = mlib.polygon.isPolygonCompletelyInside( polygon1, polygon2 )`
|
||||
- Arguments:
|
||||
- `polygon1`: Table. The vertices of the first polygon in the format `{ x1, y1, x2, y2, x3, y3, ... }`
|
||||
- `polygon2`: Table. The vertices of the second polygon in the format `{ x1, y1, x2, y2, x3, y3, ... }`
|
||||
- Returns:
|
||||
- `inPolygon`: Boolean.
|
||||
- `true` if the `polygon2` is __completely__ inside of `polygon1`.
|
||||
- `false` if `polygon2` is not inside of `polygon2`.
|
||||
|
||||
##### mlib.polygon.isSegmentInside
|
||||
- Checks if a line segment is inside a polygon.
|
||||
- Synopses:
|
||||
- `inPolygon = mlib.polygon.isSegmentInside( x1, y1, x2, y2, vertices )`
|
||||
- `inPolygon = mlib.polygon.isSegmentInside( x1, y1, x2, y2, ... )`
|
||||
- Arguments:
|
||||
- `x1`, `y1`, `x2`, `y2`: Numbers. The x and y coordinates of the line segment.
|
||||
- `vertices`: Table. The vertices of the polygon in the format `{ x1, y1, x2, y2, x3, y3, ... }`
|
||||
- `...`: Numbers. The x and y coordinates of the polygon. (Same as using `unpack( vertices )`)
|
||||
- Returns:
|
||||
- `inPolygon`: Boolean.
|
||||
- `true` if the line segment is inside the polygon.
|
||||
- `false` if the line segment is not inside the polygon.
|
||||
- Note:
|
||||
- Only one of the points has to be in the polygon to be considered 'inside' of the polygon.
|
||||
- This is really just a faster version of [mlib.polygon.getPolygonIntersection](#mlibpolygongetpolygonintersection) that does not give the points of intersection.
|
||||
|
||||
##### mlib.polygon.isSegmentCompletelyInside
|
||||
- Checks if a line segment is completely inside a polygon.
|
||||
- Synopses:
|
||||
- `inPolygon = mlib.polygon.isSegmentCompletelyInside( x1, y1, x2, y2, vertices )`
|
||||
- `inPolygon = mlib.polygon.isSegmentCompletelyInside( x1, y1, x2, y2, ... )`
|
||||
- Arguments:
|
||||
- `x1`, `y1`, `x2`, `y2`: Numbers. The x and y coordinates of the line segment.
|
||||
- `vertices`: Table. The vertices of the polygon in the format `{ x1, y1, x2, y2, x3, y3, ... }`
|
||||
- `...`: Numbers. The x and y coordinates of the polygon. (Same as using `unpack( vertices )`)
|
||||
- Returns:
|
||||
- `inPolygon`: Boolean.
|
||||
- `true` if the line segment is __completely__ inside the polygon.
|
||||
- `false` if the line segment is not inside the polygon.
|
||||
|
||||
#### mlib.circle
|
||||
- Handles aspects involving circles.
|
||||
|
||||
##### mlib.circle.checkPoint
|
||||
- Checks if a point is on the inside or on the edge the circle.
|
||||
- Synopsis:
|
||||
- `inCircle = mlib.circle.checkPoint( px, px, cx, cy, radius )`
|
||||
- Arguments:
|
||||
- `px`, `py`: Numbers. The x and y coordinates of the point being tested.
|
||||
- `cx`, `cy`: Numbers. The x and y coordinates of the center of the circle.
|
||||
- `radius`: Number. The radius of the circle.
|
||||
- Returns:
|
||||
- `inCircle`: Boolean.
|
||||
- `true` if the point is inside or on the circle.
|
||||
- `false` if the point is outside of the circle.
|
||||
|
||||
##### mlib.circle.getArea
|
||||
- Gives the area of a circle.
|
||||
- Synopsis:
|
||||
- `area = mlib.circle.getArea( radius )`
|
||||
- Arguments:
|
||||
- `radius`: Number. The radius of the circle.
|
||||
- Returns:
|
||||
- `area`: Number. The area of the circle.
|
||||
|
||||
##### mlib.circle.getCircleIntersection
|
||||
- Gives the intersections of two circles.
|
||||
- Synopsis:
|
||||
- `intersections = mlib.circle.getCircleIntersection( c1x, c1y, radius1, c2x, c2y, radius2 )
|
||||
- Arguments:
|
||||
- `c1x`, `c1y`: Numbers. The x and y coordinate of the first circle.
|
||||
- `radius1`: Number. The radius of the first circle.
|
||||
- `c2x`, `c2y`: Numbers. The x and y coordinate of the second circle.
|
||||
- `radius2`: Number. The radius of the second circle.
|
||||
- Returns:
|
||||
- `intersections`: Table. A table that contains the type and where the circle collides. See the [specs](spec.lua# L698) for more.
|
||||
|
||||
##### mlib.circle.getCircumference
|
||||
- Returns the circumference of a circle.
|
||||
- Synopsis:
|
||||
- `circumference = mlib.circle.getCircumference( radius )`
|
||||
- Arguments:
|
||||
- `radius`: Number. The radius of the circle.
|
||||
- Returns:
|
||||
- `circumference`: Number. The circumference of a circle.
|
||||
|
||||
##### mlib.circle.getLineIntersection
|
||||
- Returns the intersections of a circle and a line.
|
||||
- Synopsis:
|
||||
- `intersections = mlib.circle.getLineIntersections( cx, cy, radius, x1, y1, x2, y2 )`
|
||||
- Arguments:
|
||||
- `cx`, `cy`: Numbers. The x and y coordinates for the center of the circle.
|
||||
- `radius`: Number. The radius of the circle.
|
||||
- `x1`, `y1`, `x2`, `y2`: Numbers. Two x and y coordinates the lie on the line.
|
||||
- Returns:
|
||||
- `intersections`: Table. A table with the type and where the intersections happened. Table is formatted:
|
||||
- `type`, `x1`, `y1`, `x2`, `y2`
|
||||
- String (`'secant'`), Number, Number, Number, Number
|
||||
- The numbers are the x and y coordinates where the line intersects the circle.
|
||||
- String (`'tangent'`), Number, Number, Boolean (`nil`), Boolean (`nil`)
|
||||
- `x1` and `x2` represent where the line intersects the circle.
|
||||
- Boolean (`false`), Boolean (`nil`), Boolean (`nil`), Boolean (`nil`), Boolean (`nil`)
|
||||
- No intersection.
|
||||
- For more see the [specs](spec.lua# L660).
|
||||
|
||||
##### mlib.circle.getSegmentIntersection
|
||||
- Returns the intersections of a circle and a line segment.
|
||||
- Synopsis:
|
||||
- `intersections = mlib.circle.getSegmentIntersections( cx, cy, radius, x1, y1, x2, y2 )`
|
||||
- Arguments:
|
||||
- `cx`, `cy`: Numbers. The x and y coordinates for the center of the circle.
|
||||
- `radius`: Number. The radius of the circle.
|
||||
- `x1`, `y1`, `x2`, `y2`: Numbers. The two x and y coordinates of the line segment.
|
||||
- Returns:
|
||||
- `intersections`: Table. A table with the type and where the intersections happened. Table is formatted:
|
||||
- `type`, `x1`, `y1`, `x2`, `y2`
|
||||
- String (`'chord'`), Number, Number, Number, Number
|
||||
- The numbers are the x and y coordinates where the line segment is on both edges of the circle.
|
||||
- String (`'enclosed'`), Number, Number, Number, Number
|
||||
- The numbers are the x and y coordinates of the line segment if it is fully inside of the circle.
|
||||
- String (`'secant'`), Number, Number, Number, Number
|
||||
- The numbers are the x and y coordinates where the line segment intersects the circle.
|
||||
- String (`'tangent'`), Number, Number, Boolean (`nil`), Boolean (`nil`)
|
||||
- `x1` and `x2` represent where the line segment intersects the circle.
|
||||
- Boolean (`false`), Boolean (`nil`), Boolean (`nil`), Boolean (`nil`), Boolean (`nil`)
|
||||
- No intersection.
|
||||
- For more see the [specs](spec.lua# L676).
|
||||
|
||||
##### mlib.circle.isCircleCompletelyInside
|
||||
- Checks if one circle is completely inside of another circle.
|
||||
- Synopsis:
|
||||
- `completelyInside = mlib.circle.isCircleCompletelyInside( c1x, c1y, c1radius, c2x, c2y, c2radius )`
|
||||
- Arguments:
|
||||
- `c1x`, `c1y`: Numbers. The x and y coordinates of the first circle.
|
||||
- `c1radius`: Number. The radius of the first circle.
|
||||
- `c2x`, `c2y`: Numbers. The x and y coordinates of the second circle.
|
||||
- `c2radius`: Number. The radius of the second circle.
|
||||
- Returns:
|
||||
- `completelyInside`: Boolean.
|
||||
- `true` if circle1 is inside of circle2.
|
||||
- `false` if circle1 is not __completely__ inside of circle2.
|
||||
|
||||
##### mlib.circle.isCircleCompletelyInsidePolygon
|
||||
- Checks if a circle is completely inside the polygon.
|
||||
- Synopses:
|
||||
- `inPolygon = mlib.polygon.isCircleCompletelyInside( cx, cy, radius, vertices )`
|
||||
- `inPolygon = mlib.polygon.isCircleCompletelyInside( cx, cy, radius, ... )`
|
||||
- Arguments:
|
||||
- `cx`, `cy`: Numbers. The x and y coordinates for the center of the circle.
|
||||
- `radius`: Number. The radius of the circle.
|
||||
- `vertices`: Table. The vertices of the polygon in the format `{ x1, y1, x2, y2, x3, y3, ... }`
|
||||
- `...`: Numbers. The x and y coordinates of the polygon. (Same as using `unpack( vertices )`)
|
||||
- Returns:
|
||||
- `inPolygon`: Boolean.
|
||||
- `true` if the circle is __completely__ inside the polygon.
|
||||
- `false` if the circle is not inside the polygon.
|
||||
|
||||
##### mlib.circle.isPointOnCircle
|
||||
- Checks if a point is __exactly__ on the edge of the circle.
|
||||
- Synopsis:
|
||||
- `onCircle = mlib.circle.checkPoint( px, px, cx, cy, radius )`
|
||||
- Arguments:
|
||||
- `px`, `py`: Numbers. The x and y coordinates of the point being tested.
|
||||
- `cx`, `cy`: Numbers. The x and y coordinates of the center of the circle.
|
||||
- `radius`: Number. The radius of the circle.
|
||||
- Returns:
|
||||
- `onCircle`: Boolean.
|
||||
- `true` if the point is on the circle.
|
||||
- `false` if the point is on the inside or outside of the circle.
|
||||
- Notes:
|
||||
- Will return false if the point is inside __or__ outside of the circle.
|
||||
|
||||
##### mlib.circle.isPolygonCompletelyInside
|
||||
- Checks if a polygon is completely inside of a circle.
|
||||
- Synopsis:
|
||||
- `completelyInside = mlib.circle.isPolygonCompletelyInside( circleX, circleY, circleRadius, vertices )`
|
||||
- `completelyInside = mlib.circle.isPolygonCompletelyInside( circleX, circleY, circleRadius, ... )`
|
||||
- Arguments:
|
||||
- `circleX`, `circleY`: Numbers. The x and y coordinates of the circle.
|
||||
- `circleRadius`: Number. The radius of the circle.
|
||||
- `vertices`: Table. A table containing all of the vertices of the polygon.
|
||||
- `...`: Numbers. All of the points of the polygon.
|
||||
- Returns:
|
||||
- `completelyInside`: Boolean.
|
||||
- `true` if the polygon is inside of the circle.
|
||||
- `false` if the polygon is not __completely__ inside of the circle.
|
||||
|
||||
#### mlib.statistics
|
||||
- Handles statistical aspects of math.
|
||||
|
||||
##### mlib.statistics.getCentralTendency
|
||||
- Gets the central tendency of the data.
|
||||
- Synopses:
|
||||
- `modes, occurrences, median, mean = mlib.statistics.getCentralTendency( data )`
|
||||
- `modes, occurrences, median, mean = mlib.statistics.getCentralTendency( ... )`
|
||||
- Arguments:
|
||||
- `data`: Table. A table containing the values of data.
|
||||
- `...`: Numbers. All of the numbers in the data set.
|
||||
- Returns:
|
||||
- `modes, occurrences`: Table, Number. The modes of the data and the number of times it occurs. See [mlib.statistics.getMode](#mlibstatisticsgetmode).
|
||||
- `median`: Number. The median of the data set.
|
||||
- `mean`: Number. The mean of the data set.
|
||||
|
||||
##### mlib.statistics.getDispersion
|
||||
- Gets the dispersion of the data.
|
||||
- Synopses:
|
||||
- `variationRatio, range, standardDeviation = mlib.statistics.getDispersion( data )`
|
||||
- `variationRatio, range, standardDeviation = mlib.statistics.getDispersion( ... )`
|
||||
- Arguments:
|
||||
- `data`: Table. A table containing the values of data.
|
||||
- `...`: Numbers. All of the numbers in the data set.
|
||||
- Returns:
|
||||
- `variationRatio`: Number. The variation ratio of the data set.
|
||||
- `range`: Number. The range of the data set.
|
||||
- `standardDeviation`: Number. The standard deviation of the data set.
|
||||
|
||||
##### mlib.statistics.getMean
|
||||
- Gets the arithmetic mean of the data.
|
||||
- Synopses:
|
||||
- `mean = mlib.statistics.getMean( data )`
|
||||
- `mean = mlib.statistics.getMean( ... )`
|
||||
- Arguments:
|
||||
- `data`: Table. A table containing the values of data.
|
||||
- `...`: Numbers. All of the numbers in the data set.
|
||||
- Returns:
|
||||
- `mean`: Number. The arithmetic mean of the data set.
|
||||
|
||||
##### mlib.statistics.getMedian
|
||||
- Gets the median of the data set.
|
||||
- Synopses:
|
||||
- `median = mlib.statistics.getMedian( data )`
|
||||
- `median = mlib.statistics.getMedian( ... )`
|
||||
- Arguments:
|
||||
- `data`: Table. A table containing the values of data.
|
||||
- `...`: Numbers. All of the numbers in the data set.
|
||||
- Returns:
|
||||
- `median`: Number. The median of the data.
|
||||
|
||||
##### mlib.statistics.getMode
|
||||
- Gets the mode of the data set.
|
||||
- Synopses:
|
||||
- `mode, occurrences = mlib.statistics.getMode( data )`
|
||||
- `mode, occurrences = mlib.statistics.getMode( ... )`
|
||||
- Arguments:
|
||||
- `data`: Table. A table containing the values of data.
|
||||
- `...`: Numbers. All of the numbers in the data set.
|
||||
- Returns:
|
||||
- `mode`: Table. The mode(s) of the data.
|
||||
- `occurrences`: Number. The number of time the mode(s) occur.
|
||||
|
||||
##### mlib.statistics.getRange
|
||||
- Gets the range of the data set.
|
||||
- Synopses:
|
||||
- `range = mlib.statistics.getRange( data )`
|
||||
- `range = mlib.statistics.getRange( ... )`
|
||||
- Arguments:
|
||||
- `data`: Table. A table containing the values of data.
|
||||
- `...`: Numbers. All of the numbers in the data set.
|
||||
- Returns:
|
||||
- `range`: Number. The range of the data.
|
||||
|
||||
##### mlib.statistics.getStandardDeviation
|
||||
- Gets the standard deviation of the data.
|
||||
- Synopses:
|
||||
- `standardDeviation = mlib.statistics.getStandardDeviation( data )`
|
||||
- `standardDeviation = mlib.statistics.getStandardDeviation( ... )`
|
||||
- Arguments:
|
||||
- `data`: Table. A table containing the values of data.
|
||||
- `...`: Numbers. All of the numbers in the data set.
|
||||
- Returns:
|
||||
- `standardDeviation`: Number. The standard deviation of the data set.
|
||||
|
||||
##### mlib.statistics.getVariance
|
||||
- Gets the variation of the data.
|
||||
- Synopses:
|
||||
- `variance = mlib.statistics.getVariance( data )`
|
||||
- `variance = mlib.statistics.getVariance( ... )`
|
||||
- Arguments:
|
||||
- `data`: Table. A table containing the values of data.
|
||||
- `...`: Numbers. All of the numbers in the data set.
|
||||
- Returns:
|
||||
- `variance`: Number. The variation of the data set.
|
||||
|
||||
##### mlib.statistics.getVariationRatio
|
||||
- Gets the variation ratio of the data.
|
||||
- Synopses:
|
||||
- `variationRatio = mlib.statistics.getVariationRatio( data )`
|
||||
- `variationRatio = mlib.statistics.getVariationRatio( ... )`
|
||||
- Arguments:
|
||||
- `data`: Table. A table containing the values of data.
|
||||
- `...`: Numbers. All of the numbers in the data set.
|
||||
- Returns:
|
||||
- `variationRatio`: Number. The variation ratio of the data set.
|
||||
|
||||
#### mlib.math
|
||||
- Miscellaneous functions that have no home.
|
||||
|
||||
##### mlib.math.getAngle
|
||||
- Gets the angle between three points.
|
||||
- Synopsis:
|
||||
- `angle = mlib.math.getAngle( x1, y1, x2, y2, x3, y3 )`
|
||||
- Arguments:
|
||||
- `x1`, `y1`: Numbers. The x and y coordinates of the first point.
|
||||
- `x2`, `y2`: Numbers. The x and y coordinates of the vertex of the two points.
|
||||
- `x3`, `y3`: Numbers. The x and y coordinates of the second point.
|
||||
|
||||
##### mlib.math.getPercentage
|
||||
- Gets the percentage of a number.
|
||||
- Synopsis:
|
||||
- `percentage = mlib.math.getPercentage( percent, number )`
|
||||
- Arguments:
|
||||
- `percent`: Number. The decimal value of the percent (i.e. 100% is 1, 50% is .5).
|
||||
- `number`: Number. The number to get the percentage of.
|
||||
- Returns:
|
||||
- `percentage`: Number. The `percent`age or `number`.
|
||||
|
||||
##### mlib.math.getPercentOfChange
|
||||
- Gets the percent of change from one to another.
|
||||
- Synopsis:
|
||||
- `change = mlib.math.getPercentOfChange( old, new )`
|
||||
- Arguments:
|
||||
- `old`: Number. The original number.
|
||||
- `new`: Number. The new number.
|
||||
- Returns:
|
||||
- `change`: Number. The percent of change from `old` to `new`.
|
||||
|
||||
##### mlib.math.getQuadraticRoots
|
||||
- Gets the quadratic roots of the the equation.
|
||||
- Synopsis:
|
||||
- `root1, root2 = mlib.math.getQuadraticRoots( a, b, c )`
|
||||
- Arguments:
|
||||
- `a`, `b`, `c`: Numbers. The a, b, and c values of the equation `a * x ^ 2 + b * x ^ 2 + c`.
|
||||
- Returns:
|
||||
- `root1`, `root2`: Numbers. The roots of the equation (where `a * x ^ 2 + b * x ^ 2 + c = 0`).
|
||||
|
||||
##### mlib.math.getRoot
|
||||
- Gets the `n`th root of a number.
|
||||
- Synopsis:
|
||||
- `x = mlib.math.getRoot( number, root )`
|
||||
- Arguments:
|
||||
- `number`: Number. The number to get the root of.
|
||||
- `root`: Number. The root.
|
||||
- Returns:
|
||||
- `x`: The `root`th root of `number`.
|
||||
- Example:
|
||||
```lua
|
||||
local a = mlib.math.getRoot( 4, 2 ) -- Same as saying 'math.pow( 4, .5 )' or 'math.sqrt( 4 )' in this case.
|
||||
local b = mlib.math.getRoot( 27, 3 )
|
||||
|
||||
print( a, b ) --> 2, 3
|
||||
```
|
||||
- For more, see the [specs](spec.lua# L860).
|
||||
|
||||
##### mlib.math.getSummation
|
||||
- Gets the summation of numbers.
|
||||
- Synopsis:
|
||||
- `summation = mlib.math.getSummation( start, stop, func )`
|
||||
- Arguments:
|
||||
- `start`: Number. The number at which to start the summation.
|
||||
- `stop`: Number. The number at which to stop the summation.
|
||||
- `func`: Function. The method to add the numbers.
|
||||
- Arguments:
|
||||
- `i`: Number. Index.
|
||||
- `previous`: Table. The previous values used.
|
||||
- Returns:
|
||||
- `Summation`: Number. The summation of the numbers.
|
||||
- For more, see the [specs](spec.lua# L897).
|
||||
|
||||
##### mlib.math.isPrime
|
||||
- Checks if a number is prime.
|
||||
- Synopsis:
|
||||
- `isPrime = mlib.math.isPrime( x )`
|
||||
- Arguments:
|
||||
- `x`: Number. The number to check if it's prime.
|
||||
- Returns:
|
||||
- `isPrime`: Boolean.
|
||||
- `true` if the number is prime.
|
||||
- `false` if the number is not prime.
|
||||
|
||||
##### mlib.math.round
|
||||
- Rounds a number to the given decimal place.
|
||||
- Synopsis:
|
||||
- `rounded = mlib.math.round( number, [place] )
|
||||
- Arguments:
|
||||
- `number`: Number. The number to round.
|
||||
- `place (1)`: Number. The decimal place to round to. Defaults to 1.
|
||||
- Returns:
|
||||
- The rounded number.
|
||||
- For more, see the [specs](spec.lua# L881).
|
||||
|
||||
#### Aliases
|
||||
| Alias | Corresponding Function |
|
||||
| ----------------------------------------------|:---------------------------------------------------------------------------------:|
|
||||
| milb.line.getDistance | [mlib.line.getLength](#mliblinegetlength) |
|
||||
| mlib.line.getCircleIntersection | [mlib.circle.getLineIntersection](#mlibcirclegetlineintersection) |
|
||||
| milb.line.getPolygonIntersection | [mlib.polygon.getLineIntersection](#mlibpolygongetlineintersection) |
|
||||
| mlib.line.getLineIntersection | [mlib.line.getIntersection](#mliblinegetintersection) |
|
||||
| mlib.segment.getCircleIntersection | [mlib.circle.getSegmentIntersection](#mlibcirclegetsegmentintersection) |
|
||||
| milb.segment.getPolygonIntersection | [mlib.pollygon.getSegmentIntersection](#mlibpollygongetsegmentintersection) |
|
||||
| mlib.segment.getLineIntersection | [mlib.line.getSegmentIntersection](#mliblinegetsegmentintersection) |
|
||||
| mlib.segment.getSegmentIntersection | [mlib.segment.getIntersection](#mlibsegmentgetintersection) |
|
||||
| milb.segment.isSegmentCompletelyInsideCircle | [mlib.circle.isSegmentCompletelyInside](#mlibcircleissegmentcompletelyinside) |
|
||||
| mlib.segment.isSegmentCompletelyInsidePolygon | [mlib.polygon.isSegmentCompletelyInside](#mlibpolygonissegmentcompletelyinside) |
|
||||
| mlib.circle.getPolygonIntersection | [mlib.polygon.getCircleIntersection](#mlibpolygongetcircleintersection) |
|
||||
| mlib.circle.isCircleInsidePolygon | [mlib.polygon.isCircleInside](#mlibpolygoniscircleinside) |
|
||||
| mlib.circle.isCircleCompletelyInsidePolygon | [mlib.polygon.isCircleCompletelyInside](#mlibpolygoniscirclecompletelyinside) |
|
||||
| mlib.polygon.isCircleCompletelyOver | [mlib.circleisPolygonCompletelyInside](#mlibcircleispolygoncompletelyinside) |
|
||||
|
||||
## License
|
||||
A math library made in Lua
|
||||
copyright (C) 2014 Davis Claiborne
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
Contact me at davisclaib at gmail.com
|
||||
1152
deps/windfield/mlib/mlib.lua
vendored
Normal file
1152
deps/windfield/mlib/mlib.lua
vendored
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user