Using Gregory Seidman's ImageMap and MappedObject PROTOs

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 VRMLscript, so they will work on all browsers.

Annotated ImageMap EXTERNPROTO


EXTERNPROTO ImageMap [
	field SFString defaultURL
	field SFString defaultDescription
	field MFString parameters
	field SFBool loadURL
	eventIn SFVec2f texCoord
	eventIn SFBool isActive
	eventOut MFString descOver
	eventOut SFInt32 choice_changed
#################################################################
# int	geometry type		point data format               #
#                                                               #
# -1	end of list		REQUIRED                        #
# 0	point			x,y                             #
# 1	circle			centerX,centerY radiusX,radiusY #
# 2	rectangle		minX,minY maxX,maxY             #
# 3+	polygon (n points)	x1,y1 x2,y2 x3,y3 [ x4,y4 ... ] #
#################################################################
	field MFInt32 type
	field MFVec2f point
	field MFString url
	field MFString description
	] "http://zing.ncsl.nist.gov/~gseidman/vrml/wprotos.wrl#ImageMap"

Annotated MappedObject EXTERNPROTO


EXTERNPROTO MappedObject [
	field SFString defaultURL
	field SFString defaultDescription
	field MFString parameters
	field SFBool loadURL
	eventOut MFString descOver
	eventOut SFInt32 choice_changed
#################################################################
# int	geometry type		point data format               #
#                                                               #
# -1	end of list		REQUIRED                        #
# 0	point			x,y                             #
# 1	circle			centerX,centerY radiusX,radiusY #
# 2	rectangle		minX,minY maxX,maxY             #
# 3+	polygon (n points)	x1,y1 x2,y2 x3,y3 [ x4,y4 ... ] #
#################################################################
	field MFInt32 type
	field MFVec2f point
	field MFString url
	field MFString description
	exposedField SFNode material
	exposedField SFNode texture
	exposedField SFNode textureTransform
	exposedField SFNode geometry
	] "http://zing.ncsl.nist.gov/~gseidman/vrml/wprotos.wrl#MappedObject"

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.
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 gotourl 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 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 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.