Пример #1
0
/*------------------------------------------------------------------------------
   theta_ij = angle in radians between two unit vectors.
*/
double thij(vec rpi, vec rpj)
{
    double cm, th;

    cm = cmij(rpi, rpj);
    th = 2. * asin(cm / 2.);

    return(th);
}
Пример #2
0
/*------------------------------------------------------------------------------
  Determine whether the first vertex in vert
  is closer to the nearest vertex or to the nearest antivertex of poly.

  Return value: 0 or 1 as first vertex of vert is closer to the nearest
		       vertex or antivertex of poly;
		-1 if error.
*/
int antivert(vertices *vert, polygon *poly)
{
    const int do_vcirc = 0, nve = 1, per = 0;
    int anti, ier, iv, nev, nev0, nv;
    int *ipv, *gp, *ev;
    double cm, cmmax, cmmin, tol;
    double *angle;
    vec rp;
    vec *ve;

    /* vert has no vertices */
    if (vert->nv == 0) return(0);

    /* vertices of polygon */
    tol = mtol;
    ier = gverts(poly, do_vcirc, &tol, per, nve, &nv, &ve, &angle, &ipv, &gp, &nev, &nev0, &ev);

    /* error */
    if (ier) return(-1);

    /* poly has less than 3 vertices */
    if (nv < 3) return(0);

    /* convert first vertex to unit vector */
    azel_to_rp(&vert->v[0], rp);

    cmmin = 2.;
    cmmax = 0.;
    for (iv = 0; iv < nv; iv++) {
	cm = cmij(rp, ve[iv]);
	if (cm < cmmin) cmmin = cm;
	if (cm > cmmax) cmmax = cm;
    }
    anti = ((cmmin + cmmax <= 2.)? 0 : 1);

    return(anti);
}
Пример #3
0
/*------------------------------------------------------------------------------
  Snap edge of poly2 to cap boundary of poly1.
  Caps of poly2 are adjusted to equal those of poly1.

  Input:  poly1, poly2 = pointers to polygon structures.
	  thtol = edge tolerance in radians.
	  ytol = edge to length tolerance;
		 if the two vertices and centre point of an edge of poly2 are
		 all closer to a boundary of poly1 than the lesser of
		 (1) thtol, and
		 (2) ytol times the length of the edge,
		 and if in addition at least one of the three points lies
		 inside poly1 (sans said boundary),
		 then make boundary of the poly2 cap equal to that of poly1.
	  mtol = initial tolerance angle for multiple intersections in radians.
  Output: adjusted caps of poly2 (i.e. poly2->rp, poly2->cm).
  Return value: number of caps adjusted,
		or -1 if error occurred.
*/
int snap_polyth(polygon *poly1, polygon *poly2, double thtol, double ytol, double mtol)
{
    const int per = 0;
    const int nve = 2;

    int adjusted, do_vcirc, i, ier, in, ip1, ip2, iv, ivp, nadj, nev, nev0, nv;
    int *ipv, *gp, *ev;
    double cm, cm1, dth, dthmax, sp, tol;
    double *angle;
    vec *v, *ve;
        
    // vertices and centres of edges of poly2 
    do_vcirc = 0;
    tol = mtol;
    ier = gverts(poly2, do_vcirc, &tol, per, nve, &nv, &ve, &angle, &ipv, &gp, &nev, &nev0, &ev);
    if (ier != 0) return(-1);

    // convert angle of each edge to scalar length angle * sin(theta)
    for (iv = 0; iv < nv; iv++) {
	ip2 = ipv[iv];
	cm = fabs(poly2->cm[ip2]);
	angle[iv] = angle[iv] * sqrt(cm * (2. - cm));
    }

    nadj = 0;
    
    // for each edge of poly2 ... 
    for (iv = 0; iv < nv; iv++) {
	ivp = (iv + 1) % nv;
	ip2 = ipv[iv];
	
	// ... and each axis of poly1
	for (ip1 = 0; ip1 < poly1->np; ip1++) {
	    adjusted = 0;

	    // distance from edge of poly2 to cap of poly1
	    cm1 = poly1->cm[ip1];
            poly1->cm[ip1] = 2.;        // suppress cap of poly1
	    in = 0;
	    dthmax = 0.;
	    
	    for (i = 0; i < 3; i++) {
	      // vertex, centre point, vertex of edge of poly2
	      v = &ve[(iv * nve + i) % (nv * nve)];  //doesn't segfault without this line
	      in |= gptin(poly1, *v);	// in if any one point is in  doesn't segfault without this line
	      cm = cmij(*v, poly1->rp[ip1]); // doesn't segfault without this line
	      dth = 2. * (sqrt(cm/2.) - sqrt(fabs(cm1/2.)));
	      dth = fabs(dth);	// angle from point to cap of poly1
	      if (dth > dthmax) dthmax = dth;
	    }
            poly1->cm[ip1] = cm1;       // restore cap of poly1
	    
	      
	    // three points of poly2 edge are all close to boundary of poly1
	    
	    if (in && dthmax <= thtol && dthmax <= ytol * angle[iv]) {
	      sp = poly1->rp[ip1][0] * poly2->rp[ip2][0] + poly1->rp[ip1][1] * poly2->rp[ip2][1] + poly1->rp[ip1][2] * poly2->rp[ip2][2];
	      sp = (sp >= 0.)? 1. : -1.;
	      if (!(poly2->rp[ip2][0] == poly1->rp[ip1][0]
		    && poly2->rp[ip2][1] == poly1->rp[ip1][1]
		    && poly2->rp[ip2][2] == poly1->rp[ip1][2])) {
		// make axis of poly2 cap exactly equal to that of poly1 
		poly2->rp[ip2][0] = poly1->rp[ip1][0];
		poly2->rp[ip2][1] = poly1->rp[ip1][1];
		poly2->rp[ip2][2] = poly1->rp[ip1][2];
		adjusted = 1;
	      }
	      // set latitude of poly2 cap equal to that of poly1 
	      cm = (poly2->cm[ip2] >= 0.)?
		sp * fabs(poly1->cm[ip1]):
		- sp * fabs(poly1->cm[ip1]);
	      if (poly2->cm[ip2] != cm) {
		poly2->cm[ip2] = cm;
		adjusted = 1;
	      }
	      if (adjusted) nadj++;
	    }
	    
	}
    }

    // trim adjusted polygon
    if (nadj > 0) trim_poly(poly2);
    
    return(nadj);
}
Пример #4
0
/*------------------------------------------------------------------------------
  Counts of pairs in bins bounded by radii th, centred at az el.

  Anglar positions az, el are read from azel_in_filename,
  angular radii th are read from th_in_filename,
  or from azel_in_filename if th_in_filename is null,
  and the results are written to out_filename.

  Implemented as interpretive read/write, to permit interactive behaviour.

   Input: azel_in_filename = name of file to read az, el from;
			"" or "-" means read from standard input.
	  th_in_filename = name of file to read th from;
			"" or "-" means read from standard input.
	  out_filename = name of file to write to;
			"" or "-" means write to standard output.
	  fmt = pointer to format structure.
	  npoly = number of polygons in poly array.
	  poly = array of pointers to polygons.
  Return value: number of distinct pairs counted,
		or -1 if error occurred.
*/
long ddcount(char *azel_in_filename, char *th_in_filename, char *out_filename, format *fmt, int npoly, polygon *poly[/*npoly*/])
{
#define AZEL_STR_LEN	32
    char input[] = "input", output[] = "output";
    /* maximum number of angular angular radii: will expand as necessary */
    static int nthmax = 0;
    /* maximum number of az-el points: will expand as necessary */
    static int nazelmax = 0;
    static int *dd = 0x0, *id = 0x0, *iord = 0x0;
    static long double *cm = 0x0, *th = 0x0;
    static azel *v = 0x0;
    static vec *rp = 0x0;

#ifdef TIME
    clock_t time;
#endif
    char inunit;
    char *word, *next;
    char th_str[AZEL_STR_LEN];
    int i, iazel, idi, ird, ith, j, jazel, manyid, nazel, nid, noid, nth;
    int *id_p;
    long np;
    long double az, cmm, el, s, t;
    char *out_fn;
    FILE *outfile;

    /* open th_in_filename for reading */
    if (strcmp(th_in_filename, "-") == 0) {
	file.file = stdin;
	file.name = input;
    } else {
	file.file = fopen(th_in_filename, "r");
	if (!file.file) {
	    fprintf(stderr, "cannot open %s for reading\n", th_in_filename);
	    return(-1);
	}
	file.name = th_in_filename;
    }
    file.line_number = 0;

    inunit = (fmt->inunit == 'h')? 'd' : fmt->inunit;
    msg("will take units of input th angles in %s to be ", file.name);
    switch (inunit) {
#include "angunit.h"
    }
    msg("\n");

    /* read angular radii th from th_in_filename */
    nth = 0;
    while (1) {
	/* read line */
	ird = rdline(&file);
	/* serious error */
	if (ird == -1) return(-1);
	/* EOF */
	if (ird == 0) break;
	/* read angular radius from line */
	ird = rdangle(file.line, &next, inunit, &t);
	/* error */
	if (ird < 1) {
	    /* retry if nothing read, otherwise break */
	    if (nth > 0) break;
	/* ok */
	} else if (ird == 1) {
	    if (nth >= nthmax) {
		if (nthmax == 0) {
		    nthmax = 64;
		} else {
		    nthmax *= 2;
		}
		/* (re)allocate memory for th array */
		th = (long double *) realloc(th, sizeof(long double) * nthmax);
		if (!th) {
		    fprintf(stderr, "ddcount: failed to allocate memory for %d long doubles\n", nthmax);
		    return(-1);
		}
	    }
	    /* store th */
	    th[nth] = t;
	    nth++;
	}
    }

    if (file.file != stdin) {
	/* close th_in_filename */
	fclose(file.file);
	/* advise */
	msg("%d angular radii read from %s\n", nth, file.name);
    }

    if (nth == 0) return(nth);

    /* open azel_in_filename for reading */
    if (!azel_in_filename || strcmp(azel_in_filename, "-") == 0) {
	file.file = stdin;
	file.name = input;
    } else {
	file.file = fopen(azel_in_filename, "r");
	if (!file.file) {
	    fprintf(stderr, "cannot open %s for reading\n", azel_in_filename);
	    return(-1);
	}
	file.name = azel_in_filename;
    }
    file.line_number = 0;

    /* advise input angular units */
    msg("will take units of input az, el angles in %s to be ", file.name);
    switch (fmt->inunit) {
#include "angunit.h"
    }
    msg("\n");

    /* read angular positions az, el from azel_in_filename */
    nazel = 0;
    while (1) {
	/* read line */
	ird = rdline(&file);
	/* serious error */
	if (ird == -1) return(-1);
	/* EOF */
	if (ird == 0) break;

	/* read <az> */
	word = file.line;
	ird = rdangle(word, &next, fmt->inunit, &az);
	/* skip header */
	if (ird != 1 && nazel == 0) continue;
	/* otherwise exit on unrecognized characters */
	if (ird != 1) break;

	/* read <el> */
	word = next;
	ird = rdangle(word, &next, fmt->inunit, &el);
	/* skip header */
	if (ird != 1 && nazel == 0) continue;
	/* otherwise exit on unrecognized characters */
	if (ird != 1) break;

	/* (re)allocate memory for array of az-el points */
	if (nazel >= nazelmax) {
	    if (nazelmax == 0) {
		nazelmax = 64;
	    } else {
		nazelmax *= 2;
	    }
	    v = (azel *) realloc(v, sizeof(azel) * nazelmax);
	    if (!v) {
		fprintf(stderr, "ddcount: failed to allocate memory for %d az-el points\n", nazelmax);
		return(-1);
	    }
	}

	/* record az-el */
	v[nazel].az = az;
	v[nazel].el = el;

        /* increment number of az-el points */
	nazel++;
    }

    if (file.file != stdin) {
	/* close azel_in_filename */
	fclose(file.file);
	/* advise */
	msg("%d angular positions az, el read from %s\n", nazel, file.name);
    }

    if (nazel == 0) return(nazel);

    /* open out_filename for writing */
    if (!out_filename || strcmp(out_filename, "-") == 0) {
	outfile = stdout;
	out_fn = output;
    } else {
	outfile = fopen(out_filename, "w");
	if (!outfile) {
	    fprintf(stderr, "cannot open %s for writing\n", out_filename);
	    return(-1);
	}
	out_fn = out_filename;
    }

    /* (re)allocate memory */
    cm = (long double *) realloc(dd, sizeof(long double) * nth);
    if (!cm) {
	fprintf(stderr, "ddcount: failed to allocate memory for %d long doubles\n", nth);
	return(-1);
    }
    dd = (int *) realloc(dd, sizeof(int) * nth);
    if (!dd) {
	fprintf(stderr, "ddcount: failed to allocate memory for %d ints\n", nth);
	return(-1);
    }
    id = (int *) realloc(id, sizeof(int) * nazel);
    if (!id) {
	fprintf(stderr, "ddcount: failed to allocate memory for %d ints\n", nazel);
	return(-1);
    }
    rp = (vec *) realloc(rp, sizeof(vec) * nazel);
    if (!rp) {
	fprintf(stderr, "ddcount: failed to allocate memory for %d unit vectors\n", nazel);
	return(-1);
    }
    iord = (int *) realloc(iord, sizeof(int) * nazel);
    if (!iord) {
	fprintf(stderr, "ddcount: failed to allocate memory for %d ints\n", nazel);
	return(-1);
    }

    /* store 1 - cosl(th) in cm array */
    for (ith = 0; ith < nth; ith++) {
	t = th[ith];
	scale(&t, inunit, 'r');
	s = sinl(t / 2.);
	cm[ith] = 2. * s * s;
    }

    /* convert az-el angles to radians */
    for (iazel = 0; iazel < nazel; iazel++) {
	scale_azel(&v[iazel], fmt->inunit, 'r');
    }

    /* convert az-el points to unit vectors */
    for (iazel = 0; iazel < nazel; iazel++) {
	azel_to_rp(&v[iazel], rp[iazel]);
    }

    /* polygon id number(s) of az-el points */
    msg("figuring polygon id number(s) of each az-el point ...");
    noid = 0;
    manyid = 0;
    for (iazel = 0; iazel < nazel; iazel++) {
	nid = poly_id(npoly, poly, v[iazel].az, v[iazel].el, &id_p);
	if (nid == 0) {
	    noid++;
	} else if (nid > 1) {
	    manyid++;
	}
	/* store first polygon id of point */
	if (nid == 0) {
	    id[iazel] = -1;
	} else {
	    id[iazel] = id_p[0];
	}
    }
    msg(" done\n");
    if (noid > 0) {
	msg("%d az-el points lie outside the angular mask: discard them\n", noid);
    }
    if (manyid > 0) {
	msg("%d az-el points lie inside more than one polygon: use only first polygon\n", manyid);
    }

    /* order az-el points in increasing order of polygon id */
    finibot(id, nazel, iord, nazel);

    /* write header */
    fprintf(outfile, "th(%c):", inunit);
    for (ith = 0; ith < nth; ith++) {
	wrangle(th[ith], inunit, fmt->outprecision, AZEL_STR_LEN, th_str);
	fprintf(outfile, "\t%s", th_str);
    }
    fprintf(outfile, "\n");

    msg("counting pairs ...");

#ifdef TIME
    printf(" timing ... ");
    fflush(stdout);
    time = clock();
#endif

    /* loop over az-el points */
    idi = -1;
    nid = 0;
    np = 0;
    for (iazel = 0; iazel < nazel; iazel++) {
	i = iord[iazel];
	/* skip points outside mask */
	if (id[i] == -1) continue;
	/* new polygon */
	if (id[i] != idi) {
	    idi = id[i];
	    /* reset pair counts to zero */
	    for (ith = 0; ith < nth; ith++) dd[ith] = 0;
	}
//printf(" %d", idi);
	/* az-el neighbours within same polygon */
	for (jazel = iazel + 1; jazel < nazel; jazel++) {
	    j = iord[jazel];
	    /* exit at new polygon */
	    if (id[j] != idi) break;
	    /* 1 - cosl(th_ij) */
	    cmm = cmij(rp[i], rp[j]);
	    /* ith such that cm[ith-1] <= cmm < cm[ith] */
	    ith = search(nth, cm, cmm);
	    /* increment count in this bin */
	    if (ith < nth) dd[ith]++;
	    /* increment total pair count */
	    np++;
	}
	/* write counts for this polygon */
	if (iazel + 1 == nazel || id[iord[iazel + 1]] != idi) {
	    fprintf(outfile, "%d", idi);
	    for (ith = 0; ith < nth; ith++) {
		fprintf(outfile, "\t%d", dd[ith]);
	    }
	    fprintf(outfile, "\n");
	    fflush(outfile);
	    nid++;
//printf("\n");
	}
    }

#ifdef TIME
    time = clock() - time;
    printf("done in %Lg sec\n", (float)time / (float)CLOCKS_PER_SEC);
#else
    msg("\n");
#endif

    /* advise */
    if (outfile != stdout) {
	fclose(outfile);
	msg("%d distinct pairs in %d th-bins x %d polygons written to %s\n", np, nth, nid, out_fn);
    }

    return(np);
}