Beyond the Basics

Dynamically Generating Image Maps

An image map describes areas of an image which can be clicked on in the browser. Clicking on the designated area will then reference a designated URL, which can be another html page or a cgi-bin script.

Image maps are commonly used to create tool bars on HTMLpages, but they can also be used to allow users to "drill down" into the image for a more detailed view. Page designers can make elements of their images, such as bars in a bar chart or segments in a pie chart, reference additional data related to the selected image area. This technique is often referred to as information drill down.

Gsharp includes a function, bounding_polygon(), which returns the coordinates of any graphical component found in a Gsharp graph hierarchy. Bounding polygon coordinates can be used to create HTML image map elements which link the graphical component to a specific URL.

Image Maps

A mapped image is a standard HTML image, with an extra tag, USEMAP, specifying the name of an image map to use. The following HTML is a simple example of an image map:
<IMG SRC="toolbar.gif" USEMAP=#mymap>
<MAP NAME="mymap">
   <AREA SHAPE=rect COORDS="0,0,115,33" HREF="support.html">
   <AREA SHAPE=circle COORDS="116,30,20" HREF="sales.html">
   <AREA SHAPE=polygon COORDS="217,0 247,33 277,0"
    HREF="info.html">
</MAP>
Elsewhere in the HTML the image map is defined, usually just following the reference to the image. The MAP consists of any number of AREA elements. Each AREA can be either a rectangle, circle or a polygon and contains the definition of the active image area, and the URL which should be referenced if the area is clicked on. It is also possible to include a DEFAULT element defining the URL to referenced if no active area is selected.

Creating Image Maps with Gsharp

In addition to the built-in function bounding_polygon(), GsharpWE includes functions for creating the HTML elements for the image map. The following functions are included in $UNIDIR/lib/libhtml.gsl ($UNIDIR is an environment variable set dynamically by GsharpWE. $UNIDIR points to the path of the top level GsharpWE directory):
	HTMLimagemap(stream, image, mapname)
	HTMLmaprect(stream, url, left, bottom, right, top)
	HTMLmapcircle(stream, url, centre, radius)
	HTMLmappoly(stream, url, x, y)
The following code make use of these functions to simplify the image map example in the previous section:

include "$UNIDIR/lib/libhtml.gsl"

