[R] Enumerating unit cell traversals Re: Interpolate? a line
David Winsemius
dwinsemius at comcast.net
Wed Sep 15 15:23:56 CEST 2010
On Sep 15, 2010, at 8:58 AM, Rainer M Krug wrote:
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
>
> On 15/09/10 14:46, Michael Bedward wrote:
>> Nice posts David. I like the way that 'simple' problems such as this
>> one give rise to an interesting assortment of approaches and gotchas
>> :)
>>
>> Michael
>>
>> On 15 September 2010 22:41, David Winsemius
>> <dwinsemius at comcast.net> wrote:
>>>
>>> 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?
>
> This is a known problem in computer graphics and the algorythm used to
> identify these cells is the "Bresenham's Line Drawing Algorithm"
>
> You can check out one version at
>
> http://www.falloutsoftware.com/tutorials/dd/dd4.htm
>
> or
>
> http://en.wikipedia.org/wiki/Bresenham's_line_algorithm
After viewing the Wikipedia description and the illustration I think
that may not be the same problem. Note that the cells traversed only
at their very outer corners do not get chosen. The goal is to
"approximate a line" rather than to enumerate traversals.
--
David.
>
> Cheers,
>
> Rainer
>
>>>>>>>
>>>>>>> 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
>>>
>>> ______________________________________________
>>> R-help at r-project.org mailing list
>>> https://stat.ethz.ch/mailman/listinfo/r-help
>>> PLEASE do read the posting guide http://www.R-project.org/posting-guide.html
>>> and provide commented, minimal, self-contained, reproducible code.
>>>
>>
>> ______________________________________________
>> R-help at r-project.org mailing list
>> https://stat.ethz.ch/mailman/listinfo/r-help
>> PLEASE do read the posting guide http://www.R-project.org/posting-guide.html
>> and provide commented, minimal, self-contained, reproducible code.
>
>
> - --
> Rainer M. Krug, PhD (Conservation Ecology, SUN), MSc (Conservation
> Biology, UCT), Dipl. Phys. (Germany)
>
> Centre of Excellence for Invasion Biology
> Natural Sciences Building
> Office Suite 2039
> Stellenbosch University
> Main Campus, Merriman Avenue
> Stellenbosch
> South Africa
>
> Tel: +33 - (0)9 53 10 27 44
> Cell: +27 - (0)8 39 47 90 42
> Fax (SA): +27 - (0)8 65 16 27 82
> Fax (D) : +49 - (0)3 21 21 25 22 44
> Fax (FR): +33 - (0)9 58 10 27 44
> email: Rainer at krugs.de
>
> Skype: RMkrug
> -----BEGIN PGP SIGNATURE-----
> Version: GnuPG v1.4.10 (GNU/Linux)
> Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/
>
> iEYEARECAAYFAkyQwwUACgkQoYgNqgF2egrDSACeJPgbW5tQtqh7RyUMIezeNNL9
> 1+QAn2Vgow6lgeCuzZ2N2ysgxVTxmNm4
> =NFGN
> -----END PGP SIGNATURE-----
David Winsemius, MD
West Hartford, CT
More information about the R-help
mailing list