/* decomp2d.f -- translated by f2c (version of 22 July 1992  22:54:52).
   You must link the resulting object file with the libraries:
	-lF77 -lI77 -lm -lc   (in that order)
*/

#include "f2c.h"

/* Common Block Declarations */

struct {
    integer ierr;
} gerror_;

#define gerror_1 gerror_

struct {
    doublereal pi, tol;
} gconst_;

#define gconst_1 gconst_

struct {
    integer iprt, msglvl;
} gprint_;

#define gprint_1 gprint_


/*     The following code was excerpted from: cvdec2.f */

/* Subroutine */ int cvdec2_(angspc, angtol, nvc, npolg, nvert, maxvc, maxhv, 
	maxpv, maxiw, maxwk, vcl, regnum, hvl, pvl, iang, iwk, wk)
doublereal *angspc, *angtol;
integer *nvc, *npolg, *nvert, *maxvc, *maxhv, *maxpv, *maxiw, *maxwk;
doublereal *vcl;
integer *regnum, *hvl, *pvl;
doublereal *iang;
integer *iwk;
doublereal *wk;
{
    static integer v, w1, w2;
    extern /* Subroutine */ int insed2_();
    static doublereal piptol;
    extern /* Subroutine */ int resvrt_();


/*     Written and copyright by: */
/*        Barry Joe, Dept. of Computing Science, Univ. of Alberta */
/*        Edmonton, Alberta, Canada  T6G 2H1 */
/*        Phone: (403) 492-5757      Email: barry@cs.ualberta.ca */

/*     Purpose: Decompose general polygonal region (which is decomposed */

/*        into simple polygons on input) into convex polygons using */
/*        vertex coordinate list, head vertex list, and polygon vertex */
/*        list data structures. */

/*     Input parameters: */
/*        ANGSPC - angle spacing parameter in radians used in controlling 
*/
/*              vertices to be considered as an endpoint of a separator */

/*        ANGTOL - angle tolerance parameter in radians used in accepting 
*/
/*              separator(s) */
/*        NVC - number of vertex coordinates or positions used in VCL */
/*              array */
/*        NPOLG - number of polygonal subregions or positions used in */
/*              HVL array */
/*        NVERT - number of polygon vertices or positions used in PVL */
/*              array */
/*        MAXVC - maximum size available for VCL array, should be >= */
/*              number of vertex coordinates required for decomposition */

/*        MAXHV - maximum size available for HVL, REGNUM arrays, should */

/*              be >= number of polygons required for decomposition */
/*        MAXPV - maximum size available for PVL, IANG arrays; should be 
*/
/*              >= number of polygon vertices required for decomposition 
*/
/*        MAXIW - maximum size available for IWK array; should be about */

/*              3 times maximum number of vertices in any polygon */
/*        MAXWK - maximum size available for WK array; should be about */
/*              5 times maximum number of vertices in any polygon */
/*        VCL(1:2,1:NVC) - vertex coordinate list */
/*        REGNUM(1:NPOLG) - region numbers */
/*        HVL(1:NPOLG) - head vertex list */
/*        PVL(1:4,1:NVERT),IANG(1:NVERT) - polygon vertex list and */
/*              interior angles; see routine DSPGDC for more details */
/*        [Note: The data structures should be as output from routine */
/*              SPDEC2.] */

/*     Updated parameters: */
/*        NVC,NPOLG,NVERT,VCL,REGNUM,HVL,PVL,IANG */

/*     Working parameters: */
/*        IWK(1:MAXIW) - integer work array */
/*        WK(1:MAXWK) - double precision work array */

/*     Abnormal return: */
/*        IERR is set to 3, 4, 5, 6, 7, 206, 207, 208, 209, 210, or 212 */


/*     Routines called: */
/*        INSED2, RESVRT */



/*     For each reflex vertex, resolve it with one or two separators */
/*     and update VCL, HVL, PVL, IANG. */

    /* Parameter adjustments */
    --wk;
    --iwk;
    --iang;
    pvl -= 5;
    --hvl;
    --regnum;
    vcl -= 3;

    /* Function Body */
    piptol = gconst_1.pi + gconst_1.tol;
    v = 1;
L10:
    if (v > *nvert) {
	return 0;
    }
    if (iang[v] > piptol) {
	resvrt_(&v, angspc, angtol, nvc, nvert, maxvc, maxpv, maxiw, maxwk, &
		vcl[3], &pvl[5], &iang[1], &w1, &w2, &iwk[1], &wk[1]);
	if (gerror_1.ierr != 0) {
	    return 0;
	}
	insed2_(&v, &w1, npolg, nvert, maxhv, maxpv, &vcl[3], &regnum[1], &
		hvl[1], &pvl[5], &iang[1]);
	if (gerror_1.ierr != 0) {
	    return 0;
	}
	if (w2 > 0) {
	    insed2_(&v, &w2, npolg, nvert, maxhv, maxpv, &vcl[3], &regnum[1], 
		    &hvl[1], &pvl[5], &iang[1]);
	}
	if (gerror_1.ierr != 0) {
	    return 0;
	}
    }
    ++v;
    goto L10;
} /* cvdec2_ */


/*     The following code was excerpted from: dsmcpr.f */

/* Subroutine */ int dsmcpr_(nhole, nvbc, vcl, maxhv, maxpv, maxho, nvc, 
	npolg, nvert, nhola, regnum, hvl, pvl, iang, holv)
integer *nhole, *nvbc;
doublereal *vcl;
integer *maxhv, *maxpv, *maxho, *nvc, *npolg, *nvert, *nhola, *regnum, *hvl, *
	pvl;
