Iteratation through variables of an objects (java) - java

I have a class Room with the following constructor:
public Room (int x, int y, int z, int Stockwerk) {
this.x = x;
this.y = y;
this.z = z;
this.Stockwerk = Stockwerk;
}
In another class I want to calculate the similarity of two rooms by using the Euclidean distance. Therefore I want to iterate trough the object room to compare the first value(x) of room1 with the first value(x) of room2, the second(y) with the second(y) and so on. (The code below describes how I tried to get a result). Is there any option to iterate through the object room?
Iterator itrRoom1 = room1.iterator();
Iterator itrRoom2 = room2.iterator();
while (itrRoom1.hasNext()) {
while (itrRoom2.hasNext()) {
int value1 = itrRoom1.next();
int value2 = itrRoom2.next();
}
//this is the function how I get the similarity of two rooms (euclidean distance)
squareSubtraction = squareSubtraction + Math.pow(Math.abs(value1 - value2)), 2);
}
distance = Math.sqrt(squareSubtraction);

You do it with a very complicated way and Iterator is not needed.
If you want to get the euclidean distance, you only have to parse these two instances of Room to be compared. I assume your Room class has the getters.
You can use the following method with the arbitrary number of arguments based on looping through of all instances of Room given.
public static void main(String[] args) {
Room room1 = new Room(10,12,2,0);
Room room2 = new Room(4,8,2,0);
Room room3 = new Room(7,5,2,0);
Room room4 = new Room(10,2,2,0);
double result = similarity(room1, room2, room3, room4);
}
public static double similarity(Room ... r) {
double sum = 0;
for (int i=0; i<r.length-1; i++) {
double a = Math.pow(r[i].getX() - r[i+1].getX(), 2);
double b = Math.pow(r[i].getY() - r[i+1].getY(), 2);
sum += a + b;
}
return Math.sqrt(sum);
}
This is giving you the result:
9.38083151964686

You can't iterate fields like that. You could iterate fields using reflection, but don't.
You only have 3 values. Just use them.
long dx = room1.getX() - room2.getX();
long dy = room1.getY() - room2.getY();
long dz = room1.getZ() - room2.getZ();
double distance = Math.sqrt(dx * dx + dy * dy + dz * dz);
Note that dx and the others are declared long, so dx * dx won't overflow, and dx * dx is much faster than Math.pow(dx, 2).
It's actually even less code than what you were trying to do.

Related

Iterate through 3 dimensional radius in world from center position

I am trying to get all positions in a radius from a 3 dimensional world(In this case the game Minecraft) this is the current code I use.
public static List<BlockPos> getBlocksInRadius(double radius) {
List<BlockPos> circleblocks = new ArrayList<>();
int centralx = mc.player.posX;
int centraly = mc.player.posY;
int centralz = mc.player.posZ;
for (int x = centralx - radius; x <= centralx + radius; x++) {
for (int z = centralz - radius; z <= centralz + radius; z++) {
for (int y = centraly - radius; y < centraly + radius; y++) {
double dist = mc.player.getDistance(x, y, z);
if (dist < radius) {
BlockPos l = new BlockPos(x, y, z);
circleblocks.add(l);
}
}
}
}
return circleblocks;
}
This method goes from the x coord farthest away and keeps coming closer to the player. I want it to iterate it by starting at central x,y,z and then increase distance from the player. This is to make it easier to find block x closest to player. Any help would be apreciated!
Depending on how large of a radius you have, you might try the static method BlockPos::getAllInBox. There doesn't seem to be any official documentation on it, but it looks like it takes two BlockPos parameters and returns an Iterable<BlockPos>. It finds all the blocks in a cube in between the two parameters, so you probably want to center it on the player.
Here's what I would do. This code hasn't been tested, and you might need to adapt it for all of the 1.14 and 1.13 changes, but the theory should be the same, with just name changes.
BlockPos playerPos = player.getPosition(); // Or some other method of getting a BlockPos of the player
positiveRadiusPosition = playerPos.add(radius, radius, radius); // Gets one corner of the cube in the positive X, Y, and Z direction
negativeRadiusPosition = playerPos.add(-1 * radius, -1 * radius, -1 * radius); // Gets the opposite corner
Iterable<BlockPos> cubeResult = BlockPos.getAllInBox(positiveRadiusPosition, negativeRadiusPosition);
for (BlockPos pos: cubeResult) {
// cubeResult will contain blocks that are outside of the sphere with the
// radius you want. If that's okay, cool! If that's not okay, you should
// check each pos' distance from the player. If it's outside of the radius,
// remove it from the list.
}
Now you need to figure out which block is closest. The method I would use would be to use a Comparator to sort the Iterable, which is copied into a List. For reference:
public static Iterator sortedIterator(Iterator it, Comparator comparator) {
List list = new ArrayList();
while (it.hasNext()) {
list.add(it.next());
}
Collections.sort(list, comparator);
return list.iterator();
}
In the Comparator, you should check the distance from the player to each block.
public static double getDistanceToEntity(Entity entity, BlockPos pos) {
double deltaX = entity.posX - pos.getX();
double deltaY = entity.posY - pos.getY();
double deltaZ = entity.posZ - pos.getZ();
return Math.sqrt((deltaX * deltaX) + (deltaY * deltaY) + (deltaZ * deltaZ));
}
Of course, this method doesn't actually start at the player and work outwards. It's just a cleaner and expanded version of your original method that should do what you want. If you are working with a very large radius, it's probably not a good idea to use this, as you'll have to work with the entire cube.

