Finding n-distance neighbors in a hexagonal grid

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP





.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty margin-bottom:0;







up vote
2
down vote

favorite












In a grid of hexagons, we often want to find the neighbors of a cell with distance n. In the image below we have a rhombus-shaped grid of hexagons with an axial coordinate system showing the cell (row, col) = (3,3) (dark gray), its 1-distance neighbors (medium gray) and its 2-distance neighbors (light gray).





In the code below (which has the correct output), we create 5 arrays. Array #1 contains, for each row and column, indecies of neighbors with a distance of 1 or less. Array #2, #3, and #4 contain indecies of neighbors with distance 2, 3, 4 or less respectively.
The last array contains, for each distance 1,2,3, and 4, for each cell, the number of neighbors of the cell with the given distance or less. This is necessary as cells close to the grid boundary have fewer neighbors than cells close to the center.



#[macro_use]
extern crate ndarray;

use ndarray::prelude::*;
use std::ops::AddAssign;


fn hex_distance(r1: i8, c1: i8, r2: i8, c2: i8) -> i8
// Distance from cell (r1, c1) to cell (r2, c2) in a hexagonal grid
((r1 - r2).abs() + (r1 + c1 - r2 - c2).abs() + (c1 - c2).abs()) / 2


fn generate_neighs() -> (Array<usize, Ix4>, Array<usize, Ix4>,Array<usize, Ix4>,
Array<usize, Ix4>, Array<usize, Ix3>)
// Return 4 arrays with indecies of neighbors (including self) with distance of (1..5) or less;
// and a (4 X rows x cols) array with the number of neighbors for each row and column since
// the number of n-distance neighbors can vary for each cell.
let rows = 7;
let cols = 7;
// Indecies of neighbors with distance of 1 or less
let mut neighs1 = Array::zeros((rows, cols, 7, 2));
let mut neighs2 = Array::zeros((rows, cols, 19, 2));
let mut neighs3 = Array::zeros((rows, cols, 37, 2));
let mut neighs4 = Array::zeros((rows, cols, 43, 2));
// For distance 1..5 or less, for each row and col: the number of neighbors.
let mut n_neighs = Array::zeros((4, rows, cols));
neighs1.slice_mut(s![0, 0, 0, ..]).assign(&Array::ones(2));
for r1 in 0..rows
for c1 in 0..cols
// Want to store index of self first, so that it can be easily excluded
neighs1.slice_mut(s![r1, c1, 0, ..]).assign(&array![r1, c1]);
n_neighs.slice_mut(s![.., r1, c1]).add_assign(1);
for r2 in 0..rows
for c2 in 0..cols
let dist = hex_distance(r1 as i8, c1 as i8, r2 as i8, c2 as i8);
if (r1, c1) != (r2, c2) && dist <= 4
let n = n_neighs[[3, r1, c1]];
neighs4 .slice_mut(s![r1, c1, n, ..])
.assign(&array![r2, c2]);
n_neighs[[3, r1, c1]] += 1;
if dist <= 3
let n = n_neighs[[2, r1, c1]];
neighs3 .slice_mut(s![r1, c1, n, ..])
.assign(&array![r2, c2]);
n_neighs[[2, r1, c1]] += 1;
if dist <= 2
let n = n_neighs[[1, r1, c1]];
neighs2 .slice_mut(s![r1, c1, n, ..])
.assign(&array![r2, c2]);
n_neighs[[1, r1, c1]] += 1;
if dist == 1
let n = n_neighs[[0, r1, c1]];
neighs1 .slice_mut(s![r1, c1, n, ..])
.assign(&array![r2, c2]);
n_neighs[[0, r1, c1]] += 1;








return (neighs1, neighs2, neighs3, neighs4, n_neighs)


fn main()
let neighs = generate_neighs();
println!("", neighs.4);