doublereal *iang;
integer *holv;
{
    /* System generated locals */
    integer i__1, i__2;

    /* Local variables */
    static integer i, j;
    extern doublereal angle_();
    static integer iv, lv, nv;
    extern /* Subroutine */ int holvrt_();
    static integer ivs, lvp, lvs, nvs;


/*     Written and copyright by: */
/*        Barry Joe, Dept. of Computing Science, Univ. of Alberta */
/*        Edmonton, Alberta, Canada  T6G 2H1 */
/*        Phone: (403) 492-5757      Email: barry@cs.ualberta.ca */

/*     Purpose: Initialize the polygonal decomposition data structure */
/*        given a multiply-connected polygonal region with 1 outer */
/*        boundary curve and 0 or more inner boundary curves of holes. */

/*     Input parameters: */
/*        NHOLE - number of holes in region */
/*        NVBC(1:NHOLE+1) - number of vertices per boundary curve; first 
*/
/*              boundary curve is the outer boundary of the region */
/*        VCL(1:2,1:NVC) - vertex coordinates of boundary curves in CCW */

/*              order; NVC = NVBC(1) + ... + NVBC(NHOLE+1); positions 1 */

/*              to NVBC(1) of VCL contain the vertex coordinates of the */

/*              outer boundary in CCW order; positions NVBC(1)+1 to */
/*              NVBC(1)+NVBC(2) contain the vertex coordinates of the */
/*              first hole boundary in CCW order, etc. */
/*        MAXHV - maximum size available for HVL, REGNUM arrays, should */

/*              be >= NHOLE + 1 */
/*        MAXPV - maximum size available for PVL, IANG arrays; should be 
*/
/*               >= NVC */
/*        MAXHO - maximum size available for HOLV array; should be */
/*               >= NHOLE*2 */

/*     Output parameters: */
/*        NVC - number of vertex coordinates, set to sum of NVBC(I) */
/*        NPOLG - number of polygonal subregions, set to 1 */
/*        NVERT - number of vertices in PVL, set to NVC */
/*        NHOLA - number of attached holes, set to 0 */
/*        REGNUM(1:1) - region number of only subregion, set to 1 */
/*        [Note: Above 4 parameters are for consistency with DSPGDC.] */
/*        HVL(1:NHOLE+1) - head vertex list; first entry is the head */
/*              vertex (index in PVL) of outer boundary curve; next */
/*              NHOLE entries contain the head vertex of a hole */
/*        PVL(1:4,1:NVC),IANG(1:NVC) - polygon vertex list and interior */

/*              angles; vertices of outer boundary curve are in CCW order 
*/
/*              followed by vertices of each hole in CW hole; vertices */
/*              of each polygon are in a circular linked list; see */
/*              routine DSPGDC for more details of this data structure */
/*        HOLV(1:NHOLE*2) - indices in PVL of top and bottom vertices of 
*/
/*              holes; first (last) NHOLE entries are for top (bottom) */
/*              vertices; top (bottom) vertices are sorted in decreasing 
*/
/*              (increasing) lexicographic (y,x) order of coordinates */

/*     Abnormal return: */
/*        IERR is set to 2, 4, or 5 */

/*     Routines called: */
/*        ANGLE, HOLVRT */




    /* Parameter adjustments */
    --holv;
    --iang;
    pvl -= 5;
    --hvl;
    --regnum;
    vcl -= 3;
    --nvbc;

    /* Function Body */
    *nvc = 0;
    i__1 = *nhole + 1;
    for (i = 1; i <= i__1; ++i) {
	*nvc += nvbc[i];
/* L10: */
    }
    *npolg = 1;
    *nvert = *nvc;
    *nhola = 0;
    regnum[1] = 1;
    if (*nhole + 1 > *maxhv) {
	gerror_1.ierr = 4;
	return 0;
    } else if (*nvc > *maxpv) {
	gerror_1.ierr = 5;
	return 0;
    } else if (*nhole + *nhole > *maxho) {
	gerror_1.ierr = 2;
	return 0;
    }

/*     Initialize HVL, PVL arrays. */

/* L20: */
    hvl[1] = 1;
    nv = nvbc[1];
    i__1 = nv;
    for (i = 1; i <= i__1; ++i) {
	pvl[(i << 2) + 1] = i;
	pvl[(i << 2) + 2] = 1;
	pvl[(i << 2) + 3] = i + 1;
	pvl[(i << 2) + 4] = 0;
/* L30: */
    }
    pvl[(nv << 2) + 3] = 1;
    i__1 = *nhole;
    for (j = 1; j <= i__1; ++j) {
	hvl[j + 1] = nv + 1;
	nvs = nv + nvbc[j + 1];
	i__2 = nvs;
	for (i = nv + 1; i <= i__2; ++i) {
	    pvl[(i << 2) + 1] = i;
	    pvl[(i << 2) + 2] = 1;
	    pvl[(i << 2) + 3] = i - 1;
	    pvl[(i << 2) + 4] = 0;
/* L40: */
	}
	pvl[(nv + 1 << 2) + 3] = nvs;
	nv = nvs;
/* L50: */
    }

/*     Initialize IANG array. */

    i__1 = *nhole + 1;
    for (i = 1; i <= i__1; ++i) {
	j = hvl[i];
	lvp = pvl[(j << 2) + 1];
	iv = pvl[(j << 2) + 3];
	lv = pvl[(iv << 2) + 1];
L60:
	ivs = pvl[(iv << 2) + 3];
	lvs = pvl[(ivs << 2) + 1];
	iang[iv] = angle_(&vcl[(lvp << 1) + 1], &vcl[(lvp << 1) + 2], &vcl[(
		lv << 1) + 1], &vcl[(lv << 1) + 2], &vcl[(lvs << 1) + 1], &
		vcl[(lvs << 1) + 2]);
	if (iv == j) {
	    goto L70;
	}
	lvp = lv;
	iv = ivs;
	lv = lvs;
	goto L60;
L70:
	;
    }

/*     Initialize HOLV array. */

    if (*nhole > 0) {
	holvrt_(nhole, &vcl[3], &hvl[2], &pvl[5], &holv[1]);
    }
} /* dsmcpr_ */


/*     The following code was excerpted from: edght.f */

/* Subroutine */ int edght_(a, b, v, n, htsiz, maxedg, hdfree, last, ht, edge,
	 w)
integer *a, *b, *v, *n, *htsiz, *maxedg, *hdfree, *last, *ht, *edge, *w;
{
    static integer bptr, newp, k, aa, bb, ptr;


/*     Written and copyright by: */
/*        Barry Joe, Dept. of Computing Science, Univ. of Alberta */
/*        Edmonton, Alberta, Canada  T6G 2H1 */
/*        Phone: (403) 492-5757      Email: barry@cs.ualberta.ca */

/*     Purpose: Search in hash table HT for record in EDGE containing */
/*        key (A,B). */

/*     Input parameters: */
/*        A,B - vertex indices, > 0, of edge (also key of hash table) */
/*        V - value associated with edge */
/*        N - upper bound on A, B */
/*        HTSIZ - size of hash table HT */
/*        MAXEDG - maximum size available for EDGE array */
/*        HDFREE - head pointer to linked list of free entries of EDGE */
/*              array due to deletions */
/*        LAST - index of last entry used in EDGE array */
/*        HT(0:HTSIZ-1) - hash table of head pointers (direct chaining */
/*              with ordered lists is used) */
/*        EDGE(1:4,1:MAXEDG) - entries of hash table records; */
/*              EDGE(1,I) = MIN(A,B); EDGE(2,I) = MAX(A,B); */
/*              EDGE(3,I) = V; EDGE(4,I) = link */
/*        [Note: Before first call to this routine, HDFREE, LAST, and */
/*              entries of HT should be set to 0.] */

/*     Updated parameters: */
/*        HDFREE,LAST - at least one of these is updated */
/*        HT,EDGE - if key with A,B is found then this record is deleted 
*/
/*              from hash table, else record is inserted in hash table */

/*     Output parameters: */
/*        W - EDGE(3,INDEX), where INDEX is index of record, if found; */
/*              else 0 */

/*     Abnormal return: */
/*        IERR is set to 1 */



    /* Parameter adjustments */
    edge -= 5;

    /* Function Body */
    if (*a < *b) {
	aa = *a;
	bb = *b;
    } else {
	aa = *b;
	bb = *a;
    }
    k = (aa * *n + bb) % *htsiz;
    bptr = -1;
    ptr = ht[k];
L10:
    if (ptr != 0) {
	if (edge[(ptr << 2) + 1] > aa) {
	    goto L20;
	} else if (edge[(ptr << 2) + 1] == aa) {
	    if (edge[(ptr << 2) + 2] > bb) {
		goto L20;
	    } else if (edge[(ptr << 2) + 2] == bb) {
		if (bptr == -1) {
		    ht[k] = edge[(ptr << 2) + 4];
		} else {
		    edge[(bptr << 2) + 4] = edge[(ptr << 2) + 4];
		}
		edge[(ptr << 2) + 4] = *hdfree;
		*hdfree = ptr;
		*w = edge[(ptr << 2) + 3];
		return 0;
	    }
	}
	bptr = ptr;
	ptr = edge[(ptr << 2) + 4];
	goto L10;
    }
L20:
    if (*hdfree > 0) {
	newp = *hdfree;
	*hdfree = edge[(*hdfree << 2) + 4];
    } else {
	++(*last);
	newp = *last;
	if (*last > *maxedg) {
	    gerror_1.ierr = 1;
	    return 0;
	}
    }
    if (bptr == -1) {
	ht[k] = newp;
    } else {
	edge[(bptr << 2) + 4] = newp;
    }
    edge[(newp << 2) + 1] = aa;
    edge[(newp << 2) + 2] = bb;
    edge[(newp << 2) + 3] = *v;
    edge[(newp << 2) + 4] = ptr;
    *w = 0;
} /* edght_ */


/*     The following code was excerpted from: fndsep.f */

/* Subroutine */ int fndsep_(angac1, xr, yr, nvrt, xc, yc, ivis, theta, nv, 
	iv, vcl, pvl, iang, angsep, i1, i2, wkang)
