ImageMap {
   field        SFString   defaultURL ""
   field        SFString   defaultDescription ""
   field        MFString   parameters []
   field        SFBool     loadURL TRUE
   field        SFBool     setDescription TRUE
   eventIn      SFVec2f    texCoord
   eventIn      SFBool     isActive
   eventOut     MFString   descOver
   eventOut     SFInt32    choice_changed
   field        MFInt32    type []
   field        MFVec2f    point []
   field        MFString   url []
   field        MFString   description []
}

MappedShape {
   field        SFString   defaultURL ""
   field        SFString   defaultDescription ""
   field        MFString   parameters []
   field        SFBool     loadURL TRUE
   field        SFBool     setDescription TRUE
   eventOut     MFString   descOver
   eventOut     SFInt32    choice_changed
   field        MFInt32    type []
   field        MFVec2f    point []
   field        MFString   url []
   field        MFString   description []
   exposedField SFNode     material NULL
   exposedField SFNode     texture NULL
   exposedField SFNode     textureTransform NULL
   exposedField SFNode     geometry NULL
}

type and point fields
meaningvaluevertex format
point0x,y
circle/ellipse1centerX,centerY radiusX,radiusY
rectangle2minX,minY maxX,maxY
polygonvertices (>=3)x1,y1 x2,y2 x3,y3 [ x4,y4 ... ]
end of list-1N/A

These PROTOs offer the same functionality as the server-side imagemap CGI script included with most HTTP servers, including points (nearest wins), rectangles, circles, and polygons. The code is written in both Java and JavaScript, so they will work on all browsers. Note that MappedShape is just a convenience wrapper around ImageMap, which is why they are grouped together here.

An example use of the MappedShape PROTO uses a rectangular area, two circular areas, a polygonal area, and two points. The rectangle, circles, and polygon are shown in green lines. The equivalent imagemap in HTML can be seen below (minus the points, which are not supported by netscape's client-side imagemaps).



Notes

The texCoord eventIn should receive an MFVec2f, almost certainly from a TouchSensor. The PROTO is useless if it does not receive this event.
The isActive eventIn should receive an SFBool eventIn, probably from the same TouchSensor as the texCoord. This eventIn need not receive events, since its only function is to load a URL on a true value. The PROTO can be used to simply describe or choose based on the region it is over (see below).
The descOver eventOut is a single-element MFString chosen from the description (or the defaultDescription) field and is suitable for ROUT'ing to the set_string eventIn of a Text node. If setDescription is TRUE, that same description string will be sent to a Browser.setDescription() call (generally setting the status line of the HTML browser).
The choice_changed eventOut is an SFInt32 indicating which region (or point) was chosen. If gotourl is TRUE, an event is sent in response to every texCoord eventIn; if gotourl is FALSE, an event is sent in response to every TRUE isActive eventIn. It is suitable for ROUT'ing to the set_whichChoice eventIn of a Switch node. If no points are defined and we are not inside a region, the value will be -1.
If loadURL is TRUE, a TRUE isActive eventIn will trigger a Browser.loadURL() of the current URL (computed from the texCoord eventIn) with the parameters MFString field as its parameters argument. This allows an ImageMap to control another frame in the web browser.

Converting Other Imagemap Formats

I have an imagemap to VRML converter, written (by John Messina) in perl (requires perl5) here. This converts an imagemap config file suitable for the server-side imagemap CGI script to an ImageMap node, with the additional information of the dimensions of the image on the first line of the file (e.g. for a 320 by 240 pixel image, the first line of the file should be #320x240). The specific information on how to convert files is below for the technical types and any imagemap tool vendors who might want to include VRML support in their products.

First of all, some information on the server-side imagemap CGI script config file format. Each (relevant) line contains one of the following (the second coordinate pair for a circle is any point on the circle):

To explain how to convert I will start with an imagemap file for a 250x250 pixel image:

#250x250
point point.html 250,250
poly poly.html 22,16 80,19 26,42 7,26 
rect rect.html 14,58 54,96 
circle circle.html 200,84 227,119 

The first thing to notice is that while HTML browser imagemapping treats an image as a discrete grid of integer pixel locations from 0 to the width/height of the image in pixels with the origin at the top left, VRML treats an image as a continuous grid of floating point locations from 0.0 to 1.0 with the origin at the lower left. Converting a single point from image-space to texture-space requires the following two equations, with the exception of circles:

Circles are a special case in which we cannot represent them as they are represented in the original imagemap file format, i.e. center + point on circumference. The specifics of the problem involve the aspect ratio, causing circles to become ellipses unless the texture is exactly square. The equations for the circle are (note that radius is a temporary value and not needed in the resulting file):

The file now becomes:

default default.html
point point.html 1.0,0.0
poly poly.html .088,.936 .32,.924 .104,.832 .028,.896 
rect rect.html .056,.768 .216,.616 
circle circle.html .8,.664 0.177,0.177

Now that we have converted all of the points, we concatenate them and place them in the point field. The URLs (except the default) go in the url field. Optional descriptions for each URL go in the description field. The default's URL goes in the defaultURL field and a description for the default URL goes in the defaultDescription field. We now have a node like this, missing the type field:


ImageMap {
	defaultURL "default.html"
	defaultDescription "The default"
	type []
	point [	1.0,0.0
		.088,.936 .32,.924 .104,.832 .028,.896 
		.056,.768 .216,.616 
		.8,.664 0.177,0.177 ]
	url [ "point.html", "poly.html", "rect.html", "circle.html" ]
	description [ "A point", "A polygon", "A rectangle", "A circle" ]
}

Filling in the type field is simple; a point becomes 0, a circle becomes 1, a rectangle becomes 2, and a polygon becomes its number of vertices. We also need to remember to end the list with a -1. Our type field is therefore

type [ 0, 4, 2, 1, -1 ]

...and we have a complete node.