Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Join two coordinates of a matrix with minimum distance

I am working on a process of completion (I am not sure of the correct term) of a matrix based on two coordinates considering the minimum distance, let me explain.

I have a matrix of nxm (rows and columns), of NA values and 1 see figure 1:

enter image description here

The goal is:

  1. Find end points of the contiguous elements that are joined by a distance equal to 1 (adjacent on the horizontal and vertical) or 1.4142 (adjacent on the diagonal). The extreme coordinates in the example are represented by the rectangles in the figure.
  2. After locating the extreme coordinates, it is required to complete the coordinates that describe "preferably" the minimum distance between the two points. (represented by the line in the figure 1)

Assuming I find the extreme coordinates (a and b see figure 2), I am trying to use the vector equation of a line:

enter image description here

So I'm trying to create a function that uses the extreme values (a and b) and the constant k (see figure 2)

completa <- function(a, b, k){
  x <- y <- NULL
  resta <- b - a
  u_ba <- resta / sqrt(sum(resta^2))
  for (i in seq(0, 1, k)) {
    posi <- a + i * u_ba
    x <- c(x, posi[1])
    y <- c(y, posi[2])
  }
  coordenadas  <- round(cbind(x, y))
  return(coordenadas)
}

The example matrix is in:

data_mat <- read.csv("https://www.dropbox.com/s/hz42scjuf9uib9y/data_test.csv?dl=1")
a <- c(25, 6)
b <- c(20, 10)

When using the function with the coordinates a, b and k = 0.5 (the value of k can vary between 0 and 1), the following is obtained:

completa(a,b,0.5)
#      x y
#[1,] 25 6
#[2,] 25 6
#[3,] 24 7

but the expected output is:

#      x y
#[1,] 25 6
#[2,] 24 7
#[3,] 23 8
#[4,] 22 9
#[5,] 21 10 # or 21 9,  
#[6,] 20 10

It is evident that there is more than one solution for the line, therefore, comment that the minimum distance is preferably considered.

Finally, after having these coordinates, it would only be enough to assign them a value equal to one. The main idea is to make this process recursive. And that in the end all the coordinates of the matrix can be joined.

Please any suggestion is welcome, thank you.

like image 947
rral Avatar asked Sep 15 '20 08:09

rral


2 Answers

as far as i see, you have made a mathematical problem. When i understand it right, you want to "hit" the squares in between your extreme coordinates to build a bridge between your 2 cluster. The error you have made is in your for loop. You are adding at the end of the loop only 1 times the unit vector of ab, so you travelled only the distance of 1 in your grid. I have corrected your code in that way, that it travels the full distance. I hope it solved your Problem:

completa <- function(a, b, k){
  if(k!=0){
    x <- y <- NULL
    resta <- b - a
    vector_length = sqrt(sum(resta^2))        
    for (i in seq(0, 1, length.out=(vector_length/k))) {
      posi <- a + i * resta
      x <- c(x, posi[1])
      y <- c(y, posi[2])
    }
    coordenadas  <- round(cbind(x, y))
    coordenadas <- unique(coordenadas[,1:2])
  }
if(k==0) coordenadas = a
return(coordenadas)
}

Result is

 > completa(a,b,0.5)
         x  y
   [1,] 25  6
   [2,] 24  7
   [3,] 23  7
   [4,] 23  8
   [5,] 22  8
   [6,] 22  9
   [7,] 21  9
   [8,] 20 10
like image 172
Christian Avatar answered Nov 14 '22 11:11

Christian


Why not just use a linear approximation between the identified extreme points and round the values...

> x_12 <- c(25, 20)
> y_12 <- c(6, 10)
> do.call(cbind, lapply(approx(x_12, y_12, xout = seq(x_12[1], x_12[2], ifelse(x_12[1]>x_12[2], -1, 1))), round))
     x  y
[1,] 25 6
[2,] 24 7
[3,] 23 8
[4,] 22 8
[5,] 21 9
[6,] 20 10
like image 1
Fred Viole Avatar answered Nov 14 '22 11:11

Fred Viole