Besides the code review I have a question, namely, how can I make these 5 arrays easily available throughout my program (without ever calling the function twice)? Is there any way of making them immutable (they won't change), making them global (for use in same file), and exporting them (for use in other files)?







share|improve this question



























    up vote
    2
    down vote

    favorite












    In a grid of hexagons, we often want to find the neighbors of a cell with distance n. In the image below we have a rhombus-shaped grid of hexagons with an axial coordinate system showing the cell (row, col) = (3,3) (dark gray), its 1-distance neighbors (medium gray) and its 2-distance neighbors (light gray).





    In the code below (which has the correct output), we create 5 arrays. Array #1 contains, for each row and column, indecies of neighbors with a distance of 1 or less. Array #2, #3, and #4 contain indecies of neighbors with distance 2, 3, 4 or less respectively.
    The last array contains, for each distance 1,2,3, and 4, for each cell, the number of neighbors of the cell with the given distance or less. This is necessary as cells close to the grid boundary have fewer neighbors than cells close to the center.



    #[macro_use]
    extern crate ndarray;

    use ndarray::prelude::*;
    use std::ops::AddAssign;


    fn hex_distance(r1: i8, c1: i8, r2: i8, c2: i8) -> i8
    // Distance from cell (r1, c1) to cell (r2, c2) in a hexagonal grid
    ((r1 - r2).abs() + (r1 + c1 - r2 - c2).abs() + (c1 - c2).abs()) / 2


    fn generate_neighs() -> (Array<usize, Ix4>, Array<usize, Ix4>,Array<usize, Ix4>,
    Array<usize, Ix4>, Array<usize, Ix3>)
    // Return 4 arrays with indecies of neighbors (including self) with distance of (1..5) or less;
    // and a (4 X rows x cols) array with the number of neighbors for each row and column since
    // the number of n-distance neighbors can vary for each cell.
    let rows = 7;
    let cols = 7;
    // Indecies of neighbors with distance of 1 or less
    let mut neighs1 = Array::zeros((rows, cols, 7, 2));
    let mut neighs2 = Array::zeros((rows, cols, 19, 2));
    let mut neighs3 = Array::zeros((rows, cols, 37, 2));
    let mut neighs4 = Array::zeros((rows, cols, 43, 2));
    // For distance 1..5 or less, for each row and col: the number of neighbors.
    let mut n_neighs = Array::zeros((4, rows, cols));
    neighs1.slice_mut(s![0, 0, 0, ..]).assign(&Array::ones(2));
    for r1 in 0..rows
    for c1 in 0..cols
    // Want to store index of self first, so that it can be easily excluded
    neighs1.slice_mut(s![r1, c1, 0, ..]).assign(&array![r1, c1]);
    n_neighs.slice_mut(s![.., r1, c1]).add_assign(1);
    for r2 in 0..rows
    for c2 in 0..cols
    let dist = hex_distance(r1 as i8, c1 as i8, r2 as i8, c2 as i8);
    if (r1, c1) != (r2, c2) && dist <= 4
    let n = n_neighs[[3, r1, c1]];
    neighs4 .slice_mut(s![r1, c1, n, ..])
    .assign(&array![r2, c2]);
    n_neighs[[3, r1, c1]] += 1;
    if dist <= 3
    let n = n_neighs[[2, r1, c1]];
    neighs3 .slice_mut(s![r1, c1, n, ..])
    .assign(&array![r2, c2]);
    n_neighs[[2, r1, c1]] += 1;
    if dist <= 2
    let n = n_neighs[[1, r1, c1]];
    neighs2 .slice_mut(s![r1, c1, n, ..])
    .assign(&array![r2, c2]);
    n_neighs[[1, r1, c1]] += 1;
    if dist == 1
    let n = n_neighs[[0, r1, c1]];
    neighs1 .slice_mut(s![r1, c1, n, ..])
    .assign(&array![r2, c2]);
    n_neighs[[0, r1, c1]] += 1;








    return (neighs1, neighs2, neighs3, neighs4, n_neighs)


    fn main()
    let neighs = generate_neighs();
    println!("", neighs.4);



    Besides the code review I have a question, namely, how can I make these 5 arrays easily available throughout my program (without ever calling the function twice)? Is there any way of making them immutable (they won't change), making them global (for use in same file), and exporting them (for use in other files)?







    share|improve this question























      up vote
      2
      down vote

      favorite









      up vote
      2
      down vote

      favorite











      In a grid of hexagons, we often want to find the neighbors of a cell with distance n. In the image below we have a rhombus-shaped grid of hexagons with an axial coordinate system showing the cell (row, col) = (3,3) (dark gray), its 1-distance neighbors (medium gray) and its 2-distance neighbors (light gray).





      In the code below (which has the correct output), we create 5 arrays. Array #1 contains, for each row and column, indecies of neighbors with a distance of 1 or less. Array #2, #3, and #4 contain indecies of neighbors with distance 2, 3, 4 or less respectively.
      The last array contains, for each distance 1,2,3, and 4, for each cell, the number of neighbors of the cell with the given distance or less. This is necessary as cells close to the grid boundary have fewer neighbors than cells close to the center.



      #[macro_use]
      extern crate ndarray;

      use ndarray::prelude::*;
      use std::ops::AddAssign;


      fn hex_distance(r1: i8, c1: i8, r2: i8, c2: i8) -> i8
      // Distance from cell (r1, c1) to cell (r2, c2) in a hexagonal grid
      ((r1 - r2).abs() + (r1 + c1 - r2 - c2).abs() + (c1 - c2).abs()) / 2


      fn generate_neighs() -> (Array<usize, Ix4>, Array<usize, Ix4>,Array<usize, Ix4>,
      Array<usize, Ix4>, Array<usize, Ix3>)
      // Return 4 arrays with indecies of neighbors (including self) with distance of (1..5) or less;
      // and a (4 X rows x cols) array with the number of neighbors for each row and column since
      // the number of n-distance neighbors can vary for each cell.
      let rows = 7;
      let cols = 7;
      // Indecies of neighbors with distance of 1 or less
      let mut neighs1 = Array::zeros((rows, cols, 7, 2));
      let mut neighs2 = Array::zeros((rows, cols, 19, 2));
      let mut neighs3 = Array::zeros((rows, cols, 37, 2));
      let mut neighs4 = Array::zeros((rows, cols, 43, 2));
      // For distance 1..5 or less, for each row and col: the number of neighbors.
      let mut n_neighs = Array::zeros((4, rows, cols));
      neighs1.slice_mut(s![0, 0, 0, ..]).assign(&Array::ones(2));
      for r1 in 0..rows
      for c1 in 0..cols
      // Want to store index of self first, so that it can be easily excluded
      neighs1.slice_mut(s![r1, c1, 0, ..]).assign(&array![r1, c1]);
      n_neighs.slice_mut(s![.., r1, c1]).add_assign(1);
      for r2 in 0..rows
      for c2 in 0..cols
      let dist = hex_distance(r1 as i8, c1 as i8, r2 as i8, c2 as i8);
      if (r1, c1) != (r2, c2) && dist <= 4
      let n = n_neighs[[3, r1, c1]];
      neighs4 .slice_mut(s![r1, c1, n, ..])
      .assign(&array![r2, c2]);
      n_neighs[[3, r1, c1]] += 1;
      if dist <= 3
      let n = n_neighs[[2, r1, c1]];
      neighs3 .slice_mut(s![r1, c1, n, ..])
      .assign(&array![r2, c2]);
      n_neighs[[2, r1, c1]] += 1;
      if dist <= 2
      let n = n_neighs[[1, r1, c1]];
      neighs2 .slice_mut(s![r1, c1, n, ..])
      .assign(&array![r2, c2]);
      n_neighs[[1, r1, c1]] += 1;
      if dist == 1
      let n = n_neighs[[0, r1, c1]];
      neighs1 .slice_mut(s![r1, c1, n, ..])
      .assign(&array![r2, c2]);
      n_neighs[[0, r1, c1]] += 1;








      return (neighs1, neighs2, neighs3, neighs4, n_neighs)


      fn main()
      let neighs = generate_neighs();
      println!("", neighs.4);



      Besides the code review I have a question, namely, how can I make these 5 arrays easily available throughout my program (without ever calling the function twice)? Is there any way of making them immutable (they won't change), making them global (for use in same file), and exporting them (for use in other files)?







      share|improve this question













      In a grid of hexagons, we often want to find the neighbors of a cell with distance n. In the image below we have a rhombus-shaped grid of hexagons with an axial coordinate system showing the cell (row, col) = (3,3) (dark gray), its 1-distance neighbors (medium gray) and its 2-distance neighbors (light gray).





      In the code below (which has the correct output), we create 5 arrays. Array #1 contains, for each row and column, indecies of neighbors with a distance of 1 or less. Array #2, #3, and #4 contain indecies of neighbors with distance 2, 3, 4 or less respectively.
      The last array contains, for each distance 1,2,3, and 4, for each cell, the number of neighbors of the cell with the given distance or less. This is necessary as cells close to the grid boundary have fewer neighbors than cells close to the center.



      #[macro_use]
      extern crate ndarray;

      use ndarray::prelude::*;
      use std::ops::AddAssign;


      fn hex_distance(r1: i8, c1: i8, r2: i8, c2: i8) -> i8
      // Distance from cell (r1, c1) to cell (r2, c2) in a hexagonal grid
      ((r1 - r2).abs() + (r1 + c1 - r2 - c2).abs() + (c1 - c2).abs()) / 2


      fn generate_neighs() -> (Array<usize, Ix4>, Array<usize, Ix4>,Array<usize, Ix4>,
      Array<usize, Ix4>, Array<usize, Ix3>)
      // Return 4 arrays with indecies of neighbors (including self) with distance of (1..5) or less;
      // and a (4 X rows x cols) array with the number of neighbors for each row and column since
      // the number of n-distance neighbors can vary for each cell.
      let rows = 7;
      let cols = 7;
      // Indecies of neighbors with distance of 1 or less
      let mut neighs1 = Array::zeros((rows, cols, 7, 2));
      let mut neighs2 = Array::zeros((rows, cols, 19, 2));
      let mut neighs3 = Array::zeros((rows, cols, 37, 2));
      let mut neighs4 = Array::zeros((rows, cols, 43, 2));
      // For distance 1..5 or less, for each row and col: the number of neighbors.
      let mut n_neighs = Array::zeros((4, rows, cols));
      neighs1.slice_mut(s![0, 0, 0, ..]).assign(&Array::ones(2));
      for r1 in 0..rows
      for c1 in 0..cols
      // Want to store index of self first, so that it can be easily excluded
      neighs1.slice_mut(s![r1, c1, 0, ..]).assign(&array![r1, c1]);
      n_neighs.slice_mut(s![.., r1, c1]).add_assign(1);
      for r2 in 0..rows
      for c2 in 0..cols
      let dist = hex_distance(r1 as i8, c1 as i8, r2 as i8, c2 as i8);
      if (r1, c1) != (r2, c2) && dist <= 4
      let n = n_neighs[[3, r1, c1]];
      neighs4 .slice_mut(s![r1, c1, n, ..])
      .assign(&array![r2, c2]);
      n_neighs[[3, r1, c1]] += 1;
      if dist <= 3
      let n = n_neighs[[2, r1, c1]];
      neighs3 .slice_mut(s![r1, c1, n, ..])
      .assign(&array![r2, c2]);
      n_neighs[[2, r1, c1]] += 1;
      if dist <= 2
      let n = n_neighs[[1, r1, c1]];
      neighs2 .slice_mut(s![r1, c1, n, ..])
      .assign(&array![r2, c2]);
      n_neighs[[1, r1, c1]] += 1;
      if dist == 1
      let n = n_neighs[[0, r1, c1]];
      neighs1 .slice_mut(s![r1, c1, n, ..])
      .assign(&array![r2, c2]);
      n_neighs[[0, r1, c1]] += 1;








      return (neighs1, neighs2, neighs3, neighs4, n_neighs)


      fn main()
      let neighs = generate_neighs();
      println!("", neighs.4);



      Besides the code review I have a question, namely, how can I make these 5 arrays easily available throughout my program (without ever calling the function twice)? Is there any way of making them immutable (they won't change), making them global (for use in same file), and exporting them (for use in other files)?









      share|improve this question












      share|improve this question




      share|improve this question








      edited Jun 23 at 19:58
























      asked Jun 23 at 19:41









      tsorn

      2007




      2007

























          active

          oldest

          votes











          Your Answer




          StackExchange.ifUsing("editor", function ()
          return StackExchange.using("mathjaxEditing", function ()
          StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix)
          StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
          );
          );
          , "mathjax-editing");

          StackExchange.ifUsing("editor", function ()
          StackExchange.using("externalEditor", function ()
          StackExchange.using("snippets", function ()
          StackExchange.snippets.init();
          );
          );
          , "code-snippets");

          StackExchange.ready(function()
          var channelOptions =
          tags: "".split(" "),
          id: "196"
          ;
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function()
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled)
          StackExchange.using("snippets", function()
          createEditor();
          );

          else
          createEditor();

          );

          function createEditor()
          StackExchange.prepareEditor(
          heartbeatType: 'answer',
          convertImagesToLinks: false,
          noModals: false,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: null,
          bindNavPrevention: true,
          postfix: "",
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          );



          );








           

          draft saved


          draft discarded


















          StackExchange.ready(
          function ()
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f197133%2ffinding-n-distance-neighbors-in-a-hexagonal-grid%23new-answer', 'question_page');

          );

          Post as a guest



































          active

          oldest

          votes













          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes










           

          draft saved


          draft discarded


























           


          draft saved


          draft discarded














          StackExchange.ready(
          function ()
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f197133%2ffinding-n-distance-neighbors-in-a-hexagonal-grid%23new-answer', 'question_page');

          );

          Post as a guest













































































          Popular posts from this blog

          Greedy Best First Search implementation in Rust

          Function to Return a JSON Like Objects Using VBA Collections and Arrays

          C++11 CLH Lock Implementation