I'm trying to use class behavior in lua where there is a ship that has two other classes pos and vector
But I cannot get it working like I assumed I would be able to
Point = {x=0, y=0}
function Point:new(p)
p = p or {}
return p
end
Ship =
{
pos = {Point:new{x=0,y=0}},
vector = {Point:new{x=0,y=0}} -- I thought this would be sufficient for access being available for vector
}
-- create new ship class
function Ship:new(pos)
p = p or {}
p.pos = pos
p.vector = Point:new{x=0,y=0} -- I need to do this or accessing vector will crash (The problem)
return p
end
-- Create new ship...
plrShip = Ship:new{}
plrShip.pos.x = 300
plrShip.pos.y = 300
If anyone knows how to make the above code cleaner/better I would be thankful
You can use metatables to set default fields. (I've made some assumptions about what you're trying to do. If this doesn't work for you, please add some clarification to your question.)
local Point = {x=0, y=0}
Point.__index = Point
function Point:new(p)
p = p or {}
setmetatable(p, self)
return p
end
-- create new ship class
local Ship = {}
Ship.__index = Ship
function Ship:new(pos)
setmetatable(pos, Point)
local p = {pos = pos, vector = Point:new()}
setmetatable(p, self)
return p
end
-- Create new ship...
local plrShip = Ship:new{}
plrShip.pos.x = 300
plrShip.pos.y = 300
I found solution to do this, it still not perfect but only I got working was this modified code:
Ship =
{
pos = Point:new{x=0,y=0},
vector = Point:new{x=0,y=0}
}
function Ship:new()
p = p or {}
p.pos = self.pos
p.vector = self.vector
return p
end
plrShip = Ship:new()
plrShip.pos.x = 300
plrShip.pos.y = 300
Related
First of all, try not to rip me to shreds :) I am relatively new to programming in general and this is my first question on StackOverflow!
This is hopefully a simple question, how can I return the "var m = ..." line outside of the function given below? I am trying to implement the Bisection Numerical Method (seen on rayweiderlich.com) but for a different equation. I am trying to access the variable outside of the function in order to update a label on a viewcontroller. Note: The iterative variable I am trying to solve does output correctly and that number is the 0.8789. Therefore, I think the algorithm is correct. Here is the tutorial link https://www.raywenderlich.com/99559/numeric-algorithms-using-playgrounds and my version of tutorials code:
//: Playground - noun: a place where people can play
import UIKit
func bisection(x: Double) -> Double {
var lower = 0.0
var upper = x
let constant1 = Double((1+2*60))
let constant2 = Double(1+4*60)
var m = (constant1 - pow(constant2, 0.5)) / (2.0*60.0) //This returns the number I want (0.8789)
let epsilon = 1e-3
while (fabs(m * m - x) > epsilon) {
m = (lower + upper)/2
if m * m > x {
upper = m
print(m)
} else {
lower = m
print(m)
}
}
print(m)
return m //This returns the number I DON'T want (0.9995)
}
let bis = bisection(x: 1.0)
//somewhere around here is where I would like to use the "m" variable to update a label in a view controller
import UIKit
func bisection(x: Double) -> Double {
let constant1 = Double((1+2*60))
let constant2 = Double(1+4*60)
let m = (constant1 - pow(constant2, 0.5)) / (2.0*60.0)
return m
}
let bis = bisection(x: 1.0)
print(bis)
Is this what you want?
First, sorry for the bad title - I'm new to OO programming - basically I'd like to understand how Matlab works with oop classes.
Before I ask my question, here is a basic example of what I want to do:
I have two houses and some data about them and I got the idea, to work with oop classes. Here is my .m file.
classdef building
properties
hohe = 0;
lange = 0;
breite = 0;
xabstandsolar = 0;
yabstandsolar = 0;
end
methods
function obj = building(hohe, lange, breite, xabstandsolar, yabstandsolar)
obj.hohe = hohe;
obj.lange = lange;
obj.breite = breite;
obj.xabstandsolar = xabstandsolar;
obj.yabstandsolar = yabstandsolar;
end
function hohenwinkel(h)
h = h
d = sqrt(obj.xabstandsolar^2 + yabstandsolar^2);
gamma_v = atand((obj.hohe - h)/(d));
end
end
end
I filled it with some data - for example
>>H1 = building(10,8,6,14,8)
>>H2 = building(18,8,6,14,0)
And now I want to calculate "gamma_v" (as an 1x2 array) for each building. Any ideas, how I can archive this?
Edit:
I want to create gamma_v (as an array) automatically for all objects in the class "building". There will be a lot more "houses" in the final script.
Your hohenwinkel method needs to accept two input arguments. The first argument for non-static methods is always the object itself (unlike C++, you'll have to explicitly list it as an input argument) and the second input will be your h variable. You'll also want to actually return the gamma_v value using an output argument for your method.
function gamma_v = hohenwinkel(obj, h)
d = sqrt(obj.xabstandsolar^2 + obj.yabstandsolar^2);
gamma_v = atand((obj.hohe - h)/(d));
end
Then you can invoke this method on each building to get the value
gamma_v1 = hohenwinkel(H1);
gamma_v2 = hohenwinkel(H2);
If you want to have an array of buildings, you can create that array
houses = [building(10,8,6,14,8), building(18,8,6,14,0)];
gamma_v = hohenwinkel(houses);
and then construct your hohenwinkel function to operate on each one and return the result
function gamma_v = hohenwinkel(obj, h)
if numel(obj) > 1
% Compute hohenwinkel for each one
gamma_v = arrayfun(#(x)hohenwinkel(x, h), obj);
return
end
d = sqrt(obj.xabstandsolar^2 + obj.yabstandsolar^2);
gamma_v = atand((obj.hohe - h)/(d));
end
there is some tricky solution (and its not recommended)(#Suever solution is better)
you should create a handle class
classdef gvclass<handle
properties
gvarr=[];
end
methods
function setgvarr(obj,value)
obj.gvarr=[obj.gvarr,value];
end
end
end
then use this class in your building class
classdef building<handle
properties
gv
hohe = 0;
lange = 0;
breite = 0;
xabstandsolar = 0;
yabstandsolar = 0;
end
methods
function obj = building(hohe, lange, breite, xabstandsolar, yabstandsolar,handle_of_your_gv_class,h)
obj.hohe = hohe;
obj.lange = lange;
obj.breite = breite;
obj.xabstandsolar = xabstandsolar;
obj.yabstandsolar = yabstandsolar;
obj.gv=handle_of_your_gv_class;
obj.hohenwinkel(h);
end
function hohenwinkel(obj,h)
d = sqrt(obj.xabstandsolar^2 + yabstandsolar^2);
gamma_v = atand((obj.hohe - h)/(d));
obj.gv.setgvarr(gamma_v);
end
end
end
finally before creating any building you should create an object of gv class and pass it to the building constructor,
Egv=gvclass();
H1 = building(10,8,6,14,8,Egv,2)
H2 = building(18,8,6,14,0,Egv,3)
and to access gv array:
Egv.gvarr
you should do more effort on this issue to debug possible errors.
I am quite new to Matlab and I am trying to use this code I found online.
I am trying to fit a graph described by the HydrodynamicSpectrum. But instead of having it fit after inputting fvA and fmA, I am trying to obtain the fitted parameters for this value also.
I have tried removing them, changing them. But none is working. I was wondering if any one here will be able to point me into the right direction of fixing this.
specFunc = #(f, para)HydrodynamicSpectrum(f, [para fvA fmA]);
[fit.AXfc, fit.AXD] = NonLinearFit(fit.f(indXY), fit.AXSpec(indXY), specFunc, [iguess_AXfc iguess_AXD]);
[fit.AYfc, fit.AYD] = NonLinearFit(fit.f(indXY), fit.AYSpec(indXY), specFunc, [iguess_AYfc iguess_AYD]);
[fit.ASumfc, fit.ASumD] = NonLinearFit(fit.f(indSum), fit.ASumSpec(indSum), specFunc, [iguess_ASumfc iguess_ASumD]);
predictedAX = HydrodynamicSpectrum(fit.f, [fit.AXfc fit.AXD fvA fmA]);
predictedAY = HydrodynamicSpectrum(fit.f, [fit.AYfc fit.AYD fvA fmA]);
predictedASum = HydrodynamicSpectrum(fit.f, [fit.ASumfc fit.ASumD fvA fmA]);
function spec = HydrodynamicSpectrum(f, para);
fc = para(1);
D = para(2);
fv = para(3);
fm = para(4);
f = abs(f); %Kludge!
spec = D/pi^2*(1+sqrt(f/fv))./((fc - f.*sqrt(f./fv) - (f.^2)/fm).^2 + (f + f.*sqrt(f./fv)).^2);
function [fc, D, sfc, sD] = NonLinearFit(f, spec, specFunc, init);
func = #(para, f)spec./specFunc(f, para);
[paraFit, resid, J] = nlinfit(f, ones(1, length(spec)), func, init);
fc = paraFit(1);
D = paraFit(2);
ci = nlparci(real(paraFit), real(resid), real(J)); % Kludge!!
sfc = (ci(1,2) - ci(1,1))/4;
sD = (ci(2,2) - ci(2,1))/4;
[paraFit, resid, J] = nlinfit(f, ones(1, length(spec)), func, init);
It looks like you get your fitted parameter using this line. And you are further processing them to get other stuff out from the function. You can modify your second function to get them out as well.
As there are very few comments, and questions seems to be application specific, there is not much help I can give with what you have presented.
I have written in MATLAB the following
for i = 1:3
alpha11(i) = b+a.*randn(1,1);
alpha22(i) = b+a.*randn(1,1);
alpha12(i) = b+a.*randn(1,1);
alpha21(i) = b+a.*randn(1,1);
AoD11(i) = randi([-180/6 +180/6],1,1);
AoA11(i) = randi([-180/6 +180/6 ],1,1);
AoD22(i) = randi([-180/6 +180/6],1,1);
AoA22(i) = randi([-180/6 +180/6 ],1,1);
AoD21(i) = randi([-180 +180],1,1);
AoA21(i) = randi([-180 +180 ],1,1);
AoD12(i) = randi([-180 +180],1,1);
AoA12(i) = randi([-180 +180 ],1,1);
ctet11(i)= ((2*pi)/lambda)*d*sin(AoD11(i));
ctet22(i)= ((2*pi)/lambda)*d*sin(AoD22(i));
ctet12(i)= ((2*pi)/lambda)*d*sin(AoD12(i));
ctet21(i)= ((2*pi)/lambda)*d*sin(AoD21(i));
f_t11_ula{i}=transpose((1/sqrt(M))*[ 1 exp(j*ctet11(i)) exp(j*2*ctet11(i)) exp(j*3*ctet11(i)) ]);
f_t22_ula{i}=transpose((1/sqrt(M))*[ 1 exp(j*ctet22(i)) exp(j*2*ctet22(i)) exp(j*3*ctet22(i)) ]);
f_t12_ula{i}=transpose((1/sqrt(M))*[ 1 exp(j*ctet12(i)) exp(j*2*ctet12(i)) exp(j*3*ctet12(i)) ]);
f_t21_ula{i}=transpose((1/sqrt(M))*[ 1 exp(j*ctet21(i)) exp(j*2*ctet21(i)) exp(j*3*ctet21(i)) ]);
cter11(i)= ((2*pi)/lambda)*d*sin(AoA11(i));
cter22(i)= ((2*pi)/lambda)*d*sin(AoA22(i));
cter12(i)= ((2*pi)/lambda)*d*sin(AoA12(i));
cter21(i)= ((2*pi)/lambda)*d*sin(AoA21(i));
f_r11_ula{i}=transpose((1/sqrt(O))*[ 1 exp(j*cter11(i)) exp(j*2*cter11(i)) exp(j*3*cter11(i)) ]);
f_r22_ula{i}=transpose((1/sqrt(O))*[ 1 exp(j*cter22(i)) exp(j*2*cter22(i)) exp(j*3*cter22(i))]);
f_r12_ula{i}=transpose((1/sqrt(O))*[ 1 exp(j*cter12(i)) exp(j*2*cter12(i)) exp(j*3*cter12(i)) ]);
f_r21_ula{i}=transpose((1/sqrt(O))*[ 1 exp(j*cter21(i)) exp(j*2*cter21(i)) exp(j*3*cter21(i))]);
channel11{i}= alpha11(i) * f_r11_ula{i}* conj(transpose(f_t11_ula{i})) ;
channel22{i}= alpha22(i) * f_r22_ula{i}* conj(transpose(f_t22_ula{i})) ;
channel12{i}= alpha12(i) * f_r12_ula{i}* conj(transpose(f_t12_ula{i})) ;
channel21{i}= alpha21(i) * f_r21_ula{i}* conj(transpose(f_t21_ula{i})) ;
end
I am writing this question here to ask how I can compress this code, as you can see its not very nicely written and I have basically many repetitions. I don't know how to write them in few commands. Every command is repeated four times and indexed by 11, 12, 21, 22..
P.S If someone wants to run the code the following variables are needed
a = 1;
b = 0;
M=4;
O = 4;
lambda=0.15;
d=lambda/2;
Looking forward for suggestions.
As #David mentioned, it can be done using 3D arrays. This removes much of the code repetition.
Here is an example of how it could be done:
sz=[2,2,3];
alpha=b+a.*randn(sz);
AoD = randi([-180/6 +180/6],sz);
AoA = randi([-180 +180],sz);
mask = logical(repmat(eye(2),1,1,3));
[AoA(mask), AoD(~mask)] = deal(AoD(~mask),AoA(mask));
ctet = 2*pi/lambda * d * sin(AoD);
f_t = reshape(arrayfun(#(x) exp(1j*(0:3)'*ctet(x))/sqrt(M),1:12,'UniformOutput',0),sz);
cter = (2*pi)/lambda*d*sin(AoA);
f_r = reshape(arrayfun(#(x) exp(1j*(0:3)'*cter(x))/sqrt(O),1:12,'UniformOutput',0),sz);
channel = reshape(arrayfun(#(x) alpha(x) * f_r{x} * conj(transpose(f_t{x})), 1:12, 'UniformOutput',0),sz);
Note that for each of the variables mentioned in the question, the same values can be accessed using the corresponding 3D index. For example, using the code above, the value that was previously in AoA11(1) is now in AoA(1,1,1). Similarly, the matrix that was stored in channel11{1} is now in channel{1,1,1}.
Hope this helps.
class Matrix:
def __init__(self, nr, nc):
self.NRows = nr
self.NCols = nc
self.data = [ [0]*self.NCols for r in range(self.NRows) ]
def max(self, other):
""" return: a matrix with as many rows as the shorter of self and other and as many columns as the narrower of self and other.
Each entry of the returned matrix should be the larger (the max) of the corresponding entries in self and other.
"""
minrows = min(other.NRows, self.NRows)
mincols = min(other.NCols, self.NCols)
M = Matrix(minrows, mincols)
for i in range(minrows):
for j in range(mincols):
M.data[i][j] = max(self.data[i][j], other[i][j])
return M
This code give Traceback in max when tested and output said:
...in max
M.data[i][j] = max(self.data[i][j], other[i][j])
AttributeError: Matrix instance has no attribute '__getitem__'
How to get rid of this error? Where I made mistake?. Please help someone.
You should use this :
M.data[i][j] = max(self.data[i][j], other.data[i][j])
instead of
M.data[i][j] = max(self.data[i][j], other[i][j])