How to get the nearest Vector to a given target from a list

So imagine I've created a Vector class with two variables x and y in Java:
public class Vector {
private int x;
private int y;
public Vector(int x, int y) {
this.x = x;
this.y = y;
}
public int getX() {
return this.x;
}
public int getY(){
return this.y;
}
}
Then I've craeted an ArrayList of vectors:
private List<Vector> vecs = new ArrayList<Vector>();
I've created in that list:
8,9
10,5
83473834,938849584985
etc ...
Now I want to get the closest vector to another vector.
Example:
private List<Vector> vecs = new ArrayList<Vector>();
private Vector vec = new Vector(1,1);
for(Vector vector:vecs) {
//What do i put here??
}
So what do i put in the for loop to make it select the nearest vector from the vector list?
I would start by adding a method to the Vector class, distanceTo, that calculates the distance from this vector to another one:
public double distanceTo(Vector vec) {
double dx = x - vec.x; //calculate the diffrence in x-coordinate
double dy = y - vec.y; //calculate the diffrence in y-coordinate
return Math.sqrt(dx*dx + dy*dy); //use the distance formula to find the difference
}
And then you can write the following method that returns the closest vector in a list to a given vector:
public static Vector closest(Vector target, List<Vector> list) {
Vector closest = list.get(0); //this variable will kep track of the closest vector we have found yet. We simply start with the first one
for(int i = 1; i < list.size(); i++) { //loop over the list, skipping the first entry
Vector curr = list.get(i); //get the current vector from the list
if (target.distanceTo(curr) < target.distanceTo(closest)) //if the current vector is closer to target than the closest one yet
closest = curr; //keep the current vector as the new closest one
}
return closest; //return the resulting vector
}
This method can then be used like this:
Vector target = new Vector(1, 2);
List<Vector> vecs = new ArrayList<Vector>();
vecs.add(new Vector(-2, 6));
vecs.add(new Vector(1, 3));
vecs.add(new Vector(4, 0));
vecs.add(new Vector(8, -1));
Vector closest = findClosest(target, vecs);
As you can see I tried to explain the code as best as I could, but feel free to ask any further questions!
EDIT another method is:
public double distanceTo(Vector vec1,Vector vec2) {
double dx = vec2.x - vec1.x; //calculate the diffrence in x-coordinate
double dy = vec.y - vec1.y; //calculate the diffrence in y-coordinate
return Math.sqrt(dx*dx + dy*dy); //use the distance formula to find the difference
}
This is if you can't put it into the vector class
This is a basic programming question. It is not related to OpenGL. A simple linear search could look as follows:
private List<Vector> vecs = new ArrayList<Vector>();
private Vector vec = new Vector(1,1);
Vector minDistanceVector = null;
int minDistanceSquared = Integer.MAX_VALUE;
for(Vector vector : vecs) {
//Calculate the distance
//This could be a member function of Vector
int dx = vector.getX() - vec.getX();
int dy = vector.getY() - vec.getY();
int squaredDistance = dx * dx + dy * dy;
if(squaredDistance < minDistanceSquared) {
minDistanceSquared = squaredDistance;
minDistanceVector = vector;
}
}
After that, you will have the closest vector in minDistanceVector. I chose Euclidean distance because this is probably what you want. But you could use any other distance, of course.
If you want something more efficient, you may want to build some acceleration data structure over the points and query that one (e.g. grid, kd-tree, quadtree...).

