Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Mike Lewis on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

How to determine whether a clicked point is inside an irregular polygon outlining an Image-Map?

Graphics

How to determine whether a clicked point is inside an irregular polygon outlining an Image-Map?

by  wgcs  Posted    (Edited  )
It's easy to tell if someone clicked on a convex shape (rectangle, circle) particularly because it's "Click" event get's fired!

However, if you use an ImageMap-like outline that surrounds a concave / irregular polygon outlining a feature on a graphic image, it gets a whole lot more complicated to determine whether that click was inside or outside the polygon.

Here's code that works (with a test sample) (this was converted by me into VFP from the noted code that was written in C++):

Code:
********************************************************************************
* The following routines are used to determine whether a point that is clicked
*   is inside an imagemap polygon.  The original source was borrowed:
*!*	// Copyright 2001, softSurfer (www.softsurfer.com)
*!*	// This code may be freely used and modified for any purpose
*!*	// providing that this copyright notice is included with it.
*!*	// SoftSurfer makes no warranty for this code, and cannot be held
*!*	// liable for any real or imagined damage resulting from its use.
*!*	// Users of this code must verify correctness for their application.
*
*//    a Point is defined by its coordinates {int x, y;}
*//===================================================================


*!*	// cn_PnPoly(): crossing number test for a point in a polygon
*!*	//      Input:   P = a point,
*!*	//               V[] = vertex points of a polygon V[n+1] with V[n]=V[0]
*!*	//      Return:  0 = outside, 1 = inside
*!*	// This code is patterned after [Franklin, 2000]
FUNCTION InPoly( P_X, P_Y, V )
EXTERNAL ARRAY V
LOCAL cn, lnI, lnALen, vt 
lnALen = ALEN( V, 1 ) && Number of Vertices
cn = 0  &&    // the crossing number counter
* // loop through all edges of the polygon
for lnI = 1 TO lnALen-1 && (int i=0; i<n; i++) {    // edge from V[i] to V[i+1]
  **  if (((V[i,2] <= P_y) && (V[i+1].y > P.y))    // an upward crossing
  **        || ((V[i].y > P.y) && (V[i+1].y <= P.y))) { // a downward crossing
  if (((V[lnI,2] <= P_y) AND (V[lnI+1,2] > P_y))    ;
        OR ((V[lnI,2] > P_y) AND (V[lnI+1,2] <= P_y)))
    ** // compute the actual edge-ray intersect x-coordinate
    **float vt = (float)(P.y - V[i].y) / (V[i+1].y - V[i].y)
    vt = (P_y - V[lnI,2]) / (V[lnI+1,2] - V[lnI,2])
    **if (P.x < V[i].x + vt * (V[i+1].x - V[i].x))   // P.x < intersect
    if (P_x < V[lnI,1] + vt * (V[lnI+1,1] - V[lnI,1]))  && // P.x < intersect
      cn = cn + 1 &&   ++cn;   // a valid crossing of y=P.y right of P.x
    ENDIF
  ENDIF
ENDFOR
RETURN cn=1 && // 0 if even (out), and 1 if odd (in)


PROCEDURE TestPoly
* This routine tests the above routines that calculate whether
*  a point is within a polygon.
* Vertices:
* (these vertices define a convex, irregular polygon 
*   that looks somewhat like:
*      /*     /  *     \/\/
*   and the test case runs horizontally 
*   through it's "legs" )

DIMENSION aPoly[6,2]
aPoly[1,1]=66
aPoly[1,2]=121
aPoly[2,1]=129
aPoly[2,2]=52
aPoly[3,1]=237
aPoly[3,2]=105
aPoly[4,1]=205
aPoly[4,2]=227
aPoly[5,1]=148
aPoly[5,2]=136
aPoly[6,1]=98
aPoly[6,2]=223

SET PROCEDURE TO AhRooming
?InPoly( 20, 140, @aPoly)  && Out
?InPoly(104, 130, @aPoly)  && in
?InPoly(147, 174, @aPoly)  && Out
?InPoly(194, 130, @aPoly)  && In
?InPoly(267, 140, @aPoly)  && Out

RETURN
Register to rate this FAQ  : BAD 1 2 3 4 5 6 7 8 9 10 GOOD
Please Note: 1 is Bad, 10 is Good :-)

Part and Inventory Search

Back
Top