123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485 |
- #include <stdio.h>
- #include <stdlib.h>
- #include <unistd.h>
- #include <math.h>
- #include <grass/gis.h>
- #include <grass/vector.h>
- #include <grass/glocale.h>
- #include "sw_defs.h"
- #include "defs.h"
- int sorted, plot, debug, mode3d;
- struct Site *sites;
- int nsites;
- int siteidx;
- int sqrt_nsites;
- int nvertices;
- struct Freelist sfl;
- struct Site *bottomsite;
- int nedges;
- struct Freelist efl;
- double xmin, xmax, ymin, ymax, deltax, deltay;
- struct Freelist hfl;
- struct Halfedge *ELleftend, *ELrightend;
- int ELhashsize;
- struct Halfedge **ELhash;
- int PQhashsize;
- struct Halfedge *PQhash;
- int PQcount;
- int PQmin;
- struct Cell_head Window;
- struct bound_box Box;
- struct Map_info In, Out;
- int Type;
- int Field;
- int in_area;
- int skeleton;
- double segf;
- int nsites_alloc;
- /* sort sites on y, then x, coord */
- int scomp(const void *v1, const void *v2)
- {
- struct Point *s1 = (struct Point *)v1;
- struct Point *s2 = (struct Point *)v2;
- if (s1->y < s2->y)
- return (-1);
- if (s1->y > s2->y)
- return (1);
- if (s1->x < s2->x)
- return (-1);
- if (s1->x > s2->x)
- return (1);
- return (0);
- }
- /* return a single in-storage site */
- struct Site *nextone(void)
- {
- struct Site *s;
- if (siteidx < nsites) {
- s = &sites[siteidx];
- siteidx++;
- return (s);
- }
- else
- return ((struct Site *)NULL);
- }
- /* removes duplicate sites that would break the voronoi alghoritm */
- void removeDuplicates()
- {
- int i, j;
- i = j = 1;
- while (i < nsites)
- if (mode3d) {
- if (sites[i].coord.x == sites[i - 1].coord.x &&
- sites[i].coord.y == sites[i - 1].coord.y &&
- sites[i].coord.z == sites[i - 1].coord.z)
- i++;
- else {
- if (i != j)
- sites[j] = sites[i];
- i++;
- j++;;
- }
- }
- else {
- if (sites[i].coord.x == sites[i - 1].coord.x &&
- sites[i].coord.y == sites[i - 1].coord.y)
- i++;
- else {
- if (i != j)
- sites[j] = sites[i];
- i++;
- j++;;
- }
- }
- if (j != nsites) {
- nsites = j;
- sites = (struct Site *)G_realloc(sites, nsites * sizeof(struct Site));
- }
- }
- int addsite(double x, double y, double z, int id)
- {
- if (nsites >= nsites_alloc) {
- nsites_alloc += 100;
- sites =
- (struct Site *)G_realloc(sites,
- (nsites_alloc) * sizeof(struct Site));
- }
- sites[nsites].coord.x = x;
- sites[nsites].coord.y = y;
- sites[nsites].coord.z = z;
- sites[nsites].sitenbr = id;
- sites[nsites].refcnt = 0;
- if (nsites > 0) {
- if (xmin > sites[nsites].coord.x)
- xmin = sites[nsites].coord.x;
- if (xmax < sites[nsites].coord.x)
- xmax = sites[nsites].coord.x;
- if (ymin > sites[nsites].coord.y)
- ymin = sites[nsites].coord.y;
- if (ymax < sites[nsites].coord.y)
- ymax = sites[nsites].coord.y;
- }
- else {
- xmin = xmax = sites[nsites].coord.x;
- ymin = ymax = sites[nsites].coord.y;
- }
- nsites++;
- return nsites;
- }
- /* read all sites, sort, and compute xmin, xmax, ymin, ymax */
- int readsites(void)
- {
- int nlines, ltype;
- struct line_pnts *Points;
- struct line_cats *Cats;
- double z = 0.;
-
- Points = Vect_new_line_struct();
- Cats = Vect_new_cats_struct();
-
- nlines = Vect_get_num_primitives(&In, GV_POINTS);
- nsites = 0;
- sites = (struct Site *)G_malloc(nlines * sizeof(struct Site));
- Vect_set_constraint_type(&In, GV_POINTS);
- Vect_set_constraint_field(&In, Field);
-
- while(TRUE) {
- ltype = Vect_read_next_line(&In, Points, Cats);
- if(ltype == -2)
- break;
- if (!(ltype & GV_POINTS))
- continue;
- /* G_percent(Vect_get_next_line_id(&In), nlines, 2); */
- if (!Vect_point_in_box(Points->x[0], Points->y[0], 0.0, &Box))
- continue;
- if (mode3d) {
- G_debug(3, "Points->z[0]: %f", Points->z[0]);
- z = Points->z[0];
- }
- addsite(Points->x[0], Points->y[0], z, nsites);
- }
- if (nsites < 2) {
- const char *name = Vect_get_full_name(&In);
- Vect_close(&In);
- G_fatal_error(n_("Found %d point/centroid in <%s>, but at least 2 are needed",
- "Found %d points/centroids in <%s>, but at least 2 are needed",
- nsites),
- nsites, name);
- }
- if (nsites < nlines)
- sites =
- (struct Site *)G_realloc(sites,
- (nsites) * sizeof(struct Site));
- qsort(sites, nsites, sizeof(struct Site), scomp);
- removeDuplicates();
- Vect_destroy_line_struct(Points);
- Vect_destroy_cats_struct(Cats);
- return 0;
- }
- /* valid boundary: one area with centroid */
- int n_areas(int line, int *aid)
- {
- int larea, rarea, ncentroids;
-
- ncentroids = 0;
- Vect_get_line_areas(&In, line, &larea, &rarea);
-
- if (larea < 0)
- larea = Vect_get_isle_area(&In, -larea);
- if (larea > 0) {
- if (Vect_get_area_centroid(&In, larea) > 0) {
- ncentroids++;
- *aid = larea;
- }
- }
- if (rarea < 0)
- rarea = Vect_get_isle_area(&In, -rarea);
- if (rarea > 0) {
- if (Vect_get_area_centroid(&In, rarea) > 0) {
- ncentroids++;
- *aid = rarea;
- }
- }
-
- return ncentroids;
- }
- /* read all boundaries, sort, and compute xmin, xmax, ymin, ymax */
- int readbounds(void)
- {
- int line, nlines, ltype, node, nnodes;
- struct line_pnts *Points;
- struct line_cats *Cats;
- int i;
- int area_id;
- double x, y, z, x1, y1, z1;
- double maxdist, sdist, l, dx, dy, dz;
- int nconnected;
- struct ilist *linelist, *arealist;
-
- Points = Vect_new_line_struct();
- Cats = Vect_new_cats_struct();
-
- nlines = Vect_get_num_lines(&In);
- nsites = 0;
- nsites_alloc = nlines * 2;
- sites = (struct Site *)G_malloc(nsites_alloc * sizeof(struct Site));
- Vect_set_constraint_type(&In, GV_BOUNDARY);
- Vect_set_constraint_field(&In, Field);
-
- l = 0;
- maxdist = 0;
- for (line = 1; line <= nlines; line++) {
- if (!Vect_line_alive(&In, line))
- continue;
- ltype = Vect_get_line_type(&In, line);
- if (!(ltype & GV_BOUNDARY))
- continue;
- area_id = 0;
- if (n_areas(line, &area_id) != 1)
- continue;
- Vect_read_line(&In, Points, Cats, line);
- Vect_line_prune(Points);
-
- l += Vect_line_length(Points);
- nsites += Points->n_points;
- }
- if (nsites)
- maxdist = segf * l / nsites;
- G_verbose_message("Maximum segment length: %g", maxdist);
-
- nsites = 0;
- z = 0.;
- z1 = 0;
- dz = 0;
- for (line = 1; line <= nlines; line++) {
- if (!Vect_line_alive(&In, line))
- continue;
- ltype = Vect_get_line_type(&In, line);
- if (!(ltype & GV_BOUNDARY))
- continue;
- area_id = 0;
- if (n_areas(line, &area_id) != 1)
- continue;
- Vect_read_line(&In, Points, Cats, line);
- Vect_line_prune(Points);
- if (nsites + Points->n_points > nsites_alloc) {
- nsites_alloc = nsites + Points->n_points;
- sites =
- (struct Site *)G_realloc(sites,
- (nsites_alloc) * sizeof(struct Site));
- }
- for (i = 0; i < Points->n_points; i++) {
- if (!Vect_point_in_box(Points->x[i], Points->y[i], 0.0, &Box))
- continue;
- x = Points->x[i];
- y = Points->y[i];
- if (mode3d) {
- G_debug(3, "Points->z[i]: %f", Points->z[i]);
- z = Points->z[i];
- }
- if (i > 0 && i < Points->n_points - 1)
- addsite(x, y, z, area_id);
-
- /* densify */
- if (maxdist > 0 && i < Points->n_points - 1) {
- dx = Points->x[i + 1] - Points->x[i];
- dy = Points->y[i + 1] - Points->y[i];
- if (mode3d)
- dz = Points->z[i + 1] - Points->z[i];
- l = sqrt(dx * dx + dy * dy);
-
- if (l > maxdist) {
- int n = ceil(l / maxdist) + 0.5;
- double step = l / n;
-
- while (--n) {
- sdist = (step * n) / l;
- x1 = x + sdist * dx;
- y1 = y + sdist * dy;
- if (mode3d)
- z1 = z + sdist * dz;
- addsite(x1, y1, z1, area_id);
- }
- }
- }
- }
- }
-
- /* process nodes */
- nnodes = Vect_get_num_nodes(&In);
- linelist = Vect_new_list();
- arealist = Vect_new_list();
-
- for (node = 1; node <= nnodes; node++) {
- Vect_get_node_coor(&In, node, &x, &y, &z);
- if (!mode3d)
- z = 0.;
- if (!Vect_point_in_box(x, y, 0.0, &Box))
- continue;
- /* count number of connected boundaries
- * must be >= 2 */
- /* count number of valid boundaries */
- nlines = Vect_get_node_n_lines(&In, node);
- nconnected = 0;
- Vect_reset_list(linelist);
- Vect_reset_list(arealist);
-
- for (i = 0; i < nlines; i++) {
- line = Vect_get_node_line(&In, node, i);
-
- ltype = Vect_get_line_type(&In, abs(line));
-
- if (!(ltype & GV_BOUNDARY))
- continue;
-
- if (n_areas(abs(line), &area_id) == 1) {
- Vect_list_append(linelist, line);
- Vect_list_append(arealist, area_id);
- nconnected++;
- }
- }
-
- if (arealist->n_values == 1) {
-
- area_id = arealist->value[0];
- addsite(x, y, z, area_id);
- }
- else if (arealist->n_values > 1) {
- /* displacement */
- double displace;
-
- if (fabs(x) > fabs(y))
- displace = d_ulp(fabs(x));
- else
- displace = d_ulp(fabs(y));
-
- displace *= 2;
-
- for (i = 0; i < linelist->n_values; i++) {
- line = linelist->value[i];
-
- if (n_areas(abs(line), &area_id) != 1)
- G_fatal_error(_("All boundaries in the list should be valid"));
- Vect_read_line(&In, Points, Cats, abs(line));
- Vect_line_prune(Points);
-
- if (Points->n_points < 2)
- G_fatal_error(_("Boundary is degenerate"));
- if (line < 0) {
- dx = Points->x[Points->n_points - 2] - Points->x[Points->n_points - 1];
- dy = Points->y[Points->n_points - 2] - Points->y[Points->n_points - 1];
- }
- else {
- dx = Points->x[1] - Points->x[0];
- dy = Points->y[1] - Points->y[0];
- }
- l = sqrt(dx * dx + dy * dy);
- if (displace > l)
- displace = l;
- }
- for (i = 0; i < linelist->n_values; i++) {
- line = linelist->value[i];
-
- if (n_areas(abs(line), &area_id) != 1)
- G_fatal_error(_("All boundaries in the list should be valid"));
- Vect_read_line(&In, Points, Cats, abs(line));
- Vect_line_prune(Points);
-
- if (Points->n_points < 2)
- G_fatal_error(_("Boundary is degenerate"));
- if (line < 0) {
- dx = Points->x[Points->n_points - 2] - Points->x[Points->n_points - 1];
- dy = Points->y[Points->n_points - 2] - Points->y[Points->n_points - 1];
- }
- else {
- dx = Points->x[1] - Points->x[0];
- dy = Points->y[1] - Points->y[0];
- }
- l = sqrt(dx * dx + dy * dy);
- if (l > displace * 2) {
- sdist = displace / l;
- x1 = x + sdist * dx;
- y1 = y + sdist * dy;
- z1 = 0;
- addsite(x1, y1, z1, area_id);
- }
- }
- }
- }
- if (nsites < 2) {
- const char *name = Vect_get_full_name(&In);
- Vect_close(&In);
- G_fatal_error(n_("Found %d vertex in <%s>, but at least 2 are needed",
- "Found %d vertices in <%s>, but at least 2 are needed",
- nsites),
- nsites, name);
- }
- qsort(sites, nsites, sizeof(struct Site), scomp);
- removeDuplicates();
- Vect_destroy_line_struct(Points);
- Vect_destroy_cats_struct(Cats);
- Vect_destroy_list(linelist);
- Vect_destroy_list(arealist);
- return 0;
- }
|