Polygons - array clockwise

Hi,
In Oracle spatial 10g, we are having few millions of circular arc polygons (simply polygon, no interior polygon) "sdo_geometry (2003, null, null, sdo_elem_info_array (1, 1003, *2*)," and are finding the whether the user gps locations falling in any of these polygons (POI in polygon) . We are storing the vertices array in counter clockwise direction.
Now, we are going to buy POIs (sdo_geometry (2003, null, null, sdo_elem_info_array (1, 1003, *1*)) just straight line connected polygons, no interior poygons.
The problem here is, the third party poi may have vertices in clockwise or counter clockwise directions.
Whether loading the third party's poi will impact my current table having circular poly in counter clockwise directions and calculating the Point in polygon?
Is there any best practice to be followed here.

Hi unnamed user 810260,
Oracle Spatial defines a valid outer ring as counter-clockwise, no ifs ands or buts about it. Getting your rings into this orientation is your responsibility either by not accepting backwards polygons or by running SDO_UTIL.RECTIFY_GEOMETRY (or SDO_MIGRATE.TO_CURRENT) on each polygon you bring into Oracle Spatial.
A reference might be similar issues surrounding importing WKT into Oracle Spatial
SDO_UTIL.FROM_WKTGEOMETRY seems ignorant of ring rotation
The OGC spec for WKT does not specify a ring rotation so your average WKT polygon could have rings going either way. As Dr. Ravada responds in that thread, it our problem to fix it. The generic WKT utility for Oracle Spatial just loads whatever its given however the rings are rotated and does not attempt to fix anything.
So a best practice might be to rectify everything. I am not really a big fan of rectify myself (search the list for folks talking about NULL output). Rather I just test the ring rotation and reverse it if I find the problem.
Cheers,
Paul

Similar Messages

  • Bus error - Help!

    Hi,
    I've been asked to see if I can fix a C program so that it will run on a mac. It currently compiles and runs perfectly on a linux machine, but as soon as you run it on a mac, it will compile, but quit with a bus error very early on. The full code is here:
    // Program for the construction of cartograms (density-equalizing map
    // projections) using the Gastner-Newman technique. The program needs polygon
    // coordinates and a count of cases in each region as input, calculates the new
    // coordinates, and writes these to a file. Postscript images of the original
    // map and the cartogram are created.
    // WRITTEN BY MICHAEL GASTNER, September 20, 2004.
    // If you use output created by this program please acknowledge the use of this
    // code and its first publication in:
    // "Generating population density-equalizing maps", Michael T. Gastner and
    // M. E. J. Newman, Proceedings of the National Academy of Sciences of the
    // United States of America, vol. 101, pp. 7499-7504, 2004.
    // The input coordinates in MAPGENFILE must be in ArcInfo "generate" format of
    // the type:
    // 1
    // 0.3248690E+06 0.8558454E+06
    // 0.3248376E+06 0.8557575E+06
    // 0.3248171E+06 0.8556783E+06
    // 0.3247582E+06 0.8556348E+06
    // 0.3246944E+06 0.8555792E+06
    // 0.3246167E+06 0.8555253E+06
    // 0.3250221E+06 0.8557324E+06
    // 0.3249436E+06 0.8557322E+06
    // 0.3248690E+06 0.8558454E+06
    // END
    // 1
    // 0.3248690E+06 0.8558454E+06
    // 0.3249651E+06 0.8558901E+06
    // 0.3250519E+06 0.8559769E+06
    // 0.3250691E+06 0.8561246E+06
    // 0.3249678E+06 0.8560541E+06
    // 0.3249003E+06 0.8560088E+06
    // 0.3076424E+06 0.8477603E+06
    // 0.3075691E+06 0.8477461E+06
    // 0.3075595E+06 0.8476719E+06
    // END
    // 2
    // 0.6233591E+06 0.6056502E+06
    // 0.6235193E+06 0.6056467E+06
    // 0.6235054E+06 0.6055372E+06
    // 0.7384296E+06 0.2334260E+06
    // 0.7383532E+06 0.2345770E+06
    // END
    // END
    // The number of cases in CENSUSFILE must be given in the form
    // region #cases (optional comment), e. g:
    // 43 0.9 Alabama
    // 51 0.3 Alaska
    // 37 0.8 Arizona
    // 47 0.6 Arkansas
    // 25 5.4 California
    // 32 0.8 Colorado
    // 19 0.8 Connecticut
    // 29 0.3 Delaware
    // 28 0.3 District of Columbia
    // 49 2.5 Florida
    // 45 1.3 Georgia
    // 1 0.4 Hawaii
    // The output coordinates are written to CARTGENFILE in ArcInfo "generate"
    // format. A postscript image of the original input is prepared as MAP2PS,
    // an image of the cartogram as CART2PS.
    // Modified on Oct 29, 2004. The number of divisions in each dimension lx, ly
    // will now be determined from the input map. Also fixed array bound
    // violations in intpol and newt2, and centered the ps-files.
    // Modified on Dec 3, 2004. Introduced pointers bbmaxx,bbmaxy,bbminx,bbminy -
    // the bounding box coordinates for each polygon - to reduce calculations in
    // crnmbr. Thanks to Chris Brunsdon for the suggestion.
    // Program now terminates with error message if there is no density specified
    // in CENSUSFILE for a region on the map.
    // "Donut" polygons are now handled properly. Polygons oriented clockwise will
    // be considered exterior boundaries. If they are oriented anti-clockwise they
    // are holes inside an enclosing polygon. (Unconventional for mathematicians,
    // but this is ArcGIS standard.) The identifier is either that of the enclosing
    // polygon, or -99999 in which case it is a hole in the preceding polygon.
    // The population can now be a floating-point number.
    // If a region contains exactly zero population, it will be replaced by
    // MINPOPFAC times the smallest positive population in any region.
    // Obviously, MINPOPFAC should be <1, I will set it to 0.1 by default. This
    // should reduce the value of sigma necessary for the integrator to finish
    // properly.
    // Modified on March 31, 2005. Initialized maxchange in nonlinvoltra() as
    // INFTY. Replaced crnmbr() by a similar, but faster routine interior().
    // Many thanks to Stuart Anderson for pointing out this shortcut.
    // TO DO LIST:
    // - Do Gaussian blur within nonlinvoltra as a simple call to calcv and
    // eliminate gaussianblur().
    // - Modify the NR code for the FFTs to deal more naturally with the fencepost
    // issue. No more copying of arrays in sinft and cosft.
    // - Write truly two-dimensional versions of coscosft, cossinft, and sincosft.
    // See Chan and Ho: A new two-dimensional fast cosine transform algorithm,
    // IEEE Transactions on Signal Processing, 39, 481ff. (1991).
    // - Read polygon data directly from shapefile instead of generate file.
    // - Reorganize data structures. It is currently quite a mess to read.
    // Inclusions
    #include <math.h>
    #include <stdio.h>
    #include <stdlib.h>
    // Definitions
    #define CART2PS "./cart.ps","w" // Cartogram image.
    #define CARTGENFILE "./cartogram.gen" // Cartogram generate file.
    #define CENSUSFILE "./census.dat","r" // Input.
    #define CONVERGENCE 1e-100 // Convergence criterion for integrator.
    // #define DISPLFILE "./displ.dat","w"
    #define FALSE 0
    #define HINITIAL 1e-4 // Initial time step size in nonlinvoltra.
    #define IMAX 50 // Maximum number of iterations in Newton-Raphson routine.
    #define INFTY 1e100
    #define LINELENGTH 1000
    #define MAP2PS "map.ps","w" // Map image.
    #define MAPGENFILE "./map.gen","r" // Input coordinates.
    #define MAX(a,b) ((b>a)?(b):(a))
    #define MAXINTSTEPS 3000 // Maximum number of time steps in nonlinvoltra.
    #define MAXNSQLOG 18 // The number of sample points for rho_0 is <~2^MAXNSQLOG.
    #define MIN(a,b) ((b<a)?(b):(a))
    #define MINH 1e-5 // Smallest permitted time step in the integrator.
    #define MINPOPFAC 0.1 // Replace 0 population by a fraction of the minimum.
    #define NR_END 1
    #define NSUBDIV 1 // Number of linear subdivisions for digitizing the density.
    #define PADDING 1.5 // Determines space between map and boundary.
    #define PI 3.141592653589793
    #define SIGMA 0.1 // Initial width of Gaussian blur.
    #define SIGMAFAC 1.2 // Increase sigma by this factor. Must be > 1.
    #define SWAP(a,b) tempr=(a);(a)=(b);(b)=tempr;
    #define TIMELIMIT 1e8 // Maximum time allowed in integrator.
    #define TOLF 1e-3 // Sensitivity w. r. t. function value in newt2.
    #define TOLINT 1e-3 // Sensitivity of the integrator.
    #define TOLX 1e-3 // Sensitivity w. r. t. independent variables in newt2.
    #define TRUE !FALSE
    // Types
    typedef int BOOLEAN;
    typedef struct
    float x;
    float y;
    } POINT;
    // Globals
    float bbmaxx,*bbmaxy,*bbminx,*bbminy,**gridvx,*gridvy,maxx,maxy,minpop,
    minx,miny,polymaxx,polymaxy,polyminx,polyminy,*rho,**rho_0,**vx,**vy,*x,
    *xappr,xstepsize,**y,*yappr,ystepsize;
    int lx,ly,maxid,nblurs=0,npoly,npolycorn,*npolyinreg,nregcorn,nregion,
    polygonid,**polyinreg,*regionid,*regionidinv,*within;
    POINT *polycorn,*regcorn;
    // Function prototypes
    int readline(char line[],FILE *infile);
    void countpoly(FILE *infile);
    void countcorn(FILE *infile);
    void readcorn(FILE *infile);
    void makeregion(void);
    void pspicture(FILE *outfile);
    void bboxes(void);
    void interior(void);
    double regionarea(int ncrns,POINT *polygon);
    void digdens(void);
    void four1(float data[],unsigned long nn,int isign);
    void realft(float data[],unsigned long n,int isign);
    void cosft(float z[],unsigned long n,int isign);
    void sinft(float z[],unsigned long n,int isign);
    void coscosft(float **y,int isign1,int isign2);
    void cossinft(float **y,int isign1,int isign2);
    void sincosft(float **y,int isign1,int isign2);
    float **dmatrix(long nrl,long nrh,long ncl,long nch);
    float *d3tensor(long nrl, long nrh, long ncl, long nch, long ndl, long ndh);
    void free_matrix(float **m,long nrl,long nrh,long ncl,long nch);
    void free_f3tensor(float *t,long nrl,long nrh,long ncl,long nch,long ndl,
    long ndh);
    void fourn(float data[],unsigned long nn[],int ndim,int isign);
    void rlft3(float *data,float **speq,unsigned long nn1,unsigned long nn2,
    unsigned long nn3,int isign);
    void gaussianblur(void);
    void initcond(void);
    void calcv(float t);
    float intpol(float **arr,float x,float y);
    BOOLEAN newt2(float h,float *xappr,float xguess,float *yappr,float yguess,
    int j,int k);
    BOOLEAN nonlinvoltra(void);
    POINT transf(POINT p);
    void cartogram(void);
    // Function to read one line.
    int readline(char line[],FILE *infile)
    if (fgets(line,LINELENGTH,infile)==NULL) return 1;
    return 0;
    // Function to count the number of polygons.
    void countpoly(FILE *infile)
    char line[LINELENGTH];
    npoly = 0;
    while (!readline(line,infile)) if (line[0] == 'E') npoly++;
    npoly--; // The .gen file ends with two consecutive "END"s.
    // Function to count polygon corners. Also determines minimum/maximum x-/y-
    // coordinate.
    void countcorn(FILE *infile)
    BOOLEAN bnd_ok = FALSE;
    char line[LINELENGTH];
    float x,y;
    int polyctr=0,ratiolog;
    npolycorn = (int*)calloc(npoly,sizeof(int));
    polycorn = (POINT*)malloc(npoly*sizeof(POINT));
    readline(line,infile); // Skip first line.
    readline(line,infile);
    sscanf(line,"%f %f",&x,&y);
    polyminx = x; polymaxx = x; polyminy = y; polymaxy = y;
    npolycorn[0] = 1;
    while (!readline(line,infile))
    if (line[0] != 'E')
    sscanf(line,"%f %f",&x,&y);
    if (x < polyminx) polyminx = x;
    if (x > polymaxx) polymaxx = x;
    if (y < polyminy) polyminy = y;
    if (y > polymaxy) polymaxy = y;
    npolycorn[polyctr]++;
    else
    readline(line,infile);
    polycorn[polyctr] = (POINT)malloc(npolycorn[polyctr]sizeof(POINT));
    polyctr++;
    if (ceil(log((polymaxx-polyminx)/(polymaxy-polyminy))/log(2))+
    floor(log((polymaxx-polyminx)/(polymaxy-polyminy))/log(2))>
    2*log((polymaxx-polyminx)/(polymaxy-polyminy))/log(2))
    ratiolog = (int)floor(log((polymaxx-polyminx)/(polymaxy-polyminy))/log(2));
    else
    ratiolog = (int)ceil(log((polymaxx-polyminx)/(polymaxy-polyminy))/log(2));
    lx = (int)pow(2,(int)(0.5*(ratiolog+MAXNSQLOG)));
    ly = (int)pow(2,(int)(0.5*(MAXNSQLOG-ratiolog)));
    if ((polymaxx-polyminx)/lx > (polymaxy-polyminy)/ly)
    maxx = 0.5((1PADDING)*polymaxx(1-PADDING)polyminx);
    minx = 0.5((1-PADDING)*polymaxx(1PADDING)polyminx);
    maxy = 0.5(polymaxypolyminy(maxx-minx)ly/lx);
    miny = 0.5(polymaxy+polyminy-(maxx-minx)ly/lx);
    else
    maxy = 0.5((1PADDING)*polymaxy(1-PADDING)polyminy);
    miny = 0.5((1-PADDING)*polymaxy(1PADDING)polyminy);
    maxx = 0.5(polymaxxpolyminx(maxy-miny)lx/ly);
    minx = 0.5(polymaxx+polyminx-(maxy-miny)lx/ly);
    // Uncomment the next lines for interactive choice of boundary conditions.
    /* printf("For the %i polygon(s) under consideration:\n",npoly);
    printf("minimum x = %f\tmaximum x = %f\n",polyminx,polymaxx);
    printf("minimum y = %f\tmaximum y = %f\n",polyminy,polymaxy);
    while (!bnd_ok)
    printf("Type in your choice of boundaries.\nminx = ");
    scanf("%f",&minx);
    printf("maxx = ");
    scanf("%f",&maxx);
    printf("miny = ");
    scanf("%f",&miny);
    printf("maxy = ");
    scanf("%f",&maxy);
    if (minx>polyminx || maxx<polymaxx || miny>polyminy || maxy<polymaxy)
    printf("Invalid choice, does not enclose the polygon(s).\n");
    else bnd_ok = TRUE;
    // Function to read polygon corners. The first and last vertex of each polygon
    // must be identical.
    void readcorn(FILE *infile)
    char line[LINELENGTH];
    float xcoord,ycoord;
    int i,id,polyctr=0;
    polygonid = (int)malloc(npolysizeof(int));
    xstepsize = (maxx-minx)/lx;
    ystepsize = (maxy-miny)/ly;
    if (fabs((xstepsize/ystepsize)-1)>1e-3)
    fprintf(stderr,"WARNING: Area elements are not square: %f : %f\n",
    xstepsize,ystepsize);
    readline(line,infile);
    sscanf(line,"%i",&id);
    polygonid[polyctr] = id;
    i = 0;
    while (!readline(line,infile))
    if (line[0] != 'E')
    sscanf(line,"%f %f",&xcoord,&ycoord);
    polycorn[polyctr].x = (xcoord-minx)/xstepsize;
    polycorn[polyctr][i++].y = (ycoord-miny)/ystepsize;
    else
    // Is first and last vertex the same?
    if (fabs(polycorn[polyctr][0].x-
    polycorn[polyctr][npolycorn[polyctr]-1].x)+
    fabs(polycorn[polyctr][0].y-
    polycorn[polyctr][npolycorn[polyctr]-1].y)>1e-12)
    fprintf(stderr,
    "ERROR: %i-th polygon does not close upon itself.\n",
    polyctr+1);
    fprintf(stderr,"Identifier %i, first point %f %f.\n",
    polygonid[polyctr],polycorn[polyctr][0].x*xstepsize+minx,
    polycorn[polyctr][0].y*ystepsize+miny);
    exit(1);
    readline(line,infile);
    sscanf(line,"%i",&id);
    i = 0;
    polyctr++;
    if (polyctr<npoly) polygonid[polyctr] = id;
    polyminx = (polyminx-minx)/xstepsize;
    polyminy = (polyminy-miny)/ystepsize;
    polymaxx = (polymaxx-minx)/xstepsize;
    polymaxy = (polymaxy-miny)/ystepsize;
    // Function to make regions from polygons.
    void makeregion(void)
    BOOLEAN repeat;
    int i,lastid,minid,polyctr,ptctr,regctr;
    // Count the number of regions.
    nregion = 0;
    maxid = minid = polygonid[0];
    for (polyctr=0; polyctr<npoly; polyctr++)
    if (polygonid[polyctr] == -99999) continue;
    if (polygonid[polyctr]>maxid || polygonid[polyctr]<minid) nregion++;
    else
    repeat = FALSE;
    for (i=0; i<polyctr; i++)
    if (polygonid[polyctr]==polygonid)
    repeat = TRUE;
    break;
    if (!repeat) nregion++;
    if (polygonid[polyctr]>maxid) maxid = polygonid[polyctr];
    if (polygonid[polyctr]<minid) minid = polygonid[polyctr];
    if (minid < 0)
    fprintf(stderr,
    "ERROR: Negative region identifier %i.\n",minid);
    exit(1);
    // Match region identifiers.
    regionid = (int)malloc(nregionsizeof(int));
    nregion = 0;
    maxid = minid = polygonid[0];
    for (polyctr=0; polyctr<npoly; polyctr++)
    if (polygonid[polyctr] == -99999) continue;
    if (polygonid[polyctr]>maxid || polygonid[polyctr]<minid)
    regionid[nregion++] = polygonid[polyctr];
    else
    repeat = FALSE;
    for (i=0; i<polyctr; i++)
    if (polygonid[polyctr]==polygonid)
    repeat = TRUE;
    break;
    if (!repeat) regionid[nregion++] = polygonid[polyctr];
    if (polygonid[polyctr]>maxid) maxid = polygonid[polyctr];
    if (polygonid[polyctr]<minid) minid = polygonid[polyctr];
    regionidinv = (int)malloc((maxid+1)sizeof(int));
    // Negative number for unused identifiers.
    for (i=0; i<=maxid; i++) regionidinv = -1;
    for (regctr=0; regctr<nregion; regctr++)
    regionidinv[regionid[regctr]] = regctr;
    // Which polygons contribute to which regions?
    npolyinreg = (int*)calloc(nregion,sizeof(int));
    polyinreg = (int*)malloc(nregion*sizeof(int));
    lastid = polygonid[0];
    for (polyctr=0; polyctr<npoly; polyctr++)
    if (polygonid[polyctr] != -99999)
    npolyinreg[regionidinv[polygonid[polyctr]]]++;
    lastid = polygonid[polyctr];
    else npolyinreg[regionidinv[lastid]]++;
    for (regctr=0; regctr<nregion; regctr++)
    polyinreg[regctr] = (int)malloc(npolyinreg[regctr]sizeof(int));
    for (regctr=0; regctr<nregion; regctr++) npolyinreg[regctr] = 0;
    lastid = polygonid[0];
    for (polyctr=0; polyctr<npoly; polyctr++)
    if (polygonid[polyctr] != -99999)
    polyinreg[regionidinv[polygonid[polyctr]]]
    [npolyinreg[regionidinv[polygonid[polyctr]]]++] = polyctr;
    lastid = polygonid[polyctr];
    else polyinreg[regionidinv[lastid]][npolyinreg[regionidinv[lastid]]++]
    = polyctr;
    // Make regions from polygons. Start and end each polygon at (0,0).
    nregcorn = (int*)calloc(nregion,sizeof(int));
    regcorn = (POINT*)malloc(nregion*sizeof(POINT));
    for (regctr=0; regctr<nregion; regctr++)
    for (i=0; i<npolyinreg[regctr]; i++)
    nregcorn[regctr] += npolycorn[polyinreg[regctr]]+1;
    nregcorn[regctr]++;
    for (regctr=0; regctr<nregion; regctr++)
    regcorn[regctr] = (POINT)malloc(nregcorn[regctr]sizeof(POINT));
    ptctr = 0;
    regcorn[regctr][ptctr].x = regcorn[regctr][ptctr++].y = 0.0;
    for (polyctr=0; polyctr<npolyinreg[regctr]; polyctr++)
    for (i=0; i<npolycorn[polyinreg[regctr][polyctr]]; i++)
    regcorn[regctr][ptctr++] = polycorn[polyinreg[regctr][polyctr]];
    regcorn[regctr][ptctr].x = regcorn[regctr][ptctr++].y = 0.0;
    // Function to prepare a map in postscript standard letter format.
    void pspicture(FILE *outfile)
    char line[LINELENGTH];
    float addx,addy,b,conv,g,r;
    int ptctr,regctr;
    if (11*lx > 8.5*ly)
    conv = (float)8.5*72/lx;
    addx = 0;
    addy = 1136-8.5*36ly/lx;
    else
    conv = (float)11*72/ly;
    addx = 8.536-11*36lx/ly;
    addy = 0;
    fprintf(outfile,"0.5 setlinewidth\n");
    for (regctr=0; regctr<nregion; regctr++)
    fprintf(outfile,"newpath\n");
    fprintf(outfile,"%f %f moveto\n",
    regcorn[regctr][1].x*conv+addx,
    regcorn[regctr][1].y*conv+addy);
    for (ptctr=2; ptctr<nregcorn[regctr]; ptctr++)
    if (fabs(regcorn[regctr][ptctr].x)+
    fabs(regcorn[regctr][ptctr].y)>1e-12)
    fprintf(outfile,"%f %f lineto\n",
    regcorn[regctr][ptctr].x*conv+addx,
    regcorn[regctr][ptctr].y*conv+addy);
    else
    fprintf(outfile,"closepath\n");
    if (ptctr<nregcorn[regctr]-1)
    ptctr++;
    fprintf(outfile,"%f %f moveto\n",
    regcorn[regctr][ptctr].x*conv+addx,
    regcorn[regctr][ptctr].y*conv+addy);
    // Determine colors for map (without better knowledge I will do it
    // arbitrarily).
    if (regctr%3 == 0)
    r = (float)regctr/nregion;
    g = 1-(float)regctr/nregion;
    b = fabs(1-2*(float)regctr/nregion);
    else if (regctr%3 == 1)
    b = (float)regctr/nregion;
    r = 1-(float)regctr/nregion;
    g = fabs(1-2*(float)regctr/nregion);
    else
    g = (float)regctr/nregion;
    b = 1-(float)regctr/nregion;
    r = fabs(1-2*(float)regctr/nregion);
    fprintf(outfile,"%f %f %f setrgbcolor\ngsave\nfill\n",r,g,b);
    fprintf(outfile,"grestore\n0 setgray stroke\n");
    fprintf(outfile,"showpage\n");
    // Function to find the bounding box for each polygon.
    void bboxes(void)
    int i,j;
    float maxx, minx, maxy, miny;
    bbmaxx = (float)malloc(npolysizeof(float));
    bbmaxy = (float)malloc(npolysizeof(float));
    bbminx = (float)malloc(npolysizeof(float));
    bbminy = (float)malloc(npolysizeof(float));
    for (i = 0; i < npoly; i++)
    maxx = polycorn[0].x;
    maxy = polycorn[0].y;
    minx = maxx;
    miny = maxy;
    for (j = 0; j < npolycorn; j++)
    if (polycorn[j].x > maxx) maxx = polycorn[j].x;
    if (polycorn[j].x < minx) minx = polycorn[j].x;
    if (polycorn[j].y < miny) miny = polycorn[j].y;
    if (polycorn[j].y > maxy) maxy = polycorn[j].y;
    bbmaxx=maxx;
    bbmaxy=maxy;
    bbminx=minx;
    bbminy=miny;
    void interior(void)
    int i,inhowmanyregions,inregion[2],j,k,l,m,n,regctr;
    // Initialize within[][]. -1 means outside all regions.
    for (i=0; i<=lx; i++) for (j=0; j<=ly; j++) within[j] = -1;
    // Fill within[][].
    for (i=0; i<nregion; i++) for (j=0; j<npolyinreg; j++)
    for (k=0, n=npolycorn[polyinreg[j]]-1;
    k<npolycorn[polyinreg[j]]; n=k++)
    for (l=(int)ceil(MIN(polycorn[polyinreg[j]][k-1].y,
    polycorn[polyinreg[j]][k].y));
    l<MAX(polycorn[polyinreg[j]][k-1].y,
    polycorn[polyinreg[j]][k].y); l++)
    for (m=(int)floor(bbminx[polyinreg[j]]);
    m<(polycorn[polyinreg[j]][n].x-
    polycorn[polyinreg[j]][k].x)*
    (l-polycorn[polyinreg[j]][k].y)/
    (polycorn[polyinreg[j]][n].y-
    polycorn[polyinreg[j]][k].y)+
    polycorn[polyinreg[j]][k].x;
    m++)
    within[m][l] = i-within[m][l]-1;
    // Function to determine polygon area. This is needed to determine the average
    // population.
    // The problem in short is to find the area of a polygon whose vertices are
    // given. Recall Stokes' theorem in 3d for a vector field v:
    // integral[around closed curve dA]v(x,y,z).ds =
    // integral[over area A]curl(v).dA.
    // Now let v(x,y,z) = (0,Q(x,y),0) and dA = (0,0,dx*dy). Then
    // integral[around closed curve dA]Q(x,y)dy = integral[over area A]dQ/dxdxdy.
    // If Q = x:
    // A = integral[over area A]dx*dy = integral[around closed curve dA]x dy.
    // For every edge from (x,y) to (x[i1],y[i1]) there is a
    // parametrization
    // (x(t),y(t)) = ((1-t)xtx[i+1],(1-t)y+ty[i1]), 0<t<1
    // so that the path integral along this edge is
    // int[from 0 to 1]{(1-t)xt*x[i+1]}(y[i1]-y)dt =
    // 0.5(y[i1]-y)(x+x[i1]).
    // Summing over all edges yields:
    // Area = 0.5*[(x[0]+x[1])(y[1]-y[0]) + (x[1]+x[2])(y[2]-y[1]) + ...
    // ...(x[n-1]+x[n])(y[n]-y[n-1])+(x[n]x[0])(y[0]-y[n])]
    // ArcGIS treats a clockwise direction as positive, so there is a minus sign.
    double regionarea(int ncrns,POINT *polygon)
    double area=0;
    int i;
    for (i=0; i<ncrns-1; i++)
    area -=
    0.5(polygon.xpolygon[i+1].x)(polygon[i1].y-polygon.y);
    return area -= 0.5(polygon[ncrns-1].x+polygon[0].x)
    (polygon[0].y-polygon[ncrns-1].y);
    // Function to digitize density.
    void digdens(void)
    char line[LINELENGTH];
    double area,avgdens,*cases,dens,minpop=INFTY,ncases,totarea=0.0,totpop=0.0;
    FILE* infile;
    int i,id,ii,inhowmanyregions,inregion[2],j,jj,regctr;
    if ((infile=fopen(CENSUSFILE))==NULL)
    fprintf(stderr,"ERROR: Cannot find CENSUSFILE.\n");
    exit(1);
    // Find the minimum positive number of cases.
    while (!readline(line,infile))
    sscanf(line,"%i %lf",&id,&ncases);
    if (ncases<minpop && ncases>1e-12) minpop = ncases;
    fclose(infile);
    // Store the number of cases in an array.
    cases = (double)malloc(nregionsizeof(double));
    for (i=0; i<nregion; i++) cases = -1.0;
    infile = fopen(CENSUSFILE);
    while (!readline(line,infile))
    sscanf(line,"%i %lf",&id,&ncases);
    if (id>maxid || regionidinv[id]<0)
    fprintf(stderr,"ERROR: Identifier %i in CENSUSFILE does not\n",id);
    fprintf(stderr,"match any identifier in generate file.\n");
    exit(1);
    if (ncases>1e-12) totpop += (cases[regionidinv[id]] = ncases);
    else totpop += (cases[regionidinv[id]] = MINPOPFAC*minpop);
    for (regctr=0; regctr<nregion; regctr++) if (cases[regctr] < 0.0)
    fprintf(stderr,"ERROR: No density for region %i?\n",regionid[regctr]);
    fprintf(stderr,"cases = %f\n",cases[regctr]);
    exit(1);
    fclose(infile);
    // Calculate regions' areas, total area to be mapped, regional and average
    // densities.
    area = (double)malloc(nregionsizeof(double));
    for (regctr=0; regctr<nregion; regctr++)
    totarea += (area[regctr] = regionarea(nregcorn[regctr],regcorn[regctr]));
    dens = (double)malloc(nregionsizeof(double));
    for (regctr=0; regctr<nregion; regctr++)
    dens[regctr] = cases[regctr]/area[regctr];
    avgdens = totpop/totarea;
    // Digitize density.
    for (i=0; i<=lx; i++) for (j=0; j<=ly; j++) rho_0[j] = 0; // Initialize.
    printf("digitizing density ...\n");
    for (i=0; i<lx; i++) for (j=0; j<ly; j++)
    if (within[j]==-1) rho_0[j] = avgdens;
    else rho_0[j] = dens[within[j]];
    // Fill the edges correctly.
    rho_0[0][0] += rho_0[0][ly] + rho_0[lx][0] + rho_0[lx][ly];
    for (i=1; i<lx; i++) rho_0[0] += rho_0[ly];
    for (j=1; j<ly; j++) rho_0[0][j] += rho_0[lx][j];
    for (i=0; i<lx; i++) rho_0[ly] = rho_0[0];
    for (j=0; j<=ly; j++) rho_0[lx][j] = rho_0[0][j];
    // Replace rho_0 by Fourier transform
    coscosft(rho_0,1,1);
    free(area);
    free(cases);
    for (i=0; i<npoly; i++) free(polycorn);
    free(polycorn);
    for (i=0; i<nregion; i++) free(regcorn);
    free(regcorn);
    free(dens);
    free(npolycorn);
    free(nregcorn);
    free(polygonid);
    free(regionid);
    free(regionidinv);
    free(bbmaxx);
    free(bbmaxy);
    free(bbminx);
    free(bbminy);
    for (i=0; i<nregion; i++) free(polyinreg);
    free(polyinreg);
    free(npolyinreg);
    // Function to replace data[1...2*nn] by its discrete Fourier transform, if
    // isign is input as 1; or replaces data[1...2*nn] by nn times its inverse
    // discrete Fourier transform, if isign is input as -1. data is a complex array
    // of length nn or, equivalently, a real array of length 2*nn. nn MUST be an
    // integer power of 2 (this is not checked for!).
    // From "Numerical Recipes in C".
    void four1(float data[],unsigned long nn,int isign)
    double theta,wi,wpi,wpr,wr,wtemp;
    float tempi,tempr;
    unsigned long i,istep,j,m,mmax,n;
    n=nn<<1;
    j=1;
    for (i=1; i<n; i+=2)
    if (j>i)
    // This is the bit-reversal section of the routine.
    SWAP(data[j],data);
    SWAP(data[j1],data[i1]); // Exchange the two complex numbers.
    m=n>>1;
    while (m>=2 && j>m)
    j -= m;
    m>>=1;
    j += m;
    // Here begins the Danielson-Lanczos section of the routine.
    mmax=2;
    while (n>mmax) // Outer loop executed log_2 nn times.
    istep = mmax<<1;
    // Initialize the trigonometric recurrence.
    theta = isign*(6.28318530717959/mmax);
    wtemp = sin(0.5*theta);
    wpr = -2.0wtempwtemp;
    wpi = sin(theta);
    wr = 1.0;
    wi = 0.0;
    for (m=1; m<mmax; m+=2) // Here are the two nested inner loops.
    for (i=m; i<=n; i+=istep)
    j=i+mmax; // This is the Danielson-Lanczos formula
    tempr=wrdata[j]-widata[j+1];
    tempi=wrdata[j1]widata[j];
    data[j]=data-tempr;
    data[j1]=data[i1]-tempi;
    data += tempr;
    data[i+1] += tempi;
    wr = (wtemp=wr)wpr-wiwpi+wr; // Trigonometric recurrence.
    wi = wiwprwtempwpiwi;
    mmax=istep;
    // Function to calculate the Fourier Transform of a set of n real-valued data
    // points. It replaces this data (which is stored in array data[1...n]) by the
    // positive frequency half of its complex Fourier Transform. The real-valued
    // first and last components of the complex transform are returned as elements
    // data[1] and data[2] respectively. n must be a power of 2. This routine also
    // calculates the inverse transform of a complex data array if it is the
    // transform of real data. (Result in this case must be multiplied by 2/n).
    // From "Numerical Recipes in C".
    void realft(float data[],unsigned long n,int isign)
    double theta,wi,wpi,wpr,wr,wtemp;
    float c1=0.5,c2,h1i,h1r,h2i,h2r;
    unsigned long i,i1,i2,i3,i4,np3;
    theta = 3.141592653589793/(double) (n>>1); // Initialize the recurrence
    if (isign == 1)
    c2 = -0.5;
    four1(data,n>>1,1); // The forward transform is here.
    else // Otherwise set up for an inverse transform.
    c2 = 0.5;
    theta = -theta;
    wtemp = sin(0.5*theta);
    wpr = -2.0wtempwtemp;
    wpi = sin(theta);
    wr = 1.0+wpr;
    wi = wpi;
    np3 = n+3;
    for (i=2; i<=(n>>2); i++) // Case i=1 done separately below.
    i4 = 1(i3=np3-(i2=1+(i1=ii-1)));
    // The two separate transforms are separated out of data.
    h1r = c1*(data[i1]+data[i3]);
    h1i = c1*(data[i2]-data[i4]);
    h2r = -c2*(data[i2]+data[i4]);
    h2i = c2*(data[i1]-data[i3]);
    // Here they are recombined to form the true transform of the original
    // data.
    data[i1] = h1r+wrh2r-wih2i;
    data[i2] = h1iwrh2iwih2r;
    data[i3] = h1r-wrh2r+wih2i;
    data[i4] = -h1iwrh2iwih2r;
    wr = (wtemp=wr)wpr-wiwpi+wr; // The recurrence.
    wi = wiwprwtempwpiwi;
    if (isign == 1)
    data[1] = (h1r=data[1])+data[2]; // Squeeze the first and last data
    // together to get them all within the original array.
    data[2] = h1r-data[2];
    else
    data[1] = c1*((h1r=data[1])+data[2]);
    data[2] = c1*(h1r-data[2]);
    // This is the inverse transform for the case isign = -1.
    four1(data,n>>1,-1);
    // Function to calculate the cosine transform of a set z[0...n] of real-valued
    // data points. The transformed data replace the original data in array z. n
    // must be a power of 2. For forward transform set isign=1, for back transform
    // isign = -1. (Note: The factor 2/n has been taken care of.)
    // From "Numerical Recipes in C".
    void cosft(float z[],unsigned long n,int isign)
    double theta,wi=0.0,wpi,wpr,wr=1.0,wtemp;
    float *a,sum,y1,y2;
    int j,n2;
    // Numerical Recipes starts counting at 1 which is rather confusing. I will
    // count from 0.
    a = (float)malloc((n+2)sizeof(float));
    for (j=1; j<=n+1; j++) a[j] = z[j-1];
    // Here is the Numerical Recipes code.
    theta=PI/n; //Initialize the recurrence.
    wtemp = sin(0.5*theta);
    wpr = -2.0wtempwtemp;
    wpi = sin(theta);
    sum = 0.5*(a[1]-a[n+1]);
    a[1] = 0.5*(a[1]a[n1]);
    n2 = n+2;
    for (j=2; j<=(n>>1); j++)
    wr = (wtemp=wr)wpr-wiwpi+wr;
    wi = wiwprwtempwpiwi;
    y1 = 0.5*(a[j]+a[n2-j]);
    y2 = (a[j]-a[n2-j]);
    a[j] = y1-wi*y2;
    a[n2-j] = y1+wi*y2;
    sum += wr*y2;
    realft(a,n,1);
    a[n+1] = a[2];
    a[2] = sum;
    for (j=4; j<=n; j+=2)
    sum += a[j];
    a[j] = sum;
    // Finally I revert to my counting method.
    if (isign == 1) for (j=1; j<=n+1; j++) z[j-1] = a[j];
    else if (isign == -1) for (j=1; j<=n+1; j++) z[j-1] = 2.0*a[j]/n;
    free(a);
    // Function to calculate the sine transform of a set of n real-valued data
    // points stored in array z[0..n]. The number n must be a power of 2. On exit
    // z is replaced by its transform. For forward transform set isign=1, for back
    // transform isign = -1.
    void sinft(float z[],unsigned long n,int isign)
    double theta,wi=0.0,wpi,wpr,wr=1.0,wtemp;
    float *a,sum,y1,y2;
    int j;
    unsigned long n2=n+2;
    // See my comment about Numerical Recipe's counting above. Note that the last
    // component plays a completely passive role and does not need to be stored.
    a = (float*) malloc((n+1)*sizeof(float));
    for (j=1; j<=n; j++) a[j] = z[j-1];
    // Here is the Numerical Recipes code.
    theta = PI/(double)n; // Initialize the recurrence.
    wtemp = sin(0.5*theta);
    wpr = -2.0wtempwtemp;
    wpi = sin(theta);
    a[1] = 0.0;
    for (j=2; j<=(n>>1)+1; j++)
    // Calculate the sine for the auxiliary array.
    wr = (wtemp=wr)wpr-wiwpi+wr;
    // The cosine is needed to continue the recurrence.
    wi = wiwprwtempwpiwi;
    // Construct the auxiliary array.
    y1 = wi*(a[j]+a[n2-j]);
    y2 = 0.5*(a[j]-a[n2-j]);
    // Terms j and N-j are related.
    a[j] = y1+y2;
    a[n2-j] = y1-y2;
    // Transform the auxiliary array.
    realft(a,n,1);
    // Initialize the sum used for odd terms below.
    a[1] *= 0.5;
    sum = a[2] = 0.0;
    // Even terms determined directly. Odd terms determined by running sum.
    for (j=1; j<=n-1; j+=2)
    sum += a[j];
    a[j] = a[j+1];
    a[j+1] = sum;
    // Change the indices.
    if (isign == 1) for (j=1; j<=n; j++) z[j-1] = a[j];
    else if (isign == -1) for (j=1; j<=n; j++) z[j-1] = 2.0*a[j]/n;
    z[n] = 0.0;
    free(a);
    // Function to calculate a two-dimensional cosine Fourier transform. Forward/
    // backward transform in x: isign1 = +/-1, in y: isign2 = +/-1.
    void coscosft(float **y,int isign1,int isign2)
    float temp[lx+1];
    unsigned long i,j;
    for (i=0; i<=lx; i++)
    cosft(y,ly,isign2);
    for (j=0; j<=ly; j++)
    for (i=0; i<=lx; i++) temp=y[j];
    cosft(temp,lx,isign1);
    for (i=0; i<=lx; i++) y[j]=temp;
    // Function to calculate a cosine Fourier transform in x and a sine transform
    // in y. Forward/backward transform in x: isign1 = +/-1, in y: isign2 = +/-1.
    void cossinft(float **y,int isign1,int isign2)
    float temp[lx+1];
    unsigned long i,j;
    for (i=0; i<=lx; i++)
    sinft(y,ly,isign2);
    for (j=0; j<=ly; j++)
    for (i=0; i<=lx; i++) temp=y[j];
    cosft(temp,lx,isign1);
    for (i=0; i<=lx; i++) y[j]=temp;
    // Function to calculate a sine Fourier transform in x and a cosine transform
    // in y. Forward/backward transform in x: isign1 = +/-1, in y: isign2 = +/-1.
    void sincosft(float **y,int isign1,int isign2)
    float temp[lx+1];
    unsigned long i,j;
    for (i=0; i<=lx; i++)
    cosft(y,ly,isign2);
    for (j=0; j<=ly; j++)
    for (i=0; i<=lx; i++) temp=y[j];
    sinft(temp,lx,isign1);
    for (i=0; i<=lx; i++) y[j]=temp;
    // Function to allocate a float matrix with subscript range
    // m[nrl..nrh][ncl..nch]. From "Numerical Recipes in C".
    float **dmatrix(long nrl,long nrh,long ncl,long nch)
    long i, nrow=nrh-nrl1,ncol=nch-ncl1;
    float **m;
    /* allocate pointers to rows */
    m=(float **) malloc((unsigned int)((nrow+NR_END)sizeof(float)));
    if (!m)
    fprintf(stderr,"allocation failure 1 in matrix()\n");
    exit(1);
    m += NR_END;
    m -= nrl;
    /* allocate rows and set pointers to them */
    m[nrl]=(float *) malloc((unsigned int)((nrowncol+NR_END)sizeof(float)));
    if (!m[nrl])
    fprintf(stderr,"allocation failure 2 in matrix()\n");
    exit(1);
    m[nrl] += NR_END;
    m[nrl] -= ncl;
    for(i=nrl1;i<=nrh;i+) m=m[i-1]+ncol;
    /* return pointer to array of pointers to rows */
    return m;
    // Function to allocate a float 3tensor with range
    // t[nrl..nrh][ncl..nch][ndl..ndh]. From "Numerical Recipes in C".
    float *d3tensor(long nrl, long nrh, long ncl, long nch, long ndl, long ndh)
    long i,j,nrow=nrh-nrl1,ncol=nch-ncl+1,ndep=ndh-ndl1;
    float *t;
    /* allocate pointers to pointers to rows */
    t=(float *) malloc((sizet)((nrow+NREND)sizeof(float*)));
    if (!t)
    fprintf(stderr,"allocation failure 1 in f3tensor()\n");
    exit(1);
    t += NR_END;
    t -= nrl;
    /* allocate pointers to rows and set pointers to them */
    t[nrl]=(float **) malloc((sizet)((nrowncol+NREND)*sizeof(float)));
    if (!t[nrl])
    fprintf(stderr,"allocation failure 2 in f3tensor()\n");
    exit(1);
    t[nrl] += NR_END;
    t[nrl] -= ncl;
    /* allocate rows and set pointers to them */
    t[nrl][ncl]=(float *) malloc((sizet)((nrowncol*ndep+NREND)sizeof(float)));
    if (!t[nrl][ncl])
    fprintf(stderr,"allocation failure 3 in f3tensor()\n");
    exit(1);
    t[nrl][ncl] += NR_END;
    t[nrl][ncl] -= ndl;
    for(j=ncl1;j<=nch;j+) t[nrl][j]=t[nrl][j-1]+ndep;
    for(i=nrl1;i<=nrh;i+) {
    t=t[i-1]+ncol;
    t[ncl]=t[i-1][ncl]+ncol*ndep;
    for(j=ncl1;j<=nch;j+) t[j]=t[j-1]+ndep;
    /* return pointer to array of pointers to rows */
    return t;
    void free_matrix(float **m,long nrl,long nrh,long ncl,long nch)
    free((char*) (m[nrl]+ncl-1));
    free((char*) (m+nrl-1));
    void free_f3tensor(float *t,long nrl,long nrh,long ncl,long nch,long ndl,
    long ndh)
    free((char*) (t[nrl][ncl]+ndl-1));
    free((char*) (t[nrl]+ncl-1));
    free((char*) (t+nrl-1));
    // Function to replace data by its ndim-dimensional discrete Fourier transform,
    // if isign is input as 1. nn[1..ndim] is an integer array containing the
    // lengths of each dimension (number of complex values), which MUST be all
    // powers of 2. data is a real array of length twice the product of these
    // lengths, in which the data are stored as in a multidimensional complex
    // array: real and imaginary parts of each element are in consecutive
    // locations, and the rightmost index of the array increases most rapidly as
    // one proceeds along data. For a two-dimensional array, this is equivalent to
    // storing the arrays by rows. If isign is input as -1, data is replaced by its
    // inverse transform times the product of the lengths of all dimensions.
    void fourn(float data[],unsigned long nn[],int ndim,int isign)
    int idim;
    unsigned long i1,i2,i3,i2rev,i3rev,ip1,ip2,ip3,ifp1,ifp2;
    unsigned long ibit,k1,k2,n,nprev,nrem,ntot;
    double tempi,tempr;
    float theta,wi,wpi,wpr,wr,wtemp;
    for (ntot=1, idim=1; idim<=ndim; idim++)
    ntot *= nn[idim];
    nprev = 1;
    for (idim=ndim; idim>=1; idim--)
    n = nn[idim];
    nrem = ntot/(n*nprev);
    ip1=nprev << 1;
    ip2 = ip1*n;
    ip3 = ip2*nrem;
    i2rev = 1;
    for (i2=1; i2<=ip2; i2+=ip1)
    if (i2 < i2rev)
    for (i1=i2; i1<=i2+ip1-2; i1+=2)
    for (i3=i1; i3<=ip3; i3+=ip2)
    i3rev = i2rev+i3-i2;
    SWAP(data[i3],data[i3rev]);
    SWAP(data[i31],data[i3rev1]);
    ibit = ip2>>1;
    while (ibit>=ip1 && i2rev>ibit)
    i2rev -= ibit;
    ibit >>= 1;
    i2rev += ibit;
    ifp1 = ip1;
    while (ifp1 < ip2)
    ifp2 = ifp1 << 1;
    theta = 2isignPI/(ifp2/ip1);
    wtemp = sin(0.5*theta);
    wpr = -2.0wtempwtemp;
    wpi = sin(theta);
    wr = 1.0;
    wi = 0.0;
    for (i3=1; i3<=ifp1; i3+=ip1)
    for (i1=i3; i1<=i3+ip1-2; i1+=2)
    for (i2=i1; i2<=ip3; i2+=ifp2)
    k1 = i2;
    k2 = k1+ifp1;
    tempr = (float)wrdata[k2]-(float)widata[k2+1];
    tempi = (float)wrdata[k21](float)widata[k2];
    data[k2] = data[k1]-tempr;
    data[k2+1] = data[k1+1]-tempi;
    data[k1] += tempr;
    data[k1+1] += tempi;
    wr = (wtemp=wr)wpr-wiwpi+wr;
    wi = wiwprwtempwpiwi;
    ifp1 = ifp2;
    nprev *= n;
    // Function to calculate a three-dimensional Fourier transform of
    // data[1..nn1][1..nn2][1..nn3] (where nn1=1 for the case of a logically two-
    // dimensional array). This routine returns (for isign=1) the complex fast
    // Fourier transform as two complex arrays: On output, data contains the zero
    // and positive frequency values of the third frequency component, while
    // speq[1..nn1][1..2*nn2] contains the Nyquist critical frequency values of the
    // third frequency component. First (and second) frequency components are
    // stored for zero, positive, and negative frequencies, in standard wrap-around
    // order. See Numerical Recipes for description of how complex values are
    // arranged. For isign=-1, the inverse transform (times nn1nn2nn3/2 as a
    // constant multiplicative factor) is performed, with output data (viewed as
    // real array) deriving from input data (viewed as complex) and speq. For
    // inverse transforms on data not generated first by a forward transform, make
    // sure the complex input data array satisfies property 12.5.2 from NR. The
    // dimensions nn1, nn2, nn3 must always be integer powers of 2.
    void rlft3(float *data,float **speq,unsigned long nn1,unsigned long nn2,
    unsigned long nn3,int isign)
    double theta,wi,wpi,wpr,wr,wtemp;
    float c1,c2,h1r,h1i,h2r,h2i;
    unsigned long i1,i2,i3,j1,j2,j3,nn[4],ii3;
    if (1+&data[nn1][nn2][nn3]-&data[1][1][1] != nn1nn2nn3)
    fprintf(stderr,
    "rlft3: problem with dimensions or contiguity of data array\n");
    exit(1);
    c1 = 0.5;
    c2 = -0.5*isign;
    theta = 2isign(PI/nn3);
    wtemp = sin(0.5*theta);
    wpr = -2.0wtempwtemp;
    wpi = sin(theta);
    nn[1] = nn1;
    nn[2] = nn2;
    nn[3] = nn3 >> 1;
    // Case of forward transform. Here is where most all of the compute time is
    // spent. Extend data periodically into speq.
    if (isign == 1)
    fourn(&data[1][1][1]-1,nn,3,isign);
    for (i1=1; i1<=nn1; i1++)
    for (i2=1, j2=0; i2<=nn2; i2++)
    speq[i1][++j2] = data[i1][i2][1];
    speq[i1][++j2] = data[i1][i2][2];
    for (i1=1; i1<=nn1; i1++)
    // Zero frequency is its own reflection; otherwise locate corresponding
    // negative frequency in wrap-around order.
    j1 = (i1 != 1 ? nn1-i1+2 : 1);
    // Initialize trigonometric recurrence.
    wr = 1.0;
    wi = 0.0;
    for (ii3=1, i3=1; i3<=(nn3>>2)+1; i3+,ii3=2)
    for (i2=1; i2<=nn2; i2++)
    if (i3 == 1)
    j2 = (i2 != 1 ? ((nn2-i2)<<1)+3 : 1);
    h1r = c1*(data[i1][i2][1]+speq[j1][j2]);
    h1i = c1*(data[i1][i2][2]-speq[j1][j2+1]);
    h2i = c2*(data[i1][i2][1]-speq[j1][j2]);
    h2r = -c2*(data[i1][i2][2]speq[j1][j21]);
    data[i1][i2][1] = h1r+h2r;
    data[i1][i2][2] = h1i+h2i;
    speq[j1][j2] = h1r-h2r;
    speq[j1][j2+1] = h2i-h1i;
    else
    j2 = (i2 != 1 ? nn2-i2+2 : 1);
    j3 = nn3+3-(i3<<1);
    h1r = c1*(data[i1][i2][ii3]+data[j1][j2][j3]);
    h1i = c1*(data[i1][i2][ii31]-data[j1][j2][j31]);
    h2i = c2*(data[i1][i2][ii3]-data[j1][j2][j3]);
    h2r = -c2*(data[i1][i2][ii31]+data[j1][j2][j31]);
    data[i1][i2][ii3] = h1r+wrh2r-wih2i;
    data[i1][i2][ii3+1] = h1iwrh2iwih2r;
    data[j1][j2][j3] = h1r-wrh2r+wih2i;
    data[j1][j2][j3+1] = -h1iwrh2iwih2r;
    // Do the recurrence.
    wr = (wtemp=wr)wpr-wiwpi+wr;
    wi = wiwprwtempwpiwi;
    // Case of reverse transform.
    if (isign == -1)
    fourn(&data[1][1][1]-1,nn,3,isign);
    // Function to perform Gaussian blur.
    void gaussianblur(void)
    float **blur,***conv,***pop,**speqblur,**speqconv,*speqpop;
    int i,j,p,q;
    blur = d3tensor(1,1,1,lx,1,ly);
    conv = d3tensor(1,1,1,lx,1,ly);
    pop = d3tensor(1,1,1,lx,1,ly);
    speqblur = dmatrix(1,1,1,2*lx);
    speqconv = dmatrix(1,1,1,2*lx);
    speqpop = dmatrix(1,1,1,2*lx);
    // Fill population and convolution matrix.
    for (i=1; i<=lx; i++) for (j=1; j<=ly; j++)
    if (i > lx/2) p = i-1-lx;
    else p = i-1;
    if (j > ly/2) q = j-1-ly;
    else q = j-1;
    pop[1][j] = rho_0[i-1][j-1];
    conv[1][j] = 0.5*
    (erf((p+0.5)/(sqrt(2.0)(SIGMApow(SIGMAFAC,nblurs))))-
    erf((p-0.5)/(sqrt(2.0)(SIGMA*pow(SIGMAFAC,nblurs)))))
    (erf((q+0.5)/(sqrt(2.0)(SIGMApow(SIGMAFAC,nblurs))))-
    erf((q-0.5)/(sqrt(2.0)(SIGMA*pow(SIGMAFAC,nblurs)))))/(lxly);
    // Fourier transform.
    rlft3(pop,speqpop,1,lx,ly,1);
    rlft3(conv,speqconv,1,lx,ly,1);
    // Multiply pointwise.
    for (i=1; i<=lx; i++)
    for (j=1; j<=ly/2; j++)
    blur[1][2*j-1] =
    pop[1][2j-1]*conv[1][2j-1]-
    pop[1][2j]*conv[1][2j];
    blur[1][2*j] =
    pop[1][2j]*conv[1][2j-1]+
    pop[1][2j-1]*conv[1][2j];
    for (i=1; i<=lx; i++)
    speqblur[1][2*i-1] =
    speqpop[1][2i-1]*speqconv[1][2i-1]-
    speqpop[1][2i]*speqconv[1][2i];
    speqblur[1][2*i] =
    speqpop[1][2i]*speqconv[1][2i-1]+
    speqpop[1][2i-1]*speqconv[1][2i];
    // Backtransform.
    rlft3(blur,speqblur,1,lx,ly,-1);
    // Write to rho_0.
    for (i=1; i<=lx; i++) for (j=1; j<=ly; j++) rho_0[i-1][j-1] = blur[1][j];
    free_f3tensor(blur,1,1,1,lx,1,ly);
    free_f3tensor(conv,1,1,1,lx,1,ly);
    free_f3tensor(pop,1,1,1,lx,1,ly);
    free_matrix(speqblur,1,1,1,2*lx);
    free_matrix(speqconv,1,1,1,2*lx);
    free_matrix(speqpop,1,1,1,2*lx);
    // Function to initialize rho_0. The original density is blurred with width
    // SIGMA*pow(SIGMAFAC,nblurs).
    void initcond(void)
    float maxpop;
    int i,j;
    // Reconstruct population density.
    coscosft(rho_0,-1,-1);
    // There must not be negative densities.
    for (i=0; i<lx; i++) for (j=0; j<ly; j++) if (rho_0[j]<-1e10)
    fprintf(stderr,"ERROR: Negative density in DENSITYFILE.\n");
    exit(1);
    // Perform Gaussian blur.
    printf("Gaussian blur ...\n");
    gaussianblur();
    // Find the mimimum density. If it is very small suggest an increase in
    // SIGMA.
    minpop = rho_0[0][0];
    maxpop = rho_0[0][0];
    for (i=0; i<lx; i++) for (j=0; j<ly; j++) if (rho_0[j]<minpop)
    minpop = rho_0[j];
    for (i=0; i<lx; i++) for (j=0; j<ly; j++) if (rho_0[j]>maxpop)
    maxpop = rho_0[j];
    if (0<minpop && minpop<1e-8*maxpop)
    fprintf(stderr,"Minimimum population very small (%f). Integrator\n",
    minpop);
    fprintf(stderr,
    "will probably converge very slowly. You can speed up the\n");
    fprintf(stderr,"process by increasing SIGMA to a value > %f.\n",
    SIGMA*pow(SIGMAFAC,nblurs));
    // Replace rho_0 by cosine Fourier transform in both variables.
    coscosft(rho_0,1,1);
    // Function to calculate the velocity field
    void calcv(float t)
    int j,k;
    // Fill rho with Fourier coefficients.
    for (j=0; j<=lx; j++) for (k=0; k<=ly; k++)
    rho[j][k] = exp(-((PIj/lx)*(PI*j/lx)+(PI*k/ly)*(PI*k/ly))*t)rho_0[j][k];
    // Calculate the Fourier coefficients for the partial derivative of rho.
    // Store temporary results in arrays gridvx, gridvy.
    for (j=0; j<=lx; j++) for (k=0; k<=ly; k++)
    gridvx[j][k] = -(PIj/lx)rho[j][k];
    gridvy[j][k] = -(PIk/ly)rho[j][k];
    // Replace rho by cosine Fourier backtransform in both variables.
    coscosft(rho,-1,-1);
    // Replace vx by sine Fourier backtransform in the first and cosine Fourier
    // backtransform in the second variable.
    sincosft(gridvx,-1,-1);
    // Replace vy by cosine Fourier backtransform in the first and sine Fourier
    // backtransform in the second variable.
    cossinft(gridvy,-1,-1);
    // Calculate the velocity field.
    for (j=0; j<=lx; j++) for (k=0; k<=ly; k++)
    gridvx[j][k] = -gridvx[j][k]/rho[j][k];
    gridvy[j][k] = -gridvy[j][k]/rho[j][k];
    // Function to bilinearly interpolate a two-dimensional array. For higher
    // accuracy one could consider higher order interpolation schemes.
    float intpol(float **arr,float x,float y)
    int gaussx,gaussy;
    float deltax,deltay;
    // Decompose x and y into an integer part and a decimal.
    gaussx = (int)x;
    gaussy = (int)y;
    deltax = x-gaussx;
    deltay = y-gaussy;
    // Interpolate.
    if (gaussx==lx && gaussy==ly)
    return arr[gaussx][gaussy];
    if (gaussx==lx)
    return (1-deltay)arr[gaussx][gaussy]deltayarr[gaussx][gaussy1];
    if (gaussy==ly)
    return (1-deltax)arr[gaussx][gaussy]deltaxarr[gaussx1][gaussy];
    return (1-deltax)(1-deltay)arr[gaussx][gaussy]+
    (1-deltax)deltayarr[gaussx][gaussy1]
    deltax(1-deltay)arr[gaussx1][gaussy]
    deltaxdeltayarr[gaussx1][gaussy1];
    // Function to find the root of the system of equations
    // xappr-0.5h*v_x(t+h,xappr,yappr)-x[j][k]-0.5*hvx[j][k]=0,
    // yappr-0.5h*v_y(t+h,xappr,yappr)-y[j][k]-0.5*hvy[j][k]=0
    // with Newton-Raphson. Returns TRUE after sufficient convergence.
    BOOLEAN newt2(float h,float *xappr,float xguess,float *yappr,float yguess,
    int j,int k)
    float deltax,deltay,dfxdx,dfxdy,dfydx,dfydy,fx,fy;
    int gaussx,gaussxplus,gaussy,gaussyplus,i;
    // Initial guess.
    *xappr = xguess;
    *yappr = yguess;
    for (i=1; i<=IMAX; i++)
    // fx, fy are the left-hand sides of the two equations. Find
    // v_x(t+h,xappr,yappr), v_y(t+h,xappr,yappr) by interpolation.
    fx = xappr-0.5*h*intpol(gridvx,*xappr,*yappr)-x[j][k]-0.5*hvx[j][k];
    fy = yappr-0.5*h*intpol(gridvy,*xappr,*yappr)-y[j][k]-0.5*hvy[j][k];
    // Linearly approximate the partial derivatives of fx, fy with a finite
    // difference method. More elaborate techniques are possible, but this
    // quick and dirty method appears to work reasonably for our purpose.
    gaussx = (int)(*xappr);
    gaussy = (int)(*yappr);
    if (gaussx == lx) gaussxplus = 0;
    else gaussxplus = gaussx+1;
    if (gaussy == ly) gaussyplus = 0;
    else gaussyplus = gaussy+1;
    deltax = x[j][k] - gaussx;
    deltay = y[j][k] - gaussy;
    dfxdx = 1 - 0.5h
    ((1-deltay)*(gridvx[gaussxplus][gaussy]-gridvx[gaussx][gaussy])+
    deltay*(gridvx[gaussxplus][gaussyplus]-gridvx[gaussx][gaussyplus]));
    dfxdy = -0.5h
    ((1-deltax)*(gridvx[gaussx][gaussyplus]-gridvx[gaussx][gaussy])+
    deltax*(gridvx[gaussxplus][gaussyplus]-gridvx[gaussxplus][gaussy]));
    dfydx = -0.5h
    ((1-deltay)*(gridvy[gaussxplus][gaussy]-gridvy[gaussx][gaussy])+
    deltay*(gridvy[gaussxplus][gaussyplus]-gridvy[gaussx][gaussyplus]));
    dfydy = 1 - 0.5h
    ((1-deltax)*(gridvy[gaussx][gaussyplus]-gridvy[gaussx][gaussy])+
    deltax*(gridvy[gaussxplus][gaussyplus]-gridvy[gaussxplus][gaussy]));
    // If the current approximation is (xappr,yappr) for the zero of
    // (fx(x,y),fy(x,y)) and J is the Jacobian, then we can approximate (in
    // vector notation) for |delta|<<1:
    // f((xappr,yappr)+delta) = f(xappr,yappr)+J*delta.
    // Setting f((xappr,yappr)+delta)=0 we obtain a set of linear equations
    // for the correction delta which moves f closer to zero, namely
    // J*delta = -f.
    // The improved approximation is then x = xappr+delta.
    // The process will be iterated until convergence is reached.
    if ((fx*fx + fy*fy) < TOLF) return TRUE;
    deltax = (fy*dfxdy - fxdfydy)/(dfxdxdfydy - dfxdy*dfydx);
    deltay = (fx*dfydx - fydfxdx)/(dfxdxdfydy - dfxdy*dfydx);
    if ((deltax*deltax + deltay*deltay) < TOLX) return TRUE;
    *xappr += deltax;
    *yappr += deltay;
    //printf("deltax %f, deltay %f\n",deltax,deltay);
    fprintf(stderr,"newt2 failed, increasing sigma to %f.\n",
    SIGMA*pow(SIGMAFAC,nblurs));
    return FALSE;
    // Function to integrate the nonlinear Volterra equation. Returns TRUE after
    // the displacement field converged, after MAXINTSTEPS integration steps, or
    // if the time exceeds TIMELIMIT.
    BOOLEAN nonlinvoltra(void)
    BOOLEAN stepsize_ok;
    #ifdef DISPLFILE
    FILE *displfile = fopen(DISPLFILE);
    #endif
    float h,maxchange=INFTY,t,vxplus,vyplus,xguess,yguess;
    int i,j,k;
    do
    initcond();
    nblurs++;
    if (minpop<0.0)
    fprintf(stderr,
    "Minimum population negative, will increase sigma to %f\n",
    SIGMA*pow(SIGMAFAC,nblurs));
    while (minpop<0.0);
    h = HINITIAL;
    t = 0; // Start at time t=0.
    // (x[j][k],y[j][k]) is the position for the element that was at position
    // (j,k) at time t=0.
    for (j=0; j<=lx; j++) for (k=0; k<=ly; k++)
    x[j][k] = j;
    y[j][k] = k;
    calcv(0.0);
    // (gridvx[j][k],gridvy[j][k]) is the velocity at position (j,k).
    // (vx[j][k],vy[j][k]) is the velocity at position (x[j][k],y[j][k]).
    // At t=0 they are of course identical.
    for (j=0; j<=lx; j++) for (k=0; k<=ly; k++)
    vx[j][k] = gridvx[j][k];
    vy[j][k] = gridvy[j][k];
    i = 1; // i counts the integration steps.
    // Here is the integrator.
    do
    stepsize_ok = TRUE;
    calcv(t+h);
    for (j=0; j<=lx; j++) for (k=0; k<=ly; k++)
    // First take a naive integration step. The velocity at time t+h for
    // the element [j][k] is approximately
    // v(th,x[j][k]+hvx[j][k],y[j][k]hvy[j][k]).
    // The components, call them vxplus and vyplus, are interpolated from
    // gridvx and gridvy.
    vxplus = intpol(gridvx,x[j][k]hvx[j][k],y[j][k]hvy[j][k]);
    vyplus = intpol(gridvy,x[j][k]hvx[j][k],y[j][k]hvy[j][k]);
    // Based on (vx[j][k],vy[j][k]) and (vxplus,vyplus) we expect the
    // new position at time t+h to be:
    xguess = x[j][k] + 0.5h(vx[j][k]+vxplus);
    yguess = y[j][k] + 0.5h(vy[j][k]+vyplus);
    // Then we make a better approximation by solving the two nonlinear
    // equations:
    // xappr[j][k]-0.5hv_x(t+h,xappr[j][k],yappr[j][k])-
    // x[j][k]-0.5hvx[j][k]=0,
    // yappr[j][k]-0.5hv_y(t+h,xappr[j][k],yappr[j][k])-
    // y[j][k]-0.5hvy[j][k]=0
    // with Newton-Raphson and (xguess,yguess) as initial guess.
    // If newt2 fails to converge, exit nonlinvoltra.
    if (!newt2(h,&xappr[j][k],xguess,&yappr[j][k],yguess,j,k))
    return FALSE;
    // If the integration step was too large reduce the step size.
    if ((xguess-xappr[j][k])*(xguess-xappr[j][k])+
    (yguess-yappr[j][k])*(yguess-yappr[j][k]) > TOLINT)
    if (h<MINH)
    fprintf(stderr,
    "Time step below %f, increasing SIGMA to %f\n",
    h,SIGMA*pow(SIGMAFAC,nblurs));
    nblurs++;
    return FALSE;
    h /= 10;
    stepsize_ok = FALSE;
    break;
    if (!stepsize_ok) continue;
    else
    t += h;
    maxchange = 0.0; // Monitor the maximum change in positions.
    for (j=0; j<=lx; j++) for (k=0; k<=ly; k++)
    if ((x[j][k]-xappr[j][k])*(x[j][k]-xappr[j][k])+
    (y[j][k]-yappr[j][k])*(y[j][k]-yappr[j][k]) > maxchange)
    maxchange =
    (x[j][k]-xappr[j][k])*(x[j][k]-xappr[j][k])+
    (y[j][k]-yappr[j][k])*(y[j][k]-yappr[j][k]);
    x[j][k] = xappr[j][k];
    y[j][k] = yappr[j][k];
    vx[j][k] = intpol(gridvx,xappr[j][k],yappr[j][k]);
    vy[j][k] = intpol(gridvy,xappr[j][k],yappr[j][k]);
    h *= 1.2; // Make the next integration step larger.
    if (i%10==0) printf("time %f\n",t);
    i++;
    } while (i<MAXINTSTEPS && t<TIMELIMIT && maxchange>CONVERGENCE);
    if (maxchange>CONVERGENCE)
    fprintf(stderr,
    "WARNING: Insufficient convergence within %i steps, time %f.\n",
    MAXINTSTEPS,TIMELIMIT);
    #ifdef DISPLFILE
    // Write displacement field to file.
    fprintf(displfile,"time %f\nminx %f\nmaxx %f\nminy %f\nmaxy %f\n",
    t,minx,maxx,miny,maxy);
    fprintf(displfile,"sigma %f\n",SIGMA*pow(SIGMAFAC,nblurs-1));
    fprintf(displfile,"background %f\nlx\nly\n\n",0,lx,ly);
    for (j=0; j<=lx; j++) for (k=0; k<=ly; k++)
    fprintf(displfile,"j %i, k %i, x %f, y %f\n",j,k,x[j][k],y[j][k]);
    fclose(displfile);
    #endif
    return TRUE;
    // Function to transform points according to displacement field.
    POINT transf(POINT p)
    float deltax,deltay,den,t,u;
    int gaussx,gaussy;
    POINT a,b,c,d,ptr;
    p.x = (p.x-minx)*lx/(maxx-minx);
    p.y = (p.y-miny)*ly/(maxy-miny);
    gaussx = (int)p.x;
    gaussy = (int)p.y;
    if (gaussx<0 || gaussx>lx || gaussy<0 || gaussy>ly)
    fprintf(stderr,"ERROR: Coordinate limits exceeded in transf.\n");
    exit(1);
    deltax = p.x - gaussx;
    deltay = p.y - gaussy;
    // The transformed point is the intersection of the lines:
    // (I) connecting
    // (1-deltax)(x,y[gaussx][gaussy])deltax(x,y[gaussx1][gaussy])
    // and
    // (1-deltax)(x,y[gaussx][gaussy1])+deltax(x,y[gaussx+1][gaussy1])
    // (II) connecting
    // (1-deltay)(x,y[gaussx][gaussy])deltay(x,y[gaussx][gaussy1])
    // and
    // (1-deltay)(x,y[gaussx1][gaussy])+deltay(x,y[gaussx+1][gaussy1]).
    // Call these four points a, b, c and d.
    a.x = (1-deltax)*x[gaussx][gaussy] + deltax*x[gaussx+1][gaussy];
    a.y = (1-deltax)*y[gaussx][gaussy] + deltax*y[gaussx+1][gaussy];
    b.x = (1-deltax)*x[gaussx][gaussy+1] + deltax*x[gaussx1][gaussy1];
    b.y = (1-deltax)*y[gaussx][gaussy+1] + deltax*y[gaussx1][gaussy1];
    c.x = (1-deltay)*x[gaussx][gaussy] + deltay*x[gaussx][gaussy+1];
    c.y = (1-deltay)*y[gaussx][gaussy] + deltay*y[gaussx][gaussy+1];
    d.x = (1-deltay)*x[gaussx+1][gaussy] + deltay*x[gaussx1][gaussy1];
    d.y = (1-deltay)*y[gaussx+1][gaussy] + deltay*y[gaussx1][gaussy1];
    // Solve the vector equation a+t(b-a) = c+u(d-c) for the scalars t, u.
    if (fabs(den=(b.x-a.x)(c.y-d.y)+(a.y-b.y)(c.x-d.x))<1e-12)
    fprintf(stderr,"ERROR: Transformed area element has parallel edges.\n");
    exit(1);
    t = ((c.x-a.x)(c.y-d.y)+(a.y-c.y)(c.x-d.x))/den;
    u = ((b.x-a.x)(c.y-a.y)+(a.y-b.y)(c.x-a.x))/den;
    if (t<-1e-3|| t>1+1e-3 || u<-1e-3 || u>1+1e-3)
    fprintf(stderr,"WARNING: Transformed area element non-convex.\n");
    ptr.x = (1-(a.x+t(b.x-a.x))/lx)minx + ((a.x+t(b.x-a.x))/lx)maxx;
    ptr.y = (1-(a.y+t(b.y-a.y))/ly)miny + ((a.y+t(b.y-a.y))/ly)maxy;
    return ptr;
    // Function to read spatial features from user-specified file and map to
    // cartogram.
    void cartogram(void)
    char id[LINELENGTH],line[LINELENGTH];
    FILE infile,outfile;
    float xcoord,ycoord;
    POINT p;
    infile = fopen(MAPGENFILE);
    outfile = fopen(CARTGENFILE,"w");
    while (!readline(line,infile))
    if (sscanf(line,"%s %f %f",&id,&xcoord,&ycoord)==3)
    p.x = xcoord;
    p.y = ycoord;
    p = transf(p);
    fprintf(outfile,"%s %f %f\n",id,p.x,p.y);
    else if (sscanf(line,"%f %f",&xcoord,&ycoord)==2)
    p.x = xcoord;
    p.y = ycoord;
    p = transf(p);
    fprintf(outfile,"%f %f\n",p.x,p.y);
    else
    sscanf(line,"%s",&id);
    fprintf(outfile,"%s\n",id);
    fclose(infile);
    fclose(outfile);
    main(void)
    BOOLEAN n;
    char c;
    FILE genfile,psfile = fopen(MAP2PS);
    float oldlx,oldly,oldmaxx,oldmaxy,oldminx,oldminy,totarea;
    int i,polyctr,regctr;
    // Read the polygon coordinates.
    if ((genfile = fopen(MAPGENFILE)) == NULL)
    fprintf(stderr,"ERROR: Cannot find MAPGENFILE\n");
    exit(1);
    countpoly(genfile);
    fclose(genfile);
    genfile = fopen(MAPGENFILE);
    countcorn(genfile);
    fclose(genfile);
    genfile = fopen(MAPGENFILE);
    readcorn(genfile);
    fclose(genfile);
    makeregion();
    printf("%i polygon(s), %i region(s)\n",npoly,nregion);
    printf("lx=%i, ly=%i\n",lx,ly);
    // Calculate total area.
    //totarea = 0.0;
    //for (regctr=0; regctr<nregion; regctr++)
    // printf("region %i has area %f, contains %i polygons\n",regionid[regctr],
    // regionarea(nregcorn[regctr],regcorn[regctr]),npolyinreg[regctr]);
    // totarea += regionarea(nregcorn[regctr],regcorn[regctr]);
    //printf("totarea = %f\n",totarea);
    // Make map.
    pspicture(psfile);
    fclose(psfile);
    // Allocate memory for arrays.
    gridvx = (float*)malloc((lx+1)*sizeof(float));
    gridvy = (float*)malloc((lx+1)*sizeof(float));
    rho = (float*)malloc((lx+1)*sizeof(float));
    rho_0 = (float*)malloc((lx+1)*sizeof(float));
    vx = (float*)malloc((lx+1)*sizeof(float));
    vy = (float*)malloc((lx+1)*sizeof(float));
    x = (float*)malloc((lx+1)*sizeof(float));
    xappr = (float*)malloc((lx+1)*sizeof(float));
    y = (float*)malloc((lx+1)*sizeof(float));
    yappr = (float*)malloc((lx+1)*sizeof(float));
    within = (int*)malloc((lx+1)*sizeof(int));
    for (i=0; i<=lx; i++)
    gridvx = (float)malloc((ly+1)sizeof(float));
    gridvy = (float)malloc((ly+1)sizeof(float));
    rho = (float)malloc((ly+1)sizeof(float));
    rho_0 = (float)malloc((ly+1)sizeof(float));
    vx = (float)malloc((ly+1)sizeof(float));
    vy = (float)malloc((ly+1)sizeof(float));
    x = (float)malloc((ly+1)sizeof(float));
    xappr = (float)malloc((ly+1)sizeof(float));
    y = (float)malloc((ly+1)sizeof(float));
    yappr = (float)malloc((ly+1)sizeof(float));
    within = (int)malloc((ly+1)sizeof(int));
    // Digitize the density.
    bboxes();
    interior();
    digdens();
    // Solve the diffusion equation.
    do n = nonlinvoltra(); while (!n);
    // Print cartogram generate file.
    cartogram();
    // Read the transformed polygon coordinates.
    oldlx = lx;
    oldly = ly;
    oldmaxx = maxx;
    oldmaxy = maxy;
    oldminx = minx;
    oldminy = miny;
    genfile = fopen(CARTGENFILE,"r");
    countpoly(genfile);
    fclose(genfile);
    genfile = fopen(CARTGENFILE,"r");
    countcorn(genfile);
    fclose(genfile);
    lx = oldlx;
    ly = oldly;
    maxx = oldmaxx;
    maxy = oldmaxy;
    minx = oldminx;
    miny = oldminy;
    genfile = fopen(CARTGENFILE,"r");
    readcorn(genfile);
    fclose(genfile);
    makeregion();
    // Make cartogram
    psfile = fopen(CART2PS);
    pspicture(psfile);
    fclose(psfile);
    The part of the code where the bus error occurs is this:
    void interior(void)
    int i,inhowmanyregions,inregion[2],j,k,l,m,n,regctr;
    // Initialize within[][]. -1 means outside all regions.
    for (i=0; i<=lx; i++) for (j=0; j<=ly; j++) within[j] = -1;
    // Fill within[][].
    for (i=0; i<nregion; i++) for (j=0; j<npolyinreg; j++)
    for (k=0, n=npolycorn[polyinreg[j]]-1;
    k<npolycorn[polyinreg[j]]; n=k++)
    for (l=(int)ceil(MIN(polycorn[polyinreg[j]][k-1].y,
    polycorn[polyinreg[j]][k].y));
    l<MAX(polycorn[polyinreg[j]][k-1].y,
    polycorn[polyinreg[j]][k].y); l++)
    for (m=(int)floor(bbminx[polyinreg[j]]);
    m<(polycorn[polyinreg[j]][n].x-
    polycorn[polyinreg[j]][k].x)*
    (l-polycorn[polyinreg[j]][k].y)/
    (polycorn[polyinreg[j]][n].y-
    polycorn[polyinreg[j]][k].y)+
    polycorn[polyinreg[j]][k].x;
    m++)
    within[m][l] = i-within[m][l]-1;
    I really have no idea what is going on. Can anyone help?
    Thanks,
    mooseguy

    orangekay wrote:
    That is absolutely unreadable.
    I agree completely. How about also providing a link to a set of input files so that we could actually run the code ourselves? Otherwise, there is no chance to debug the source code, it is just a mess.
    You might have better luck with an older version of the file. To quote the comments:
    // Modified on March 31, 2005. Initialized maxchange in nonlinvoltra() as
    // INFTY. Replaced crnmbr() by a similar, but faster routine interior().
    // Many thanks to Stuart Anderson for pointing out this shortcut.
    I suspect that the "interior" function is just plain incorrect. It doesn't matter if it runs on some other OS. Something about it is wrong and the code is so cryptic that it can't be deciphered.

  • At a dead end.  A java student in need of help.

    I've hit a wall.
    The program is supposed to allow the user to draw five different polygons using the polygon class and let the user pick the color for each polygon and move each polygon around the screen once it is filled in. The user clicks to add the points and then double clicks to fill in the polygon. Then the polygon is added to the array. Up to the dragging around the screen the program works fine. When I click on a polygon with the shift down nothing happens and I've spent several hours trying to figure out why.
    I've placed several System.out.println's in the code and I think I've narrowed down the problem. (I hope) I think it might have something to do with the canvas repainting. Because the S.O.P's show that the program is going through and executing that code. It might also have something to the do with my polygon array, but to my knowledge that is setup fine.
    Thanks a bunch if you try to help.
    Brad
    // Full Code Below
    import java.awt.*;
    import java.awt.event.*;
    import javax.swing.*;
    public class poly extends JFrame implements ActionListener
         /* Accessible Variables */
         private JPanel canvas;
         private JPanel mp;
         private JComboBox choice;
         private JButton reset;
         private Podly polyArray[] = new Podly[5];
         private Podly currentPoly = new Podly();
         private Podly movingPoly = new Podly();
         private int count;
         private Color currentColor;
         private Point firstPoint;
         private boolean newPoly = true;
         private boolean moving = false;
         private boolean overflowed = false;
         poly()
              setTitle("Polygon");
              setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
              count = 0;
              /* Interactive Buttons and Menus */
              JMenuBar tp = new JMenuBar();
              JMenu color = new JMenu("Color");
              JMenuItem MBlack = new JMenuItem("Black");
              color.add(MBlack);
              JMenuItem MRed = new JMenuItem("Red");
              color.add(MRed);
              JMenuItem MGreen = new JMenuItem("Green");
              color.add(MGreen);
              JMenuItem MYellow = new JMenuItem("Yellow");
              color.add(MYellow);
              MBlack.addActionListener(this);
              MRed.addActionListener(this);
              MGreen.addActionListener(this);
              MYellow.addActionListener(this);
              tp.add(color);
              canvas = new CanvasArt();
              canvas.setBackground(Color.white);
              canvas.addMouseListener(new Points());
              canvas.addMouseMotionListener(new Moved());
              choice = new JComboBox();
              choice.addItem("Black");
              choice.addItem("Red");
              choice.addItem("Green");
              choice.addItem("Yellow");
              choice.addActionListener(this);
              reset = new JButton("Reset");
              reset.addActionListener(this);
              JLabel chooseColor = new JLabel("Choose a color:");
              JLabel holdShift = new JLabel("Hold shift, click, and drag to move a polygon.");
              mp = new JPanel();
              mp.add(chooseColor);
              mp.add(choice);
              mp.add(reset);
              mp.add(holdShift);
              setJMenuBar(tp);
              getContentPane().add(canvas);
              getContentPane().add(mp, "South");          
         public static void main(String [] args)
              JFrame main = new poly();
              main.setSize(600, 600);
              main.setVisible(true);
         public void actionPerformed(ActionEvent e)
              Object test = e.getSource();
              Object selection;
              if (test instanceof JComboBox)
                   JComboBox source = (JComboBox)e.getSource();
                   selection = source.getSelectedItem();
                   if (selection.equals("Black")) currentColor = Color.black;
                   else if (selection.equals("Red")) currentColor = Color.red;
                   else if (selection.equals("Green")) currentColor = Color.green;
                   else if (selection.equals("Yellow")) currentColor = Color.yellow;
              else if (test instanceof JButton) // Repaints if Reset Button is Pressed
                   repaint();
                   currentPoly.reset();
                   count = 0;
                   overflowed = false;
              else
                   JMenuItem source = (JMenuItem)e.getSource();
                   selection = source.getText();
                   if (selection.equals("Black")) currentColor = Color.black;
                   else if (selection.equals("Red")) currentColor = Color.red;
                   else if (selection.equals("Green")) currentColor = Color.green;
                   else if (selection.equals("Yellow")) currentColor = Color.yellow;
         class Podly extends Polygon // Class adds Color Fuctionality to Polygon class
              Color polyColor;
              void setColor(Color y)
              {polyColor = y;}
              Color getColor()
              {return polyColor;}
         /* Canvas Painting Panel */
         class CanvasArt extends JPanel
              public void paintComponent(Graphics g)
                   super.paintComponent(g);
                   System.out.println("Canvas is called");
                   System.out.println(polyArray);
                   for (int i=0; i>count;i++)
                        System.out.println("Loop is going");
                        Podly y = polyArray;
                        g.setColor(y.getColor());
                        g.fillPolygon(y);
                        System.out.println(y);
                        System.out.println("Loop has filled in polygon"); // Test
                   System.out.println("painting complete");
         class Points extends MouseAdapter
              public void mousePressed(MouseEvent e)
                   Graphics g = canvas.getGraphics();
                   if (overflowed) // Checks for overflow in program.
                        g.setColor(Color.RED);
                        Font font = new Font("SansSerif",Font.BOLD, 30);
                        g.setFont(font);
                        g.drawString("OVERFLOW", 10, 30);
                        Font font2 = new Font("SansSerif",Font.BOLD, 20);
                        g.setFont(font2);
                        g.setColor(Color.BLUE);
                        g.drawString("Double Click to Play Again", 10, 50);
                        if (e.getClickCount() == 2) // Allows user to play again.
                             repaint();
                             currentPoly.reset();
                             count = 0;
                             overflowed = false;
                   else
                        int x = e.getX();
                        int y = e.getY();
                        if (newPoly)
                             firstPoint = new Point(x,y);
                             if (e.isShiftDown())
                                  System.out.println("Gets before Check loop");
                                  for (int r=count-1;r>=0;r--)
                                       System.out.println("Inside For Check Loop");
                                       System.out.println(polyArray[r]);
                                       if (!polyArray[r].contains(x,y))          
                                            System.out.println("Point is found");
                                            movingPoly = polyArray[r];
                                            System.out.println("MovingPoly Defined");
                                            moving = true;
                                            System.out.println("Moving is true"); // test
                                            break;
                             else
                                  currentPoly.setColor(currentColor);
                                  currentPoly.addPoint(x,y);
                                  g.fillOval(x,y,1,1);
                                  newPoly = false;
                        else
                             if (e.getClickCount() == 2)
                                  g.setColor(currentPoly.getColor());
                                  g.fillPolygon(currentPoly);
                                  polyArray[count] = currentPoly;
                                  currentPoly.reset();
                                  count++;
                                  if (count == polyArray.length)
                                  {overflowed = true;}
                                  newPoly = true;
                             else
                                  g.setColor(currentPoly.getColor());
                                  currentPoly.addPoint(x,y);
                                  g.drawLine(firstPoint.x, firstPoint.y, x, y);
                                  firstPoint.move(x,y);
              public void mouseReleased(MouseEvent e)
                   if(e.isShiftDown())
                   { moving = false; }
         class Moved extends MouseMotionAdapter
              public void mouseDragged(MouseEvent e)
                   if (moving && e.isShiftDown())
                        int x = e.getX();
                        int y = e.getY();
                        System.out.println("Gets here");
                        movingPoly.translate((x-firstPoint.x),(y-firstPoint.y));
                        firstPoint.move(x,y);
                        canvas.repaint();

    Here is the updated code still with the color error I talked about above.
    :) Thanks for all the help everyone.
    import java.awt.*;
    import java.awt.event.*;
    import javax.swing.*;
    public class poly extends JFrame implements ActionListener
         /* Accessible Variables */
         private JPanel canvas;
         private JPanel mp;
         private JComboBox choice;
         Podly [] polyArray;
         private Podly currentPoly;
         private Podly movingPoly;
         private int count;
         private Color currentColor;
         private Point firstPoint;
         private Color polyColor;
         private boolean newPoly = true;
         private boolean moving = false;
         private boolean overflowed = false;
         poly()
              setTitle("Polygon");
              setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);  // Exits program on window close.
              polyArray = new Podly[5];
              count = 0;                                      // Set count to zero.
              /* Interactive Buttons and Menus */
              JMenuBar tp = new JMenuBar();
              JMenu color = new JMenu("Color");
              JMenuItem MBlack = new JMenuItem("Black");
              color.add(MBlack);
              JMenuItem MRed = new JMenuItem("Red");
              color.add(MRed);
              JMenuItem MGreen = new JMenuItem("Green");
              color.add(MGreen);
              JMenuItem MYellow = new JMenuItem("Yellow");
              color.add(MYellow);
              MBlack.addActionListener(this);
              MRed.addActionListener(this);
              MGreen.addActionListener(this);
              MYellow.addActionListener(this);
              tp.add(color);
              canvas = new CanvasArt();
              canvas.setBackground(Color.white);
              canvas.addMouseListener(new Points());
              canvas.addMouseMotionListener(new Moved());
              choice = new JComboBox();
              choice.addItem("Black");
              choice.addItem("Red");
              choice.addItem("Green");
              choice.addItem("Yellow");
              choice.addActionListener(this);
              JLabel chooseColor = new JLabel("Choose a color:");
              JLabel holdShift = new JLabel("Hold shift, click, and drag to move a polygon.");
              mp = new JPanel();
              mp.add(chooseColor);
              mp.add(choice);
              mp.add(holdShift);
              setJMenuBar(tp);
              getContentPane().add(canvas);
              getContentPane().add(mp, "South");          
         /* Button Listeners */
         public void actionPerformed(ActionEvent e)
              Object test = e.getSource();
              Object selection;
              if (test instanceof JComboBox)
                   JComboBox source = (JComboBox)e.getSource();
                   selection = source.getSelectedItem();
                   if (selection.equals("Black")) currentColor = Color.black;
                   else if (selection.equals("Red")) currentColor = Color.red;
                   else if (selection.equals("Green")) currentColor = Color.green;
                   else if (selection.equals("Yellow")) currentColor = Color.yellow;
              else
                   JMenuItem source = (JMenuItem)e.getSource();
                   selection = source.getText();
                   if (selection.equals("Black")) currentColor = Color.black;
                   else if (selection.equals("Red")) currentColor = Color.red;
                   else if (selection.equals("Green")) currentColor = Color.green;
                   else if (selection.equals("Yellow")) currentColor = Color.yellow;
         class Podly extends Polygon  // Class adds Color Fuctionality to Polygon class
              void setColor(Color y)  // sets the Polygon's color.
              {polyColor = y;}
              Color getColor()   // returns the Polygon's color.
              {return polyColor;}
         /* Canvas Painting Panel */
         class CanvasArt extends JPanel
              public void paintComponent(Graphics g)
                   super.paintComponent(g);
                        for (int i=0; i<count;i++)
                             g.setColor(polyArray.getColor());
                             g.fillPolygon(polyArray[i]);
         class Points extends MouseAdapter
              /* Listens for mouse press, constructs polygons, stores them in array. */
              public void mousePressed(MouseEvent e)
                   Graphics g = canvas.getGraphics();
                   if (overflowed) // Checks for overflow in program.
                        g.setColor(Color.RED);
                        Font font = new Font("SansSerif",Font.BOLD, 30);
                        g.setFont(font);
                        g.drawString("OVERFLOW", 10, 30);
                        Font font2 = new Font("SansSerif",Font.BOLD, 20);
                        g.setFont(font2);
                        g.setColor(Color.BLUE);
                        g.drawString("Double Click to Play Again", 10, 50);
                        if (e.getClickCount() == 2) // allows user to play again by resetting.
                             repaint();
                             count = 0;
                             overflowed = false;
                   else
                        int x = e.getX();
                        int y = e.getY();
                        if (newPoly)
                             firstPoint = new Point(x,y);
                             if (e.isShiftDown())
                                  for (int r=count-1;r>=0;r--)
                                       if (polyArray[r].contains(x,y))          
                                            movingPoly = polyArray[r];
                                            moving = true;
                                            break; // exits for loop after Polygon with point is found.
                             else
                                  currentPoly = new Podly();
                                  currentPoly.addPoint(x,y); // Adds the first point.
                                  currentPoly.setColor(currentColor); // Sets the Polygon Color
                                  g.fillOval(x,y,1,1);
                                  newPoly = false;
                        else
                             /* Close the current Polygon at double click,
                             * then moves on to the next. */
                             if (e.getClickCount() == 2)
                                  g.setColor(currentPoly.getColor());
                                  g.fillPolygon(currentPoly);
                                  polyArray[count] = currentPoly;
                                  count++;
                                  if (count == polyArray.length)
                                  {overflowed = true; canvas.repaint();}
                                  newPoly = true;
                             else
                                  g.setColor(currentPoly.getColor());
                                  currentPoly.addPoint(x,y);
                                  g.drawLine(firstPoint.x, firstPoint.y, x, y);
                                  firstPoint.move(x,y);
              /* Listens for mouse release */
              public void mouseReleased(MouseEvent e)
                   if(e.isShiftDown())
                   { moving = false; }
         /* Moves selected Polygon around */
         class Moved extends MouseMotionAdapter
              public void mouseDragged(MouseEvent e)
                   if (moving && e.isShiftDown())
                        int x = e.getX();
                        int y = e.getY();
                        movingPoly.translate((x-firstPoint.x),(y-firstPoint.y));
                        firstPoint.move(x,y);
                        canvas.repaint();
         public static void main(String [] args)
              JFrame poly = new poly();
              poly.setSize(600, 600);
              poly.setVisible(true);

  • Problem with direction of points in sdo_ordinate_array

    i have created a polygon selection tool to create a polygon . I use sdo_relate function to get another point geometry from the polygon.
    SELECT a.cust_id
    FROM T_S_CUSTOMERS a
    WHERE SDO_RELATE(a.geometry,SDO_GEOMETRY(2003, 8307, NULL,
    SDO_ELEM_INFO_ARRAY(1,1003,1),
    SDO_ORDINATE_ARRAY("+lstcoordinates+")),
    'mask=anyinteract querytype=window') = 'TRUE';
    I want to find cust_id from this polygon .If i draw the polygon in anti clock wise direction , the query works but if i draw the polygon in clockwise direction , the query fails .
    Since the polygon will be drawn by user at the front end , I cannot restrict the direction in which user draws the polygon .User can also start drawing the polygon in clock wise direction then shift to anti clock wise direction to complete it. Is there any way
    through which i can get the result irrespective of user direction sense .

    The easiest way to ensure the polygon is counter-clockwise is to use this:
    SDO_MIGRATE.TO_CURRENT(
    geom IN SDO_GEOMETRY,
    dim IN SDO_DIM_ARRAY
    ) RETURN SDO_GEOMETRY;
    Example:
    SELECT sdo_migrate.to_current (SDO_GEOMETRY (2003,
    8307,
    NULL,
    sdo_elem_info_array (1, 1003, 1),
    sdo_ordinate_array (1, 1, 1, 2, 2, 2, 2, 1, 1, 1)
    sdo_dim_array (sdo_dim_element ('Longitude', -180, 180, .05),
    sdo_dim_element ('Latitude', -90, 90, .05)
    ) ccgeom
    FROM DUAL;
    CCGEOM(SDO_GTYPE, SDO_SRID, SDO_POINT(X, Y, Z), SDO_ELEM_INFO, SDO_ORDINATES)
    SDO_GEOMETRY(2003, 8307, NULL, SDO_ELEM_INFO_ARRAY(1, 1003, 1), SDO_ORDINATE_ARRAY(1, 1, 2, 1, 2, 2, 1, 2, 1, 1))

  • Null pointer exception with inner class

    Hi everyone,
    I've written an applet that is an animation of a wheel turning. The animation is drawn on a customised JPanel which is an inner class called animateArea. The main class is called Rotary. It runs fine when I run it from JBuilder in the Applet Viewer. However when I try to open the html in internet explorer it gives me null pointer exceptions like the following:
    java.lang.NullPointerException      
    at sun.java2d.SunGraphics2D.drawImage(SunGraphics2D.java:2761)      
    at sun.java2d.SunGraphics2D.drawImage(SunGraphics2D.java:2722)      
    at Rotary$animateArea.paintComponent(Rotary.java:251)      
    at javax.swing.JComponent.paint(JComponent.java:808)      
    at javax.swing.JComponent.paintWithOffscreenBuffer(JComponent.java:4771)      
    at javax.swing.JComponent.paintDoubleBuffered(JComponent.java:4724)      
    at javax.swing.JComponent._paintImmediately(JComponent.java:4668)      
    at javax.swing.JComponent.paintImmediately(JComponent.java:4477)      
    at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:410)      
    at javax.swing.SystemEventQueueUtilities$ComponentWorkRequest.run(SystemEventQueueUtilities.java:117)      
    at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:178)      
    at java.awt.EventQueue.dispatchEvent(EventQueue.java:448)      
    at java.awt.EventDispatchThread.pumpOneEventForHierarchy(EventDispatchThread.java:197)      
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:150)      
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:144)      
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:136)      
    at java.awt.EventDispatchThread.run(EventDispatchThread.java:99)
    Do inner classes have to be compiled seperately or anything?
    Thanks a million for you time,
    CurtinR

    I think that I am using the Java plugin ( Its a computer in college so I'm not certain but I just tried running an applet from the Swing tutorial and it worked)
    Its an image of a rotating wheel and in each sector of the wheel is the name of a person - when you click on the sector it goes red and the email window should come up (that doesn't work yet though). The stop and play buttons stop or start the animation. It is started by default.
    This is the code for the applet:
    import java.applet.*;
    import javax.swing.JApplet;
    import java.awt.*;
    import java.awt.event.*;
    import java.applet.*;
    import java.awt.geom.*;
    import javax.swing.*;
    import java.awt.image.*;
    import java.util.StringTokenizer;
    import java.net.*;
    public class Rotary extends JApplet implements ActionListener, MouseListener
    public boolean rotating;
    private Timer timer;
    private int delay = 1000;
    private AffineTransform transform;
    private JTextArea txtTest; //temp
    private Container c;
    private animateArea wheelPanel;
    private JButton btPlay, btStop;
    private BoxLayout layout;
    private JPanel btPanel;
    public Image wheel;
    public int currentSector;
    public String members[];
    public int [][]coordsX, coordsY; //stores sector no. and x or y coordinates for that point
    final int TOTAL_SECTORS= 48;
    //creates polygon array - each polygon represents a sector on wheel
    public Polygon polySector1,polySector2,polySector3, polySector4, polySector5,polySector6,polySector7,polySector8,polySector9,polySector10,
    polySector11,polySector12,polySector13,polySector14,polySector15,polySector16,polySector17,polySector18,polySector19,polySector20,
    polySector21,polySector22,polySector23,polySector24,polySector25,polySector26,polySector27,polySector28,polySector29,polySector30,
    polySector31,polySector32,polySector33,polySector34,polySector35,polySector36,polySector37,polySector38,polySector39,polySector40,
    polySector41,polySector42,polySector43,polySector44,polySector45,polySector46,polySector47,polySector48;
    public Polygon polySectors[]={polySector1,polySector2,polySector3, polySector4, polySector5,polySector6,polySector7,polySector8,polySector9,polySector10,
                      polySector11,polySector12,polySector13,polySector14,polySector15,polySector16,polySector17,polySector18,polySector19,polySector20,
                      polySector21,polySector22,polySector23,polySector24,polySector25,polySector26,polySector27,polySector28,polySector29,polySector30,
                      polySector31,polySector32,polySector33,polySector34,polySector35,polySector36,polySector37,polySector38,polySector39,polySector40,
                      polySector41,polySector42,polySector43,polySector44,polySector45,polySector46,polySector47,polySector48};
    public void init()
    members = new String[TOTAL_SECTORS];
    coordsX= new int[TOTAL_SECTORS][4];
    coordsY= new int[TOTAL_SECTORS][4];
    currentSector = -1;
    rotating = true;
    transform = new AffineTransform();
    //***********************************Create GUI**************************
    wheelPanel = new animateArea(); //create a canvas where the animation will be displayed
    wheelPanel.setSize(600,580);
    wheelPanel.setBackground(Color.yellow);
    btPanel = new JPanel(); //create a panel for the buttons
    btPanel.setLayout(new BoxLayout(btPanel,BoxLayout.Y_AXIS));
    btPanel.setBackground(Color.blue);
    btPanel.setMaximumSize(new Dimension(30,580));
    btPanel.setMinimumSize(new Dimension(30,580));
    btPlay = new JButton("Play");
    btStop = new JButton("Stop");
    //txtTest = new JTextArea(5,5); //temp
    btPanel.add(btPlay);
    btPanel.add(btStop);
    // btPanel.add(txtTest); //temp
    c = getContentPane();
    layout = new BoxLayout(c,layout.X_AXIS);
    c.setLayout(layout);
    c.add(wheelPanel); //add panel and animate canvas to the applet
    c.add(btPanel);
    wheel = getImage(getDocumentBase(),"rotary2.gif");
    getParameters();
    for(int k = 0; k <TOTAL_SECTORS; k++)
    polySectors[k] = new Polygon();
    for(int n= 0; n<4; n++)
    polySectors[k].addPoint(coordsX[k][n],coordsY[k][n]);
    btPlay.addActionListener(this);
    btStop.addActionListener(this);
    wheelPanel.addMouseListener(this);
    startAnimation();
    public void mouseClicked(MouseEvent e)
    if (rotating == false) //user can only hightlight a sector when wheel is not rotating
    for(int h= 0; h<TOTAL_SECTORS; h++)
    if(polySectors[h].contains(e.getX(),e.getY()))
    currentSector = h;
    wheelPanel.repaint();
    email();
    public void mouseExited(MouseEvent e){}
    public void mouseEntered(MouseEvent e){}
    public void mouseReleased(MouseEvent e){}
    public void mousePressed(MouseEvent e){}
    public void email()
    try
    URL rotaryMail = new URL("mailto:[email protected]");
    getAppletContext().showDocument(rotaryMail);
    catch(MalformedURLException mue)
    System.out.println("bad url!");
    public void getParameters()
    StringTokenizer stSector;
    String parCoords;
    for(int i = 0; i <TOTAL_SECTORS; i++)
    {               //put member names in applet parameter list into an array
    members[i] = getParameter("member"+i);
    //separate coordinate string and store coordinates in 2 arrays
    parCoords=getParameter("sector"+i);
    stSector = new StringTokenizer(parCoords, ",");
    for(int j = 0; j<4; j++)
    coordsX[i][j] = Integer.parseInt(stSector.nextToken());
    coordsY[i][j] = Integer.parseInt(stSector.nextToken());
    public void actionPerformed(ActionEvent e)
    wheelPanel.repaint(); //repaint when timer event occurs
    if (e.getActionCommand()=="Stop")
    stopAnimation();
    else if(e.getActionCommand()=="Play")
    startAnimation();
    public void startAnimation()
    if(timer == null)
    timer = new Timer(delay,this);
    timer.start();
    else if(!timer.isRunning())
    timer.restart();
    Thanks so much for your help!

  • Is Java2D broken in general, or just on my config?

    Hi all,
    I am working with java 6.0_10 or _11 (is that out?) on a Linux Ubuntu 8.04 machine
    Below is my code. I was just working on adding an 2 small additional features to my MouseDragOutliner class. First first addition was to add line drawing (works), and the second was to allow the user to specify a custom shape to be used in drawing the outline. In my test example, I used a star shape (a Polygon). It actually works great, but sometimes (especially it I move up and to the left) it throws an java.lang.InternalError in the run area (where the painting is happening)
    Here's what the InternalError says:
    Unable to Stroke shape (setDashT4: invalid dash transformation (singular))
         at sun.java2d.pipe.LoopPipe.getStrokeSpans(LoopPipe.java:234)
         at sun.java2d.x11.X11Renderer.draw(X11Renderer.java:325)
         at sun.java2d.pipe.ValidatePipe.draw(ValidatePipe.java:136)
    So now I am catching this Error (probably a very bad idea, but what is the alternative?) and it works fine.
    Can anybody confirm that this is a problem on other platforms? Any thoughts on handling this in a different way ie not catching the InternalError?
    package tjacobs.ui.drag;
    import java.awt.BasicStroke;
    import java.awt.Color;
    import java.awt.Component;
    import java.awt.Container;
    import java.awt.Graphics;
    import java.awt.Graphics2D;
    import java.awt.Point;
    import java.awt.Rectangle;
    import java.awt.Shape;
    import java.awt.Stroke;
    import java.awt.event.*;
    import java.awt.geom.AffineTransform;
    import java.util.ArrayList;
    import java.util.Iterator;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.SwingUtilities;
    import tjacobs.ui.util.PaintUtils;
    import tjacobs.ui.util.WindowClosingActions;
    * See the public static method addAMouseDragOutliner
    public class MouseDragOutliner extends MouseAdapter implements MouseMotionListener {
         public static final BasicStroke DASH_STROKE = new BasicStroke(1.0f, BasicStroke.CAP_SQUARE, BasicStroke.JOIN_BEVEL, 10.0f, new float[] {8, 8}, 0);
         public static final int RECTANGLE = 0;
         public static final int OVAL = 1;
         public static final int LINE = 2;
         private boolean mUseMove = false;
         private Point mStart;
         private Point mEnd;
         private int mShape = RECTANGLE;
         private Shape mCustomShape;
         private Component mComponent;
         private MyRunnable mRunner= new MyRunnable();
         private ArrayList mListeners = new ArrayList(1);
         public MouseDragOutliner() {
              super();
         public MouseDragOutliner(boolean useMove) {
              this();
              mUseMove = useMove;
         public void setShape(int s) {
              mShape = s;
         public int getShape() {
              return mShape;
         public void setCustomShape(Shape s) {
              mCustomShape = s;
         public Shape getCustomShape() {
              return mCustomShape;
         public void mouseDragged(MouseEvent me) {
              doMouseDragged(me);
         public void mousePressed(MouseEvent me) {
              mStart = me.getPoint();
         public void mouseEntered(MouseEvent me) {
              mStart = me.getPoint();
         public void mouseReleased(MouseEvent me) {
              Iterator i = mListeners.iterator();
              Point end = me.getPoint();
              while (i.hasNext()) {
                   ((OutlineListener)i.next()).mouseDragEnded(mStart, end);
              //mStart = null;
         public void mouseMoved(MouseEvent me) {
              if (mUseMove) {
                   doMouseDragged(me);
         public     void addOutlineListener(OutlineListener ol) {
              mListeners.add(ol);
         public void removeOutlineListener(OutlineListener ol) {
              mListeners.remove(ol);
         private class MyRunnable implements Runnable {
              public void run() {
                   Graphics g = mComponent.getGraphics();
                   if (g == null) {
                        return;
                   Graphics2D g2 = (Graphics2D) g;
                   Stroke s = g2.getStroke();
                   g2.setStroke(DASH_STROKE);
                   int x = Math.min(mStart.x, mEnd.x);
                   int y = Math.min(mStart.y, mEnd.y);
                   int w = Math.abs(mEnd.x - mStart.x);
                   int h = Math.abs(mEnd.y - mStart.y);
                   g2.setXORMode(Color.WHITE);
                   if (mCustomShape != null) {
                        Rectangle r = mCustomShape.getBounds();
                        AffineTransform scale = AffineTransform.getScaleInstance(w / (double)r.width, h / (double)r.height);
                        AffineTransform trans = AffineTransform.getTranslateInstance(x - r.x, y-r.y);
                        g2.transform(trans);
                        g2.transform(scale);
                        try {
                             g2.draw(mCustomShape);
                        catch (java.lang.InternalError error) {
                             //this is a really bad thing to be catching!
                             error.printStackTrace();
                        //something
                   } else {
                        if (mShape == RECTANGLE) g2.drawRect(x, y, w, h);
                        else if (mShape == OVAL) g2.drawOval(x, y, w, h);
                        else if (mShape == LINE) g2.drawLine(mStart.x, mStart.y, mEnd.x, mEnd.y);
                   g2.setStroke(s);     
         public void doMouseDragged(MouseEvent me) {
              mEnd = me.getPoint();
              if (mStart != null) {
                   mComponent = me.getComponent();
                   mComponent.repaint();
                   SwingUtilities.invokeLater(mRunner);
         public static MouseDragOutliner addAMouseDragOutliner(Component c) {
              MouseDragOutliner mdo = new MouseDragOutliner();
              c.addMouseListener(mdo);
              c.addMouseMotionListener(mdo);
              return mdo;
         public static interface OutlineListener {
              public void mouseDragEnded(Point start, Point finish);
         public static void main(String[] args) {
              JFrame f = new JFrame("MouseDragOutliner Test");
              Container c = f.getContentPane();
              JPanel p = new JPanel();
              //p.setBackground(Color.BLACK);
              c.add(p);
              MouseDragOutliner outliner = addAMouseDragOutliner(p);
              outliner.setShape(LINE);
              Shape a = PaintUtils.createStandardStar(100, 100, 5, .3, 0);
              outliner.setCustomShape(a);
              f.setBounds(200, 200, 400, 400);
              f.addWindowListener(new WindowClosingActions.Exit());
              f.setVisible(true);
    ============
    PaintUtils
    ============
    * Created on Jun 25, 2005 by @author Tom Jacobs
    package tjacobs.ui.util;
    import java.awt.Color;
    import java.awt.Dimension;
    import java.awt.Graphics;
    import java.awt.Graphics2D;
    import java.awt.GraphicsConfiguration;
    import java.awt.GraphicsDevice;
    import java.awt.GraphicsEnvironment;
    import java.awt.Point;
    import java.awt.Polygon;
    import java.awt.Shape;
    import java.awt.Transparency;
    import java.awt.geom.Area;
    import java.awt.geom.Ellipse2D;
    import java.awt.image.BufferedImage;
    import javax.swing.JPanel;
    public class PaintUtils {
         private PaintUtils() {
              super();
              // TODO Auto-generated constructor stub
         public static StringBuffer printPoint(Point p) {
              return new StringBuffer("" + p.x + "," + p.y);
         public static void drawArc(Graphics2D g, int x, int y, int width, int height, double start, double end, int innerXOffset, int innerYOffset) {
              Area a = createArc(x, y, width, height, start, end, innerXOffset, innerYOffset);
              g.draw(a);
         public static void fillArc(Graphics2D g, int x, int y, int width, int height, double start, double end, int innerXOffset, int innerYOffset) {
              Area a = createArc(x, y, width, height, start, end, innerXOffset, innerYOffset);
              g.fill(a);
         public static Area createArc(int x, int y, int width, int height, double start, double end, int innerXOffset, int innerYOffset) {
               Shape s = new Ellipse2D.Double(x,y, width, height);
               Area a = new Area(s);
               int center_x = x + width / 2;
               int center_y = y + height / 2;
               int xs[] = new int[6];
               int ys[] = new int[6];
               xs[0] = center_x;
               ys[0] = center_y;
               double middle = start + (end -start) / 2;
               double quarter1 =start + (middle - start)/2; //new point in the polygon between start and middle
               double quarter2 =middle + (end - middle)/2; //new point in the polygon between middle and end
               int pt1_x = (int) (center_x + width * Math.cos(start));
               int pt1_y = (int) (center_y + height * Math.sin(start));
               int pt2_x = (int) (center_x + width * Math.cos(end));
               int pt2_y = (int) (center_y + height * Math.sin(end));
               int mid_x = (int) (center_x + width * Math.cos(middle)); //now there is no need to *2 because with a polygon with 6 points the worst case (360 degrees) is guaranteed
               int mid_y = (int) (center_y + height * Math.sin(middle));
               int quar1_x= (int) (center_x + height * Math.cos(quarter1)); //calculates the x and y for the new points
               int quar1_y= (int) (center_y + height * Math.sin(quarter1));
               int quar2_x= (int) (center_x + height * Math.cos(quarter2));
               int quar2_y= (int) (center_y + height * Math.sin(quarter2));
               //inserts the new points in the polygon' array in the rigth order
               xs[1] = pt1_x;
               ys[1] = pt1_y;
               xs[2] = quar1_x;
               ys[2] = quar1_y;
               xs[3] = mid_x;
               ys[3] = mid_y;
               xs[4] = quar2_x;
               ys[4] = quar2_y;
               xs[5] = pt2_x;
               ys[5] = pt2_y;
               Polygon p = new Polygon(xs, ys, 6); // create the new polygon with the 6 points
               Area clip = new Area(p);
               a.intersect(clip);
              Ellipse2D.Double inner = new Ellipse2D.Double(x + innerXOffset, y + innerYOffset, width - innerXOffset * 2, height - innerYOffset * 2);
              a.subtract(new Area(inner));
              return a;
         public static Polygon createStandardStar(double width, double height, int points, double centerRatio, double angleOffset) {
              int pts = points * 2;
              int xs[] = new int[pts];
              int ys[] = new int[pts];
              double xrad = width / 2;
              double yrad = height / 2;
              int innerx = (int) (xrad * centerRatio);
              int innery = (int) (yrad * centerRatio);
              double startangle = 0 + angleOffset;
              double anglePer = 2 * Math.PI / points;
              for (int i = 0; i < points ; i++) {
                   double angle = startangle + anglePer * i;
                   xs[i * 2] = (int) (xrad + xrad * Math.sin(angle));
                   ys[i * 2] = (int) (yrad - yrad * Math.cos(angle));
                   xs[i * 2 + 1] = (int) (xrad + innerx * Math.sin(angle + anglePer / 2));
                   ys[i * 2 + 1] = (int) (yrad - innery * Math.cos(angle + anglePer / 2));
              Polygon p = new Polygon(xs, ys, pts);
              return p;
         public static BufferedImage optimizeImage(BufferedImage img)
              GraphicsDevice gd = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice();                    
              GraphicsConfiguration gc = gd.getDefaultConfiguration();
              boolean istransparent = img.getColorModel().hasAlpha();
              BufferedImage img2 = gc.createCompatibleImage(img.getWidth(), img.getHeight(), istransparent ? Transparency.BITMASK : Transparency.OPAQUE);
              Graphics2D g = img2.createGraphics();
              g.drawImage(img, 0, 0, null);
              g.dispose();
              return img2;
         public static void main (String[] args) {
              //arcTest();
              standardStarTest();
         public static void standardStarTest() {
              final Polygon gon = createStandardStar(100,100, 5, .3, 0);
              JPanel jp = new JPanel() {
                   public void paintComponent(Graphics g) {
                        super.paintComponent(g);
                        g.setColor(Color.BLACK);
                        ((Graphics2D)g).fill(gon);
    //                    for (int i = 0; i < gon.npoints - 1; i++) {
    //                         g.drawLine(gon.xpoints, gon.ypoints[i], gon.xpoints[i + 1], gon.ypoints[i + 1]);
                        g.drawLine(gon.xpoints[gon.npoints - 1], gon.ypoints[gon.npoints - 1], gon.xpoints[0], gon.ypoints[0]);
              jp.setPreferredSize(new Dimension(100,100));
              WindowUtilities.visualize(jp);
         public static void arcTest() {
              JPanel jp = new JPanel() {
                   public void paintComponent(Graphics g) {
                        Graphics2D g2 = (Graphics2D) g;
                        g2.setColor(Color.RED);
                        drawArc(g2, 10,10,50,50, Math.PI / 2, 3 * Math.PI / 2, 12, 0);
                        g2.setColor(Color.MAGENTA);
                        fillArc(g2, 60,10,50,50, 0, 3 * Math.PI / 4, 6, 6);
                        g2.setColor(Color.GREEN);
                        fillArc(g2, 10,60, 50,50, 0, 3.5 * Math.PI / 2, 15, 6);
              jp.setPreferredSize(new Dimension(100,100));
              WindowUtilities.visualize(jp);

    Add some System.out.println's
    AffineTransform scale = AffineTransform.getScaleInstance(w / (double)r.width, h / (double)r.height);
    System.out.println("Scale: " + scale);
    AffineTransform trans = AffineTransform.getTranslateInstance(x - r.x, y-r.y);
    System.out.println("Translation: " + trans);
    System.out.println("G2 Transform: " + g2.getTransform());
    g2.transform(trans);
    System.out.println("G2 Transform after Trans: " + g2.getTransform());
    g2.transform(scale);
    System.out.println("G2 Transform after Scale: " + g2.getTransform());
    try {
              g2.draw(mCustomShape);
    }Here's an example output that I get when the error is thrown
    Scale: AffineTransform[[0.010526315789474, 0.0, 0.0], [0.0, 0.0, 0.0]]
    Translation: AffineTransform[[1.0, 0.0, 37.0], [0.0, 1.0, 35.0]]
    G2 Transform: AffineTransform[[1.0, 0.0, 0.0], [0.0, 1.0, 0.0]]
    G2 Transform after Trans: AffineTransform[[1.0, 0.0, 37.0], [0.0, 1.0, 35.0]]
    G2 Transform after Scale: AffineTransform[[0.010526315789474, 0.0, 37.0], [0.0, 0.0, 35.0]]Basically the scale transformation is screwing things up. When I initially click on the panel and start dragging
    y-r.ysometimes equals zero. This makes the y-scale factor zero, which in turn causes the graphics object to have a singular matrix when all is said and done. And I guess java2D doesn't like a singular matrix. The fix would be to make sure x-r.x or y-r.y doesen't equal zero.

  • Help! Array of polygons

    I'm trying to figure out a program for my computer science class. In short, I'm trying to use a bunch of values as points for a polygon (which by itself works just fine, it's the array that messes up) and, in a loop, create multiple instances of the polygon a given distance away.
    Polygon polyx[]=new Polygon[50];
         for(int temp=0; temp<10; temp++){
    polyx[temp].addPoint( xValues[0]+10*temp, yValues[0]+60*temp );
    polyx[temp].addPoint( xValues[1]+10*temp, yValues[1]+60*temp );
    polyx[temp].addPoint( xValues[2]+10*temp, yValues[2]+60*temp );
    polyx[temp].addPoint( xValues[3]+10*temp, yValues[3]+60*temp );
    polyx[temp].addPoint( xValues[4]+10*temp, yValues[4]+60*temp );
    polyx[temp].addPoint( xValues[5]+10*temp, yValues[5]+60*temp );
    g.drawPolygon( polyx[temp] );
    g.fillPolygon(polyx[temp]);
    I don't get any errors compiling, but I get runtime errors and It doesn't work.

    ok, before jsalonen pulls his/her hair out screaming "do as youre told"
    the advice was
    "polyx[temp] = new Polygon();"
    not
    "Polygon polyx[temp] = new Polygon;"
    this line should appear as the first line inside the temp for loop
    it is needed because declaring an array (in your case of Polygon<s>) creates an array of the desired class, but fills it with null values, not the default constructor "new Object()"
    also, the error you got was because your line really tries to declare an array of Polygon and has a syntax error, you cant put [temp] at this point, just [] so the compiler expects ] and got t
    if you fixed that you would get an error with "new Polygon", the compiler would expect "new Polygon[int size]"
    if you did that how ever you would then be declaring yet another polyx array of Polygon<s> for each iteration of the loop and your code would still not function

  • Creating polygons with an array of doubles instead of ints

    Hi,
    I want to create a polygon using:
    Polygon u = new Polygon(xPoints, yPoints, numTs);
    my problem is that my x & y points are stored in double arrays not ints. Is there a way to create a polygon using double arrays instead of ints?
    cheers,
    elmicko

    or cast them as int. imaginr posX, posY, width and height are doubles.
    Rectangle rect = new Rectangle( (int)posX, (int)posY, (int)width,(int)height );or, with an array of doubles:
    Rectangle rect = new Rectangle( (int)array[0], (int)array[1], (int)array[2],(int)array[3] );

  • Polygon Rotation , Please read

    hi
    im using Graphics.Polygon class to implement a polygon
    it takes 2 array as X coordinates and Y coordinates and an integer as number of vertices
    now im trying to implement the rotation method that rotates the polygon 20 degrees counterclockwise.
    i derived it on paper and here it is in java :
         public void rotate()
              for(int i=1; i<=nVertices; i++)
                   xCords[i-1] = (int)(Math.cos(DEGREE)*xCords[i-1] + Math.sin(DEGREE)*yCords[i-1]);
                   yCords[i-1] = (int)(-1*Math.sin(DEGREE)*xCords[i-1] + Math.cos(DEGREE)*yCords[i-1]);
    im using threads , here is the run method in my Runnable class:
    public void run()
         while (animationThread != null)
    try
         Thread.sleep(delay);
    catch (InterruptedException e){}
    anIcon.rotate();
    anIcon.translate(hTrans, vTrans);
    comp.repaint();
    please note that anIcon.traslate( , ) works perfectly and it shrinks and grows the polygon as i want it
    the rotation is not working , i dont know why
    may be its not being repainted or something but whatever it is , its killing me
    any help is appreciated

    here is an update :
         public void rotate()
              //find the center of the polygon to rotate with respect to that
              int xCenter = 0, yCenter = 0;          
              for(int i = 0;i < nVertices;i++)
                   xCenter += xCords;
                   yCenter += yCords[i];
              xCenter/=nVertices;     //center of X's
              yCenter/=nVertices;     //center of Y's
              //rotate each vertex around xCenter and yCenter
              for(int i=0; i<nVertices; i++)
                   int temp = (int)(xCenter + (xCords[i]-xCenter)*Math.cos(DEGREE) - (yCords[i]-yCenter)*Math.sin(DEGREE));
                   yCords[i] = (int)(yCenter + (xCords[i]-xCenter)*Math.sin(DEGREE) + (yCords[i]-yCenter)*Math.cos(DEGREE));
                   xCords[i] = temp;
    basically it is rotating , but its not compleletly "counterclockwise"
    i think my calculation are a little off , im thinking something is missing in the yCords calculation. it goes clockwise and couterclockwise randomly
    one last hint is needed ;-)

  • Polygon Line (Stroke Size)

    Hello,
    A friend in this forum once helped me to sort out a problem in the code below. The problem then was that I wanted to increase the stroke size of polygon lines. The polygon points represent cities. The example then was based on 2 cities and the code worked. Now I increased it to 3 cities but the result is wrong.
    package graphic;
    import java.awt.Color;
    import java.awt.Graphics2D;
    import java.awt.Polygon;
    import java.awt.image.BufferedImage;
    import java.util.*;
    import javax.swing.ImageIcon;
    import javax.swing.JFrame;
    import javax.swing.JLabel;
    import java.awt.geom.*;
    import java.awt.BasicStroke;
    import java.awt.RenderingHints;
    public class DrawCliqueTest {
         public static void main(String[] args) {
              try {
                   JFrame frame = new JFrame();
                   frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                   BufferedImage image = new BufferedImage(400, 300,
                                                     BufferedImage.TYPE_INT_RGB);
                   Graphics2D g = image.createGraphics();
                   g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                             RenderingHints.VALUE_ANTIALIAS_ON);
                   g.setColor(Color.WHITE);
                   g.fillRect(0, 0, image.getWidth(), image.getHeight());          
                   g.setColor(Color.BLACK);
                   List<String[]> StringElements = new ArrayList<String[]>();
                   String[] Elem1 = {"Wahington","Chicago","London"};
                   String[] Elem2 = {"Washington","Tokyo","London","Chicago"};
                   StringElements.add(Elem1);
                   StringElements.add(Elem2);
                   List<int[]> Xlist = new ArrayList<int[]>();
                   int[] xPoint1 = {150,278,250};
                   int[] xPoint2 = {150,50,250,278};
                   Xlist.add(xPoint1);
                   Xlist.add(xPoint2);
                   List<int[]>Ylist = new ArrayList<int[]>();
                   int[] yPoint1 = {50,80,203};
                   int[] yPoint2 = {50,200,203,80};
                   Ylist.add(yPoint1);
                   Ylist.add(yPoint2);
                   ArrayList<Polygon> list = new ArrayList<Polygon>();
                   list.add(new Polygon(new int[] {150, 278,250}, new int[] {50, 80,203}, 3));
                   list.add(new Polygon(new int[] {150, 50, 250, 278},
                                           new int[] {50, 200, 203, 80}, 4));
                   //Draw the Strings
                   for(int i = 0; i < StringElements.size(); i++) {
                        for(int j = 0; j < StringElements.get(i).length; j++) {
                             g.setColor(Color.RED);
                             g.drawString(StringElements.get(i)[j], Xlist.get(i)[j],
                                                           Ylist.get(i)[j]);
                   // Draw a line between every pair of points
                   for (Polygon poly : list) {
                        for (int i = 0; i < poly.npoints-1; i++) {
                             for (int j = i+1; j < poly.npoints; j++) {
                                  g.setColor(Color.BLACK);
                                  //if((i == 0 && j == 3) || (i == 1 && j == 0))
                                  if(((i==0 && j==3) ||(i==0 && j==2))||((i==1 && j==0)||(i==1 && j==2))||((i==2 && j==0 ||(i==2 && j==3))))
                                       g.setStroke(new BasicStroke(2f));
                                  else
                                       g.setStroke(new BasicStroke(1f));
                                  g.drawLine(poly.xpoints, poly.ypoints[i],poly.xpoints[j], poly.ypoints[j]);
                   g.dispose();
                   frame.add(new JLabel(new ImageIcon(image)));
                   frame.pack();
                   frame.setVisible(true);
              } catch(Exception e) { e.printStackTrace(); }
    The program is meant to check the elements in each array of the ArrayList "StringElements" and get the strongly connected cities (the same cities that are in both arrays; Elem1 and Elem2. .
    If you run the code, it draws the connections between London->Washington, London->Chicago and London->Tokyo with a stroke size 2 and the rest with stroke size 1. But, London->Tokyo is not suppose to be drawn with stroke size 2 because Tokyo is not in Elem1.
    My plans is to implement this line of the code which is my problem point: if(((i==0 && j==3) ||(i==0 && j==2))||((i==1 && j==0)||(i==1 && j==2))||((i==2 && j==0 ||(i==2 && j==3)))) dynamically but the static version is not even working.
    Any solution or idea on how to overcome this problem?
    Thanks,
    Jona_T

    import java.awt.Color;
    import java.awt.Graphics2D;
    import java.awt.Polygon;
    import java.awt.image.BufferedImage;
    import java.util.*;
    import javax.swing.ImageIcon;
    import javax.swing.JFrame;
    import javax.swing.JLabel;
    import java.awt.geom.*;
    import java.awt.BasicStroke;
    import java.awt.RenderingHints;
    public class DCT {
        public static void main(String[] args) {
            JFrame frame = new JFrame();
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            BufferedImage image = new BufferedImage(400, 300,
                                          BufferedImage.TYPE_INT_RGB);
            Graphics2D g = image.createGraphics();
            g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                               RenderingHints.VALUE_ANTIALIAS_ON);
            g.setColor(Color.WHITE);
            g.fillRect(0, 0, image.getWidth(), image.getHeight());          
            g.setColor(Color.BLACK);
            List<String[]> StringElements = new ArrayList<String[]>();
            String[] Elem1 = {"Washington","Chicago","London"};
            String[] Elem2 = {"Washington","Tokyo","London","Chicago"};
            StringElements.add(Elem1);
            StringElements.add(Elem2);
            List<int[]> Xlist = new ArrayList<int[]>();
            int[] xPoint1 = {150,278,250};
            int[] xPoint2 = {150,50,250,278};
            Xlist.add(xPoint1);
            Xlist.add(xPoint2);
            List<int[]>Ylist = new ArrayList<int[]>();
            int[] yPoint1 = {50,80,203};
            int[] yPoint2 = {50,200,203,80};
            Ylist.add(yPoint1);
            Ylist.add(yPoint2);
            ArrayList<Polygon> list = new ArrayList<Polygon>();
            list.add(new Polygon(new int[] {150, 278, 250},
                                 new int[] { 50,  80, 203}, 3));
            list.add(new Polygon(new int[] {150,  50, 250, 278},
                                 new int[] { 50, 200, 203,  80}, 4));
             //Draw the Strings
             for(int i = 0; i < StringElements.size(); i++) {
                 for(int j = 0; j < StringElements.get(i).length; j++) {
                     g.setColor(Color.RED);
                     g.drawString(StringElements.get(i)[j], Xlist.get(i)[j],
                                                            Ylist.get(i)[j]);
             // Draw a line between every pair of points in each polygon.
             for(int i = 0; i < list.size(); i++) {
                 Polygon poly = (Polygon)list.get(i);
                 for (int j = 0; j < poly.npoints; j++) {
                     for (int k = j+1; k < poly.npoints; k++) {
                         g.setColor(Color.BLACK);
                         // Use heavy Stroke if route is duplicated.
                         if(isDuplicated(i, j, k, StringElements))
                             g.setStroke(new BasicStroke(2f));
                         else
                             g.setStroke(new BasicStroke(1f));
                         g.drawLine(poly.xpoints[j], poly.ypoints[j],
                                    poly.xpoints[k], poly.ypoints[k]);
             g.dispose();
             frame.add(new JLabel(new ImageIcon(image)));
             frame.pack();
             frame.setVisible(true);
        private static boolean isDuplicated(int elementIndex, int origIndex,
                                   int destIndex, List<String[]> StringElements) {
            // Look for cities in StringElements.get(elementIndex) located
            // at [origIndex] and [destIndex] in the other StringElement arrays.
            String[] elementCities = StringElements.get(elementIndex);
            String orig = elementCities[origIndex];
            //System.out.println("orig = " + orig);
            String dest = elementCities[destIndex];
            //System.out.println("dest = " + dest);
            // If we find both the orig and dest cities in any other
            // element of StringElements return true.
            for(int j = 0; j < StringElements.size(); j++) {
                if(j == elementIndex)
                    continue;
                String[] element = StringElements.get(j);
                if(contains(element, orig) && contains(element, dest))
                    return true;
            return false;
        private static boolean contains(String[] circuit, String city) {
            for(int j = 0; j < circuit.length; j++) {
                if(city.equals(circuit[j]))
                    return true;
            return false;
    }

  • Creating a triangle using polygon class problem, URGENT??

    Hi i am creating a triangle using polygon class which will eventually be used in a game where by a user clicks on the screen and triangles appear.
    class MainWindow extends Frame
         private Polygon[] m_polyTriangleArr;
                       MainWindow()
                              m_nTrianglesToDraw = 0;
             m_nTrianglesDrawn = 0;
                             m_polyTriangleArr = new Polygon[15];
                             addMouseListener(new MouseCatcher() );
            setVisible(true);
                         class MouseCatcher extends MouseAdapter
                             public void mousePressed(MouseEvent evt)
                  Point ptMouse = new Point();
                  ptMouse = evt.getPoint();
                if(m_nTrianglesDrawn < m_nTrianglesToDraw)
                                int npoints = 3;
                        m_polyTriangleArr[m_nTrianglesDrawn]
                      = new Polygon( ptMouse[].x, ptMouse[].y, npoints);
    }When i compile my code i get the following error message:
    Class Expected
    ')' expectedThe two error messages are refering to the section new Polygon(....)
    line. Please help

    Cannot find symbol constructor Polygon(int, int, int)
    Can some one tell me where this needs to go and what i should generally
    look like pleaseI don't think it is a good idea to try and add the constructor that the compiler
    can't find. Instead you should use the constructor that already exists
    in the Polygon class: ie the one that looks like Polygon(int[], int[], int).
    But this requires you to pass two int arrays and not two ints as you
    are doing at the moment. As you have seen, evt.getPoint() only supplies
    you with a single pair of ints: the x- and y-coordinates of where the mouse
    button was pressed.
    And this is the root of the problem. To draw a triangle you need three
    points. From these three points you can build up two arrays: one containing
    the x-coordinates and one containing the y-coordinates. It is these two
    arrays that will be used as the first two arguments to the Polygon constructor.
    So your task is to figure out how you can respond to mouse presses
    correctly, and only try and add a new triangle when you have all three of its
    vertices.
    [Edit] This assumes that you expect the user to specify all three vertices of the
    triangle. If this isn't the case, say what you do expect.

  • Creating a triangle using polygon class problem?

    Hi i am trying to create a triangle with the polygon class. If successful, the user should be able to click on the screen and triangles should appear.
    private Polygon[] m_polyTriangleArr;
    MainWindow()
      m_polyTriangleArr = new Polygon[15];
    class MouseCatcher extends MouseAdapter
          public void mousePressed(MouseEvent evt)
                    Point ptMouse = new Point();
                    ptMouse = evt.getPoint();
                              if(m_nTrianglesDrawn < m_nTrianglesToDraw)
                         int npoints = 3;
                                               m_polyTriangleArr[m_nTrianglesDrawn]
                    = new Polygon( ptMouse.x, ptMouse.y, npoints);
                            m_nTrianglesDrawn++;
                        m_bMouse = true;
                        repaint();
            }Paint section
    public void paint(Graphics gc)
                  if(m_bMouse)
              gc.setColor(Color.green);
              for( int i = 0; i < m_nTrianglesDrawn; i++)
              gc.fillPolygon(m_polyTriangleArr.x, m_polyTriangleArr[i].y, npoints);
    When i try to compile my code i get the following error message:
    Cannot find symbol constructor Polygon(int, int, int)
    --- find symbol variable x
    --- find symbol variable y
    --- find symbol variable npoints.
    Can som1 tell me why i have these error messages when i have already declared a Polygon object array and what i need to change please??

    Check out the API
    http://java.sun.com/j2se/1.4.2/docs/api/java/awt/Polygon.html
    there's no constructor that receives 3 integers
    cheers,
    Manuel Leiria

  • How to create a generalized version of the detailed polygons?

    How to create a generalized version of the detailed polygons?
    I have a table of detailed polygons (100+ vertices) and I want to get generalized version of these polygons.
    For example, assume I have a polygon with 100 vertices. Distance between vertex n and n+1 is 1.0.
    I want to get geometry (generalized polygon, line or point) where distance between vertex n and n+1 is 10.0 or more (I want vertices to be considered as one vertex if distance between them is less then 10.0).
    Is it possible to create generalized version of polygons on the fly?
    Any help is appreciated.
    Thanks.

    Scenario A:
    If all of your polygons have no interaction among them (No polygon shares any boundary with any other ones).
    In this case you can use the sdo_util.simplify in 10g to reduce the vertices in your polygons which returns new polygon geometries on the fly.
    If you found that simplify is not doing exactly what you want, you can always roll out your own implementation using PL/SQL or the new SDOAPI JGeoemtry class in Java. Both will give you complete access to the coordinate arrays in a polygon and update them back to the database after you have simplified them in your code.
    Scenario B:
    If your polygons share boundaries, then the above methods will not work since the simplification process may not preserve the topology among your polygons. What you can do then is to use the Java topo package to create a new topology by adding all of your polygons to to an empty topology (which you first create in the database and then load into memory using oracle.spatial.topo.TopoMap). Once you have a topology built in the memory, you can use methods such as oracle.spatial.topo.TopoMap.changeEdgeCoords() to simplify the edges of your polygons. You can then recreate the simplified polygons from the topology. This is just a rough guide; for more details you need to check out the java doc for the various packages mentioned above which are shipped with 10g spatial.

  • Filling in quadrilaterals in a pixel array

    Short version: Does anyone know of an algorithm like fillPolygon, but that works with a pixel array? (and doesn't need more than v1.1) Thanks.
    Long version:
    Hi. Hope there's a math guru among you who can give me a clue...
    I'm doing an animated 3D applet but restricted to pre-plugin Java - nothing post about 1.1. I'm double buffering for speed, with an int array [screenwidth*screenheight] for the pixels.
    At the start of each frame I want to colour in the areas where some flat rectangles (walls) are as the 'camera' sees them - quadrilaterals whose corners could be anywhere on or off the screen.
    For each line of the quadrilateral I can figure out how to find the on-screen start and end points - stopping where either the line or the screen stops, but I can't think of a fast algorithm to get from those 8 numbers per wall to a correctly filled-in pixel array.
    Thanks for your help.

    As your quadrilaterals are transformed rectangles,
    they should also be convex.
    From one vertex, with the most extreem ordiante in a
    chosen direction (eg the left-most) iterate in one
    direction (eg +ve x) along the two edges to the
    adjacent vertices using Bresenham's algorithm. That
    will give you two points with a common ordinate (eg
    (x, y0(x)) and (x, y1(x))), between which you may
    fill a line.
    On encountering another vertex, continue iterating
    along the next edge until the next vertex. When the
    furthest vertex is reached, you have filled your
    convex quadrilateral.
    Petethis approach is just fine and about as fast as you can get.
    another approach is filling the qualiteral (works as well for any convex
    polygon) by means of a triangle fan ...
    so for quadliteral with vertices A, B, C, D (each having x and y copmonents) you draw a triangle fan around a pivot point (lets say that is vertex A) like this
    drawTri (A, B, C)
    drawTri (A, C, D)
    or for a 5 vertex polygon (A, B, C, D, E)it would be
    drawTri (A, B, C)
    drawTri (A, C, D)
    drawTri (A, D, E)
    this works just as well, with a few minor advantages and disadvantages ...

  • Is there a limit to the number of points in a polygon?

    Please excuse the entry-level question (and possible use of words like 'point' in a non-technically-precise way) but we've lost out Spatial expert!
    Anyway, we get problems occassionally with complex polygons and it seems that there's a limit fo the number of points they can have.
    Are we able to set a higher limit?

    SQL> desc MDSYS.SDO_ORDINATE_ARRAY
    MDSYS.SDO_ORDINATE_ARRAY VARRAY(1048576) OF NUMBERSo this means you have have a maximum of 1048576 ordinates in your ordiante array. So that would be 1048576/2 vertices if your data is 2d, or 1048576/3 if you have z or m values.
    However... you can change this if you really need to.
    See [Increasing the Size of Ordinate Arrays to Support Very Large Geometries|http://download.oracle.com/docs/cd/E11882_01/appdev.112/e11830/sdo_migrat.htm#SPATL1426]
    I recommend you don't make this change unless you need to as it adds a bit of overhead if you want to export the data later.
    Its always worth thinking about why your polygons are so big. Maybe they are country boundaries and there are vertices every few metres and maybe you need this level of data in your system. Or maybe the data was captured in this way, but that level of details is meaningless in your context and you'd be better off by simplifying it (i.e. reducing the number of vertices). Or maybe the polygons have lots of duplicate vertices that should be removed.
    Only you can answer those questions but you need to be aware that the performance of polygons with huge number of vertices is likely to suck.

Maybe you are looking for

  • Report Bug: Application Alias Issue

    Hi, I have a unique problem of Application Alias not working. For a particular application only this happens. For all other Application in this DB it works nicely. I am using ApEx 3.0.1 Regards Rana

  • Ios 7 air drop not working with mountain lion air drop

    Hi, didn't see an iOS 7 forum, so I'm posting it here since I was testing it out on my iPhone 5. I tried to use air drop to share photos b/w my iPhone and my MBP running mountain lion, both has air drop enabled, but I couldn't see either on the air d

  • Epson xp-202 will not print "Filter failed"

    I am moving from SuSE to Arch - installed couple of days ago.  My epsonxp202 was working (well) under SuSE with 'drivers' downloaded late November.  The download now gives *different 'drivers', offering .rpm, .deb, dource (.src.rpm). Cups finds print

  • Error in FI reports

    Hi all I am getting below error.Please help out. Initial RANGE-LOW for customer exit variable 0P_FVAEX corrected to # No value could be determined for variable 0P_FVAEX Thanks, Harika.

  • How to calculate  database downtime ?

    I have a request to calculate the downtime of a production database. Is there anyway by which we can know when (during which time of a day) a database was down in the past 1 year - Using OEM or data dictionary tables.