I am trying to implement a mathematical procedure to ensure that a circle c1 is completely inside another circle c2.
It should work the following way:
Given c1(x, y, r) and c2(x, y, r) and c2.r>c1.r
return true if c1 is inside c2
return a vector V(x,y) being the minimum correction to apply to c1 so it is inside c2.
How does it look to you? should be easy for a mathematician or a physicist but it's quite hard for me.
I already tried an implementation in lua, but there's definitely something wrong on it.
local function newVector(P1, P2)
local w, h=(P2.x-P1.x), (P2.y-P1.y)
local M=math.sqrt(w^2 + h^2)
local alpha=math.atan(h/w)
return {m=M, alpha=alpha}
end
local function isWithin(C1, C2)
local V12=newVector(C1, C2)
local R12=C2.r-C1.r
local deltaR=R12-V12.m
if deltaR>=0 then
return true
else
local correctionM=(V12.m+deltaR) --module value to correct
local a=V12.alpha
print("correction angle: "..math.deg(a))
local correctionX=correctionM*math.cos(a)
local correctionY=correctionM*math.sin(a)
return {x=correctionX, y=correctionY}
end
end
Thanks!
Isn't it enough to check that distance(Center1, Center2) + Radius1 <= Radius2 ?
local function isWithin(C1, C2)
local distance = math.sqrt((C1.x-C2.x)^2+(C1.y-C2.y)^2)
return distance + C1.r <= C2.r + Epsilon
Epsilon is used in order to avoid numerical errors. (e.g. Epsilon = 1e-9)
Sounds easy this way.
Ok, finally I have it working fine.
The key was to use math.atan2 as lhf suggested. And I had some numerical mistake in the correction value.
Here's the final code. I have also included the circleFromBounds function that I use to create the circles from any corona display object.
local function newVector(P1, P2)
local w, h=(P2.x-P1.x), (P2.y-P1.y)
local M=math.sqrt(w^2 + h^2)
local alpha=math.atan2(h, w)
return {m=M, alpha=alpha}
end
local function isWithin(C1, C2)
local V12=newVector(C1, C2)
local epsilon = 10^(-9)
if (V12.m + C1.r <= C2.r + epsilon) then
return true
else
local correctionM=(C2.r-(C1.r+V12.m)) --module value to correct
local A=V12.alpha
local correctionX=correctionM*math.cos(A)
local correctionY=correctionM*math.sin(A)
return {x=correctionX, y=correctionY}
end
end
local function circleFromBounds(bounds, type)
local x, y, r
local width, height = (bounds.xMax-bounds.xMin), (bounds.yMax-bounds.yMin)
local ratio=width/height
x=bounds.xMin+width*.5
y=bounds.yMin+height*.5
if "inner"==type then
if ratio>1 then
r=height*.5
else
r=width*.5
end
elseif "outer"==type then
local c1, c2 = width*.5, height*.5
r = math.sqrt(c1^2 + c2^2)
end
return {x=x, y=y, r=r}
end
Thanks for your help!
Related
So i found out how to create a vector2 in 2D using only one angle but now i need a vector3 using two or three angles
The code i used to get the 2D vector:
function V2ToForce(Angle,Force)
local Force = Force or 1
local X,Y = math.cos(Angle)*Force,math.sin(Angle)*Force
return X,Y
end
Any pseudocode would help.
Edit:
I found this formula but dosent work either
function Test(X,Y,Force)
local x = math.cos(X) * math.cos(Y);
local z = math.sin(X) * math.cos(Y);
local y = math.sin(Y);
return x*Force,y*Force,z*Force
end
Ty who commented got it to work, still has some bugs but nothing that a if statement can't solve.
Thats what i ended up with for anyone with the same problem
function Test1(X,Y,Force)
local X1 = math.cos(Y)*Force
local Y1 = (math.sin(Y)*math.sin(X))*Force
local Z1 = (-math.sin(Y)*math.cos(X))*Force
return X1,Y1,Z1
end
function Test2(X,Y,Force)
local X1 = math.cos(X) * math.cos(Y)
local Z1 = -math.sin(X) * math.cos(Y)
local Y1 = math.sin(Y)
return X*Force,Y*Force,Z1*Force
end
Sry for my bad english
I have a big file (75GB) memory mapped in an array d that I want to copy in another m. Because I do not have 75GB of RAM available, I did:
for (i,v) in enumerate(d)
m[i] = v
end
In order to copy the file value after value. But I get a copy rate of ~2MB/s on a SSD where I expect at least 50MB/s both in read and write.
How could I optimize this copy rate?
=== [edit] ===
According to the comments, I changed my code to the following, which sped up the write rate to 15MB/s
function copydcimg(m::Array{UInt16,4}, d::Dcimg)
m .= d
Mmap.sync!(m)
end
copydcimg(m,d)
At this point, I think I should optimize the Dcimg code. This binary file is made of frames spaced by a timestamp. Here is the code I use to access the frames:
module dcimg
using Mmap
using TOML
struct Dcimg <: AbstractArray{UInt16,4} # struct allowing to access dcimg file
filename::String # filename of the dcimg
header::Int # header size in bytes
clock::Int # clock size in bytes
x::Int
y::Int
z::Int
t::Int
m # linear memory map
Dcimg(filename, header, clock, x, y, z, t) =
new(filename, header, clock, x, y, z, t,
Mmap.mmap(open(filename), Array{UInt16, 3},
(x*y+clock÷sizeof(UInt16), z, t), header)
)
end
# following functions allows to access DCIMG like an Array
Base.size(D::Dcimg) = (D.x, D.y, D.z, D.t)
# skip clock
Base.getindex(D::Dcimg, i::Int) =
D.m[i + (i ÷ (D.x*D.y))*D.clock÷sizeof(UInt16)]
Base.getindex(D::Dcimg, x::Int, y::Int, z::Int, t::Int) =
D[x + D.x*((y-1) + D.y*((z-1) + D.z*(t-1)))]
# allowing to automatically parse size
function Dcimg(pathtag)
p = TOML.parsefile(pathtag * ".toml")
return Dcimg(pathtag * ".dcimg",
# ...
)
end
export Dcimg, getframe
end
I got it! The solution was to copy the file chunk by chunk lets say by frame (around 1024×720 UInt16). This way I reached 300MB/s, which I didn't even know was possible in single thread. Here is the code.
In module dcimg, I added the methods to access the file frame by frame
# get frame number n (starting form 1)
getframe(D::Dcimg,n::Int) =
reshape(D.m[
D.x*D.y*(n-1)+1 + (n-1)*D.clock÷sizeof(UInt16) : # cosmetic line break
D.x*D.y*n + (n-1)*D.clock÷sizeof(UInt16)
], D.x, D.y)
# get frame for layer z, time t (starting from 1)
getframe(D::Dcimg,z::Int,t::Int) =
getframe(D::Dcimg,(z-1)+D.z*(t-1))
Iterating over the frames within a loop
function copyframes(m::Array{UInt16,4}, d::Dcimg)
N = d.z*d.t
F = d.x*d.y
for i in 1:N
m[(i-1)*F+1:i*F] = getframe(d, i)
end
end
copyframes(m,d)
Thanks all in comments for leading me to this.
===== edit =====
for further reading, you might look at:
dd: How to calculate optimal blocksize?
http://blog.tdg5.com/tuning-dd-block-size/
which give hints about the optimal block size to copy at a time.
folks!
I have a working function named "LookAt" written in Lua language.
There is no mistakes in code and logic of this function.
But i believe we can simplify the math logic.
function LookAt(target)
local origin = Vec3.New(Engine.ClientData.Origin)
local direction = origin - target
Engine.Pitch = math.deg(math.atan(direction.Z, math.sqrt((direction.X ^ 2) + (direction.Y ^ 2))))
Engine.Yaw = math.deg(math.atan(direction.Y, direction.X)) - 180.0
end
I don't think there's much you can do to simplify the math logic. There's very little redundancy here you can take advantage of. But you can factor it into pieces like this:
function atan_deg(y, x)
return (math.deg(math.atan(y, x)))
end
function hypotenuse(x, y)
return (math.sqrt(x^2 + y^2))
end
function LookAt(target)
local origin = Vec3.New(Engine.ClientData.Origin)
local direction = origin - target
local X, Y, Z = direction.X, direction.Y, direction.Z
Engine.Pitch = atan_deg(Z, hypotenuse(X, Y))
Engine.Yaw = atan_deg(Y, X) - 180.0
end
I want to use instead of matlab integration command, a basic self created one. Do you have any Idea how to fix the error? If I use Matlab quad command, my algorithm works good but when I try to use my self created integral function,not suprisingly for sure, it does not work:(
M-File:
function y = trapapa(low, up, ints, fun)
y = 0;
step = (up - low) / ints;
for j = low : step : up
y = y + feval(fun,j);
end
y = (y - (feval(fun, low) + feval(fun, up))/2) * step;
Mean algorithm:
clear;
x0=linspace(0,4,3);
y=linspace(0,2,3);
for i=1:length(x0)
for j=1:length(y)
x(i,j)=y(j)+x0(i);
alpha=#(rho)((5-2*x(i,j)).*exp(y(j)-rho))./2;
%int(i,j)=quad(alpha,0,y(j))
int(i,j)=trapapa(alpha,0,y(j),10)
end
end
You are not following your function definition in the script. The fun parameter (variable alpha) is supposed to be the last one.
Try int(i,j)=trapapa(0,y(j),10,alpha)
Ok, first up, this is NOT for a class, test, or other student type activity.
I'm a scripter for a game, and am trying to implement the math library for all to use, and unfortunately, all I have available to me is very basic lua. The implemented version cannot be changed, and does not include any libraries. For those wondering, its for scripting in Fold.It.
Here's what I have...
math={}
math.fact = function(b) if(b==1)or(b==0) then return 1 end e=1 for c=b,1,-1 do e=e*c end return e end
math.pow = function(b,p) e=b if(p==0) then return 1 end if(p<0) then p=p*(-1) end for c=p,2,-1 do e=e*b end return e end
math.cos = function(b,p) e=0 p=p or 10 for i=1,p do e=e+(math.pow(-1,i)*math.pow(b,2*i)/math.fact(2*i)) end return e end
To clarify above, math.fact returns factorial, which is returning accurate to about 10 points of precision, and is a new function I've done to aid in cosine calculation.
The math.pow is also a new function to handle returning powers, also working as expected.
The issue is with the cosine function. Its returning unexpected values. Here's an easier to digest version (I've been writing my library stuff ultra lean)...
function math.cos(value,precision)
result=0
precision=precision or 10
for i=1,precision do
result=result+(math.pow(-1,i)*math.pow(value,2*i)/math.fact(2*i))
end
return e
end
The problem is, with those functions, for print(math.cos(90)) it returns 4.77135... when I'm expecting -0.44807... (based on calc in scientific mode, or using an online tool to cos(90)).
I'm also having issues with sin and tan, however they are similarly written to cos, which seems to have been done in many languages. If I can figure out what I'm doing wrong, I can get them all fixed.
EDIT: Corrected typo
First, your lua doesn't run. Second, you need to make your variables local. Third, cosine starts with a one.
The problem is because the Taylor series you are using only converges on the correct values of cosine close to zero. You would have to use a far more terms of the series to get it to handle 90 correctly. You can fix this for your implementation two ways:
Add a pi constant. Then use a while loop to adjust the value such that abs(value) < 2*pi:
math.pi = 3.14159265358
while value > math.pi*2 do
value = value - math.pi * 2
end
while value < -math.pi*2 do
value = value + math.pi * 2
end
Or - find or implement a version of fmod in lua.
Here is the corrected code (you can minify it):
math={}
math.fact = function(b)
if(b==1)or(b==0) then
return 1
end
local e=1
for c=b,1,-1 do
e=e*c
end
return e
end
math.pow = function(b,p)
local e=b
if(p==0) then
return 1
end
if(p<0) then
p=p*(-1)
end
for c=p,2,-1 do
e=e*b
end
return e
end
math.cos = function(b,p)
local e=1
b = math.correctRadians(b)
p=p or 10
for i=1,p do
e=e+(math.pow(-1,i)*math.pow(b,2*i)/math.fact(2*i))
end
return e
end
math.pi = 3.1415926545358
math.correctRadians = function( value )
while value > math.pi*2 do
value = value - math.pi * 2
end
while value < -math.pi*2 do
value = value + math.pi * 2
end
return value
end
interactive lua run:
imac:~ root$ lua -i temp.lua
Lua 5.1.4 Copyright (C) 1994-2008 Lua.org, PUC-Rio
> print( math.cos( 90 ) )
-0.44807359244883
>