comp.lang.idl-pvwave archive
Messages from Usenet group comp.lang.idl-pvwave, compiled by Paulo Penteado

Home » Public Forums » archive » Re: fast search
Show: Today's Messages :: Show Polls :: Message Navigator
E-mail to friend 
Switch to threaded view of this topic Create a new topic Submit Reply
Re: fast search [message #50778] Wed, 18 October 2006 08:25 Go to next message
greg michael is currently offline  greg michael
Messages: 163
Registered: January 2006
Senior Member
All but one indestructible loop removed. Wish I had a use for this
program now... hope it's useful to you, Marie!

pro splitsearch3,p,dist
;recursively splits the search volume into n_split^3 subvolumes. When
;there are fewer than 'threshold' points
;in a subvolume, checks for matches the brute force way - every point
;against every other.

n_split=4 ;1-D cutting factor (for 3, cube is cut into 3x3x3=27
subvolumes)
threshold=75 ;no. of points to start pairwise comparison
n=n_elements(p)

if n gt threshold then begin
mxx=max(p.x,min=mnx)
mxy=max(p.y,min=mny)
mxz=max(p.z,min=mnz)
bx=fix((p.x-mnx)/(mxx-mnx)*n_split)<(n_split-1) ;< to ensure max
element not in new bin
by=fix((p.y-mny)/(mxy-mny)*n_split)<(n_split-1)
bz=fix((p.z-mnz)/(mxz-mnz)*n_split)<(n_split-1)
b=bx+by*n_split+bz*n_split^2
h=histogram(b,min=0,reverse_indices=ri)

for i=0,n_elements(h)-1 do begin
if ri[i] ne ri[i+1] then begin
q=[ri[ri[i]:ri[i+1]-1]]
if n_elements(q) ge 2 then splitsearch3,p[q],dist ;splitsearch
again, if enough to compare
endif
endfor

endif else begin
q1=rebin(indgen(n),n,n) ;set up indices for pairwise matching
q2=transpose(q1)
d=sqrt((p[q1].x-p[q2].x)^2+(p[q1].y-p[q2].y)^2+(p[q1].z-p[q2 ].z)^2)
;calculate pair distances
i=where((d le dist) and (q1 gt q2)) ;select close neigbours (q1>q2 to
avoid reverse pairs)
if i[0] ne -1 then print,p[q1[i]],p[q2[i]] ;print the neighbours, if
found
endelse
end

IDL> p=ss_makegalaxies(5e6)
IDL> splitsearch3,p,.02
{ 915.876 843.515 319.991}{ 915.861 843.528
319.994}
Re: fast search [message #50798 is a reply to message #50778] Tue, 17 October 2006 11:25 Go to previous messageGo to next message
greg michael is currently offline  greg michael
Messages: 163
Registered: January 2006
Senior Member
And here's a proper IDL version that uses histograms and the pairwise
comparisons that David likes... still got three loops, though - have to
think some more to get rid of those.

function ss_MakeGalaxies,n
p=replicate({x:0.,y:0.,z:0.},n)
seed=0
p.x=randomu(seed,n)*1000.
p.y=randomu(seed,n)*1000.
p.z=randomu(seed,n)*1000.
return,p
end

pro splitsearch2,p,dist
;recursively splits the search volume into n_split^3 subvolumes. When
;there are fewer than 'threshold' points
;in a subvolume, checks for matches the brute force way - every point
;against every other.

n_split=3 ;1-D cutting factor (for 3, cube is cut into 3x3x3=27
subvolumes)
threshold=75 ;no. of points to start pairwise comparison
n=n_elements(p)

if n gt threshold then begin
hx=histogram(p.x,nbins=n_split+1,locations=x,reverse_indices =rx) ;1-D
binning
hy=histogram(p.y,nbins=n_split+1,locations=y,reverse_indices =ry)
hz=histogram(p.z,nbins=n_split+1,locations=z,reverse_indices =rz)

for i=0,n_split-1 do begin
for j=0,n_split-1 do begin
for k=0,n_split-1 do begin
qx=[rx[rx[i]:rx[i+1]-1]] ;indices from 1-D x bins
qy=[ry[ry[j]:ry[j+1]-1]]
qz=[rz[rz[k]:rz[k+1]-1]]
q=where(histogram([qx,qy,qz],min=0) eq 3) ;indices from 3-D bins
(i.e. where all of x,y,z
;lie inside subvolume

if n_elements(q) ge 2 then splitsearch2,p[q],dist ;splitsearch
again, if enough to compare
endfor
endfor
endfor

endif else begin
q1=rebin(indgen(n),n,n) ;set up indices for pairwise comparison
q2=transpose(q1)
d=sqrt((p[q1].x-p[q2].x)^2+(p[q1].y-p[q2].y)^2+(p[q1].z-p[q2 ].z)^2)
;calculate pair distances
i=where((d le dist) and (q1 gt q2)) ;select close neighbours (q1>q2
to avoid reverse pairs and q1=q2)
if i[0] ne -1 then print,p[q1[i]],p[q2[i]] ;print the neighbours, if
found
endelse
end

IDL> p=ss_MakeGalaxies(1e6)
IDL> splitsearch2,p,.1
{ 98.4014 461.355 673.278}{ 98.4379 461.400
673.197}
{ 190.002 444.629 924.567}{ 189.966 444.613
924.605}
{ 254.499 823.541 494.128}{ 254.492 823.492
494.062}
{ 638.107 100.159 240.530}{ 638.083 100.108
240.606}
{ 720.787 820.032 405.215}{ 720.754 820.070
405.199}

Greg
Re: fast search [message #50803 is a reply to message #50798] Tue, 17 October 2006 10:17 Go to previous messageGo to next message
greg michael is currently offline  greg michael
Messages: 163
Registered: January 2006
Senior Member
Actually, there's a mistake in that code - it's got mixed
procedure/function syntax. Should be like this:

function ss_MakeGalaxies,n
p=replicate({x:0.,y:0.,z:0.},n)
seed=0
p.x=randomu(seed,n)*1000.
p.y=randomu(seed,n)*1000.
p.z=randomu(seed,n)*1000.
return,p
end

function ss_distance,p1,p2
return,sqrt((p2.x-p1.x)^2+(p2.y-p1.y)^2+(p2.z-p1.z)^2)
end

pro splitsearch,p,dist
;recursively splits the search volume into n_split^3 subvolumes. When
;there are fewer than 'threshold' points
;in a subvolume, checks for matches the brute force way - every point
;against every other.

n_split=3
threshold=75

s=(size(p))[1]

if s gt threshold then begin
xmn=min(p.x,max=xmx)
ymn=min(p.y,max=ymx)
zmn=min(p.z,max=zmx)

xg=xmn+findgen(n_split+1)*(xmx-xmn)/n_split ;grid boundaries
yg=ymn+findgen(n_split+1)*(ymx-ymn)/n_split
zg=zmn+findgen(n_split+1)*(zmx-zmn)/n_split

for j=0,n_split-1 do begin
for k=0,n_split-1 do begin
for l=0,n_split-1 do begin
w= where( (p.x ge xg[j]-dist) and (p.x lt xg[j+1]+dist) and $
(p.y ge yg[k]-dist) and (p.y lt yg[k+1]+dist) and $
(p.z ge zg[l]-dist) and (p.z lt zg[l+1]+dist))
if n_elements(w) ge 2 then begin
splitsearch,p[w],dist
endif
endfor
endfor
endfor

endif else begin
for i=0,s-2 do begin
for j=i+1,s-1 do begin
if ss_distance(p[i],p[j]) le dist then begin
print,p[i],p[j]
endif
endfor
endfor
endelse
end

Then call it using:

IDL> p=ss_MakeGalaxies(1e5)
IDL> splitsearch,p,.5
{ 454.665 175.794 87.0097}{ 454.816 175.504
87.3471}
{ 556.761 981.076 933.809}{ 556.654 980.922
934.065}
{ 981.340 196.286 105.551}{ 981.387 196.102
105.703}

The left and right columns are the neigbouring (< .5 units distant) xyz
triples.

regards,
Greg
Re: fast search [message #50811 is a reply to message #50803] Tue, 17 October 2006 07:15 Go to previous messageGo to next message
greg michael is currently offline  greg michael
Messages: 163
Registered: January 2006
Senior Member
Hi Marie,

Also take a look at this thread...

http://groups.google.de/group/comp.lang.idl-pvwave/browse_th read/thread/1d020842b165598a/8e57c4b2c3841851?#8e57c4b2c3841 851

A program to search for pairs closer than a given distance d in a point
cloud. It recursively cuts up the volume until there are fewer than a
given threshold of points in the subvolume, and then directly compares
those few. At each cutting of the space, it's necessary to leave an
overlap of d so that points in adjoining subvolumes aren't missed. I
don't remember - looks like it might be necessary to check for the
uniqueness of the solutions at the end. Anyway, the recursion is the
fun part...

By the way, it looks like there are a lot of for-loops there, but
they're powerful ones - each run of the loop cuts the space.

regards,
Greg

m.goullant@gmail.com wrote:
> Hi there,
>
> I have the following problem:
>
> ;data structure of an irregular point cloud
> x = points.x
> y = points.y
> z = points.z
>
> search radio
> radio = 8
>
> FOR i=0L,N_ELEMENTS(z)-1 DO BEGIN
>
> square = WHERE(x LE x[i] + radio AND x GE x[i] - radio AND y LE
> y[i] + radio AND y GE y[i] - radio)
> ;(...)
>
> ENDFOR
>
> I realize that WHERE will do the job, but at very low efficiency.
> WHERE
> makes no assumptions about the list being ordered. It seems to me it
> has
> to check every element of the array, requiring N steps for an N-element
> array
>
> There is a faster way to do this?
>
> thanks,
> Marie
Re: fast search [message #50818 is a reply to message #50811] Tue, 17 October 2006 05:53 Go to previous messageGo to next message
Paolo Grigis is currently offline  Paolo Grigis
Messages: 171
Registered: December 2003
Senior Member
This link may be useful to you:

http://www.dfanning.com/code_tips/pts_in_sphere.html

Ciao,
Paolo


m.goullant@gmail.com wrote:
> Hi there,
>
> I have the following problem:
>
> ;data structure of an irregular point cloud
> x = points.x
> y = points.y
> z = points.z
>
> search radio
> radio = 8
>
> FOR i=0L,N_ELEMENTS(z)-1 DO BEGIN
>
> square = WHERE(x LE x[i] + radio AND x GE x[i] - radio AND y LE
> y[i] + radio AND y GE y[i] - radio)
> ;(...)
>
> ENDFOR
>
> I realize that WHERE will do the job, but at very low efficiency.
> WHERE
> makes no assumptions about the list being ordered. It seems to me it
> has
> to check every element of the array, requiring N steps for an N-element
> array
>
> There is a faster way to do this?
>
> thanks,
> Marie
>
Re: fast search [message #50889 is a reply to message #50818] Thu, 19 October 2006 04:01 Go to previous message
m.goullant@gmail.com is currently offline  m.goullant@gmail.com
Messages: 10
Registered: July 2006
Junior Member
Hi Paolo,

thanks for the article, i'll read cautiously!

regards,
Marie

Paolo Grigis wrote:
> This link may be useful to you:
>
> http://www.dfanning.com/code_tips/pts_in_sphere.html
>
> Ciao,
> Paolo
>
>
> m.goullant@gmail.com wrote:
>> Hi there,
>>
>> I have the following problem:
>>
>> ;data structure of an irregular point cloud
>> x = points.x
>> y = points.y
>> z = points.z
>>
>> search radio
>> radio = 8
>>
>> FOR i=0L,N_ELEMENTS(z)-1 DO BEGIN
>>
>> square = WHERE(x LE x[i] + radio AND x GE x[i] - radio AND y LE
>> y[i] + radio AND y GE y[i] - radio)
>> ;(...)
>>
>> ENDFOR
>>
>> I realize that WHERE will do the job, but at very low efficiency.
>> WHERE
>> makes no assumptions about the list being ordered. It seems to me it
>> has
>> to check every element of the array, requiring N steps for an N-element
>> array
>>
>> There is a faster way to do this?
>>
>> thanks,
>> Marie
>>
Re: fast search [message #50891 is a reply to message #50778] Thu, 19 October 2006 03:46 Go to previous message
m.goullant@gmail.com is currently offline  m.goullant@gmail.com
Messages: 10
Registered: July 2006
Junior Member
Hi Greg,
thank you very much, for your time!

I even dont understood the second algorithm and you already have the
3!! :-(. In this weekend i'll take a better look in your explendid
work!

I'm a newbie in IDL, so I have to understand some functions that you
use! I
If is not ask to much, can you coment all the lines of your code?

What I want is a point to points search, so I am trying to understand
in your "quadtree" technique where I can adapt to my needs. I only need
to compare (x,y) - 2D and get the Z values to compare

This is more and less What I want to do:

have this geographic data (could be 100000, 2 million, 4 million
depends):


PRO example


points = myData()

;data structure of an irregular point cloud
x = points.x ;X coord
y = points.y ;Y coord
z = points.z ; Elevation


n = 5 ; number of iterations
mask = 4.0 ; diameter. in meters. Like your dist
maskType = 0 ; 0 a circle, 1 square

FOR i=0L,n-1 DO BEGIN
newZ = erosion(x,y,z,dist,MaskType)
;(...)
dist = dist + 2
ENDFOR

END

FUNCTION erosion,x,y,z,mask,maskType ; Apply erosion to the data

newZ=z
radio = mask /2
FOR i=0L,N_ELEMENTS(z)-1 DO BEGIN
kernel = applyKernel(x,y,z,i,radio,maskType)
;center the kernel in the data(i) and get neighbours there are inside
of the mask
newZ[i]=MAX(z[kernel])
ENDFOR
RETURN,newZ

END

FUNCTION applyKernel,x,y,z,i,dist,maskType

square = WHERE(x LE x[i] + dist AND x GE x[i] - dist AND y LE y[i]
+ dist AND y GE y[i] - dist)

IF (maskType EQ 0) THEN BEGIN
sqDistance = sqrt((x[square] - x[i])^2 + (y[square] -
y[i])^2)
neighbors = WHERE(sqDistance LE dist)
circle = square[neighbors]
RETURN,circle
ENDIF

RETURN,square
END

Because this is an iterative process with a "dist" variable, it's
posible implement your code?


Thank's in advance,
Marie
  Switch to threaded view of this topic Create a new topic Submit Reply
Previous Topic: Re: vector of bin indices using histogram?
Next Topic: Re: Weirdest Error Ever

-=] Back to Top [=-
[ Syndicate this forum (XML) ] [ RSS ] [ PDF ]

Current Time: Wed Oct 08 15:13:38 PDT 2025

Total time taken to generate the page: 0.00614 seconds