doublereal *angac1, *xr, *yr;
integer *nvrt;
doublereal *xc, *yc;
integer *ivis;
doublereal *theta;
integer *nv, *iv;
doublereal *vcl;
integer *pvl;
doublereal *iang, *angsep;
integer *i1, *i2;
doublereal *wkang;
{
    /* System generated locals */
    integer i__1;
    doublereal d__1, d__2;

    /* Local variables */
    static integer i, k, l, m, p, q, r;
    static doublereal angsp2;
    static integer ii, nl, nr;
    extern doublereal minang_();
    static doublereal ang, phi;


/*     Written and copyright by: */
/*        Barry Joe, Dept. of Computing Science, Univ. of Alberta */
/*        Edmonton, Alberta, Canada  T6G 2H1 */
/*        Phone: (403) 492-5757      Email: barry@cs.ualberta.ca */

/*     Purpose: Find 1 or 2 separators which can resolve reflex vertex */
/*        (XR,YR) using a max-min angle criterion from list of vertices */

/*        in increasing polar angle w.r.t. reflex vertex. Preference */
/*        is given to 1 separator. */

/*     Input parameters: */
/*        ANGAC1 - angle tolerance parameter used for preference */
/*              in accepting one separator */
/*        XR,YR - coordinates of reflex vertex */
/*        NVRT - (number of vertices) - 1 */
/*        XC(0:NVRT), YC(0:NVRT) - vertex coordinates of possible */
/*              endpoints of a separator */
/*        IVIS(0:NVRT) - contains information about the vertices of */
/*              XC, YC arrays w.r.t. the polygon vertex list; if */
/*              IVIS(I) > 0 then vertex (XC(I),YC(I)) has index IVIS(I) */

/*              in PVL; if IVIS(I) < 0 then vertex (XC(I),YC(I)) is on */
/*              the edge joining vertices with indices -IVIS(I) and */
/*              SUCC(-IVIS(I)) in PVL */
/*        THETA(0:NVRT) - polar angles of vertices in increasing order; */

/*              THETA(NVRT) is the interior angle of reflex vertex; */
/*              THETA(I), I >= 0, is the polar angle of (XC(I),YC(I)) */
/*              w.r.t. reflex vertex */
/*        NV - (number of vertices to be considered as endpoint of a */
/*              separator) - 1 */
/*        IV(0:NV) - indices of vertices in XC, YC arrays to be */
/*              considered as endpoint of a separator; angle between */
/*              consecutive vertices is assumed to be < 180 degrees */
/*        VCL(1:2,1:*) - vertex coordinate list */
/*        PVL(1:4,1:*),IANG(1:*) - polygon vertex list, interior angles */


/*     Output parameters: */
/*        ANGSEP - minimum of the 4 or 7 angles at the boundary */
/*              resulting from 1 or 2 separators, respectively */
/*        I1,I2 - indices of endpoints of separators in XC, YC arrays; */
/*              I2 = -1 if there is only one separator, else I1 < I2 */

/*     Working parameters: */
/*        WKANG(0:NV) - working array for angles */

/*     Routines called: */
/*        MINANG */



/*     Determine the vertices in the inner cone - indices P to Q. */

    /* Parameter adjustments */
    --iang;
    pvl -= 5;
    vcl -= 3;

    /* Function Body */
    i = 0;
    p = -1;
    phi = theta[*nvrt] - gconst_1.pi + gconst_1.tol;
L10:
    if (p >= 0) {
	goto L20;
    }
    if (theta[iv[i]] >= phi) {
	p = i;
    } else {
	++i;
    }
    goto L10;
L20:
    i = *nv;
    q = -1;
    phi = gconst_1.pi - gconst_1.tol;
L30:
    if (q >= 0) {
	goto L40;
    }
    if (theta[iv[i]] <= phi) {
	q = i;
    } else {
	--i;
    }
    goto L30;
L40:

/*     Use the max-min angle criterion to find the best separator */
/*     in inner cone. */

    *angsep = 0.;
    i__1 = q;
    for (i = p; i <= i__1; ++i) {
	k = iv[i];
	ang = minang_(xr, yr, &xc[k], &yc[k], &ivis[k], &theta[k], &theta[*
		nvrt], &vcl[3], &pvl[5], &iang[1]);
	if (ang > *angsep) {
	    *angsep = ang;
	    ii = iv[i];
	}
/* L50: */
    }
    angsp2 = *angsep;
    if (*angsep >= *angac1) {
	goto L110;
    }

/*     If the best separator in inner cone is not 'good' enough, */
/*     use max-min angle criterion to try to find a better pair */
/*     of separators from the right and left cones. */

    nr = 0;
    nl = 0;
    i__1 = p - 1;
    for (r = 0; r <= i__1; ++r) {
	wkang[r] = 0.;
	if (theta[iv[r]] > *angsep) {
	    k = iv[r];
	    ang = minang_(xr, yr, &xc[k], &yc[k], &ivis[k], &theta[k], &theta[
		    *nvrt], &vcl[3], &pvl[5], &iang[1]);
	    if (ang > *angsep) {
		++nr;
		wkang[r] = ang;
	    }
	}
/* L60: */
    }
    if (nr == 0) {
	goto L110;
    }
    phi = theta[*nvrt] - *angsep;
    i__1 = *nv;
    for (l = q + 1; l <= i__1; ++l) {
	wkang[l] = 0.;
	if (theta[iv[l]] < phi) {
	    k = iv[l];
	    ang = minang_(xr, yr, &xc[k], &yc[k], &ivis[k], &theta[k], &theta[
		    *nvrt], &vcl[3], &pvl[5], &iang[1]);
	    if (ang > *angsep) {
		++nl;
		wkang[l] = ang;
	    }
	}
/* L70: */
    }
    if (nl == 0) {
	goto L110;
    }

/*     Check all possible pairs for the best pair of separators */
/*     in the right and left cones. */

    m = *nv;
    for (r = p - 1; r >= 0; --r) {
	if (m > q && wkang[r] > angsp2) {
	    phi = theta[iv[r]];
L80:
	    if (m > q && (wkang[m] <= angsp2 || theta[iv[m]] - phi > 
		    gconst_1.pi - gconst_1.tol)) {
		--m;
		goto L80;
	    }
	    i__1 = m;
	    for (l = q + 1; l <= i__1; ++l) {
		if (wkang[l] > angsp2) {
/* Computing MIN */
		    d__1 = theta[iv[l]] - phi, d__2 = wkang[r], d__1 = min(
			    d__1,d__2), d__2 = wkang[l];
		    ang = min(d__1,d__2);
		    if (ang > angsp2) {
			angsp2 = ang;
			*i1 = iv[r];
			*i2 = iv[l];
		    }
		}
/* L90: */
	    }
	}
/* L100: */
    }

/*     Choose 1 or 2 separators based on max-min angle criterion or */
/*     ANGAC1 parameter. */

L110:
    if (angsp2 <= *angsep) {
	*i1 = ii;
	*i2 = -1;
    } else {
	*angsep = angsp2;
    }
} /* fndsep_ */


/*     The following code was excerpted from: holvrt.f */

/* Subroutine */ int holvrt_(nhole, vcl, hvl, pvl, holv)
integer *nhole;
doublereal *vcl;
integer *hvl, *pvl, *holv;
{
    /* System generated locals */
    integer i__1;

    /* Local variables */
    static integer imin, imax;
    static doublereal xmin, ymin, xmax, ymax;
    static integer i, j;
    static doublereal x, y;
    static integer hv, iv, lv, nhp1;


/*     Written and copyright by: */
/*        Barry Joe, Dept. of Computing Science, Univ. of Alberta */
/*        Edmonton, Alberta, Canada  T6G 2H1 */
/*        Phone: (403) 492-5757      Email: barry@cs.ualberta.ca */

/*     Purpose: Determine top and bottom vertices of holes in polygonal */

/*        region(s), and sort top vertices in decreasing (y,x) order */
/*        and bottom vertices in increasing (y,x) order. */

/*     Input parameters: */
/*        NHOLE - number of holes in region(s) */
/*        VCL(1:2,1:*) - vertex coordinate list */
/*        HVL(1:NHOLE) - head vertex list; HVL(I) is index in PVL of */
/*              head vertex of Ith hole */
/*        PVL(1:4,1:*) - polygon vertex list; see routine DSPGDC */

/*     Output parameters: */
/*        HOLV(1:NHOLE*2) - indices in PVL of top and bottom vertices of 
*/
/*              holes; first (last) NHOLE entries are for top (bottom) */
/*              vertices; top (bottom) vertices are sorted in decreasing 
*/
/*              (increasing) lexicographic (y,x) order of coordinates */



/*     Determine top and bottom vertices of holes. */

    /* Parameter adjustments */
    --holv;
    pvl -= 5;
    --hvl;
    vcl -= 3;

    /* Function Body */
    i__1 = *nhole;
    for (i = 1; i <= i__1; ++i) {
	hv = hvl[i];
	iv = hv;
L10:
	lv = pvl[(iv << 2) + 1];
	if (iv == hv) {
	    imin = iv;
	    imax = iv;
	    xmin = vcl[(lv << 1) + 1];
	    ymin = vcl[(lv << 1) + 2];
	    xmax = xmin;
	    ymax = ymin;
	} else {
	    x = vcl[(lv << 1) + 1];
	    y = vcl[(lv << 1) + 2];
	    if (y < ymin || y == ymin && x < xmin) {
		imin = iv;
		xmin = x;
		ymin = y;
	    } else if (y > ymax || y == ymax && x > xmax) {
		imax = iv;
		xmax = x;
		ymax = y;
	    }
	}
	iv = pvl[(iv << 2) + 3];
	if (iv != hv) {
	    goto L10;
	}
	holv[i] = imax;
	holv[i + *nhole] = imin;
/* L20: */
    }

/*     Use linear insertion sort to sort the top vertices of holes */
/*     in decreasing (y,x) order, then bottom vertices in increasing */
/*     (y,x) order. It is assumed NHOLE is small. */

    i__1 = *nhole;
    for (i = 2; i <= i__1; ++i) {
	hv = holv[i];
	lv = pvl[(hv << 2) + 1];
	x = vcl[(lv << 1) + 1];
	y = vcl[(lv << 1) + 2];
	j = i;
L30:
	iv = holv[j - 1];
	lv = pvl[(iv << 2) + 1];
	if (y > vcl[(lv << 1) + 2] || y == vcl[(lv << 1) + 2] && x > vcl[(lv 
		<< 1) + 1]) {
	    holv[j] = iv;
	    --j;
	    if (j > 1) {
		goto L30;
	    }
	}
	holv[j] = hv;
/* L40: */
    }

    nhp1 = *nhole + 1;
    i__1 = *nhole + *nhole;
    for (i = nhp1 + 1; i <= i__1; ++i) {
	hv = holv[i];
	lv = pvl[(hv << 2) + 1];
	x = vcl[(lv << 1) + 1];
	y = vcl[(lv << 1) + 2];
	j = i;
L50:
	iv = holv[j - 1];
	lv = pvl[(iv << 2) + 1];
	if (y < vcl[(lv << 1) + 2] || y == vcl[(lv << 1) + 2] && x < vcl[(lv 
		<< 1) + 1]) {
	    holv[j] = iv;
	    --j;
	    if (j > nhp1) {
		goto L50;
	    }
	}
	holv[j] = hv;
/* L60: */
    }
} /* holvrt_ */


