Re: sorting points or rectangles

new topic     » goto parent     » topic index » view thread      » older message » newer message

Dan,

It will work for all cases of overlap.  Here is another version of the same
algorithm which graphically demonstrates that it works correctly.

Colin Taylor

-- begin code
-- detects overlap between 2 rectangles

function min(atom a, atom b)
    if b < a then return b
    else return a
    end if
end function

function max(atom a, atom b)
    if a < b then return b
    else return a
    end if
end function

function overlap(sequence r1,sequence r2)
-- returns overlap rectangle or 0
    if r1[2][1] <= r2[1][1] or r1[1][1] >= r2[2][1] or
     r1[2][2] <= r2[1][2] or r1[1][2] >= r2[2][2] then
 return 0  -- no overlap
    end if
    return {{max(r1[1][1], r2[1][1]), max(r1[1][2], r2[1][2])},
     {min(r1[2][1], r2[2][1]), min(r1[2][2], r2[2][2])}}
end function

-- test code

include graphics.e
include get.e

if graphics_mode(261) then
end if

function randrect()
    atom a, b, c, d
    a = rand(1000)/10+300
    b = a + rand(3000)/10
    c = rand(1000)/10+200
    d = c + rand(3000)/10
    return {{a, c}, {b, d}}
end function

procedure drawrect(integer c, integer f, sequence xy1, sequence xy2)
    polygon(c, f, {xy1, {xy2[1], xy1[2]}, xy2, {xy1[1], xy2[2]}})
end procedure

sequence r1, r2
object r3
while 1 do
    r1 = randrect()
    r2 = randrect()
    r3 = overlap(r1, r2)
    drawrect(RED, 0, r1[1], r1[2])
    drawrect(GREEN, 0, r2[1], r2[2])
    if sequence(r3) then
        drawrect(WHITE, 1, r3[1], r3[2])
    end if
    puts(1, "rectangle 1 (red) = ")
    ? r1
    puts(1, "rectangle 2 (green) = ")
    ? r2
    puts(1, "overlap = ")
    ? r3
    puts(1, "\nPress spacebar for next or any other key to exit.\n")
    if wait_key() = 32 then
        clear_screen()
    else
        exit
    end if
end while

-- end code

----- Original Message -----
>
> Colin,
>
> Looking at your revision of my code quickly, I can't be sure if it handles
> small rectangles to the upper right of the big rectangle.  I can see that
> the coords. of the lower left point of the small rectangle can in fact be
> expressed in terms of the two defining points/corners, but I can't be sure
> your code tests for the possible presence of lower left corner of small
(and
> upper right corner, too) in big.  I'll look at it more later, but maybe
you
> can verify sooner.  (That kind of question was why I output samples of the
> test rectangles coords., to compare against the big rectangles coords. &
> make sure all that were at least partly inside were found, not just those
> wholly inside.)
>
> Dan Moyer
>
> >
> > Rectangles oriented parallel to the x-y axes are normally defined by
only
> 2
> > points {upper-left xy, lower-right xy}.  To determine if a rectangle
falls
> > within another, it is quicker to eliminate those that aren't inside, as
> > shown below:
> >
> > Colin Taylor
> >
> > -- start code:
> >
> > -- TEST TO SEE IF ANY RECTANGLE IS AT LEAST PARTLY INSIDE A BIGGER ONE:
> > -- for rectangles each defined by 2 corner points in this order:
> > -- upper-left xy, lower-right xy:  {{ulx,uly}, {lrx,lry}}
> >
> > include misc.e
> >
> > constant ul = 1, lr = 2, x = 1, y = 2
> >
> > sequence BigRectangle, testRects, aHit
> > integer hit
> > atom TotHits, TotTime, stime, etime
> > BigRectangle = {{200,200},{699,699}}
> > testRects = repeat({{0,0},{0,0}}, 20000)
> > aHit = {}
> > hit = 0
> > TotHits = 0
> > TotTime = 0
> >
> > function randrange(object range)
> > -- borrowed following two from Derek, & then altered 2nd:
> >     if atom(range) then
> >          return rand(range)
> >     end if
> >     return rand(range[2]-range[1]+1) + range[1] - 1
> > end function
> >
> > procedure makeTestData()
> > -- generate some test data.
> >     for i = 1 to length(testRects) do
> >          testRects[i][ul] = {randrange({50,950}), randrange({50,950})}
> >          testRects[i][lr][x] = testRects[i][ul][x] + randrange(100)
> >          testRects[i][lr][y] = testRects[i][ul][y] + randrange(100)
> >     end for
> > end procedure
> >
> > function IsPartlyInside(sequence OuterRect, sequence PossPrtlyInside)
> > -- determines if a rectangle is at least partly inside the big one:
> >     if PossPrtlyInside[lr][x] <= OuterRect[ul][x] then  -- to left
> >          return 0
> >     elsif PossPrtlyInside[ul][x] >= OuterRect[lr][x] then  -- to right
> >          return 0
> >     elsif PossPrtlyInside[lr][y] <= OuterRect[ul][y] then  -- above
> >          return 0
> >     elsif PossPrtlyInside[ul][y] >= OuterRect[lr][y] then  -- below
> >          return 0
> >     else
> >          return 1
> >     end if
> > end function
> >
> > procedure doAtest()
> >     makeTestData() -- make new test rectangles each test
> >     hit = 0
> >     aHit = {}
> >
> >     stime = time()
> >     for n = 1 to length(testRects) do
> >         if IsPartlyInside(BigRectangle, testRects[n]) then
> >              hit += 1
> >              aHit &= {testRects[n]}  -- save coords of partly inside
> > rectangle
> >         end if
> >     end for
> >     etime = time() - stime
> >
> >     puts(1, "\nhits= " & sprint(hit) & " in " & sprint(etime) & "
> > seconds\n")
> >     puts(1, "length of hits sequence: " & sprint(length(aHit)) & "\n")
> >     puts(1, "big rectangle:        ")
> >     print(1, BigRectangle)
> >     puts(1, "\na smaller rectangle: ")
> >     print(1, aHit[1]) -- just show one of them
> >     puts(1, "\n")
> >
> >     TotTime += etime
> >     TotHits += hit
> > end procedure
> >
> > for m = 1 to 10 do
> >     doAtest()
> > end for
> >
> > puts(1, "\naverage of " & sprint(floor(TotHits/10)) & " hits in average
of
> "
> >     & sprint(TotTime/10) & " seconds,\nout of 10 trials of 20,000
> rectangles
> > each trial.")
> >
> > -- end code
> >
> > ----- Original Message -----
> > Subject: Re: sorting points or rectangles
> >
> >
> > > Tone,
> > >
> > > Ok, on the assumption that you *do* want to find any rectangle that is
> > even
> > > partly within another (all oriented parallel to x-y axes), the
following
> > > should do it ...
> >
> >

new topic     » goto parent     » topic index » view thread      » older message » newer message

Search



Quick Links

User menu

Not signed in.

Misc Menu