Optimizing nested for loop in java

I'm becoming crazy by trying to optimize the following function in java with OpenCV:
static Mat testPossibleCentersFormula(int x, int y, Mat weight, double gx, double gy, Mat outSum){
Mat out = outSum;//new Mat(weight.rows(), weight.cols(), CvType.CV_64F);
float weight_array [] = new float [weight.rows()*weight.cols()];
weight.get(0,0,weight_array);
double out_array [] = new double [weight.rows()*weight.cols()];
out.get(0,0,out_array);
for (int cy = 0; cy < out.rows(); ++cy) {
for (int cx = 0; cx < out.cols(); ++cx) {
if (x == cx && y == cy) {
continue;
}
// create a vector from the possible center to the gradient origin
double dx = x - cx;
double dy = y - cy;
// normalize d
double magnitude = Math.sqrt((dx * dx) + (dy * dy));
dx = dx / magnitude;
dy = dy / magnitude;
double dotProduct = dx*gx + dy*gy;
dotProduct = Math.max(0.0,dotProduct);
// square and multiply by the weight
if (kEnableWeight) {
out_array[cy*out.cols()+cx] = out_array[cy*out.cols()+cx] +dotProduct * dotProduct * (weight_array[cy*out.cols()+cx]/kWeightDivisor);
} else {
out_array[cy*out.cols()+cx] = out_array[cy*out.cols()+cx] +dotProduct * dotProduct;
}
} }
out.put(0, 0, out_array);
return out;
}
The function accesses some pictures' values pixel by pixel, for each frame in a video, and makes it impossible to use it in real time.
I've already converted the Mat operations into array operations, and that has made a great difference, but it is still very very slow. Do you see any way to replace the nested for loop?
Thank you very much,
As I have alluded to in my comment above, I think that the allocation of weight_array and out_array is very suspicious: whilst the Javadoc that I can find for Mat is unhelpfully silent on what is put into an array larger than the image depth when you call mat.get(...), it feels like an abuse of the API to assume that it will return the entire image's data.
Allocating such large arrays each time you call the method is unnecessary. You can allocate a much smaller array, and just reuse that on each iteration:
float[] weight_array = new float[weight.depth()];
double[] out_array = new double[out.depth()];
for (int cy = 0; cy < out.rows(); ++cy) {
for (int cx = 0; cx < out.cols(); ++cx) {
// Use weight.get(cx, cy, weight_array)
// instead of weight_array[cy*out.cols()+cx].
// Use out.get(cx, cy, out_array) and out.put(cx, cy, out_array)
// instead of out_array[cy*out.cols()+cx] += ...
}
}
Note that this does still allocate (probably very small) arrays on each iteration. If you needed to, you could allocate the weight_array and out_array outside the method, and pass them in as parameters; but I would try as suggested here first, and optimize further when/if necessary.

Generating several random double numbers in java

Every time when I try to generate random coordinates of city in this way,
public City () {
super();
this.x = Math.random()*200;
this.y = Math.random()*200;
}
I get the same values for the X and Y, which means that all cities are on same line on map. My question is how to avoid this? How to create different coordinates? Thanks.
I assumed a class like this:
class City {
private double x;
private double y;
public City() {
super();
this.x = Math.random() * 200;
this.y = Math.random() * 200;
}
#Override
public String toString() {
return "City [x=" + x + ", y=" + y + "]";
}
}
When I create new City objects I get (as it should be expected by the Math API) different values:
City [x=10.552289272723247, y=28.548756787475504]
City [x=58.96588997141927, y=146.87205149574288]
City [x=186.69728798772306, y=179.3787764147533]
Don't get me wrong - maybe at the point where you check the values you use by mistake twice the same?
To get different double values use java.util.Random class. Below, there's an example, it prints four different double values:
java.util.Random random = new java.util.Random();
System.out.println(random.nextDouble());
System.out.println(random.nextDouble());
System.out.println(random.nextDouble());
System.out.println(random.nextDouble());
Use java.util.Random.
Example:
Random random = new Random();
int x = random.nextInt(11); // from 0 to 10
double y = random.nextDouble(); // from 0 to 1
You must do wrong something else which is not in question.
public static void main(String[] args) {
double x = Math.random() * 200;
double y = Math.random() * 200;
System.out.println(x + ":"+y);
}
consider above code snap and you will get different x and y values..!
Please make sure that you are using new keyword every time while creating object of city.