/*     The following code was excerpted from: insed2.f */

/* Subroutine */ int insed2_(v, w, npolg, nvert, maxhv, maxpv, vcl, regnum, 
	hvl, pvl, iang)
integer *v, *w, *npolg, *nvert, *maxhv, *maxpv;
doublereal *vcl;
integer *regnum, *hvl, *pvl;
doublereal *iang;
{
    static integer i, l;
    extern doublereal angle_();
    static integer lv, lw, vv, ww;


/*     Written and copyright by: */
/*        Barry Joe, Dept. of Computing Science, Univ. of Alberta */
/*        Edmonton, Alberta, Canada  T6G 2H1 */
/*        Phone: (403) 492-5757      Email: barry@cs.ualberta.ca */

/*     Purpose: Insert edge joining vertices V, W into head vertex */
/*        list and polygon vertex list data structures. */

/*     Input parameters: */
/*        V,W - indices in PVL of vertices which are the endpoints */
/*              of an edge to be added to decomposition */
/*        NPOLG - number of positions used in HVL array */
/*        NVERT - number of positions used in PVL array */
/*        MAXHV - maximum size available for HVL array */
/*        MAXPV - maximum size available for PVL array */
/*        VCL(1:2,1:*) - vertex coordinate list */
/*        REGNUM(1:NPOLG) - region numbers */
/*        HVL(1:NPOLG) - head vertex list */
/*        PVL(1:4,1:NVERT),IANG(1:NVERT) - polygon vertex list and */
/*              interior angles */

/*     Updated parameters: */
/*        REGNUM,HVL,PVL,IANG */

/*     Abnormal return: */
/*        IERR is set to 4 or 5 */

/*     Routines called: */
/*        ANGLE */




    /* Parameter adjustments */
    --iang;
    pvl -= 5;
    --hvl;
    --regnum;
    vcl -= 3;

    /* Function Body */
    if (*npolg >= *maxhv) {
	gerror_1.ierr = 4;
	return 0;
    } else if (*nvert + 2 > *maxpv) {
	gerror_1.ierr = 5;
	return 0;
    }

/*     Split linked list of vertices of the polygon containing vertices */

/*     V and W into two linked list of vertices of polygons with common */

/*     edge joining V and W. */

    *nvert += 2;
    vv = *nvert - 1;
    ww = *nvert;
    lv = pvl[(*v << 2) + 1];
    lw = pvl[(*w << 2) + 1];
    pvl[(vv << 2) + 1] = lv;
    pvl[(ww << 2) + 1] = lw;
    pvl[(ww << 2) + 2] = pvl[(*v << 2) + 2];
    pvl[(vv << 2) + 3] = pvl[(*v << 2) + 3];
    pvl[(ww << 2) + 3] = pvl[(*w << 2) + 3];
    pvl[(*v << 2) + 3] = ww;
    pvl[(*w << 2) + 3] = vv;
    pvl[(vv << 2) + 4] = pvl[(*v << 2) + 4];
    pvl[(ww << 2) + 4] = pvl[(*w << 2) + 4];
    pvl[(*v << 2) + 4] = *w;
    pvl[(*w << 2) + 4] = *v;
    if (pvl[(vv << 2) + 4] > 0) {
	pvl[(pvl[(vv << 2) + 4] << 2) + 4] = vv;
    }
    if (pvl[(ww << 2) + 4] > 0) {
	pvl[(pvl[(ww << 2) + 4] << 2) + 4] = ww;
    }
    l = pvl[(pvl[(vv << 2) + 3] << 2) + 1];
    iang[vv] = angle_(&vcl[(lw << 1) + 1], &vcl[(lw << 1) + 2], &vcl[(lv << 1)
	     + 1], &vcl[(lv << 1) + 2], &vcl[(l << 1) + 1], &vcl[(l << 1) + 2]
	    );
    iang[*v] -= iang[vv];
    l = pvl[(pvl[(ww << 2) + 3] << 2) + 1];
    iang[ww] = angle_(&vcl[(lv << 1) + 1], &vcl[(lv << 1) + 2], &vcl[(lw << 1)
	     + 1], &vcl[(lw << 1) + 2], &vcl[(l << 1) + 1], &vcl[(l << 1) + 2]
	    );
    iang[*w] -= iang[ww];
    ++(*npolg);
    i = vv;
L10:
    pvl[(i << 2) + 2] = *npolg;
    i = pvl[(i << 2) + 3];
    if (i != vv) {
	goto L10;
    }
    hvl[pvl[(*v << 2) + 2]] = *v;
    hvl[*npolg] = vv;
    regnum[*npolg] = regnum[pvl[(*v << 2) + 2]];

} /* insed2_ */


/*     The following code was excerpted from: insvr2.f */

/* Subroutine */ int insvr2_(xi, yi, wp, nvc, nvert, maxvc, maxpv, vcl, pvl, 
	iang, w)
doublereal *xi, *yi;
integer *wp, *nvc, *nvert, *maxvc, *maxpv;
doublereal *vcl;
integer *pvl;
doublereal *iang;
integer *w;
{
    static integer ws, ww, wwp, wws;


/*     Written and copyright by: */
/*        Barry Joe, Dept. of Computing Science, Univ. of Alberta */
/*        Edmonton, Alberta, Canada  T6G 2H1 */
/*        Phone: (403) 492-5757      Email: barry@cs.ualberta.ca */

/*     Purpose: Insert point (XI,YI) into vertex coordinate list and */
/*        polygon vertex list data structures. */

/*     Input parameters: */
/*        XI,YI - coordinates of point to be inserted */
/*        WP - index of vertex in PVL which is to be the predecessor */
/*              vertex of the inserted vertex */
/*        NVC - number of positions used in VCL array */
/*        NVERT - number of positions used in PVL array */
/*        MAXVC - maximum size available for VCL array */
/*        MAXPV - maximum size available for PVL array */
/*        VCL(1:2,1:NVC) - vertex coordinate list */
/*        PVL(1:4,1:NVERT),IANG(1:NVERT) - polygon vertex list and */
/*              interior angles */

/*     Updated parameters: */
/*        NVC,NVERT,VCL,PVL,IANG */

/*     Output parameter: */
/*        W - index of inserted vertex in PVL */

/*     Abnormal return: */
/*        IERR is set to 3 or 5 */




    /* Parameter adjustments */
    --iang;
    pvl -= 5;
    vcl -= 3;

    /* Function Body */
    if (*nvc >= *maxvc) {
	gerror_1.ierr = 3;
	return 0;
    } else if (*nvert + 2 > *maxpv) {
	gerror_1.ierr = 5;
	return 0;
    }

/*     Update linked list of vertices of polygon containing vertex WP. */

    ++(*nvc);
    vcl[(*nvc << 1) + 1] = *xi;
    vcl[(*nvc << 1) + 2] = *yi;
    ws = pvl[(*wp << 2) + 3];
    ++(*nvert);
    *w = *nvert;
    pvl[(*w << 2) + 1] = *nvc;
    pvl[(*w << 2) + 2] = pvl[(*wp << 2) + 2];
    pvl[(*wp << 2) + 3] = *w;
    pvl[(*w << 2) + 3] = ws;
    iang[*w] = gconst_1.pi;
    pvl[(*w << 2) + 4] = pvl[(*wp << 2) + 4];

/*     If edge containing (XI,YI) is shared by another polygon, */
/*     then also update linked list of vertices of that polygon. */

    if (pvl[(*wp << 2) + 4] > 0) {
	wws = pvl[(*wp << 2) + 4];
	wwp = pvl[(wws << 2) + 3];
	++(*nvert);
	ww = *nvert;
	pvl[(ww << 2) + 1] = *nvc;
	pvl[(ww << 2) + 2] = pvl[(wws << 2) + 2];
	pvl[(wws << 2) + 3] = ww;
	pvl[(ww << 2) + 3] = wwp;
	iang[ww] = gconst_1.pi;
	pvl[(*wp << 2) + 4] = ww;
	pvl[(ww << 2) + 4] = *wp;
	pvl[(wws << 2) + 4] = *w;
    }
} /* insvr2_ */


