X-Git-Url: http://pileus.org/git/?a=blobdiff_plain;f=src%2Fobjects%2Fgrits-poly.c;h=720e3b1bed37ea29f5af2d7c94104b8a6d539eb9;hb=81d8f34cc62ae85d9243ad0eb8c4587282c11710;hp=865d2887f1ebafd79d08aa353a28d488698ca9ec;hpb=12e39aa0ca2c7e6843bf1a1e0a9d73c3c84cc166;p=grits diff --git a/src/objects/grits-poly.c b/src/objects/grits-poly.c index 865d288..720e3b1 100644 --- a/src/objects/grits-poly.c +++ b/src/objects/grits-poly.c @@ -31,14 +31,12 @@ static void grits_poly_tess(gdouble (**points)[3]) { //g_debug("GritsPoly: tess"); - - /* Tesselate */ GLUtesselator *tess = gluNewTess(); - gluTessCallback(tess, GLU_TESS_BEGIN, glBegin); - gluTessCallback(tess, GLU_TESS_VERTEX, glVertex3dv); - gluTessCallback(tess, GLU_TESS_END, glEnd); - gluTessBeginPolygon(tess, NULL); + gluTessCallback(tess, GLU_TESS_BEGIN, (_GLUfuncptr)glBegin); + gluTessCallback(tess, GLU_TESS_VERTEX, (_GLUfuncptr)glVertex3dv); + gluTessCallback(tess, GLU_TESS_END, (_GLUfuncptr)glEnd); for (int pi = 0; points[pi]; pi++) { + gluTessBeginPolygon(tess, NULL); gluTessBeginContour(tess); for (int ci = 0; points[pi][ci][0]; ci++) { gluTessVertex(tess, @@ -46,28 +44,37 @@ static void grits_poly_tess(gdouble (**points)[3]) points[pi][ci]); } gluTessEndContour(tess); + gluTessEndPolygon(tess); } - gluTessEndPolygon(tess); gluDeleteTess(tess); +} - /* Outline */ +static void grits_poly_outline(gdouble (**points)[3]) +{ + //g_debug("GritsPoly: outline"); for (int pi = 0; points[pi]; pi++) { - glColor4d(1,1,1,0.2); - glBegin(GL_LINE_LOOP); - for (int ci = 0; points[pi][ci][0]; ci++) + glBegin(GL_POLYGON); + for (int ci = 0; points[pi][ci][0] && + points[pi][ci][1] && + points[pi][ci][2]; ci++) glVertex3dv(points[pi][ci]); glEnd(); } } -static gboolean grits_poly_genlist(gpointer _poly) + +static gboolean grits_poly_runlist(GritsPoly *poly, int i, + void (*render)(gdouble(**)[3])) { //g_debug("GritsPoly: genlist"); - GritsPoly *poly = GRITS_POLY(_poly); - guint list = glGenLists(1); - glNewList(list, GL_COMPILE); - grits_poly_tess(poly->points); - glEndList(); - poly->list = list; + if (poly->list[i]) { + glCallList(poly->list[i]); + } else { + guint list = glGenLists(1); + glNewList(list, GL_COMPILE_AND_EXECUTE); + render(poly->points); + glEndList(); + poly->list[i] = list; + } return FALSE; } @@ -76,19 +83,43 @@ static void grits_poly_draw(GritsObject *_poly, GritsOpenGL *opengl) //g_debug("GritsPoly: draw"); GritsPoly *poly = GRITS_POLY(_poly); - if (!poly->list) - return; - glPushAttrib(GL_COLOR_BUFFER_BIT | GL_ENABLE_BIT | GL_CURRENT_BIT); glDisable(GL_TEXTURE_2D); glDisable(GL_ALPHA_TEST); glDisable(GL_CULL_FACE); glDisable(GL_LIGHTING); - glColor4dv(poly->color); - glCallList(poly->list); + glEnable(GL_POLYGON_OFFSET_FILL); + glPolygonOffset(1, 1); + if (poly->color[3]) { + glColor4dv(poly->color); + grits_poly_runlist(poly, 0, grits_poly_tess); + } + glLineWidth(poly->width); + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + if (poly->border[3]) { + glColor4dv(poly->border); + grits_poly_runlist(poly, 1, grits_poly_outline); + } + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + glPopAttrib(); +} + +static void grits_poly_pick(GritsObject *_poly, GritsOpenGL *opengl) +{ + //g_debug("GritsPoly: pick"); + GritsPoly *poly = GRITS_POLY(_poly); + glPushAttrib(GL_ENABLE_BIT); + glDisable(GL_CULL_FACE); + grits_poly_runlist(poly, 0, grits_poly_tess); glPopAttrib(); } +static gboolean grits_poly_delete(gpointer list) +{ + glDeleteLists((guint)list, 1); + return FALSE; +} + /** * grits_poly_new: * @points: TODO @@ -103,7 +134,58 @@ GritsPoly *grits_poly_new(gdouble (**points)[3]) //g_debug("GritsPoly: new - %p", points); GritsPoly *poly = g_object_new(GRITS_TYPE_POLY, NULL); poly->points = points; - g_idle_add(grits_poly_genlist, poly); + 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); + + /* 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); return poly; } @@ -111,14 +193,20 @@ GritsPoly *grits_poly_new(gdouble (**points)[3]) G_DEFINE_TYPE(GritsPoly, grits_poly, GRITS_TYPE_OBJECT); static void grits_poly_init(GritsPoly *poly) { + poly->border[0] = 1; + poly->border[1] = 1; + poly->border[2] = 1; + poly->border[3] = 0.2; + poly->width = 1; + GRITS_OBJECT(poly)->skip = GRITS_SKIP_STATE; } static void grits_poly_finalize(GObject *_poly) { - g_debug("GritsPoly: finalize"); + //g_debug("GritsPoly: finalize"); GritsPoly *poly = GRITS_POLY(_poly); - (void)poly; - // TODO: free points + if (poly->list[0]) g_idle_add(grits_poly_delete, (gpointer)poly->list[0]); + if (poly->list[1]) g_idle_add(grits_poly_delete, (gpointer)poly->list[1]); } static void grits_poly_class_init(GritsPolyClass *klass) @@ -129,4 +217,5 @@ static void grits_poly_class_init(GritsPolyClass *klass) GritsObjectClass *object_class = GRITS_OBJECT_CLASS(klass); object_class->draw = grits_poly_draw; + object_class->pick = grits_poly_pick; }