I am trying to create a Vector class for use with LuaJ. The end goal is to have the user not write much lua, and have most of the work done on my Java engine.
As my understanding goes, I need to set the metatable for the lua representation of my Java vector class? The problem I am having though, is that when I am trying to overwrite some metatable functionality it doesn't seem to have any affect in my lua script. What I am trying to do now is overwrite the + operator, so I can add two vectors together or add a vector by a constant.
Here is my Vector class so far:
package math;
import org.luaj.vm2.*;
import org.luaj.vm2.lib.*;
import org.luaj.vm2.lib.jse.*;
public class Vector3Lua {
public float X;
public float Y;
public float Z;
public Vector3Lua unit;
static {
// Setup Vector class
LuaValue vectorClass = CoerceJavaToLua.coerce(Vector3Lua.class);
// Metatable stuff
LuaTable t = new LuaTable();
t.set("__add", new TwoArgFunction() {
public LuaValue call(LuaValue x, LuaValue y) {
System.out.println("TEST1: " + x);
System.out.println("TEST2: " + y);
return x;
}
});
t.set("__index", t);
vectorClass.setmetatable(t);
// Bind "Vector3" to our class
luaj.globals.set("Vector3", vectorClass);
}
public Vector3Lua() {
// Empty
}
// Java constructor
public Vector3Lua(float X, float Y, float Z) {
this.X = X;
this.Y = Y;
this.Z = Z;
this.unit = new Vector3Lua(); // TODO Make this automatically calculate
System.out.println("HELLO");
}
// Lua constructor
static public class New extends ThreeArgFunction {
#Override
public LuaValue call(LuaValue arg0, LuaValue arg1, LuaValue arg2) {
return CoerceJavaToLua.coerce(new Vector3Lua(arg0.tofloat(), arg1.tofloat(), arg2.tofloat()));
}
}
// Lua Function - Dot Product
public float Dot(Vector3Lua other) {
if ( other == null ) {
return 0;
}
return X * other.X + Y * other.Y + Z * other.Z;
}
// Lua Function - Cross Product
public LuaValue Cross(Vector3Lua other) {
Vector3Lua result = new Vector3Lua( Y * other.Z - Z * other.Y,
Z * other.X - X * other.Z,
X * other.Y - Y * other.X );
return CoerceJavaToLua.coerce(result);
}
}
Here is the lua script that makes use of this:
local test1 = Vector3.new(2, 3, 4);
local test2 = Vector3.new(1, 2, 3);
print(test1);
print(test2);
print(test1+2);
The last line produces an error, as it says I cannot add a userdata and a number together. However, in my vector class I tried to get it to just print what is being added, and just return the original data (to test). So I believe my problem is how I am defining my metatable; In my vector class, the two print's are never called.
print(test1+2); should be print(test1+test2);. You got that error because test1 is a userdata (basically an under-the-hood version of a table) and 2 is a number.
Related
I'm half way through an assignment in java where I have two classes and need to calculate a x- and y-position. I get half of the tests correct but can't seem to get the two last ones correct. Could you perhaps guide my in the right direction?
I have one class calle Point and one PointMain. I get the arguments in PointMain and need to create the right methods in Point. I can't make any changes in the class PointMain as I got that from the assignment.
Class Point:
public class Point {
private int x = 0;
private int y = 0;
public Point() {
}
public Point(int xPoint, int yPoint) {
x = xPoint;
y = yPoint;
}
public String toString() {
return x + "," + y;
}
public double distanceTo(Point p2) {
double avstand = Math.sqrt(((p2.x*1 - p2.x*2) * (p2.x*1 - p2.x*2)) + ((p2.y*1 - p2.y*2) * (p2.y*1 - p2.y*2)));
return avstand;
}
public void move(int iPoint, int jPoint) {
x = x + iPoint; // I have a problem with this that it doesn't add
y = y + jPoint; // the 3,4 that I got from p2 with the 5,-2.
}
public void moveToXY(int xTag, int yTag) {
}
public boolean isEqualTo(Point p2) { //And I'm not really sure on how to
return false; //construct this method either...
}
}
Class PointMain:
public class PointMain {
public static void main(String[] args) {
Point p1 = new Point();
Point p2 = new Point(3,4);
System.out.println(p1.toString()); // ==> (0,0)
System.out.println(p2.toString()); // ==> (3,4)
if (p1.isEqualTo(p2)) // False!
System.out.println("The two points are equal");
double dist = p1.distanceTo(p2);
System.out.println("Point Distance: "+dist);
p2.move(5,-2); // ==> (8,2)
p1.moveToXY(8,2); // ==> (8,2)
System.out.println(p1);
System.out.println(p2);
if (p1.isEqualTo(p2)) // True!
System.out.println("The two points are equal");
}
}
First of all you should add getters
public int getX()
{
return x;
}
public int getY()
{
return y;
}
Than implement isEqual
public boolean isEqualTo(Point p2) {
return x == p2.getX() && y == p2.getY();
}
you can also declare x and y public and then there is no need for getters and code is simpler as you can see in implementation of java.awt.Point.
I don't see problem with "move" function.
And last
public void moveToXY(int xTag, int yTag) {
x = xTag;
y = yTag;
}
For additional info you can lookup how java.awt.Point implemented, and work on your function parameters naming iPoint/jPoint is horrible names
For the equality method, think that in which condition the two points are equal. Consider using if for validating the condition and getters for getting the points x and y.
And I don't see any problem with the move method.
And as #Juniar said in the comments, there's another problem in your distanceTo method. You want to get x and y of p2 but they are private variables so you can't have them by this way. In this case your are having the x and y of the object which the method is called on. So the output won't be desirable. (see getters again)
How can I program my class to accept both Integers and Floats, I suppose I'll need to use generics, am I correct?
public class Vec2 {
private int x, y;
public Vec2(int xa, int ya) {
this.x = xa;
this.y = ya;
}
public Vec2() {
this(0, 0);
}
public Vec2(Vec2 vec) {
this(vec.x, vec.y);
}
public void addX(int xa) {
x+=xa; // I get an exception here when I try to use generics.
}
public void addY(int ya) {
y+=ya; // I get an exception here when I try to use generics.
}
Any ideas how to program my class to accept floats, integers and doubles altogether?
For the time being, we cannot have generics over primitives like int or double, so you will be forced to use boxed representations. It really is easier to just make a separate class for int and double. But if you want to use generics, here's how you can do it in a type-safe way (using java8):
public class Vec2<T> {
private final BinaryOperator<T> adder;
private T x, y;
private Vec2(BinaryOperator<T> adder, T x, T y) {
this.adder = adder;
this.x = x;
this.y = y;
}
public void addX(T xa) {
x = adder.apply(x, xa);
}
public void addY(T ya) {
y = adder.apply(y, ya);
}
public static Vec2<Integer> ofInt(Integer x, Integer y) {
return new Vec2<>(Integer::sum, x, y);
}
public static Vec2<Double> ofDouble(Double x, Double y) {
return new Vec2<>(Double::sum, x, y);
}
}
Vec2<Integer> intvec = Vec2.ofInt(5, 3);
intvec.addX(8);
Vec2<Double> dblvec = Vec2.ofDouble(5.2, 8.9);
dblvec.addY(-.9);
You could use BigDecimal to back your Vec2 and then you could use create addX and addY method(s) for long and double fairly easily. Something like,
public class Vec2 {
private BigDecimal x, y;
public Vec2(double xa, double ya) {
this.x = BigDecimal.valueOf(xa);
this.y = BigDecimal.valueOf(ya);
}
public Vec2(long xa, long ya) {
this.x = BigDecimal.valueOf(xa);
this.y = BigDecimal.valueOf(ya);
}
public Vec2(Vec2 vec) {
this.x = vec.x;
this.y = vec.y;
}
public void addX(double xa) {
x = x.add(BigDecimal.valueOf(xa));
}
public void addX(long xa) {
x = x.add(BigDecimal.valueOf(xa));
}
public void addY(double ya) {
y = y.add(BigDecimal.valueOf(ya));
}
public void addY(long ya) {
y = y.add(BigDecimal.valueOf(ya));
}
#Override
public String toString() {
return String.format("x = %s, y = %s", x.toString(), y.toString());
}
}
No, you don't, merely have your class inherit from Number and use type checking to ensure that values are of the appropriate class, if necessary, e.g.
Class IsraelG99sClass {
Number n;
public Number add(Number n2) {
if (n instanceof Integer && n2 instanceof Integer) {
return new Integer(n.intValue() + n2.intValue());
} else {
return new Double(n.doubleValue() + n2.doubleValue());
}
}
public Number getValue() {
if ((n instanceof Integer) || (n instanceof Float)) {
return n;
} // handle the other case as appropriate
}
}
Floats and ints are very different values with vastly different mins and maxes. I would try using doubles as the data member with overloaded constructors for different variable types instead of generics unless generics are really needed.
Yes, you can use generics and make your x and y attributes of type T.
But you won't be able to just implement the addX and addY in they way you want.
Check these other answers on how to implement a generic number addition, it's not as simple but you should be able to do it that way.
Java Generics and adding numbers together
how to write a generic method for adding numbers
First of all, I'm operating under the assumption that you want x and y to be of varying (generic) type.
For this, you would want:
public class Vec2<E extends Number> {
private E x, y;
public Vec2(E xa, E ya) {
this.x = xa;
this.y = ya;
}
//Not _easily_ possible with generics, as the compiler has no guarantee that
//zero is an acceptable value. Consider some variation of a Factory pattern,
//but this will work. Note that there is an "officially"-unchecked cast warning.
public Vec2() {
super();
final Number zero = 0.0;
this.x = (E)zero;
this.y = (E)zero;
}
public Vec2(Vec2<E> vec) {
this(vec.x, vec.y);
}
public void addX(E xa) {
Number c = x.doubleValue() + xa.doubleValue();
x = (E)c;
}
public void addY(E ya) {
Number c = y.doubleValue() + ya.doubleValue();
x = (E)c;
}
This should work well. While I encourage you to use generics, note that keeping a numeric type (like int, float, or double) as a generic is often not advisable, as they're only similar on the surface. When you dig into the operations of, say, "+", they are radically different dependent on type. You will also have an assortment of unchecked-cast warnings in this code; perhaps I could have rooted them out properly had I the time, but this just goes back to my warning about generic numbers.
You will also notice a few flukes of the language doing this, such as the way that (E)zero works, but (E)(0.0) does not.
By and large, though, generics are a much easier and cleaner way to go about things than inheritance, when it is possible.
I am currently doing solo text book work for java(not part of a class) and I'm stuck on a question.
Write an instance method modulus for this class that could be called by a statement like
double size = z.modulus(); where z is of type Complex. If z represented the value a + ib,
then the call would set the variable size to the value of |z| = square root(a2 + b2).
What am I doing wrong?
public class complex {
double re;
double im;
complex x;
public static void main(String[] args) {
public complex z = new complex();
{
z.im = In.getDouble();
z.re = In.getDouble();
}
//public complex modulus = (x);
//{
// x.im = z.im * z.im;
// x.re = z.re * z.re;
// return ;
//}
public double size() {
System.out.println(Math.sqrt(x.im+ x.re));
return Math.sqrt(x.im+ x.re);
}
double size = z.modulus();
// {
//}
private double modulus() {
// TODO Auto-generated method stub
x.im = z.im * z.im;
x.re = z.re * z.re;
return 0;
}
}
I made the changes and came out with this but it still doesn't work i put the errors next to the line in which they occur.
public class complex {
double re;
double im;
public complex z = new complex();
{
z.im = In.getDouble();
z.re = In.getDouble();}
public static void main(String[] args) {
private double modulus() { // insert enumIdentifier and body, Syntax error on "double" # expected.
return Math.sqrt( im * im + re * re );
}
double size = z.modulus();
}
}
You don't need to refer to either x or z. You have the right fields in your class to be able to calculate the modulus.
public double modulus() {
return Math.sqrt( im * im + re * re );
}
However, in the code in your question, you seem to be defining your class's methods inside the main method. You can't do that. Close off the definition of one method (with }) before starting the next.
I am looking for a way to pass a method as a parameter into another method.
I am currently trying to simulate the Newton's-method (http://en.wikipedia.org/wiki/Newton%27s_method) in Java with the following code:
public class Newton {
// Iterationmethod
public void newtonCalc(double x0) {
double x;
// counter
int i = 0;
//Newton-Iteration for x0
x = x0 - (y2(x0) / y2Deriv(x0));
while (Math.sqrt(y2(x)*y2(x)) >= Math.pow(10, -10)){
//Newton-Iteration x(n+1)
x = x - (y2(x))/ y2Deriv(x);
i++;
System.out.printf("%d. %.11f\n",i,y2(x));
}
System.out.printf("%d steps were necessary for a resolution of 10^-10", i);
}
// Function for (2)
public static double y2(double x) {
return Math.sin(x) / (1 - Math.tan(x));
}
// Derivative for (2)
public static double y2Deriv(double x) {
return (Math.cos(x) + Math.sin(x) * Math.tan(x) * Math.tan(x))
/ ((Math.tan(x) - 1) * (Math.tan(x) - 1));
}
// Function for (4)
public static double y4(double x) {
return Math.exp(-1/Math.sqrt(x));
}
// Derivative for (4)
public static double y4Deriv(double x) {
return Math.exp(-1/Math.sqrt(x))/(2*Math.pow(x, 3d/2));
}
public static void main(String[] args) {
Newton newton = new Newton();
newton.newtonCalc(1);
}
}
newtonCalc(x0) gets an x0 at wich the iteration should be started.
But the function (y2) now is hardcoded into this method. I want it to be flexible.
For example newtonCalc(double x0, Method y) to run the iteration for y starting at x0.
I have 2 different functions (y2 and y4 which are both functions from a excercise sheet from my lecture plus its derivatives y2Deriv and y4Deriv which are used in the Iterationmethod).
I know passing a method is not possible but i dont get any easy workaround.
Forgive me if this is unclear or i have missed any necessary information!
Regards,
Tak3r07
It's entirely possible since Java 8, using lambda expressions
If you want to stay with pre-Java-8 methods, make an interface Function with member functions eval and deriv and pass (possibly anonymous) instances of derived classes to the Newton class invocation.
This could look like (I'm not sure that all details are correct, these are just code fragments to illustrate the idea)
interface Function {
public double eval(double x);
public double deriv(double);
}
class Example1 implements Function {
#override
public double eval(double x) { return x*(x+3)+1; }
#override
public double deriv(double) { return 2*x+3; }
}
....
Solver solver1 = new Newton(new Example1(),x0);
....
Solver solver2 = new Newton(new Function(){
#override
public double eval(double x) { return cos(x); }
#override
public double deriv(double) { return -sin(x); }
}, x0);
Hi im new to this site and need help with a program im working on. the problem im having is that i cant seem to store string and two integers (as the coordinates). i have looked at other code but dont see how the values are stored. below is the code ive been using. the code seems to be fine but when trying to stored the values i cant put multiply integers. thanks for your time
import java.util.HashMap;
public class map {
class Coords {
int x;
int y;
public boolean equals(Object o) {
Coords c = (Coords) o;
return c.x == x && c.y == y;
}
public Coords(int x, int y) {
super();
this.x = x;
this.y = y;
}
public int hashCode() {
return new Integer(x + "0" + y);
}
}
public static void main(String args[]) {
HashMap<Coords, Character> map = new HashMap<Coords, Character>();
map.put(new coords(65, 72), "Dan");
}
}
There is a class in java called Class Point.
http://docs.oracle.com/javase/7/docs/api/java/awt/Point.html
This is the same information provided on Java docs API 10:
https://docs.oracle.com/javase/10/docs/api/java/awt/Point.html
A point representing a location in (x,y) coordinate space, specified in integer precision.
You can see an example, and also other important topics related in this link: http://www.java2s.com/Tutorial/Java/0261__2D-Graphics/Pointclass.htm
import java.awt.Point;
class PointSetter {
public static void main(String[] arguments) {
Point location = new Point(4, 13);
System.out.println("Starting location:");
System.out.println("X equals " + location.x);
System.out.println("Y equals " + location.y);
System.out.println("\nMoving to (7, 6)");
location.x = 7;
location.y = 6;
System.out.println("\nEnding location:");
System.out.println("X equals " + location.x);
System.out.println("Y equals " + location.y);
}
}
I hope this can help you!
There seems to be several issues:
"Dan" is a String, not a Character
case is important in Java (new coords(65,72) should be new Coords(65,72))
Coords needs to be static to be instantiated without a reference to an instance the enclosing map class.
This should work:
static class Coords {
...
}
Map<Coords, String> map = new HashMap<Coords, String>();
map.put(new Coords(65, 72), "Dan");
ps: although you are allowed to name a local variable map within a class map, it is not a good idea to have such name collision. In Java, classes generally start in upper case, so you could rename your class Map. But it happens that Map is a standard class in Java. So call your class Main or Test or whatever is relevant. ;-)
Adding to #assylias
Make you inner class static in order to insert new objects like you have or new Outer().new Inner() .
Take care of Java Naming Convention
Code like:
public class XYTest {
static class Coords {
int x;
int y;
public boolean equals(Object o) {
Coords c = (Coords) o;
return c.x == x && c.y == y;
}
public Coords(int x, int y) {
super();
this.x = x;
this.y = y;
}
public int hashCode() {
return new Integer(x + "0" + y);
}
}
public static void main(String args[]) {
HashMap<Coords, String> map = new HashMap<Coords, String>();
map.put(new Coords(65, 72), "Dan");
map.put(new Coords(68, 78), "Amn");
map.put(new Coords(675, 89), "Ann");
System.out.println(map.size());
}
}
package Lecture3;
import java.util.Scanner;
public class lecture9 {
private int nInleste;
public lecture9() {/*
* tabell/ // T/*chapter 6 in the books.
**/
}
public static void main(String[] args) {
Scanner inn = new Scanner(System.in);
int nInleste = 3;
double[] tall = new double[nInleste];
double sum = 0;
for (int i = 0; i < nInleste; i++) {
System.out.println("Leste en tall!");
tall[i] = inn.nextDouble();
sum += tall[i];
}
System.out.println(sum);
double snitt = nInleste / nInleste;
System.out.println("Gjennomsnittsverdien:" + snitt);
for (int i = 0; i < nInleste; i++) {
double aavik = tall[i] - snitt;
int avvivk = 0;
System.out.println(i + 1 + " Tal sitt avvik fra gjennomsnittet " + avvivk);
}
}/* end of the main methods */
}
if you have problem with your code you can try this , simple code to store string and two int values into a map
class MyCoord{
private int X;
private int Y;
public MyCoord() {
this(0,0);
}
public MyCoord(int X, int Y) {
this.X = X;
this.Y = Y;
}
public int getX() {
return X;
}
public int getY() {
return Y;
}
public void setX(int X) {
this.X = X;
}
public void setY(int Y) {
this.Y = Y;
}
}
//main class begins
public class PointDemo{
public static void main(String[] args) {
Map <String,MyCoord> multiplePoints=new HashMap<String, MyCoord>();
multiplePoints.put("point1", new MyCoord(10, 20));
multiplePoints.put("point2", new MyCoord(100, 2000));
MyCoord coord=multiplePoints.get("point1");
System.out.println(coord.getX() +" : "+coord.getY());
}
}