/*     The following code was excerpted from: jnhole.f */

/* Subroutine */ int jnhole_(itophv, angspc, angtol, nvc, nvert, maxvc, maxpv,
	 maxiw, maxwk, vcl, hvl, pvl, iang, iwk, wk)
integer *itophv;
doublereal *angspc, *angtol;
integer *nvc, *nvert, *maxvc, *maxpv, *maxiw, *maxwk;
doublereal *vcl;
integer *hvl, *pvl;
doublereal *iang;
integer *iwk;
doublereal *wk;
{
    /* System generated locals */
    doublereal d__1, d__2, d__3;

    /* Local variables */
    static integer ilft, irgt;
    static doublereal slft, xlft, srgt, ylft, xint, xrgt, yrgt;
    static integer l;
    static doublereal s;
    extern doublereal angle_();
    static integer w, ipoly;
    static doublereal dy;
    static integer hv, iv, lv, lw, vp, vr, vs, vv;
    static doublereal xt;
    static integer ww;
    static doublereal xv, yt;
    static integer succil;
    static doublereal yv;
    static integer succir;
    extern /* Subroutine */ int resvrt_();
    static doublereal ytmtol, ytptol;
    static integer ivs;
    static doublereal xvs, yvs;


/*     Written and copyright by: */
/*        Barry Joe, Dept. of Computing Science, Univ. of Alberta */
/*        Edmonton, Alberta, Canada  T6G 2H1 */
/*        Phone: (403) 492-5757      Email: barry@cs.ualberta.ca */

/*     Purpose: Join hole boundary to boundary of polygon containing hole 
*/
/*        by finding a cut edge originating from the top vertex of hole */

/*        to a point on outer polygon boundary above it. */

/*     Input parameters: */
/*        ITOPHV - index in PVL of top vertex of hole */
/*        ANGSPC - angle spacing parameter used in controlling the */
/*              vertices to be considered as an endpoint of a separator */

/*        ANGTOL - angle tolerance parameter used in accepting */
/*              separator(s) */
/*        NVC - number of positions used in VCL array */
/*        NVERT - number of positions used in PVL array */
/*        MAXVC - maximum size available for VCL array */
/*        MAXPV - maximum size available for PVL array */
/*        MAXIW - maximum size available for IWK array; should be about */

/*              3 times number of vertices in outer polygon */
/*        MAXWK - maximum size available for WK array; should be about */
/*              5 times number of vertices in outer polygon */
/*        VCL(1:2,1:NVC) - vertex coordinate list */
/*        HVL(1:*) - head vertex list */
/*        PVL(1:4,1:NVERT),IANG(1:NVERT) - polygon vertex list and */
/*              interior angles */

/*     Updated parameters: */
/*        NVC,NVERT,VCL,PVL,IANG */

/*     Working parameters: */
/*        IWK(1:MAXIW) - integer work array */
/*        WK(1:MAXWK) - double precision work array */

/*     Abnormal return: */
/*        IERR is set to 3, 5, 6, 7, 206 to 210, 212, 218, or 219 */

/*     Routines called: */
/*        ANGLE, RESVRT */




    /* Parameter adjustments */
    --wk;
    --iwk;
    --iang;
    pvl -= 5;
    --hvl;
    vcl -= 3;

    /* Function Body */
    if (*nvc + 3 > *maxvc) {
	gerror_1.ierr = 3;
	return 0;
    } else if (*nvert + 5 > *maxpv) {
	gerror_1.ierr = 5;
	return 0;
    }

/*     Determine 'closest' vertices on outer boundary which are to the */
/*     left and right of top vertex of hole and on the horizontal line */
/*     through top vertex. The two closest vertices must be on edges */
/*     which intersect the horizontal line and are partially above the */
/*     line. Ties are broken (in the case of a vertex on a cut edge) */
/*     by choosing the vertex on the edge of maximum or minimum dx/dy */
/*     slope depending on whether the vertex is to the left or right */
/*     of top vertex, respectively. */

    ipoly = pvl[(*itophv << 2) + 2];
    lv = pvl[(*itophv << 2) + 1];
    xt = vcl[(lv << 1) + 1];
    yt = vcl[(lv << 1) + 2];
    dy = 0.;
    hv = hvl[ipoly];
    iv = hv;
    yv = vcl[(pvl[(iv << 2) + 1] << 1) + 2];
L10:
    iv = pvl[(iv << 2) + 3];
    yvs = vcl[(pvl[(iv << 2) + 1] << 1) + 2];
/* Computing MAX */
    d__2 = dy, d__3 = (d__1 = yvs - yv, abs(d__1));
    dy = max(d__2,d__3);
    yv = yvs;
    if (iv != hv) {
	goto L10;
    }
    ytmtol = yt - gconst_1.tol * dy;
    ytptol = yt + gconst_1.tol * dy;
    ilft = 0;
    irgt = 0;
    xlft = 0.;
    xrgt = 0.;
    hv = hvl[ipoly];
    iv = hv;
    lv = pvl[(iv << 2) + 1];
    xv = vcl[(lv << 1) + 1];
    yv = vcl[(lv << 1) + 2];
L20:
    ivs = pvl[(iv << 2) + 3];
    lv = pvl[(ivs << 2) + 1];
    xvs = vcl[(lv << 1) + 1];
    yvs = vcl[(lv << 1) + 2];
    if (yv <= ytptol && yvs > ytptol) {
	if (yv >= ytmtol) {
	    if (xv > xt) {
		if (xv < xrgt || irgt == 0) {
		    irgt = iv;
		    xrgt = xv;
		    yrgt = yv;
		    srgt = (xvs - xv) / (yvs - yv);
		} else if (xv == xrgt) {
		    s = (xvs - xv) / (yvs - yv);
		    if (s < srgt) {
			irgt = iv;
			yrgt = yv;
			srgt = s;
		    }
		}
	    }
	} else {
	    xint = (yt - yv) * (xvs - xv) / (yvs - yv) + xv;
	    if (xint > xt) {
		if (xint < xrgt || irgt == 0) {
		    irgt = iv;
		    xrgt = xint;
		    yrgt = yt;
		}
	    }
	}
    } else if (yv > ytptol && yvs <= ytptol) {
	if (yvs >= ytmtol) {
	    if (xvs < xt) {
		if (xvs > xlft || ilft == 0) {
		    ilft = iv;
		    xlft = xvs;
		    ylft = yvs;
		    slft = (xvs - xv) / (yvs - yv);
		} else if (xvs == xlft) {
		    s = (xvs - xv) / (yvs - yv);
		    if (s > slft) {
			ilft = iv;
			ylft = yvs;
			slft = s;
		    }
		}
	    }
	} else {
	    xint = (yt - yv) * (xvs - xv) / (yvs - yv) + xv;
	    if (xint < xt) {
		if (xint > xlft || ilft == 0) {
		    ilft = iv;
		    xlft = xint;
		    ylft = yt;
		}
	    }
	}
    }
    iv = ivs;
    xv = xvs;
    yv = yvs;
    if (iv != hv) {
	goto L20;
    }

    if (ilft == 0 || irgt == 0) {
	gerror_1.ierr = 218;
	return 0;
    }

/*     Temporarily modify PVL to pass the subregion 'above' top vertex */
/*     of hole to routine RESVRT. The top vertex is the reflex vertex */
/*     passed to RESVRT (in the temporary subregion, it has interior */
/*     angle PI). This causes one separator to be chosen by RESVRT */
/*     and its other endpoint is above the top vertex. */

    succil = pvl[(ilft << 2) + 3];
    succir = pvl[(irgt << 2) + 3];
    vcl[(*nvc + 2 << 1) + 1] = xlft;
    vcl[(*nvc + 2 << 1) + 2] = ylft;
    vcl[(*nvc + 3 << 1) + 1] = xrgt;
    vcl[(*nvc + 3 << 1) + 2] = yrgt;
    vp = *nvert + 3;
    vr = *nvert + 4;
    vs = *nvert + 5;
    iang[vr] = angle_(&xlft, &ylft, &xt, &yt, &xrgt, &yrgt);
    if (iang[vr] < gconst_1.pi - gconst_1.tol || iang[vr] > gconst_1.pi + 
	    gconst_1.tol) {
	gerror_1.ierr = 219;
	return 0;
    }
    pvl[(vp << 2) + 1] = *nvc + 2;
    pvl[(vp << 2) + 2] = ipoly;
    pvl[(vp << 2) + 3] = vr;
    pvl[(vp << 2) + 4] = 0;
    pvl[(vr << 2) + 1] = pvl[(*itophv << 2) + 1];
    pvl[(vr << 2) + 2] = ipoly;
    pvl[(vr << 2) + 3] = vs;
    pvl[(vr << 2) + 4] = 0;
    pvl[(vs << 2) + 1] = *nvc + 3;
    pvl[(vs << 2) + 2] = ipoly;
    pvl[(vs << 2) + 3] = succir;
    pvl[(vs << 2) + 4] = pvl[(irgt << 2) + 4];
    pvl[(ilft << 2) + 3] = vp;
    lv = pvl[(ilft << 2) + 1];
    iang[vp] = angle_(&vcl[(lv << 1) + 1], &vcl[(lv << 1) + 2], &xlft, &ylft, 
	    &xt, &yt);
    lv = pvl[(succir << 2) + 1];
    iang[vs] = angle_(&xt, &yt, &xrgt, &yrgt, &vcl[(lv << 1) + 1], &vcl[(lv <<
	     1) + 2]);
    w = 0;
    resvrt_(&vr, angspc, angtol, nvc, nvert, maxvc, maxpv, maxiw, maxwk, &vcl[
	    3], &pvl[5], &iang[1], &w, &ww, &iwk[1], &wk[1]);

/*     Remove temporary modification to PVL. There are three cases */
/*     depending on where the endpoint of separator is located: */
/*     successor of closest vertex to the right of top vertex, */
/*     predecessor of closest vertex to the left of top vertex, */
/*     or neither of these. */

    if (pvl[(vs << 2) + 3] == w) {
	pvl[(ilft << 2) + 3] = succil;
	pvl[(irgt << 2) + 3] = w;
	pvl[(irgt << 2) + 4] = pvl[(vs << 2) + 4];
	if (pvl[(irgt << 2) + 4] > 0) {
	    pvl[(pvl[(irgt << 2) + 4] << 2) + 4] = irgt;
	}
    } else if (pvl[(ilft << 2) + 3] == w) {
	pvl[(w << 2) + 3] = succil;
    } else {
	pvl[(ilft << 2) + 3] = succil;
    }
    if (gerror_1.ierr != 0) {
	return 0;
    }

/*     Update PVL with cut edge, i.e. join linked lists of vertices */
/*     of the hole polygon and the outer boundary polygon into one */
/*     linked list of vertices by adding the cut edge from the top */
/*     vertex of hole to the vertex on the outer boundary. */

    *nvert += 2;
    vv = *nvert - 1;
    ww = *nvert;
    lv = pvl[(*itophv << 2) + 1];
    lw = pvl[(w << 2) + 1];
    pvl[(vv << 2) + 1] = lv;
    pvl[(ww << 2) + 1] = lw;
    pvl[(vv << 2) + 2] = ipoly;
    pvl[(ww << 2) + 2] = ipoly;
    pvl[(vv << 2) + 3] = pvl[(*itophv << 2) + 3];
    pvl[(ww << 2) + 3] = pvl[(w << 2) + 3];
    pvl[(*itophv << 2) + 3] = ww;
    pvl[(w << 2) + 3] = vv;
    pvl[(vv << 2) + 4] = pvl[(*itophv << 2) + 4];
    pvl[(ww << 2) + 4] = pvl[(w << 2) + 4];
    pvl[(*itophv << 2) + 4] = w;
    pvl[(w << 2) + 4] = *itophv;
    if (pvl[(vv << 2) + 4] > 0) {
	pvl[(pvl[(vv << 2) + 4] << 2) + 4] = vv;
    }
    if (pvl[(ww << 2) + 4] > 0) {
	pvl[(pvl[(ww << 2) + 4] << 2) + 4] = ww;
    }
    l = pvl[(pvl[(vv << 2) + 3] << 2) + 1];
    iang[vv] = angle_(&vcl[(lw << 1) + 1], &vcl[(lw << 1) + 2], &vcl[(lv << 1)
	     + 1], &vcl[(lv << 1) + 2], &vcl[(l << 1) + 1], &vcl[(l << 1) + 2]
	    );
    iang[*itophv] -= iang[vv];
    l = pvl[(pvl[(ww << 2) + 3] << 2) + 1];
    iang[ww] = angle_(&vcl[(lv << 1) + 1], &vcl[(lv << 1) + 2], &vcl[(lw << 1)
	     + 1], &vcl[(lw << 1) + 2], &vcl[(l << 1) + 1], &vcl[(l << 1) + 2]
	    );
    iang[w] -= iang[ww];

} /* jnhole_ */


