[GRASS-SVN] r57812 - grass-addons/grass7/vector/v.centerpoint
svn_grass at osgeo.org
svn_grass at osgeo.org
Sun Sep 22 07:40:30 PDT 2013
Author: mmetz
Date: 2013-09-22 07:40:29 -0700 (Sun, 22 Sep 2013)
New Revision: 57812
Added:
grass-addons/grass7/vector/v.centerpoint/Makefile
grass-addons/grass7/vector/v.centerpoint/areas.c
grass-addons/grass7/vector/v.centerpoint/lines.c
grass-addons/grass7/vector/v.centerpoint/local_proto.h
grass-addons/grass7/vector/v.centerpoint/main.c
grass-addons/grass7/vector/v.centerpoint/points.c
grass-addons/grass7/vector/v.centerpoint/v.centerpoint.html
Modified:
grass-addons/grass7/vector/v.centerpoint/
Log:
add v.centerpoint
Property changes on: grass-addons/grass7/vector/v.centerpoint
___________________________________________________________________
Added: svn:ignore
+ OBJ.* *.tmp.html
Added: grass-addons/grass7/vector/v.centerpoint/Makefile
===================================================================
--- grass-addons/grass7/vector/v.centerpoint/Makefile (rev 0)
+++ grass-addons/grass7/vector/v.centerpoint/Makefile 2013-09-22 14:40:29 UTC (rev 57812)
@@ -0,0 +1,13 @@
+
+MODULE_TOPDIR = ../..
+
+PGM = v.centerpoint
+
+LIBES = $(VECTORLIB) $(GISLIB)
+DEPENDENCIES = $(VECTORDEP) $(GISDEP)
+EXTRA_INC = $(VECT_INC)
+EXTRA_CFLAGS = $(VECT_CFLAGS)
+
+include $(MODULE_TOPDIR)/include/Make/Module.make
+
+default: cmd
Property changes on: grass-addons/grass7/vector/v.centerpoint/Makefile
___________________________________________________________________
Added: svn:mime-type
+ text/x-makefile
Added: svn:eol-style
+ native
Added: grass-addons/grass7/vector/v.centerpoint/areas.c
===================================================================
--- grass-addons/grass7/vector/v.centerpoint/areas.c (rev 0)
+++ grass-addons/grass7/vector/v.centerpoint/areas.c 2013-09-22 14:40:29 UTC (rev 57812)
@@ -0,0 +1,574 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include <grass/gis.h>
+#include <grass/vector.h>
+#include <grass/glocale.h>
+#include "local_proto.h"
+
+static double d_ulp(double d)
+{
+ int exp;
+
+ if (d == 0)
+ return GRASS_EPSILON;
+
+ d = frexp(d, &exp);
+ exp -= 51;
+ d = ldexp(d, exp);
+
+ return d;
+}
+
+int areas_center(struct Map_info *In, struct Map_info *Out, int layer,
+ struct cat_list *cat_list, int mode)
+{
+ int area, nareas, isle, nisles, nisles_alloc;
+ struct line_pnts *Points, **IPoints, *OPoints;
+ struct line_cats *Cats;
+ struct bound_box box;
+ double x, y, z, meanx, meany, meanz;
+ double *xp, *yp;
+ double w, tot_w;
+ int i;
+
+ Points = Vect_new_line_struct();
+ OPoints = Vect_new_line_struct();
+ Cats = Vect_new_cats_struct();
+
+ nisles_alloc = 10;
+ IPoints = G_malloc(nisles_alloc * sizeof (struct line_pnts *));
+
+ nisles = nisles_alloc;
+ for (isle = 0; isle < nisles_alloc; isle++) {
+ IPoints[isle] = Vect_new_line_struct();
+ }
+
+ nareas = Vect_get_num_areas(In);
+
+ /* geometric mean = center of gravity */
+ if (mode & A_MEAN) {
+
+ G_message(_("Calculating centers of gravity for areas..."));
+
+ G_percent(0, nareas, 4);
+
+ for (area = 1; area <= nareas; area++) {
+
+ Vect_reset_cats(Cats);
+ if (layer > 1) {
+ Vect_get_area_cats(In, area, Cats);
+ if (!Vect_cats_in_constraint(Cats, layer, cat_list))
+ continue;
+ }
+
+ Vect_get_area_points(In, area, Points);
+ Vect_line_prune(Points);
+
+ nisles = Vect_get_area_num_isles(In, area);
+ if (nisles > nisles_alloc) {
+ IPoints = G_realloc(IPoints, nisles * sizeof (struct line_pnts *));
+ for (isle = nisles_alloc; isle < nisles; isle++) {
+ IPoints[isle] = Vect_new_line_struct();
+ }
+ nisles_alloc = nisles;
+ }
+ for (isle = 1; isle < nisles; isle++) {
+ Vect_get_isle_points(In, isle, IPoints[isle - 1]);
+ Vect_line_prune(IPoints[isle - 1]);
+ }
+
+ /* surveyor's / shoelace formula */
+ /* the surveyor should not be too far away (fp precision limit) */
+ /* surveyor's position: */
+ Vect_line_box(Points, &box);
+ x = (box.W + box.E) / 2.;
+ y = (box.S + box.N) / 2.;
+ z = 0;
+ meanx = meany = meanz = 0.;
+ tot_w = 0.;
+
+ xp = Points->x;
+ yp = Points->y;
+ for (i = 1; i < Points->n_points; i++) {
+ w = (x - xp[i - 1]) * (yp[i] - y) -
+ (x - xp[i]) * (yp[i - 1] - y);
+
+ meanx += (xp[i - 1] + xp[i] + x) * w;
+ meany += (yp[i - 1] + yp[i] + y) * w;
+ tot_w += w;
+ }
+
+ for (isle = 0; isle < nisles; isle++) {
+ xp = IPoints[isle]->x;
+ yp = IPoints[isle]->y;
+ for (i = 1; i < IPoints[isle]->n_points; i++) {
+ w = (x - xp[i - 1]) * (yp[i] - y) -
+ (x - xp[i]) * (yp[i - 1] - y);
+
+ meanx += (xp[i - 1] + xp[i] + x) * w;
+ meany += (yp[i - 1] + yp[i] + y) * w;
+ tot_w += w;
+ }
+ }
+ if (tot_w != 0) {
+ x = meanx / (tot_w * 3);
+ y = meany / (tot_w * 3);
+ }
+ if (Out) {
+ Vect_reset_line(OPoints);
+ Vect_append_point(OPoints, x, y, z);
+ Vect_write_line(Out, GV_POINT, OPoints, Cats);
+ }
+ else
+ fprintf(stdout, "7|%.15g|%.15g|%.15g\n", x, y, z);
+
+ G_percent(area, nareas, 4);
+ }
+ }
+
+ /* approximate geometric median with Weiszfeld's algorithm:
+ * iterative least squares reduction */
+ if (mode & A_MEDIAN) {
+ struct line_pnts *CPoints;
+ double sx, sy, cx, cy, dx, dy;
+ double medx, medy;
+ double *wc;
+ int nwc, nwc_alloc, wci;
+ double dist, distsum, dist2all, lastdist2all;
+ int j, iter, maxiter = 1000;
+
+ G_message(_("Calculating geometric medians for areas..."));
+
+ CPoints = Vect_new_line_struct();
+
+ nwc_alloc = 100;
+ wc = G_malloc(nwc_alloc * sizeof(double));
+
+ G_percent(0, nareas, 4);
+
+ for (area = 1; area <= nareas; area++) {
+
+ Vect_reset_cats(Cats);
+ if (layer > 1) {
+ Vect_get_area_cats(In, area, Cats);
+ if (!Vect_cats_in_constraint(Cats, layer, cat_list))
+ continue;
+ }
+
+ Vect_get_area_points(In, area, Points);
+ Vect_line_prune(Points);
+ nwc = Points->n_points - 1;
+
+ nisles = Vect_get_area_num_isles(In, area);
+ if (nisles > nisles_alloc) {
+ IPoints = G_realloc(IPoints, nisles * sizeof (struct line_pnts *));
+ for (isle = nisles_alloc; isle < nisles; isle++) {
+ IPoints[isle] = Vect_new_line_struct();
+ }
+ nisles_alloc = nisles;
+ }
+ for (isle = 1; isle < nisles; isle++) {
+ Vect_get_isle_points(In, isle, IPoints[isle - 1]);
+ Vect_line_prune(IPoints[isle - 1]);
+ nwc += IPoints[isle - 1]->n_points - 1;
+ }
+
+ if (nwc_alloc < nwc) {
+ nwc_alloc = nwc;
+ wc = G_realloc(wc, nwc_alloc * sizeof(double));
+ }
+
+ /* surveyor's / shoelace formula */
+ /* the surveyor should not be too far away (fp precision limit) */
+ /* surveyor's position: */
+ Vect_line_box(Points, &box);
+ sx = (box.W + box.E) / 2.;
+ sy = (box.S + box.N) / 2.;
+ x = y = z = 0;
+ meanx = meany = meanz = 0.;
+ tot_w = 0.;
+
+ wci = 0;
+ Vect_reset_line(CPoints);
+ xp = Points->x;
+ yp = Points->y;
+ for (i = 1; i < Points->n_points; i++) {
+ w = (sx - xp[i - 1]) * (yp[i] - sy) -
+ (sx - xp[i]) * (yp[i - 1] - sy);
+
+ tot_w += w;
+
+ cx = xp[i - 1] + xp[i] + sx;
+ cy = yp[i - 1] + yp[i] + sy;
+ meanx += cx * w;
+ meany += cy * w;
+
+ wc[wci++] = w;
+ Vect_append_point(CPoints, cx / 3., cy / 3., 0);
+ }
+
+ for (isle = 0; isle < nisles; isle++) {
+ xp = IPoints[isle]->x;
+ yp = IPoints[isle]->y;
+ for (i = 1; i < IPoints[isle]->n_points; i++) {
+ w = (sx - xp[i - 1]) * (yp[i] - sy) -
+ (sx - xp[i]) * (yp[i - 1] - sy);
+
+ tot_w += w;
+
+ cx = xp[i - 1] + xp[i] + sx;
+ cy = yp[i - 1] + yp[i] + sy;
+ meanx += cx * w;
+ meany += cy * w;
+
+ wc[wci++] = w;
+ Vect_append_point(CPoints, cx / 3., cy / 3., 0);
+ }
+ }
+ if (tot_w != 0) {
+ x = meanx / (tot_w * 3);
+ y = meany / (tot_w * 3);
+ }
+
+ medx = x;
+ medy = y;
+
+ /* update surveyor's point */
+ sx = x;
+ sy = y;
+
+ x = y = z = 0;
+ meanx = meany = meanz = 0.;
+ tot_w = 0.;
+
+ wci = 0;
+ Vect_reset_line(CPoints);
+ xp = Points->x;
+ yp = Points->y;
+ for (i = 1; i < Points->n_points; i++) {
+ w = (sx - xp[i - 1]) * (yp[i] - sy) -
+ (sx - xp[i]) * (yp[i - 1] - sy);
+
+ tot_w += w;
+
+ cx = xp[i - 1] + xp[i] + sx;
+ cy = yp[i - 1] + yp[i] + sy;
+ meanx += cx * w;
+ meany += cy * w;
+
+ wc[wci++] = w;
+ Vect_append_point(CPoints, cx / 3., cy / 3., 0);
+ }
+
+ for (isle = 0; isle < nisles; isle++) {
+ xp = IPoints[isle]->x;
+ yp = IPoints[isle]->y;
+ for (i = 1; i < IPoints[isle]->n_points; i++) {
+ w = (sx - xp[i - 1]) * (yp[i] - sy) -
+ (sx - xp[i]) * (yp[i - 1] - sy);
+
+ tot_w += w;
+
+ cx = xp[i - 1] + xp[i] + sx;
+ cy = yp[i - 1] + yp[i] + sy;
+ meanx += cx * w;
+ meany += cy * w;
+
+ wc[wci++] = w;
+ Vect_append_point(CPoints, cx / 3., cy / 3., 0);
+ }
+ }
+ if (tot_w != 0) {
+ x = meanx / (tot_w * 3);
+ y = meany / (tot_w * 3);
+ }
+
+ lastdist2all = -1;
+
+ G_debug(3, "Approximating geometric median...");
+ /* depends on the location of the surveyor
+ * why? */
+
+ for (iter = 0; iter < maxiter; iter++) {
+
+ distsum = dist2all = 0.;
+ x = y = z = 0.;
+
+ for (j = 0; j < CPoints->n_points; j++) {
+
+ dx = CPoints->x[j] - medx;
+ dy = CPoints->y[j] - medy;
+ dist = sqrt(dx * dx + dy * dy);
+
+ if (dist) {
+ w = wc[j] / dist;
+ x += CPoints->x[j] * w;
+ y += CPoints->y[j] * w;
+
+ distsum += w;
+ }
+ if (wc[j])
+ dist2all += dist / fabs(wc[j]);
+ }
+
+ if (distsum) {
+ x /= distsum;
+ y /= distsum;
+ }
+
+ G_debug(3, "dist2all: %.15g", dist2all);
+ G_debug(3, "lastdist2all: %.15g", lastdist2all);
+ if (lastdist2all > 0) {
+ double d = d_ulp(lastdist2all);
+
+ if (lastdist2all - dist2all < d)
+ break;
+ }
+ if (dist2all == 0.)
+ break;
+
+ lastdist2all = dist2all;
+
+ medx = x;
+ medy = y;
+
+ /* update surveyor's point */
+ sx = x;
+ sy = y;
+
+ x = y = z = 0;
+ meanx = meany = meanz = 0.;
+ tot_w = 0.;
+
+ wci = 0;
+ Vect_reset_line(CPoints);
+ xp = Points->x;
+ yp = Points->y;
+ for (i = 1; i < Points->n_points; i++) {
+ w = (sx - xp[i - 1]) * (yp[i] - sy) -
+ (sx - xp[i]) * (yp[i - 1] - sy);
+
+ tot_w += w;
+
+ cx = xp[i - 1] + xp[i] + sx;
+ cy = yp[i - 1] + yp[i] + sy;
+ meanx += cx * w;
+ meany += cy * w;
+
+ wc[wci++] = w;
+ Vect_append_point(CPoints, cx / 3., cy / 3., 0);
+ }
+
+ for (isle = 0; isle < nisles; isle++) {
+ xp = IPoints[isle]->x;
+ yp = IPoints[isle]->y;
+ for (i = 1; i < IPoints[isle]->n_points; i++) {
+ w = (sx - xp[i - 1]) * (yp[i] - sy) -
+ (sx - xp[i]) * (yp[i - 1] - sy);
+
+ tot_w += w;
+
+ cx = xp[i - 1] + xp[i] + sx;
+ cy = yp[i - 1] + yp[i] + sy;
+ meanx += cx * w;
+ meany += cy * w;
+
+ wc[wci++] = w;
+ Vect_append_point(CPoints, cx / 3., cy / 3., 0);
+ }
+ }
+ if (tot_w != 0) {
+ x = meanx / (tot_w * 3);
+ y = meany / (tot_w * 3);
+ }
+ }
+ G_debug(3, "Iteration converged after %d passes, dist = %.15g",
+ iter, lastdist2all);
+
+ x = medx;
+ y = medy;
+
+ if (Out) {
+ Vect_reset_line(OPoints);
+ Vect_append_point(OPoints, x, y, 0);
+ Vect_write_line(Out, GV_POINT, OPoints, Cats);
+ }
+ else
+ fprintf(stdout, "8|%.15g|%.15g|%.15g\n", x, y, 0.);
+
+ G_percent(area, nareas, 4);
+ }
+ }
+
+ /* approximate geometric median with Weiszfeld's algorithm:
+ * iterative least squares reduction */
+ if (mode & A_MEDIAN_B) {
+ struct line_pnts *CPoints;
+ double cx, cy, dx, dy;
+ double medx, medy;
+ double *wb, tot_w;
+ int nw, nw_alloc, wi;
+ double dist, distsum, dist2all, lastdist2all;
+ int j, iter, maxiter = 1000;
+
+ G_message(_("Calculating geometric medians for areas..."));
+
+ CPoints = Vect_new_line_struct();
+
+ nw_alloc = 100;
+ wb = G_malloc(nw_alloc * sizeof(double));
+
+ G_percent(0, nareas, 4);
+
+ for (area = 1; area <= nareas; area++) {
+
+ Vect_reset_cats(Cats);
+ if (layer > 1) {
+ Vect_get_area_cats(In, area, Cats);
+ if (!Vect_cats_in_constraint(Cats, layer, cat_list))
+ continue;
+ }
+
+ Vect_get_area_points(In, area, Points);
+ Vect_line_prune(Points);
+ nw = Points->n_points - 1;
+
+ nisles = Vect_get_area_num_isles(In, area);
+ if (nisles > nisles_alloc) {
+ IPoints = G_realloc(IPoints, nisles * sizeof (struct line_pnts *));
+ for (isle = nisles_alloc; isle < nisles; isle++) {
+ IPoints[isle] = Vect_new_line_struct();
+ }
+ nisles_alloc = nisles;
+ }
+ for (isle = 1; isle < nisles; isle++) {
+ Vect_get_isle_points(In, isle, IPoints[isle - 1]);
+ Vect_line_prune(IPoints[isle - 1]);
+ nw += IPoints[isle - 1]->n_points - 1;
+ }
+
+ if (nw_alloc < nw) {
+ nw_alloc = nw;
+ wb = G_realloc(wb, nw_alloc * sizeof(double));
+ }
+
+ /* segment lengths */
+ meanx = meany = 0.;
+ tot_w = 0.;
+ wi = 0;
+ Vect_reset_line(CPoints);
+ xp = Points->x;
+ yp = Points->y;
+ for (i = 1; i < Points->n_points; i++) {
+ dx = xp[i] - xp[i - 1];
+ dy = yp[i] - yp[i - 1];
+ w = sqrt(dx * dx + dy * dy);
+
+ cx = xp[i - 1] + xp[i];
+ meanx += cx * w;
+ cy = yp[i - 1] + yp[i];
+ meany += cy * w;
+
+ wb[wi++] = w;
+ tot_w += w;
+
+ Vect_append_point(CPoints, cx / 2., cy / 2., 0);
+ }
+
+ for (isle = 0; isle < nisles; isle++) {
+ xp = IPoints[isle]->x;
+ yp = IPoints[isle]->y;
+ for (i = 1; i < IPoints[isle]->n_points; i++) {
+ dx = xp[i] - xp[i - 1];
+ dy = yp[i] - yp[i - 1];
+ w = sqrt(dx * dx + dy * dy);
+
+ cx = xp[i - 1] + xp[i];
+ meanx += cx * w;
+ cy = yp[i - 1] + yp[i];
+ meany += cy * w;
+
+ wb[wi++] = w;
+ tot_w += w;
+
+ Vect_append_point(CPoints, cx / 2., cy / 2., 0);
+ }
+ }
+ if (tot_w != 0) {
+ meanx /= (tot_w * 2);
+ meany /= (tot_w * 2);
+ }
+
+ medx = meanx;
+ medy = meany;
+
+ G_debug(3, "Approximating geometric median...");
+
+ lastdist2all = -1;
+ for (iter = 0; iter < maxiter; iter++) {
+
+ distsum = dist2all = 0.;
+ x = y = z = 0.;
+
+ for (j = 0; j < CPoints->n_points; j++) {
+
+ dx = CPoints->x[j] - medx;
+ dy = CPoints->y[j] - medy;
+ dist = sqrt(dx * dx + dy * dy);
+
+ if (dist) {
+ w = wb[j] / dist;
+ x += CPoints->x[j] * w;
+ y += CPoints->y[j] * w;
+
+ distsum += w;
+ }
+ if (wb[j])
+ dist2all += dist / wb[j];
+ }
+
+ if (distsum) {
+ x /= distsum;
+ y /= distsum;
+ }
+
+ G_debug(3, "dist2all: %.15g", dist2all);
+ G_debug(3, "lastdist2all: %.15g", lastdist2all);
+ if (lastdist2all > 0) {
+ double d = d_ulp(lastdist2all);
+
+ if (lastdist2all - dist2all < d)
+ break;
+ }
+ if (dist2all == 0.)
+ break;
+
+ lastdist2all = dist2all;
+
+ medx = x;
+ medy = y;
+ }
+ G_debug(3, "Iteration converged after %d passes, dist = %.15g",
+ iter, lastdist2all);
+
+ x = meanx;
+ y = meany;
+
+ x = medx;
+ y = medy;
+
+ if (Out) {
+ Vect_reset_line(OPoints);
+ Vect_append_point(OPoints, x, y, 0);
+ Vect_write_line(Out, GV_POINT, OPoints, Cats);
+ }
+ else
+ fprintf(stdout, "9|%.15g|%.15g|%.15g\n", x, y, 0.);
+
+ G_percent(area, nareas, 4);
+ }
+ }
+
+ return 1;
+}
Property changes on: grass-addons/grass7/vector/v.centerpoint/areas.c
___________________________________________________________________
Added: svn:mime-type
+ text/x-csrc
Added: svn:eol-style
+ native
Added: grass-addons/grass7/vector/v.centerpoint/lines.c
===================================================================
--- grass-addons/grass7/vector/v.centerpoint/lines.c (rev 0)
+++ grass-addons/grass7/vector/v.centerpoint/lines.c 2013-09-22 14:40:29 UTC (rev 57812)
@@ -0,0 +1,258 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include <grass/gis.h>
+#include <grass/vector.h>
+#include <grass/glocale.h>
+#include "local_proto.h"
+
+static double d_ulp(double d)
+{
+ int exp;
+
+ if (d == 0)
+ return GRASS_EPSILON;
+
+ d = frexp(d, &exp);
+ exp -= 51;
+ d = ldexp(d, exp);
+
+ return d;
+}
+
+int lines_center(struct Map_info *In, struct Map_info *Out, int layer,
+ struct cat_list *cat_list, int n_primitives, int mode)
+{
+ struct line_pnts *Points, *OPoints;
+ struct line_cats *Cats;
+ double x, y, z;
+ int type;
+ int counter;
+
+ Points = Vect_new_line_struct();
+ OPoints = Vect_new_line_struct();
+ Cats = Vect_new_cats_struct();
+
+ /* mid point */
+ if (mode & L_MID) {
+ double len;
+
+ counter = 0;
+
+ Vect_rewind(In);
+ while ((type = Vect_read_next_line(In, Points, Cats)) > 0) {
+ G_percent(counter, n_primitives, 4);
+ counter++;
+
+ if (!(type & GV_LINE))
+ continue;
+ if (layer > 0 &&
+ !Vect_cats_in_constraint(Cats, layer, cat_list))
+ continue;
+
+ Vect_line_prune(Points);
+
+ len = Vect_line_length(Points) / 2.;
+
+ Vect_point_on_line(Points, len, &x, &y, &z, NULL, NULL);
+
+ if (Out) {
+ Vect_reset_line(OPoints);
+ Vect_append_point(OPoints, x, y, z);
+ Vect_write_line(Out, GV_POINT, OPoints, Cats);
+ }
+ else
+ fprintf(stdout, "4|%.15g|%.15g|%.15g\n", x, y, z);
+ }
+ G_percent(1, 1, 1);
+ }
+
+ /* center of gravity */
+ if (mode & L_MEAN) {
+ double len, slen;
+ double dx, dy, dz;
+ int i;
+
+ counter = 0;
+
+ Vect_rewind(In);
+ while ((type = Vect_read_next_line(In, Points, Cats)) > 0) {
+ G_percent(counter, n_primitives, 4);
+ counter++;
+ if (!(type & GV_LINE))
+ continue;
+ if (layer > 0 &&
+ !Vect_cats_in_constraint(Cats, layer, cat_list))
+ continue;
+
+ Vect_line_prune(Points);
+
+ len = 0.;
+
+ x = y = z = 0.;
+
+ for (i = 1; i < Points->n_points; i++) {
+ dx = Points->x[i - 1] - Points->x[i];
+ dy = Points->y[i - 1] - Points->y[i];
+ dz = Points->z[i - 1] - Points->z[i];
+
+ slen = sqrt(dx * dx + dy * dy + dz * dz);
+
+ x += (Points->x[i - 1] + Points->x[i]) * slen;
+ y += (Points->y[i - 1] + Points->y[i]) * slen;
+ z += (Points->z[i - 1] + Points->z[i]) * slen;
+
+ len += slen;
+ }
+
+ x /= (len * 2);
+ y /= (len * 2);
+ z /= (len * 2);
+
+ if (Out) {
+ Vect_reset_line(OPoints);
+ Vect_append_point(OPoints, x, y, z);
+ Vect_write_line(Out, GV_POINT, OPoints, Cats);
+ }
+ else
+ fprintf(stdout, "5|%.15g|%.15g|%.15g\n", x, y, z);
+ }
+ G_percent(1, 1, 1);
+ }
+
+ /* approximate geometric median with Weiszfeld's algorithm:
+ * iterative least squares reduction */
+ if (mode & L_MEDIAN) {
+ struct line_pnts *SPoints;
+ double *len;
+ double dx, dy, dz;
+ double xmean, ymean, zmean;
+ double medx, medy, medz;
+ double dist, distsum, dist2all, lastdist2all;
+ int i, j, iter, maxiter = 100;
+
+ SPoints = Vect_new_line_struct();
+
+ counter = 0;
+
+ Vect_rewind(In);
+ while ((type = Vect_read_next_line(In, Points, Cats)) > 0) {
+ G_percent(counter, n_primitives, 4);
+ counter++;
+ if (!(type & GV_LINE))
+ continue;
+ if (layer > 0 &&
+ !Vect_cats_in_constraint(Cats, layer, cat_list))
+ continue;
+
+ Vect_line_prune(Points);
+
+ len = G_malloc((Points->n_points - 1) * sizeof(double));
+ Vect_reset_line(SPoints);
+
+ xmean = ymean = zmean = 0.;
+
+ for (i = 0; i < Points->n_points - 1; i++) {
+ dx = Points->x[i + 1] - Points->x[i];
+ dy = Points->y[i + 1] - Points->y[i];
+ dz = Points->z[i + 1] - Points->z[i];
+
+ len[i] = sqrt(dx * dx + dy * dy + dz * dz);
+
+ x = (Points->x[i + 1] + Points->x[i]) / 2.;
+ y = (Points->y[i + 1] + Points->y[i]) / 2.;
+ z = (Points->z[i + 1] + Points->z[i]) / 2.;
+
+ Vect_append_point(SPoints, x, y, z);
+
+ xmean += Points->x[i];
+ ymean += Points->y[i];
+ zmean += Points->z[i];
+ }
+
+ i = Points->n_points - 1;
+ xmean += Points->x[i];
+ ymean += Points->y[i];
+ zmean += Points->z[i];
+
+ xmean /= Points->n_points;
+ ymean /= Points->n_points;
+ zmean /= Points->n_points;
+
+ medx = xmean;
+ medy = ymean;
+ medz = zmean;
+
+ lastdist2all = -1;
+
+ G_debug(3, "Approximating geometric median...");
+
+ for (iter = 0; iter < maxiter; iter++) {
+
+ distsum = dist2all = 0.;
+ x = y = z = 0.;
+
+ for (j = 0; j < SPoints->n_points; j++) {
+
+ dx = SPoints->x[j] - medx;
+ dy = SPoints->y[j] - medy;
+ dz = SPoints->z[j] - medz;
+ dist = sqrt(dx * dx + dy * dy + dz * dz);
+
+ if (dist) {
+ x += SPoints->x[j] * len[j] / dist;
+ y += SPoints->y[j] * len[j] / dist;
+ z += SPoints->z[j] * len[j] / dist;
+
+ distsum += len[j] / dist;
+ dist2all += dist;
+ }
+ if (len[j])
+ dist2all += dist / len[j];
+ }
+
+ if (distsum) {
+ x /= distsum;
+ y /= distsum;
+ z /= distsum;
+ }
+
+ G_debug(3, "dist2all: %.15g", dist2all);
+ G_debug(3, "lastdist2all: %.15g", lastdist2all);
+ if (lastdist2all > 0) {
+ double d = d_ulp(lastdist2all);
+
+ if (lastdist2all - dist2all < d)
+ break;
+ }
+ if (dist2all == 0.)
+ break;
+
+ lastdist2all = dist2all;
+
+ medx = x;
+ medy = y;
+ medz = z;
+ }
+ G_debug(3, "Iteration converged after %d passes, dist = %.15g",
+ iter, lastdist2all);
+
+ G_free(len);
+
+ x = medx;
+ y = medy;
+ z = medz;
+
+ if (Out) {
+ Vect_reset_line(OPoints);
+ Vect_append_point(OPoints, x, y, z);
+ Vect_write_line(Out, GV_POINT, OPoints, Cats);
+ }
+ else
+ fprintf(stdout, "6|%.15g|%.15g|%.15g\n", x, y, z);
+ }
+ G_percent(1, 1, 1);
+ }
+
+ return 1;
+}
Property changes on: grass-addons/grass7/vector/v.centerpoint/lines.c
___________________________________________________________________
Added: svn:mime-type
+ text/x-csrc
Added: svn:eol-style
+ native
Added: grass-addons/grass7/vector/v.centerpoint/local_proto.h
===================================================================
--- grass-addons/grass7/vector/v.centerpoint/local_proto.h (rev 0)
+++ grass-addons/grass7/vector/v.centerpoint/local_proto.h 2013-09-22 14:40:29 UTC (rev 57812)
@@ -0,0 +1,18 @@
+#define P_MEAN 0x001
+#define P_MEDIAN 0x002
+#define P_MEDIAN_P 0x004
+#define L_MID 0x008
+#define L_MEAN 0x010
+#define L_MEDIAN 0x020
+#define A_MEAN 0x040
+#define A_MEDIAN 0x080
+#define A_MEDIAN_B 0x100
+
+int points_center(struct Map_info *, struct Map_info *, int,
+ struct cat_list *, int, int);
+
+int lines_center(struct Map_info *, struct Map_info *, int,
+ struct cat_list *, int, int);
+
+int areas_center(struct Map_info *, struct Map_info *, int,
+ struct cat_list *, int);
Property changes on: grass-addons/grass7/vector/v.centerpoint/local_proto.h
___________________________________________________________________
Added: svn:mime-type
+ text/x-chdr
Added: svn:eol-style
+ native
Added: grass-addons/grass7/vector/v.centerpoint/main.c
===================================================================
--- grass-addons/grass7/vector/v.centerpoint/main.c (rev 0)
+++ grass-addons/grass7/vector/v.centerpoint/main.c 2013-09-22 14:40:29 UTC (rev 57812)
@@ -0,0 +1,260 @@
+
+/****************************************************************
+ *
+ * MODULE: v.centerpoint
+ *
+ * AUTHOR(S): GRASS Development Team, Radim Blazek, Maris Nartiss
+ *
+ * PURPOSE: copies vector data from source map to destination map
+ * prints out all point coordinates and atributes
+ *
+ * COPYRIGHT: (C) 2002-2009 by the GRASS Development Team
+ *
+ * This program is free software under the
+ * GNU General Public License (>=v2).
+ * Read the file COPYING that comes with GRASS
+ * for details.
+ *
+ ****************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <grass/gis.h>
+#include <grass/vector.h>
+#include <grass/glocale.h>
+#include "local_proto.h"
+
+int main(int argc, char *argv[])
+{
+ struct Map_info In, Out, *Outp;
+ struct line_pnts *Points;
+ struct line_cats *Cats;
+ int i, type, out3d;
+ char *mapset;
+ struct GModule *module; /* GRASS module for parsing arguments */
+ struct Option *old, *new, *type_opt, *lyr_opt, *cats_opt, *where_opt;
+ struct Option *pmode, *lmode, *amode;
+ struct Flag *topo_flag;
+ char *pdesc, *ldesc, *adesc;
+ struct cat_list *cat_list = NULL;
+ int layer, itype;
+ int nprimitives, npoints, nlines;
+ int mode;
+
+ /* initialize GIS environment */
+ /* reads grass env, stores program name to G_program_name() */
+ G_gisinit(argv[0]);
+
+ /* initialize module */
+ module = G_define_module();
+ G_add_keyword(_("vector"));
+ G_add_keyword(_("geometry"));
+ G_add_keyword(_("center"));
+ module->description = _("Calculate center points");
+
+ /* Define the different options as defined in gis.h */
+ old = G_define_standard_option(G_OPT_V_INPUT);
+
+ new = G_define_standard_option(G_OPT_V_OUTPUT);
+ new->required = NO;
+
+ type_opt = G_define_standard_option(G_OPT_V_TYPE);
+ type_opt->options = "point,line,area";
+ type_opt->answer = "point,line,area";
+ type_opt->guisection = _("Selection");
+
+ lyr_opt = G_define_standard_option(G_OPT_V_FIELD_ALL);
+ lyr_opt->guisection = _("Selection");
+
+ cats_opt = G_define_standard_option(G_OPT_V_CATS);
+ cats_opt->guisection = _("Selection");
+
+ where_opt = G_define_standard_option(G_OPT_DB_WHERE);
+ where_opt->guisection = _("Selection");
+
+ pmode = G_define_option();
+ pmode->type = TYPE_STRING;
+ pmode->key = "pcenter";
+ pmode->label = _("point center");
+ pmode->multiple = YES;
+ pmode->options = "mean,median,pmedian";
+ pmode->answer = "mean";
+ pdesc = NULL;
+ G_asprintf(&pdesc,
+ "mean;%s;"
+ "median;%s;"
+ "pmedian;%s;",
+ _("Geometric mean (center of gravity)"),
+ _("Geometric median"),
+ _("Point closest to geometric median"));
+ pmode->descriptions = pdesc;
+
+ lmode = G_define_option();
+ lmode->type = TYPE_STRING;
+ lmode->key = "lcenter";
+ lmode->label = _("line center");
+ lmode->multiple = YES;
+ lmode->options = "mid,mean,median";
+ lmode->answer = "mid";
+ ldesc = NULL;
+ G_asprintf(&ldesc,
+ "mid;%s;"
+ "mean;%s;"
+ "median;%s;",
+ _("Line mid point"),
+ _("Geometric mean (center of gravity)"),
+ _("Geometric median using line segments"));
+ lmode->descriptions = ldesc;
+
+ amode = G_define_option();
+ amode->type = TYPE_STRING;
+ amode->key = "acenter";
+ amode->label = _("area center");
+ amode->multiple = YES;
+ amode->options = "mean,median,bmedian";
+ amode->answer = "mean";
+ adesc = NULL;
+ G_asprintf(&adesc,
+ "mean;%s;"
+ "median;%s;"
+ "bmedian;%s;",
+ _("Geometric mean (center of gravity)"),
+ _("Geometric median using area sizes"),
+ _("Geometric median using boundary segments"));
+ amode->descriptions = adesc;
+
+ topo_flag = G_define_standard_flag(G_FLG_V_TOPO);
+
+ /* parse options and flags */
+ if (G_parser(argc, argv))
+ exit(EXIT_FAILURE);
+
+ if (!(itype = Vect_option_to_types(type_opt)))
+ G_fatal_error(_("No feature types selected"));
+
+ mode = 0;
+ for (i = 0; pmode->answers[i]; i++) {
+ if (!strcmp(pmode->answers[i], "mean"))
+ mode |= P_MEAN;
+ else if (!strcmp(pmode->answers[i], "median"))
+ mode |= P_MEDIAN;
+ else if (!strcmp(pmode->answers[i], "pmedian"))
+ mode |= P_MEDIAN_P;
+ else
+ G_fatal_error(_("Invalid answer '%s' for option '%s'"),
+ pmode->answers[i], pmode->key);
+ }
+ for (i = 0; lmode->answers[i]; i++) {
+ if (!strcmp(lmode->answers[i], "mid"))
+ mode |= L_MID;
+ else if (!strcmp(lmode->answers[i], "mean"))
+ mode |= L_MEAN;
+ else if (!strcmp(lmode->answers[i], "median"))
+ mode |= L_MEDIAN;
+ else
+ G_fatal_error(_("Invalid answer '%s' for option '%s'"),
+ lmode->answers[i], lmode->key);
+ }
+ for (i = 0; amode->answers[i]; i++) {
+ if (!strcmp(amode->answers[i], "mean"))
+ mode |= A_MEAN;
+ else if (!strcmp(amode->answers[i], "median"))
+ mode |= A_MEDIAN;
+ else if (!strcmp(amode->answers[i], "bmedian"))
+ mode |= A_MEDIAN_B;
+ else
+ G_fatal_error(_("Invalid answer '%s' for option '%s'"),
+ amode->answers[i], amode->key);
+ }
+
+ if ((mapset = (char *)G_find_vector2(old->answer, "")) == NULL)
+ G_fatal_error(_("Vector map <%s> not found"), old->answer);
+
+ Vect_set_open_level(1);
+
+ if (1 > Vect_open_old(&In, old->answer, mapset))
+ G_fatal_error(_("Unable to open vector map <%s>"), old->answer);
+
+ layer = -1;
+ if (lyr_opt->answer)
+ layer = Vect_get_field_number(&In, lyr_opt->answer);
+
+ if (layer > 0)
+ cat_list = Vect_cats_set_constraint(&In, layer, where_opt->answer,
+ cats_opt->answer);
+
+ out3d = Vect_is_3d(&In);
+
+ Outp = NULL;
+ if (new->answer) {
+ Vect_check_input_output_name(old->answer, new->answer, G_FATAL_EXIT);
+ Vect_open_new(&Out, new->answer, out3d);
+
+ /* Copy header and history data from old to new map */
+ Vect_copy_head_data(&In, &Out);
+ Vect_hist_copy(&In, &Out);
+ Vect_hist_command(&Out);
+
+ Outp = &Out;
+ }
+
+ Points = Vect_new_line_struct();
+ Cats = Vect_new_cats_struct();
+
+ i = 1;
+ nprimitives = npoints = nlines = 0;
+
+ /* count features */
+ while ((type = Vect_read_next_line(&In, Points, Cats)) > 0) {
+
+ nprimitives++;
+
+ if (type == GV_LINE) {
+ nlines++;
+ }
+ if (type == GV_POINT) {
+ npoints++;
+ }
+ }
+
+ /* filter feature count */
+ if (!((mode & P_MEAN) | (mode & P_MEDIAN) | (mode & P_MEDIAN_P)))
+ npoints = 0;
+ if (!((mode & L_MID) | (mode & L_MEAN) | (mode & L_MEDIAN)))
+ nlines = 0;
+
+ /* do the work */
+ if (npoints) {
+ points_center(&In, Outp, layer, cat_list, nprimitives, mode);
+ }
+ if (nlines) {
+ lines_center(&In, Outp, layer, cat_list, nprimitives, mode);
+ Vect_copy_tables(&In, &Out, layer);
+ }
+
+ Vect_close(&In);
+
+ /* areas */
+ if (itype & GV_AREA) {
+ Vect_set_open_level(2);
+
+ if (1 > Vect_open_old(&In, old->answer, mapset))
+ G_warning(_("Unable to open vector map <%s> with topology"), old->answer);
+ else {
+ int nareas = Vect_get_num_areas(&In);
+
+ if (nareas)
+ areas_center(&In, Outp, layer, cat_list, mode);
+
+ Vect_close(&In);
+ }
+ }
+
+ if (Outp) {
+ if (!topo_flag->answer)
+ Vect_build(&Out);
+ Vect_close(&Out);
+ }
+
+ exit(EXIT_SUCCESS);
+}
Property changes on: grass-addons/grass7/vector/v.centerpoint/main.c
___________________________________________________________________
Added: svn:mime-type
+ text/x-csrc
Added: svn:eol-style
+ native
Added: grass-addons/grass7/vector/v.centerpoint/points.c
===================================================================
--- grass-addons/grass7/vector/v.centerpoint/points.c (rev 0)
+++ grass-addons/grass7/vector/v.centerpoint/points.c 2013-09-22 14:40:29 UTC (rev 57812)
@@ -0,0 +1,227 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include <grass/gis.h>
+#include <grass/vector.h>
+#include <grass/glocale.h>
+#include "local_proto.h"
+
+static double d_ulp(double d)
+{
+ int exp;
+
+ if (d == 0)
+ return GRASS_EPSILON;
+
+ d = frexp(d, &exp);
+ exp -= 51;
+ d = ldexp(d, exp);
+
+ return d;
+}
+
+int points_center(struct Map_info *In, struct Map_info *Out, int layer,
+ struct cat_list *cat_list, int n_primitives, int mode)
+{
+ struct line_pnts *Points, *OPoints;
+ struct line_cats *Cats, *OCats;
+ double xsum, xmean, ysum, ymean, zsum, zmean;
+ double x, y, z;
+ double medx, medy, medz;
+ int type, counter, n;
+ int iter, maxiter = 100;
+
+ Points = Vect_new_line_struct();
+ OPoints = Vect_new_line_struct();
+ Cats = Vect_new_cats_struct();
+ OCats = Vect_new_cats_struct();
+
+ Vect_rewind(In);
+
+ /* coordinates' mean */
+ counter = n = 0;
+ xsum = ysum = zsum = 0.;
+ G_message(_("Calculating mean point coordinates (center of gravity)..."));
+ while ((type = Vect_read_next_line(In, Points, Cats)) > 0) {
+ G_percent(counter, n_primitives, 4);
+ counter++;
+ if (!(type & GV_POINT))
+ continue;
+
+ if (layer > 0 && !Vect_cats_in_constraint(Cats, layer, cat_list))
+ continue;
+
+ xsum += Points->x[0];
+ ysum += Points->y[0];
+ zsum += Points->z[0];
+ n++;
+ }
+ G_percent(1, 1, 1);
+
+ xmean = xsum / n;
+ ymean = ysum / n;
+ zmean = zsum / n;
+
+ if (mode & P_MEAN) {
+ x = xmean;
+ y = ymean;
+ z = zmean;
+
+ if (Out) {
+ Vect_reset_line(OPoints);
+ Vect_append_point(OPoints, x, y, z);
+ Vect_reset_cats(OCats);
+ Vect_cat_set(OCats, 1, 1);
+ Vect_write_line(Out, GV_POINT, OPoints, Cats);
+ }
+ else
+ fprintf(stdout, "1|%.15g|%.15g|%.15g\n", x, y, z);
+ }
+
+ medx = xmean;
+ medy = ymean;
+ medz = zmean;
+
+ /* approximate geometric median with Weiszfeld's algorithm:
+ * iterative least squares reduction */
+ if ((mode & P_MEDIAN) || (mode & P_MEDIAN_P)) {
+ double dist, distsum, dist2all, lastdist2all;
+ double dx, dy, dz;
+
+ medx = xmean;
+ medy = ymean;
+ medz = zmean;
+ lastdist2all = -1;
+
+ G_message(_("Approximating geometric median..."));
+
+ for (iter = 0; iter < maxiter; iter++) {
+
+ G_percent(iter, maxiter, 4);
+
+ distsum = dist2all = 0.;
+ x = y = z = 0.;
+
+ Vect_rewind(In);
+ while ((type = Vect_read_next_line(In, Points, Cats)) > 0) {
+ if (!(type & GV_POINT))
+ continue;
+ if (layer > 0 &&
+ !Vect_cats_in_constraint(Cats, layer, cat_list))
+ continue;
+
+ dx = Points->x[0] - medx;
+ dy = Points->y[0] - medy;
+ dz = Points->z[0] - medz;
+ dist = sqrt(dx * dx + dy * dy + dz * dz);
+
+ if (dist) {
+ x += Points->x[0] / dist;
+ y += Points->y[0] / dist;
+ z += Points->z[0] / dist;
+
+ distsum += 1 / dist;
+ dist2all += dist;
+ }
+ }
+
+ if (distsum) {
+ x /= distsum;
+ y /= distsum;
+ z /= distsum;
+ }
+
+ G_debug(3, "dist2all: %.15g", dist2all);
+ G_debug(3, "lastdist2all: %.15g", lastdist2all);
+ if (lastdist2all > 0) {
+ double d = d_ulp(lastdist2all);
+
+ if (lastdist2all - dist2all < d)
+ break;
+ }
+ if (dist2all == 0.)
+ break;
+
+ lastdist2all = dist2all;
+
+ medx = x;
+ medy = y;
+ medz = z;
+ }
+ G_percent(1, 1, 1);
+ G_message(_("Iteration converged after %d passes, dist = %.15g"),
+ iter, lastdist2all);
+
+ if (mode & P_MEDIAN) {
+ x = medx;
+ y = medy;
+ z = medz;
+
+ if (Out) {
+ Vect_reset_line(OPoints);
+ Vect_append_point(OPoints, x, y, z);
+ Vect_reset_cats(OCats);
+ Vect_cat_set(OCats, 1, 2);
+ Vect_write_line(Out, GV_POINT, OPoints, Cats);
+ }
+ else
+ fprintf(stdout, "2|%.15g|%.15g|%.15g\n", x, y, z);
+ }
+ }
+
+ /* find point closest to approximated median */
+ if (mode & P_MEDIAN_P) {
+ double dx, dy, dz;
+ double dist, mindist;
+ double xmin, ymin, zmin;
+
+ counter = 0;
+
+ xmin = medx;
+ ymin = medy;
+ zmin = medz;
+
+ mindist = -1;
+
+ G_message(_("Searching point closest to approximated median..."));
+
+ Vect_rewind(In);
+ while ((type = Vect_read_next_line(In, Points, Cats)) > 0) {
+ G_percent(counter, n_primitives, 4);
+ counter++;
+ if (!(type & GV_POINT))
+ continue;
+ if (layer > 0 &&
+ !Vect_cats_in_constraint(Cats, layer, cat_list))
+ continue;
+
+ dx = Points->x[0] - medx;
+ dy = Points->y[0] - medy;
+ dz = Points->z[0] - medz;
+ dist = sqrt(dx * dx + dy * dy + dz * dz);
+
+ if (dist < mindist || mindist < 0) {
+ xmin = Points->x[0];
+ ymin = Points->y[0];
+ zmin = Points->z[0];
+ mindist = dist;
+ }
+ }
+ G_percent(1, 1, 1);
+
+ x = xmin;
+ y = ymin;
+ z = zmin;
+ if (Out) {
+ Vect_reset_line(OPoints);
+ Vect_append_point(OPoints, x, y, z);
+ Vect_reset_cats(OCats);
+ Vect_cat_set(OCats, 1, 3);
+ Vect_write_line(Out, GV_POINT, OPoints, Cats);
+ }
+ else
+ fprintf(stdout, "3|%.15g|%.15g|%.15g\n", x, y, z);
+ }
+
+ return 1;
+}
Property changes on: grass-addons/grass7/vector/v.centerpoint/points.c
___________________________________________________________________
Added: svn:mime-type
+ text/x-csrc
Added: svn:eol-style
+ native
Added: grass-addons/grass7/vector/v.centerpoint/v.centerpoint.html
===================================================================
--- grass-addons/grass7/vector/v.centerpoint/v.centerpoint.html (rev 0)
+++ grass-addons/grass7/vector/v.centerpoint/v.centerpoint.html 2013-09-22 14:40:29 UTC (rev 57812)
@@ -0,0 +1,78 @@
+<h2>DESCRIPTION</h2>
+
+<em>v.centerpoint</em> calculates center points for point clouds, lines
+and areas. Center points can be geometric means (centers of gravity) or
+geometric medians, which is more robust in case of outliers.
+<p>
+For points, center points are calculated considering all points. For
+lines and areas, center points are calculated for each line or area
+separately.
+<p>
+If no output vector is given, center points are printed to stdout in
+ASCII point format:
+<div class="code"><pre>
+<cat>|<easting>|<northing>
+</pre></div>
+The category values are
+<ul>
+ <li><b>1</b> - mean of points</li>
+ <li><b>2</b> - median of points</li>
+ <li><b>3</b> - point closest to median of points</li>
+ <li><b>4</b> - mid point of each line</li>
+ <li><b>5</b> - mean of each line</li>
+ <li><b>6</b> - median of each line</li>
+ <li><b>7</b> - mean of each area</li>
+ <li><b>8</b> - median of each area using area triangulation</li>
+ <li><b>9</b> - median of each area using boundaries</li>
+</ul>
+If an output vector is given, center points inherit the categories of
+the respective lines and areas. For points, the category is set to 1
+
+<h4>Point centers</h4>
+<ul>
+ <li><b>mean</b> - center of gravity, mean of all point coordinates</li>
+ <li><b>median</b> - geometric median, minimum distance to all points</li>
+ <li><b>pmedian</b> - point closest to the geometric median</li>
+</ul>
+
+<h4>Line centers</h4>
+<ul>
+ <li><b>mid</b> - the mid point of each line, lies exactly on the line</li>
+ <li><b>mean</b> - center of gravity, mean of all line segments, might
+ not lie on the line</li>
+ <li><b>median</b> - geometric median, minimum distance to all line
+ segments, might not lie on the line</li>
+</ul>
+
+<h4>Area centers</h4>
+<ul>
+ <li><b>mean</b> - center of gravity, calculated using area triangulation</li>
+ <li><b>median</b> - geometric median, minimum distance to area
+ triangulation, might not lie inside the area</li>
+ <li><b>bmedian</b> - geometric median, minimum distance to boundary
+ segments, might not lie inside the area</li>
+</ul>
+
+<h2>EXAMPLE</h2>
+
+Calculate center of gravity for the LiDAR point cloud 'elev_lid_bepts'
+in the North Carolina sample dataset:
+<div class="code"><pre>
+v.centerpoint input=elev_lid_bepts output=elev_lid_bepts_mean
+</pre></div>
+
+<div class="code"><pre>
+v.centerpoint in=urbanarea out=urbanarea_median acenter=median
+</pre></div>
+
+<h2>SEE ALSO</h2>
+
+<em>
+<a href="v.centroid.html">v.centroid</a>
+</em>
+
+<h2>AUTHOR</h2>
+
+Markus Metz
+
+<p><i>Last changed: $Date$</i>
Property changes on: grass-addons/grass7/vector/v.centerpoint/v.centerpoint.html
___________________________________________________________________
Added: svn:mime-type
+ text/html
Added: svn:keywords
+ Author Date Id
Added: svn:eol-style
+ native
More information about the grass-commit
mailing list