HTMLimagemap(stdout,"toolbar.gif","mymap);
HTMLmaprect(stdout,"support.html",0,0,115,33);
HTMLmapcircle(stdout,"sales.html",(116,30),20);
HTMLmappoly(stdout,"info.html",217//247//277,0//33//0);
echo("</MAP>");

Retrieving Bounding Polygons

The function bounding_polygon() has the following syntax:
  float bounding_polygon(string object, float numvertices,
	      float x, float y);

Note:

A convenience function, HTMLbounding_polygon(), is provided in $UNIDIR/lib/libhtml.gsl, which performs the repaint, calls the function bounding_polygon() and then converts the coordinates into pixel coordinates.

HTMLbounding_polygon() has the same syntax as bounding_polygon(), but has two additional float arguments imagewidth and imageheight. The following example combines HTMLbounding_polygon() with the image map functions in libhtml.gsl to create a bar chart image map.

include "$UNIDIR/lib/libhtml.gsl";
float xpixs; xpixs = 400;
float ypixs; ypixs = 300;
float nvert, x, y;

create Viewport page_1.view;
create Domain page_1.view.domain;
create Graph page_1.view.domain.graph
 ( XuNgraphType = "bar",
   XuNyData = "log(1:4)+1"
 );

f = fopen("bars.html","w");

HTMLheader(f,"Drillable Bar Chart","Anon");

HTMLimagemap(f,"bars.gif","bars");

npoly = HTMLbounding_polygon("page_1.view.domain.graph",
                    nvert, x, y, xpixs, ypixs);

offset = 1;    #index into coordinate array

for i = 1 to npoly
  lines = offset:(offset+nvert[i]-1);
     # lines=(1:5), (6:10), ... for i = 1, 2, ...
  offset = offset+nvert[i];
  X = slicex(x,lines);
  Y = slicex(y,lines);
  url = "http:/cgi-bin/drill.gsl?bar="+(npoly-i+1);
  HTMLmappoly(f, url, X, Y);
endfor

fwrite(f,"</MAP>");

make_image(400,300,"bars.gif");
The source code for this example can be found in the subdirectory <destination>/GsharpWE/example/GsharpWE/misc/bars.gsl and can be run with the command:
  /bin/GsharpWE bars.gsl

This will produce bars.html and bars.gif. Would you like to view the result?.

More complicated examples of drill down can be found in the GsharpWE example usage.

Creating Java Applets

The Java Driver

The GsharpWE has a Java driver which can convert a graph into a Java draw method. To create this method, select the Java driver, set the filename and then print your graph. The GSL for this looks like:


	hardcopy.XuNdevice = "ljava";
	hardcopy.XuNplotFileName = "gsharp.java";
	print;
The size of the plot is based on the size of the canvas at the time print is called. The page size is given in mm, The Java driver assumes 1 mm = 0.3 pixel. The page size can be set using the GSL statement:


	page_1.XuNsize = (400*.3,300*.3);
A convenience function make_image() is provided in $UNIDIR/lib/libhtml.gsl to simplify this process. The GSL statements shown above can be reduced to the single function call:

	make_image(400,300,"gsharp.java");
make_image() recognizes the filename extensions .gif, .jpg, .png, and .java and calls the appropriate Gsharp driver.

A Simple Java applet

Having generated a Java drawing class with GsharpWE as described above, the following applet, gsharpApp.java, can be used to view this draw method:

  import java.applet.*;
  import java.awt.*;

  public class gsharpApp extends Applet {
    private static Image i = null;
    public void paint(Graphics g) {
      if (i == null) {
          i = createImage(size().width,size().height);
          gsharp.draw(this, i.getGraphics());
      }
      g.drawImage(i,0,0,this);
    }
  }
The string "gsharp" in the above code (gsharp.draw) must match the name used as the output file name in the GSL statement make_image(400,300,"gsharp.java").

You should save this program as gsharpApp.java. The file name must match the name of the class, and names are case sensitive. Your directory should now contain two files: gsharp.java written by GsharpWE and gsharpApp.java written by you.

The Gsharp Java driver requires a number of utility classes which are found in the directory <destination>/GsharpWE/lib/mjava. Before your run your applet, you must create a link to this directory:

  ln -s <destination>/GsharpWE/lib/mjava mjava
You can now compile up your Java applet with a Java compiler:
  javac gsharpApp.java
This will create .class files for both of the .java files.

Your applet can now be included in an HTML file as follows:

  <HTML>
  <TITLE>My First Java Applet from Gsharp</title>
  <APPLET CODE="gsharpApp.class" width=400 height=300>
  </APPLET>
  </HTML>
This HTML file can now be viewed from a browser or with the utility program appletviewer that comes with your Java compiler.

Writing Java from GSL

You can either write your own Java code or you can let Gsharp do it for you. Included with GsharpWE is the GSL library libjava.gsl which includes a number of functions for writing Java.

The Java files described in the previous section could all be created from the following GSL script:

  include $UNIDIR/lib/libhtml.gsl
  include $UNIDIR/lib/libjava.gsl

  # You can replace the following line with your own graph template code.
  exec("$UNIDIR/example/Gsharp/flight.gsl");

  appname = "graph";

#Create Graph output
  make_image(400,300,appname+".java");

#Create viewer applet
  f = fopen(appname+"App.java","w");

  javaappletheaders(f);
  javaawtheaders(f);

  javastartappletclass(f,appname);
  fwrite(f,"private static Image i = null;");
  javapaintmethod(f,"if (i == null) {"//
          "  i = createImage(size().width,size().height);"//
          "  "+appname+".draw(this,g);"//
          "}"//
          "g.drawImage(i,0,0,this);");
  javaendclass(f);

  fclose(f);

#Create HTML file
  f = fopen(appname+".html","w");

  HTMLheader(f,"My First Java Applet from Gsharp","Anon");
  HTMLapplet(f,appname+"App.class",400,300);
  HTMLfooter(f);

  fclose(f);

#Create *.class
  system("javac "+appname+"App.java");

As well as using GSL to create the source code for a new applet, you may also use it to export Gsharp datasets for use as static variables by your applet. The functions javaexportfloat() and javaexportint() are included in libjava.gsl and will export float and integer variables of any dimension.

Client-side Interactivity

A complete Java applet example is provided in the example profiles. This example shows client-side interactivity using a mousedrag method. It also includes code to pass data from GSL to the applet for local manipulation.

Debugging Tips

General Recommendations

When running GSL scripts in cgi-bin, your browser may suppress any error messages, making it difficult for you to determine what went wrong. You may also see a message like "Document contains no data". To view these important messages you must run your scripts from the command line. For example:

  cd /WWW/cgi-bin
  ./<your script>.gsl

This will run your script in exactly the same way as it is run by the CGI on the web server.

Note: Make sure that you are running in a shell where you have not setup standard UNIRAS. If the environment variable UNIDIR is set, GsharpWE will look for its setup files in $UNIDIR rather than <destination>.

Handling Form Data

If you are writing a script than takes input from a form, then you should write it so that your variables take a default value if the form variable is not defined. This makes it possible to run the script from the command line. For example:
  text = "Hello Wide World";
  if exists(WORK.FORM_text) text = WORK.FORM_text;
  Title.XuNtitleText = text;

In this example the form data is used if present, but the script will run even if it is not specified or if debugging from the command line.

A convenience function, HTMLget_value(), performs the steps above. This function is included in $UNIDIR/lib/libhtml.gsl. It can be used return a form value, if given, or a default value:

  HTMLget_value("text","Hello Wide World");

If your script only fails when a variable only has a certain value, HTMLget_value can be used to initialize a variable to the problem value.

Debugging Scripts with the Gsharp Professional Edition

The Gsharp Professional Edition can be run interactively, and GSL can be generated using the Script Builder tool. This is a quick and effective way to generate graph templates. If you have Gsharp Professional Edition, you should test your GSL as much as possible interactively before running it with GsharpWE.

If your script references functions found only in GsharpWE, such as bounding_polygon() or the Java driver, then you can still test much of the script by making references to Gsharp Web Edition functions conditional. This can be done by testing the first value in the argv variable:

  if strstr(argv[1],"Gsharp") = "GsharpWE" then
    npoly=bounding_polygon(nvert,x,y);
  endif
This test will always identify GsharpWE. The built-in Gsharp function batch() can also be used, but only detects batch execution, not the product edition that is running:
  if batch() then
    npoly=bounding_polygon(nvert,x,y);
  endif