/*     The following code was excerpted from: minang.f */

doublereal minang_(xr, yr, xs, ys, ind, alpha, theta, vcl, pvl, iang)
doublereal *xr, *yr, *xs, *ys;
integer *ind;
doublereal *alpha, *theta, *vcl;
integer *pvl;
doublereal *iang;
{
    /* System generated locals */
    doublereal ret_val, d__1, d__2;

    /* Local variables */
    static doublereal beta1;
    static integer j, l;
    extern doublereal angle_();
    static doublereal ang;


/*     Written and copyright by: */
/*        Barry Joe, Dept. of Computing Science, Univ. of Alberta */
/*        Edmonton, Alberta, Canada  T6G 2H1 */
/*        Phone: (403) 492-5757      Email: barry@cs.ualberta.ca */

/*     Purpose: Determine the minimum of the 4 angles at the boundary */
/*        resulting from using edge joining vertices (XR,YR) and */
/*        (XS,YS) as a separator. */

/*     Input parameters: */
/*        XR,YR - coordinates of reflex vertex */
/*        XS,YS - coordinates of other endpoint of possible separator */
/*        IND - if positive then (XS,YS) has index IND in PVL; else */
/*              (XS,YS) is on edge joining vertices with indices -IND */
/*              and SUCC(-IND) in PVL */
/*        ALPHA - polar angle of (XS,YS) w.r.t. (XR,YR) */
/*        THETA - interior angle at reflex vertex */
/*        VCL(1:2,1:*) - vertex coordinate list */
/*        PVL(1:4,1:*),IANG(1:*) - polygon vertex list, interior angles */


/*     Returned function value: */
/*        MINANG - minimum of the 4 angles in radians */

/*     Routines called: */
/*        ANGLE */




    /* Parameter adjustments */
    --iang;
    pvl -= 5;
    vcl -= 3;

    /* Function Body */
    if (*ind > 0) {
	j = pvl[(*ind << 2) + 3];
	ang = iang[*ind];
    } else {
	j = pvl[(-(*ind) << 2) + 3];
	ang = gconst_1.pi;
    }
    l = pvl[(j << 2) + 1];
    beta1 = angle_(xr, yr, xs, ys, &vcl[(l << 1) + 1], &vcl[(l << 1) + 2]);
/* Computing MIN */
    d__1 = *alpha, d__2 = *theta - *alpha, d__1 = min(d__1,d__2), d__2 = ang 
	    - beta1, d__1 = min(d__1,d__2);
    ret_val = min(d__1,beta1);
    return ret_val;
} /* minang_ */


/*     The following code was excerpted from: resvrt.f */

/* Subroutine */ int resvrt_(vr, angspc, angtol, nvc, nvert, maxvc, maxpv, 
	maxiw, maxwk, vcl, pvl, iang, w1, w2, iwk, wk)
