From ab244528448b35dc056427d8fe8d504a82267898 Mon Sep 17 00:00:00 2001 From: Andy Spencer Date: Tue, 3 Jan 2012 07:31:53 +0000 Subject: [PATCH] Move polygon parsing into grits-util This allows it to be used in other places e.g. for line parsing --- src/grits-util.c | 83 ++++++++++++++++++++++++++++++++++++++++ src/grits-util.h | 9 +++++ src/objects/grits-poly.c | 50 +++--------------------- 3 files changed, 98 insertions(+), 44 deletions(-) diff --git a/src/grits-util.c b/src/grits-util.c index 8ac6a1b..ab795f9 100644 --- a/src/grits-util.c +++ b/src/grits-util.c @@ -70,6 +70,7 @@ #include #include +#include #include "grits-util.h" @@ -303,3 +304,85 @@ void normd(gdouble *a) a[1] = a[1] / total; a[2] = a[2] / total; } + +/** + * parse_points: + * @string: String representation of the points + * @group_sep: Group separator + * @point_sep: Point separator + * @coord_sep: Coordinate separator + * @bounds: The bounding box of all the points, or NULL + * @center: The center of the @bounds, or NULL + * + * Parse a string of the form: + * string -> group [@group_sep group] ... + * group -> point [@point_sep point] ... + * point -> latitude @coord_sep longitude [@coord_sep elevation] + * + * For example + * parse_points("30,-80 30,-120 50,-120 50,-80", "\t", " ", ","); + * + * Returns: zero-terminated array of groups of points + */ +GritsPoints *parse_points(const gchar *string, + const gchar *group_sep, const gchar *point_sep, const gchar *coord_sep, + GritsBounds *bounds, GritsPoint *center) +{ + /* Split and count groups */ + gchar **sgroups = g_strsplit(string, group_sep, -1); + int ngroups = g_strv_length(sgroups); + + GritsBounds _bounds = {-90, 90, -180, 180}; + gdouble (**groups)[3] = (gpointer)g_new0(double*, ngroups+1); + for (int pi = 0; pi < ngroups; pi++) { + /* Split and count coordinates */ + gchar **scoords = g_strsplit(sgroups[pi], point_sep, -1); + int ncoords = g_strv_length(scoords); + + /* Create binary coords */ + gdouble (*coords)[3] = (gpointer)g_new0(gdouble, 3*(ncoords+1)); + for (int ci = 0; ci < ncoords; ci++) { + gdouble lat, lon; + sscanf(scoords[ci], "%lf,%lf", &lat, &lon); + if (bounds || center) { + if (lat > _bounds.n) _bounds.n = lat; + if (lat < _bounds.s) _bounds.s = lat; + if (lon > _bounds.e) _bounds.e = lon; + if (lon < _bounds.w) _bounds.w = lon; + } + lle2xyz(lat, lon, 0, + &coords[ci][0], + &coords[ci][1], + &coords[ci][2]); + } + + /* Insert coords into line array */ + groups[pi] = coords; + g_strfreev(scoords); + } + g_strfreev(sgroups); + + /* Output */ + if (bounds) + *bounds = _bounds; + if (center) { + center->lat = (_bounds.n + _bounds.s)/2; + center->lon = lon_avg(_bounds.e, _bounds.w); + center->elev = 0; + } + return groups; +} + +/** + * free_points: + * @points: Array of points allocated by parse_points() + * + * Frees all data allocated by parse_points + */ +void free_points(GritsPoints *points) +{ + gdouble (**_points)[3] = points; + for (int i = 0; _points[i]; i++) + g_free(_points[i]); + g_free(_points); +} diff --git a/src/grits-util.h b/src/grits-util.h index ccfff16..0fa144d 100644 --- a/src/grits-util.h +++ b/src/grits-util.h @@ -159,6 +159,9 @@ struct _GritsPoint { void grits_point_set_lle(GritsPoint *point, gdouble lat, gdouble lon, gdouble elev); +/* GritsPoints */ +typedef gdouble (*GritsPoints)[3]; + /* GritsBounds */ typedef struct _GritsBounds GritsBounds; struct _GritsBounds { @@ -212,4 +215,10 @@ void normd(gdouble *a); gdouble lon_avg(gdouble a, gdouble b); +GritsPoints *parse_points(const gchar *string, + const gchar *group_sep, const gchar *point_sep, const gchar *coord_sep, + GritsBounds *bounds, GritsPoint *center); + +void free_points(GritsPoints *points); + #endif diff --git a/src/objects/grits-poly.c b/src/objects/grits-poly.c index 25a81b5..c2c9923 100644 --- a/src/objects/grits-poly.c +++ b/src/objects/grits-poly.c @@ -173,55 +173,17 @@ GritsPoly *grits_poly_new(gdouble (**points)[3]) return poly; } -static void _free_points(gdouble (**points)[3]) -{ - for (int i = 0; points[i]; i++) - g_free(points[i]); - g_free(points); -} - GritsPoly *grits_poly_parse(const gchar *str, const gchar *poly_sep, const gchar *point_sep, const gchar *coord_sep) { - /* Split and count polygons */ - gchar **spolys = g_strsplit(str, poly_sep, -1); - int npolys = g_strv_length(spolys); - - GritsBounds bounds = {-90, 90, -180, 180}; - gdouble (**polys)[3] = (gpointer)g_new0(double*, npolys+1); - for (int pi = 0; pi < npolys; pi++) { - /* Split and count coordinates */ - gchar **scoords = g_strsplit(spolys[pi], point_sep, -1); - int ncoords = g_strv_length(scoords); - - /* Create binary coords */ - gdouble (*coords)[3] = (gpointer)g_new0(gdouble, 3*(ncoords+1)); - for (int ci = 0; ci < ncoords; ci++) { - gdouble lat, lon; - sscanf(scoords[ci], "%lf,%lf", &lat, &lon); - if (lat > bounds.n) bounds.n = lat; - if (lat < bounds.s) bounds.s = lat; - if (lon > bounds.e) bounds.e = lon; - if (lon < bounds.w) bounds.w = lon; - lle2xyz(lat, lon, 0, - &coords[ci][0], - &coords[ci][1], - &coords[ci][2]); - } - - /* Insert coords into poly array */ - polys[pi] = coords; - g_strfreev(scoords); - } - g_strfreev(spolys); + GritsPoint center; + gdouble (**polys)[3] = parse_points(str, + poly_sep, point_sep, coord_sep, NULL, ¢er); - /* Create GritsPoly */ GritsPoly *poly = grits_poly_new(polys); - GRITS_OBJECT(poly)->center.lat = (bounds.n + bounds.s)/2; - GRITS_OBJECT(poly)->center.lon = lon_avg(bounds.e, bounds.w); - GRITS_OBJECT(poly)->center.elev = 0; - GRITS_OBJECT(poly)->skip = GRITS_SKIP_CENTER; - g_object_weak_ref(G_OBJECT(poly), (GWeakNotify)_free_points, polys); + GRITS_OBJECT(poly)->center = center; + GRITS_OBJECT(poly)->skip = GRITS_SKIP_CENTER; + g_object_weak_ref(G_OBJECT(poly), (GWeakNotify)free_points, polys); return poly; } -- 2.43.2