[R] Enumerating unit cell traversals Re: Interpolate? a line

David Winsemius dwinsemius at comcast.net
Wed Sep 15 14:41:36 CEST 2010


On Sep 15, 2010, at 7:55 AM, David Winsemius wrote:

>
> On Sep 15, 2010, at 7:24 AM, David Winsemius wrote:
>
>> Replacing context:
>>
>>>> Hello everyone.
>>>> I have created a 100*100 matrix in R.
>>>> Let's now say that I have a line that starts from (2,3) point and  
>>>> ends to the
>>>> (62,34) point. In other words this line starts at cell (2,3) and  
>>>> ends at cell
>>>> (62,34).
>>>>
>>>> Is it possible to get by some R function all the matrix's cells  
>>>> that this line
>>>> transverses?
>>>>
>>>> I would like to thank you for your feedback.
>>>>
>>>> Best Regards
>>>> Alex
>>
>> On Sep 15, 2010, at 6:52 AM, Michael Bedward wrote:
>>
>>> Hello Alex,
>>>
>>> Here is one way to do it. It works but it's not pretty :)
>>
>> If you want an alternative, consider that produces the Y cell  
>> indices (since the x cell indices are already 2:62):
>>
>> > linefn <- function(x) 3+((34-3)/(62-2)) *(x-2)
>> > findInterval(linefn(2:62), 3:34)
>> [1]  1  1  2  2  3  3  4  4  5  5  6  6  7  7  8  8  9  9 10 10 11  
>> 11 12 12 13 13 14
>> [28] 14 15 15 16 17 17 18 18 19 19 20 20 21 21 22 22 23 23 24 24 25  
>> 25 26 26 27 27 28
>> [55] 28 29 29 30 30 31 32
>> # that seems "off" by two
>> > linefn(62)
>> [1] 34
>> > linefn(2)
>> [1] 3 # but that checks out and I realized those were just indices  
>> for the 3:34 findInterval vector
>>
>> > (3:34)[findInterval(linefn(2:62), 3:34)]
>> [1]  3  3  4  4  5  5  6  6  7  7  8  8  9  9 10 10 11 11 12 12 13  
>> 13 14 14 15 15 16
>> [28] 16 17 17 18 19 19 20 20 21 21 22 22 23 23 24 24 25 25 26 26 27  
>> 27 28 28 29 29 30
>> [55] 30 31 31 32 32 33 34
>>
>> ( no rounding and I think the logic is clearer.)
>
> But I also realized it didn't enumerate all the the cells were  
> crossed either, only indicating which cell was associated with an  
> integer value of x. Also would have even more serious problems if  
> the slope were greater than unity. To enumerate the cell indices  
> that were crossed, try:
>
> unique( floor( cbind( seq(2,62, by=0.1), linefn(seq(2,62,  
> by=0.1)) ) )  )
>      [,1] [,2]
> [1,]    2    3
> [2,]    3    3
> [3,]    4    4
> [4,]    5    4
> [5,]    5    5
> [6,]    6    5
> [7,]    7    5
> [8,]    7    6
> snipping interior results
> [83,]   58   32
> [84,]   59   32
> [85,]   60   32
> [86,]   60   33
> [87,]   61   33
> [88,]   62   34
>
> That could probably be passed to rect() to illustrate (and check  
> logic):
>
> rect(cellidxs[,1], cellidxs[,2], cellidxs[,1]+1, cellidxs[,2]+1,  
> col="red")
>
> #redraw line :
> lines(2:62, 3+(34-3)/(62-2)*(0:60))

And then I got to wondering if every 0.1 was sufficient to catch all  
the corners and discovered I could identify 3 more cell traversals  
with by=0.01

 > cellid2 <-unique( floor(cbind(seq(2,62, by=0.01), linefn(seq(2,62,  
by=0.01) )) ) )
 > NROW(cellid2) # 91 cells
 > rect(cellid2[,1], cellid2[,2], cellid2[,1]+1, cellid2[,2]+1,  
col="blue")
 > rect(cellidxs[,1], cellidxs[,2], cellidxs[,1]+1, cellidxs[,2]+1,  
col="red")
 > lines(2:62, 3+(34-3)/(62-2)*(0:60))

(Trying by=0.001 did not change the count, but did take longer)

-- 
David.

>> -
>> David.
>>
>>>
>>> interp <- approx(c(2, 62), c(3, 34), method="linear", xout=2:62)
>>> m <- matrix(c(interp$x, round(interp$y)), ncol=2)
>>> tie <- m[,2] == c(-Inf, m[-nrow(m),2])
>>> m <- m[ !tie, ]
>>>
>>> You might want to examine the result like this...
>>>
>>> plot(m)  # plots points
>>> lines(c(2,26), c(3, 34))  # overlay line for comparison
>> you can add a grid with
>> abline(v=2:62, h=3:34)
>>>
>>> Michael
>


David Winsemius, MD
West Hartford, CT



More information about the R-help mailing list