integer *vr;
doublereal *angspc, *angtol;
integer *nvc, *nvert, *maxvc, *maxpv, *maxiw, *maxwk;
doublereal *vcl;
integer *pvl;
doublereal *iang;
integer *w1, *w2, *iwk;
doublereal *wk;
{
    /* System generated locals */
    integer i__1;
    doublereal d__1;

    /* Local variables */
    static integer maxn, ivis, ivor, nvis, ivrt, nvor, nvrt, xvor, yvor, i, l,
	     v, theta, wkang, i1, i2;
    extern /* Subroutine */ int insvr2_();
    static integer xc, yc;
    static doublereal xr, yr, angsep;
    extern /* Subroutine */ int fndsep_(), vornbr_(), vispol_(), visvrt_();
    static integer nvsvrt;


/*     Written and copyright by: */
/*        Barry Joe, Dept. of Computing Science, Univ. of Alberta */
/*        Edmonton, Alberta, Canada  T6G 2H1 */
/*        Phone: (403) 492-5757      Email: barry@cs.ualberta.ca */

/*     Purpose: Resolve reflex vertex of simply connected polygon with */
/*        one or two separators. The reflex vertex must be a 'simple' */
/*        vertex of the polygon. */

/*     Input parameters: */
/*        VR - index in PVL of reflex vertex */
/*        ANGSPC - angle spacing parameter used in controlling the */
/*              vertices to be considered as an endpoint of a separator */

/*        ANGTOL - angle tolerance parameter used in accepting */
/*              separator(s) */
/*        NVC - number of positions used in VCL array */
/*        NVERT - number of positions used in PVL array */
/*        MAXVC - maximum size available for VCL array */
/*        MAXPV - maximum size available for PVL array */
/*        MAXIW - maximum size available for IWK array; should be about */

/*              3 times number of vertices in polygon */
/*        MAXWK - maximum size available for WK array; should be about */
/*              5 times number of vertices in polygon */
/*        VCL(1:2,1:NVC) - vertex coordinate list */
/*        PVL(1:4,1:NVERT),IANG(1:NVERT) - polygon vertex list and */
/*              interior angles */

/*     Updated parameters: */
/*        NVC,NVERT,VCL,PVL,IANG - are updated if INSVR2 is called */

/*     Output parameters: */
/*        W1 - index in PVL of vertex which is the endpoint of separator 
*/
/*              in inner cone or right cone w.r.t. reflex vertex */
/*        W2 - 0 if there is only one separator; else index in PVL of */
/*              vertex which is endpoint of 2nd separator in left cone */

/*     Working parameters: */
/*        IWK(1:MAXIW) - integer work array */
/*        WK(1:MAXWK) - double precision work array */

/*     Abnormal return: */
/*        IERR is set to 3, 5, 6, 7, 206, 207, 208, 209, 210, or 212 */

/*     Routines called: */
/*        FNDSEP, INSVR2, VISPOL, VISVRT, VORNBR */




/*     Determine number of vertices in polygon containing reflex vertex. 
*/

    /* Parameter adjustments */
    --wk;
    --iwk;
    --iang;
    pvl -= 5;
    vcl -= 3;

    /* Function Body */
    nvrt = 0;
    v = *vr;
L10:
    v = pvl[(v << 2) + 3];
    if (v != *vr) {
	++nvrt;
	goto L10;
    }
    maxn = nvrt + (integer) (iang[*vr] / *angspc);
    l = pvl[(*vr << 2) + 1];
    xr = vcl[(l << 1) + 1];
    yr = vcl[(l << 1) + 2];

/*     Set up work arrays for routine VISPOL, and determine whether there 
*/
/*     is enough workspace. XC, YC are d.p. arrays of length NVRT in WK, 
*/
/*     used for the coordinates of the polygon containing the reflex */
/*     vertex. MAXN positions are reserved for XC, YC since this is the */

/*     maximum space required by routine VISVRT. IVIS is an integer array 
*/
/*     of length MAXN in IWK. IVRT is an integer array of length NVRT in 
*/
/*     IWK used temporarily for storing indices of vertices in PVL. */

    if (maxn + nvrt > *maxiw) {
	gerror_1.ierr = 6;
	return 0;
    } else if (maxn + maxn > *maxwk) {
	gerror_1.ierr = 7;
	return 0;
    }
    ivis = 1;
    ivrt = ivis + maxn;
    xc = 1;
    yc = xc + maxn;
    v = pvl[(*vr << 2) + 3];
    i__1 = nvrt - 1;
    for (i = 0; i <= i__1; ++i) {
	l = pvl[(v << 2) + 1];
	wk[xc + i] = vcl[(l << 1) + 1];
	wk[yc + i] = vcl[(l << 1) + 2];
	iwk[ivrt + i] = v;
	v = pvl[(v << 2) + 3];
/* L20: */
    }
    i__1 = nvrt - 1;
    vispol_(&xr, &yr, &i__1, &wk[xc], &wk[yc], &nvis, &iwk[ivis]);
    if (gerror_1.ierr != 0) {
	return 0;
    }

/*     XC, YC now contain visibility polygon coordinates. Update MAXN */
/*     and set up d.p. array THETA of length MAXN in WK for routine */
/*     VISVRT. Elements of IVIS are changed to indices of PVL after call. 
*/

    maxn = maxn - nvrt + nvis + 1;
    theta = yc + maxn;
    if (theta + maxn - 1 > *maxwk) {
	gerror_1.ierr = 7;
	return 0;
    }
    i__1 = maxn - 1;
    visvrt_(angspc, &xr, &yr, &nvis, &wk[xc], &wk[yc], &iwk[ivis], &i__1, &
	    nvsvrt, &wk[theta]);
    wk[theta + nvsvrt] = iang[*vr];
    i__1 = ivis + nvsvrt;
    for (i = ivis; i <= i__1; ++i) {
	l = iwk[i];
	if (l >= 0) {
	    iwk[i] = iwk[ivrt + l];
	} else {
	    iwk[i] = -iwk[ivrt - l - 1];
	}
/* L30: */
    }

/*     XC, YC now contain coord. of visible vertices to be considered */
/*     as an endpoint of a separator. Set up work arrays for routine */
/*     VORNBR. Integer array IVOR and d.p. arrays XVOR, YVOR, each of */
/*     length NVSVRT+1, are added at the end of IWK and WK arrays. */

    ivor = ivis + nvsvrt + 1;
    xvor = theta + nvsvrt + 1;
    yvor = xvor + nvsvrt + 1;
    if (ivor + nvsvrt > *maxiw) {
	gerror_1.ierr = 6;
	return 0;
    } else if (yvor + nvsvrt > *maxwk) {
	gerror_1.ierr = 7;
	return 0;
    }
    vornbr_(&xr, &yr, &nvsvrt, &wk[xc], &wk[yc], &nvor, &iwk[ivor], &wk[xvor],
	     &wk[yvor]);
    if (gerror_1.ierr != 0) {
	return 0;
    }

/*     Set up d.p. array WKANG of length NVOR+1 <= NVSVRT+1 in WK for */
/*     routine FNDSEP. Only Voronoi neighbours are considered as an */
/*     endpoint of a separator in the first call to FNDSEP. If the */
/*     minimum angle created at the boundary by the separator(s) is too */

/*     small, then a second call is made to FNDSEP in which all visible */

/*     vertices are considered as an endpoint of a separator. */

    wkang = xvor;
    if (iwk[ivor + nvor] == nvsvrt) {
	--nvor;
    }
    if (iwk[ivor] == 0) {
	++ivor;
	--nvor;
    }
    d__1 = *angtol + *angtol;
    fndsep_(&d__1, &xr, &yr, &nvsvrt, &wk[xc], &wk[yc], &iwk[ivis], &wk[theta]
	    , &nvor, &iwk[ivor], &vcl[3], &pvl[5], &iang[1], &angsep, &i1, &
	    i2, &wk[wkang]);
    if (angsep < *angtol) {
	ivrt = ivis + nvsvrt + 1;
	i__1 = nvsvrt - 1;
	for (i = 1; i <= i__1; ++i) {
	    iwk[ivrt + i - 1] = i;
/* L40: */
	}
	d__1 = *angtol + *angtol;
	i__1 = nvsvrt - 2;
	fndsep_(&d__1, &xr, &yr, &nvsvrt, &wk[xc], &wk[yc], &iwk[ivis], &wk[
		theta], &i__1, &iwk[ivrt], &vcl[3], &pvl[5], &iang[1], &
		angsep, &i1, &i2, &wk[wkang]);
    }

/*     Insert endpoint(s) of separator(s) in vertex coordinate list and */

/*     polygon vertex list data structures, if they are not yet there. */

    if (i2 == -1) {
	*w2 = 0;
    } else if (iwk[ivis + i2] < 0) {
	i__1 = -iwk[ivis + i2];
	insvr2_(&wk[xc + i2], &wk[yc + i2], &i__1, nvc, nvert, maxvc, maxpv, &
		vcl[3], &pvl[5], &iang[1], w2);
	if (gerror_1.ierr != 0) {
	    return 0;
	}
    } else {
	*w2 = iwk[ivis + i2];
    }
    if (iwk[ivis + i1] < 0) {
	i__1 = -iwk[ivis + i1];
	insvr2_(&wk[xc + i1], &wk[yc + i1], &i__1, nvc, nvert, maxvc, maxpv, &
		vcl[3], &pvl[5], &iang[1], w1);
	if (gerror_1.ierr != 0) {
	    return 0;
	}
    } else {
	*w1 = iwk[ivis + i1];
    }
} /* resvrt_ */


