OPK
OPK

Reputation: 4180

How to find correct neighbors for any giving coordinate?

Update: this question is seeking guidance on how to get a set of neighbors for any given coordinate.

I created a 2d array that contains coordinates,

 int[][] coordinates= { { -1, -1 }, { -1, 0 }, { -1, +1 },
            { 0, -1 }, { 0, +1 }, { +1, -1 }, { +1, 0 }, { +1, -1 } };

As you can tell, these are the neighbors for coordinates (0,0).

Now I am trying to implement a method that takes two parameters (int positionX, int positionY), and use the input parameters value coordiante(x,y) as the starting coordinate and find all the neighbors for this coordinate.

I am thinking about something like this:

    int getNearCoordinates(int positionX, int positionY) {

        for (int[] coordinate: coordinates) {
               //I am not sure what to do after this
        }

    } 

I am trying to use a loop to get the individual coordinate from the 2d array I created and I am stuck at here. How do I find a way to appropriately find positionX's and positionY's neighbor?

What are neighbours?

All orange points in diagram below are neighbours of Origin (0,0) enter image description here

Upvotes: 7

Views: 5719

Answers (5)

Nick Mertin
Nick Mertin

Reputation: 1209

It may seem obvious, but you could duplicate coordinates, and add the given coordinate's x and y values to those of each coordinate, fit example using a for loop.

Upvotes: 0

maraca
maraca

Reputation: 8763

This is not the best way to implement it (using int[] for points), the purpose of this answer is to show the algorithms.

If you are talking about an unbounded plane then you will always have 8 points, so you could implement it the following way:

// first point index, 2nd: 0 = x, 1 = y
public int[][] getNeighbours(int x, int y) {
   int[][] ret = new int[8][2];
   int count = 0;
   for (int i = -1; i <= 1; i++)
      for (int j = -1; j <= 1; j++) {
         if (i == 0 && j == 0)
            continue;
         ret[count][0] = x + i;
         ret[count++][1] = y + j;
      }
   return ret;
}

It gets more interesting if the plane is bounded, using an ArrayList this time:

public List<int[]> getNeighbours(int x, int y, int minX, int maxX, int minY, int maxY) {
   List<int[]> ret = new ArrayList<int[]>(8); // default initial capacity is 100
   for (int i = Math.max(x - 1, minX); i <= Math.min(x + 1, maxX); i++)
      for (int j = Math.max(y - 1, minY); j <= Math.min(y + 1, maxY); j++) {
         if (i == x && j == y)
            continue;
         ret.add(new int[] {i, j});
      }
   return ret;
}

The latter will work for any point, also outside of the plane or just at the border.

Upvotes: 1

slartidan
slartidan

Reputation: 21598

I'd recommend to

  • Use a dedicated class (Coordinate) instead of int[]. This makes your code easier to extend (3rd dimention, etc) or to change (using double instead of int, etc.). In the example you can see an imutable class - this hinders code to have side effects.
  • Use Collection instead of Array. This makes handling much easier (you can simply add and remove items)
  • Use java8-Streaming-API. It is lightning fast and makes your code better readable.

Additional ideas:

  • You could even make getNearCoordinates part of the Coordinate class. This would make new Coordinate(27,35).getNearCoordinates() available.
  • Instead of storing x and y in separate fields you could also use a Map<Axis, Integer>. This would make your code a little bit harder to understand - but would reduce duplicated code.
  • You could also generate the collection of directions by using two nested loops for (int x = -1; x <= 1; x++) for (int y = -1; y <= 1; y++) use(new Coordinate(x,y)). This would make your code cleaner, but might be harder to understand.

Example code:

import java.util.*;
import java.util.stream.Collectors;

public class Snippet {

    // make a class to be more flexible
    class Coordinate {

        // final fields are making this an "imutable"
        final int x;
        final int y;

        /** constructor to take coordinate values */
        Coordinate(int x, int y) {
            this.x = x;
            this.y = y;
        }

        /** moves this coordinate by another coordinate */
        Coordinate move(Coordinate vector) {
            return new Coordinate(x + vector.x, y + vector.y);
        }
    }

    /** using Collection instead of Array makes your live easier. Consider renaming this to "directions". */
    Collection<Coordinate> coordinates = Arrays.asList(
            new Coordinate( -1, -1 ), // left top
            new Coordinate( -1,  0 ), // left middle
            new Coordinate( -1, +1 ), // left bottom
            new Coordinate(  0, -1 ), // top
            new Coordinate(  0, +1 ), // bottom
            new Coordinate( +1, -1 ), // right top
            new Coordinate( +1,  0 ), // right middle
            new Coordinate( +1, +1 )  // right bottom
            );

    /** @return a collection of eight nearest coordinates near origin */
    Collection<Coordinate> getNearCoordinates(Coordinate origin) {
        return
                // turn collection into stream
                coordinates.stream()

                // move the origin into every direction
                .map(origin::move)

                // turn stream to collection
                .collect(Collectors.toList());
    }

}

Same behaviour without Java8-streaming API would look like this:

/** @return a collection of eight nearest coordinates near origin */
Collection<Coordinate> getNearCoordinates(Coordinate origin) {
    Collection<Coordinate> neighbours = new ArrayList<>();

    for (Coordinate direction : coordinates)
        neighbours.add(origin.move(direction));

    return neighbours;
}

Upvotes: 6

AtomHeartFather
AtomHeartFather

Reputation: 958

That depends on how you define a neighbour. The code below will test the coordinates and return true for the diagonal as well as horizontal and vertical neighbours.

if (Math.abs(coordinate[0] - positionX) <= 1 && Math.abs(coordinate[1] - positionY) <= 1)
{
    System.out.println(Arrays.toString(coordinate));
}

make sure to import java.lang.Math

Printing of the coordinates is just an example of course, but may be useful for debugging.

Upvotes: 0

ka4eli
ka4eli

Reputation: 5424

Two points A(x1,y1), B(x2,y2) are neighbours if this expression is true:

 Math.abs(x1-x2) <= 1 && Math.abs(y1-y2) <= 1 

Here if both differences are equal to zero then A equals B.

Upvotes: 4

Related Questions