[R] Polygon-like interactive selection of plotted points

Marc Schwartz (via MN) mschwartz at mn.rr.com
Wed Apr 26 23:30:48 CEST 2006


Clint,

Not sure why I would be surprised (unless you meant Florian), as I have
not actually used these functions. I simply referenced them as part of
the search to assist Florian.  :-)

However, your reply did make me curious, so I installed the 'splancs'
package along with 'sp' as a dependency. Just for reference, this is on
R 2.3.0 under FC4 compiled from source.

I did run Roger's code, the result of which is attached here as a PDF,
which should come through the list.

While my 7 sided polygon is likely different than yours, the result
seems to be the same. That is, only 3 of the vertices are considered
within the boundary and this is unaffected by the use of the 'bound'
argument to input(). 

The 'bound' argument in inout() does need to be set to TRUE in order for
the boundary points to be considered 'within' the polygon. Otherwise,
with the default NULL, the assignment is arbitrary. Thus, Roger's code,
which has the default NULL value in the call to inout(), could
reasonably result in your/our finding.

One quick guess here might be that the values returned by getpoly() are
not the exact center points of the original dataset, but are the x,y
coords of where the clicks occur. There is a
"hand-to-eyeball-coordination" margin of error relative to the actual
coords.

Thus, the coordinate values returned by this approach are very slightly
outside the polygon and not picked up by inout() as being on the
boundary.

I tried the followingm using identify() instead:

  library(splancs)
  set.seed(20060426)
  xy <- cbind(x=runif(100), y=runif(100))
  plot(xy)

  # Select the SAME 7 vertices here
  pts <- identify(xy, n = 7)
  
  # These are the row indices into 'xy'
  # for the coords of the vertices
  > pts
  [1] 18 44 51 61 73 89 91
  
  > io <- inout(xy, xy[pts, ], bound = TRUE, quiet = FALSE)
  Points on boundary:
  [1] 18 44 51 61 73 89 91

Note that the same indices of the points are now returned by inout() as
were selected when using identify(). Note also the setting of 'bound =
TRUE'.

You can now use:

  points(xy[io,], pch=16, col="blue")

to draw BOTH the points inside the polygon and the boundary points as
well.

Thus, this would support my thoughts above, since identify() uses a
'tolerance' argument to identify the actual data points closest the
mouse click, much like all.equal() does with respect to floating point
comparisons.

In a case like this, identify() would seem to be a better choice
relative to selecting the polygon boundary if one wants the exact
boundary points to be considered in or out of the polygon.

HTH,

Marc Schwartz

On Wed, 2006-04-26 at 13:01 -0700, Clint Bowman wrote:
> Roger,
> 
> Just for fun I tried your script--nothing wrong with the script, but I
> created a seven sided polygon by clicking on seven points and letting
> getpoly complete the figure.  At the end I notice that only three of the
> seven vertices are coded as being inside the ploygon (the blue points.)
> 
> I'd send you a screen dump but I haven't gotten xwd to work with Exceed.
> Also I haven't checked any docs to see whether this is a known problem but
> suspect that Marc could be surprised by the behavior.
> 
> Clint

> On Wed, 26 Apr 2006, Roger Bivand wrote:
> 
> > On Wed, 26 Apr 2006, Marc Schwartz (via MN) wrote:
> >
> > > On Wed, 2006-04-26 at 18:13 +0100, Florian Nigsch wrote:
> > > > [Please CC me for all replies, since I am not currently subscribed to
> > > > the list.]
> > > >
> > > > Hi all,
> > > >
> > > > I have the following problem/question: Imagine you have a two-
> > > > dimensional plot, and you want to select a number of points, around
> > > > which you could draw a polygon. The points of the polygon are defined
> > > > by clicking in the graphics window (locator()/identify()), all points
> > > > inside the polygon are returned as an object.
> > > >
> > > > Is something like this already implemented?
> > > >
> > > > Thanks a lot in advance,
> > > >
> > > > Florian
> > >
> > > I don't know if anyone has created a single function do to this (though
> > > it is always possible).
> > >
> > > However, using:
> > >
> > >   RSiteSearch("points inside polygon")
> > >
> > > brings up several function hits that, if put together with the above
> > > interactive functions, could be used to do what you wish. That is, input
> > > the matrix of x,y coords of the interactively selected polygon and the
> > > x,y coords of the underlying points set to return the points inside or
> > > outside the polygon boundaries.
> >
> > This sequence from the splancs package should do it:
> >
> > library(splancs)
> > set.seed(20060426)
> > xy <- cbind(x=runif(100), y=runif(100))
> > plot(xy)
> > poly <- getpoly() # this gets the polygon on-screen
> > plot(xy)
> > polygon(poly)
> > io <- inout(xy, poly)
> > # this returns a logical vector for points in the polygon
> > points(xy[io,], pch=16, col="blue")
> >
> > Roger
> >
> > >
> > > Just as an FYI, you might also want to look at ?chull, which is in the
> > > base R distribution and returns the set of points on the convex hull of
> > > the underlying point set. This is to some extent, the inverse of what
> > > you wish to do.
> > >
> > > HTH,
> > >
> > > Marc Schwartz
> > >
> >
-------------- next part --------------
A non-text attachment was scrubbed...
Name: poly.pdf
Type: application/pdf
Size: 9524 bytes
Desc: not available
Url : https://stat.ethz.ch/pipermail/r-help/attachments/20060426/223f57fc/attachment-0003.pdf 


More information about the R-help mailing list