/*     The following code was excerpted from: spdec2.f */

/* Subroutine */ int spdec2_(angspc, angtol, nvc, npolg, nvert, nhole, nhola, 
	maxvc, maxhv, maxpv, maxiw, maxwk, holv, vcl, regnum, hvl, pvl, iang, 
	iwk, wk)
doublereal *angspc, *angtol;
integer *nvc, *npolg, *nvert, *nhole, *nhola, *maxvc, *maxhv, *maxpv, *maxiw, 
	*maxwk, *holv;
doublereal *vcl;
integer *regnum, *hvl, *pvl;
doublereal *iang;
integer *iwk;
doublereal *wk;
{
    /* System generated locals */
    integer i__1;

    /* Local variables */
    static integer i, j, p, w1, w2;
    extern /* Subroutine */ int insed2_();
    static logical ci, cj;
    static integer vr;
    extern /* Subroutine */ int jnhole_();
    static doublereal piptol;
    extern /* Subroutine */ int resvrt_();


/*     Written and copyright by: */
/*        Barry Joe, Dept. of Computing Science, Univ. of Alberta */
/*        Edmonton, Alberta, Canada  T6G 2H1 */
/*        Phone: (403) 492-5757      Email: barry@cs.ualberta.ca */

/*     Purpose: Decompose general polygonal region with interfaces and */
/*        holes into simple polygons using vertex coordinate list, */
/*        head vertex list, and polygon vertex list data structures. */

/*     Input parameters: */
/*        ANGSPC - angle spacing parameter in radians used in controlling 
*/
/*              vertices to be considered as an endpoint of a separator */

/*        ANGTOL - angle tolerance parameter in radians used in accepting 
*/
/*              separator(s) */
/*        NVC - number of vertex coordinates or positions used in VCL */
/*              array */
/*        NPOLG - number of polygonal subregions or positions used in */
/*              HVL array */
/*        NVERT - number of polygon vertices or positions used in PVL */
/*              array */
/*        NHOLE - number of holes and hole interfaces */
/*        NHOLA - number of 'attached' holes; these holes are attached */
/*              to the outer boundary of a subregion through vertices */
/*              or cut interfaces and have their edges in consecutive */
/*              order on the boundary */
/*        MAXVC - maximum size available for VCL array, should be >= */
/*              number of vertex coordinates required for decomposition */

/*        MAXHV - maximum size available for HVL, REGNUM arrays, should */

/*              be >= number of polygons required for decomposition */
/*        MAXPV - maximum size available for PVL, IANG arrays; should be 
*/
/*              >= number of polygon vertices required for decomposition 
*/
/*        MAXIW - maximum size available for IWK array; should be about */

/*              3 times maximum number of vertices in any polygon */
/*        MAXWK - maximum size available for WK array; should be about */
/*              5 times maximum number of vertices in any polygon */
/*        HOLV(1:NHOLE*2+NHOLA) - indices in PVL of bottom or top vertex 
*/
/*              of holes; first (next) NHOLE entries are for top (bottom) 
*/
/*              vertices of holes and hole interfaces, with top (bottom) 
*/
/*              vertices sorted in decreasing (increasing) lexicographic 
*/
/*              (y,x) order of coord; last NHOLA entries are for attached 
*/
/*              holes; if bottom vertex of attached hole is a simple */
/*              vertex of boundary curve containing the hole then entry */

/*              contains index of bottom vertex otherwise entry contains 
*/
/*              index of top vertex (which is simple) */
/*        VCL(1:2,1:NVC) - vertex coordinate list */
/*        REGNUM(1:NPOLG) - region numbers */
/*        HVL(1:NPOLG) - head vertex list */
/*        PVL(1:4,1:NVERT),IANG(1:NVERT) - polygon vertex list and */
/*              interior angles; see routine DSPGDC for more details */
/*        [Note: The data structures should be as output from routines */
/*              DSMCPR or DSPGDC.] */

/*     Updated parameters: */
/*        NVC,NPOLG,NVERT,VCL,REGNUM,HVL,PVL,IANG */

/*     Working parameters: */
/*        IWK(1:MAXIW) - integer work array */
/*        WK(1:MAXWK) - double precision work array */

/*     Abnormal return: */
/*        IERR is set to 3, 4, 5, 6, 7, 206 to 210, 212, 218, or 219 */

/*     Routines called: */
/*        INSED2, JNHOLE, RESVRT */




/*     For each simple hole, find cut edge from top vertex of hole to */
/*     a point on the outer boundary above top vertex, and update */
/*     VCL, HVL, PVL, IANG. */

    /* Parameter adjustments */
    --wk;
    --iwk;
    --iang;
    pvl -= 5;
    --hvl;
    --regnum;
    vcl -= 3;
    --holv;

    /* Function Body */
    piptol = gconst_1.pi + gconst_1.tol;
    i__1 = *nhole;
    for (i = 1; i <= i__1; ++i) {
	jnhole_(&holv[i], angspc, angtol, nvc, nvert, maxvc, maxpv, maxiw, 
		maxwk, &vcl[3], &hvl[1], &pvl[5], &iang[1], &iwk[1], &wk[1]);
	if (gerror_1.ierr != 0) {
	    return 0;
	}
/* L10: */
    }

/*     Resolve remaining vertices in HOLV array if they are reflex */
/*     vertices. These vertices may no longer be reflex if they are the */

/*     endpoint of a cut edge from the top vertex of another hole or */
/*     of a previous separator. */

    i__1 = *nhole + *nhole + *nhola;
    for (i = *nhole + 1; i <= i__1; ++i) {
	vr = holv[i];
	if (iang[vr] > piptol) {
	    resvrt_(&vr, angspc, angtol, nvc, nvert, maxvc, maxpv, maxiw, 
		    maxwk, &vcl[3], &pvl[5], &iang[1], &w1, &w2, &iwk[1], &wk[
		    1]);
	    if (gerror_1.ierr != 0) {
		return 0;
	    }
	    insed2_(&vr, &w1, npolg, nvert, maxhv, maxpv, &vcl[3], &regnum[1],
		     &hvl[1], &pvl[5], &iang[1]);
	    if (gerror_1.ierr != 0) {
		return 0;
	    }
	    if (w2 > 0) {
		insed2_(&vr, &w2, npolg, nvert, maxhv, maxpv, &vcl[3], &
			regnum[1], &hvl[1], &pvl[5], &iang[1]);
	    }
	    if (gerror_1.ierr != 0) {
		return 0;
	    }
	}
/* L20: */
    }
    if (*nhola == 0) {
	return 0;
    }

/*     Check that polygons are simple. If polygon is simply-connected and 
*/
/*     not simple then find a simple reflex vertex in polygon to resolve. 
*/

    p = 1;
L30:
    if (p > *npolg) {
	return 0;
    }
    i = hvl[p];
L40:
    if (pvl[(pvl[(i << 2) + 4] << 2) + 2] == p) {
	goto L50;
    }
    i = pvl[(i << 2) + 3];
    if (i != hvl[p]) {
	goto L40;
    }
    ++p;
    goto L30;
L50:
    ci = TRUE_;
L60:
    j = pvl[(i << 2) + 3];
    cj = pvl[(pvl[(j << 2) + 4] << 2) + 2] == p;
    if (ci || cj || iang[j] <= piptol) {
	i = j;
	ci = cj;
	goto L60;
    }
    vr = j;
    resvrt_(&vr, angspc, angtol, nvc, nvert, maxvc, maxpv, maxiw, maxwk, &vcl[
	    3], &pvl[5], &iang[1], &w1, &w2, &iwk[1], &wk[1]);
    if (gerror_1.ierr != 0) {
	return 0;
    }
    insed2_(&vr, &w1, npolg, nvert, maxhv, maxpv, &vcl[3], &regnum[1], &hvl[1]
	    , &pvl[5], &iang[1]);
    if (gerror_1.ierr != 0) {
	return 0;
    }
    if (w2 > 0) {
	insed2_(&vr, &w2, npolg, nvert, maxhv, maxpv, &vcl[3], &regnum[1], &
		hvl[1], &pvl[5], &iang[1]);
    }
    if (gerror_1.ierr != 0) {
	return 0;
    }
    goto L30;
} /* spdec2_ */