Polygon Intersection fails, collision "size" too big

OK, so I'm trying to make a simple asteroids clone. Everything works fine, except for the collision detection.
I have two different versions, the first one uses java.awt.geom.Area:
// polygon is a java.awt.Polygon and p is the other one
final Area intersect = new Area();
intersect.add(new Area(polygon));
intersect.intersect(new Area(p.polygon));
return !intersect.isEmpty();
This works like a charm... if you don't care about 40% CPU for only 120 asteroids :(
So I searched the net for the famous separating axis theorem, since I'm not thaaaaaat good a the math I took the implementation from here and converted it to fit my Java needs:
public double dotProduct(double x, double y, double dx, double dy) {
return x * dx + y * dy;
}
public double IntervalDistance(double minA, double maxA, double minB,
double maxB) {
if (minA < minB) {
return minB - maxA;
} else {
return minA - maxB;
}
}
public double[] ProjectPolygon(double ax, double ay, int p, int[] x, int[] y) {
double dotProduct = dotProduct(ax, ay, x[0], y[0]);
double min = dotProduct;
double max = dotProduct;
for (int i = 0; i < p; i++) {
dotProduct = dotProduct(x[i], y[i], ax, ay);
if (dotProduct < min) {
min = dotProduct;
} else if (dotProduct > max) {
max = dotProduct;
}
}
return new double[] { min, max };
}
public boolean PolygonCollision(Asteroid ast) {
int edgeCountA = points;
int edgeCountB = ast.points;
double edgeX;
double edgeY;
for (int edgeIndex = 0; edgeIndex < edgeCountA + edgeCountB; edgeIndex++) {
if (edgeIndex < edgeCountA) {
edgeX = xp[edgeIndex] * 0.9;
edgeY = yp[edgeIndex] * 0.9;
} else {
edgeX = ast.xp[edgeIndex - edgeCountA] * 0.9;
edgeY = ast.yp[edgeIndex - edgeCountA] * 0.9;
}
final double x = -edgeY;
final double y = edgeX;
final double len = Math.sqrt(x * x + y * y);
final double axisX = x / len;
final double axisY = y / len;
final double[] minMaxA = ProjectPolygon(axisX, axisY, points, xp,
yp);
final double[] minMaxB = ProjectPolygon(axisX, axisY, ast.points,
ast.xp, ast.yp);
if (IntervalDistance(minMaxA[0], minMaxA[1], minMaxB[0], minMaxB[1]) > 0) {
return false;
}
}
return true;
}
It works... kinda. Actually it seems that the "collision hull" of the asteroids is too big when using this code, it's like 1.2 times the size of the asteroid. And I don't have any clue why.
Here are two pictures for comparison:
http://www.spielecast.de/stuff/asteroids1.png
http://www.spielecast.de/stuff/asteroids2.png
As you can hopefully see, the asteroids in picture one are much denser than the ones in picture 2 where is use the SAT code.
So any ideas? Or does anyone knows a Polygon implementation for Java featuring intersection tests that I could use?
It looks like your second result is doing collision detection as if the polygons were circles with their radius set to the most distant point of the polygon from the center. Most collision detection stuff I've seen creates a simple bounding box (either a circle or rectangle) into which the polygon can fit. Only if two bounding boxes intersect (a far simpler calculation) do you continue on to the more detailed detection. Perhaps the appropriated algorithm is only intended as a bounding box calculator?
EDIT:
Also, from wikipedia
The theorem does not apply if one of the bodies is not convex.
Many of the asteroids in your image have concave surfaces.

Categories