2 * Copyright (C) 2010-2011 Andy Spencer <andy753421@gmail.com>
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 * @short_description: Single point polys
22 * Each #GritsPoly represents a 3 dimentional polygon.
28 #include "grits-poly.h"
31 static void grits_poly_tess(gdouble (**points)[3])
33 //g_debug("GritsPoly: tess");
34 GLUtesselator *tess = gluNewTess();
35 gluTessCallback(tess, GLU_TESS_BEGIN, (_GLUfuncptr)glBegin);
36 gluTessCallback(tess, GLU_TESS_VERTEX, (_GLUfuncptr)glVertex3dv);
37 gluTessCallback(tess, GLU_TESS_END, (_GLUfuncptr)glEnd);
38 for (int pi = 0; points[pi]; pi++) {
39 gluTessBeginPolygon(tess, NULL);
40 gluTessBeginContour(tess);
41 for (int ci = 0; points[pi][ci][0]; ci++) {
46 gluTessEndContour(tess);
47 gluTessEndPolygon(tess);
52 static void grits_poly_outline(gdouble (**points)[3])
54 //g_debug("GritsPoly: outline");
55 for (int pi = 0; points[pi]; pi++) {
57 for (int ci = 0; points[pi][ci][0] &&
59 points[pi][ci][2]; ci++)
60 glVertex3dv(points[pi][ci]);
65 static gboolean grits_poly_runlist(GritsPoly *poly, int i,
66 void (*render)(gdouble(**)[3]))
68 //g_debug("GritsPoly: genlist");
70 glCallList(poly->list[i]);
72 guint list = glGenLists(1);
73 glNewList(list, GL_COMPILE_AND_EXECUTE);
81 static void grits_poly_draw(GritsObject *_poly, GritsOpenGL *opengl)
83 //g_debug("GritsPoly: draw");
84 GritsPoly *poly = GRITS_POLY(_poly);
86 glPushAttrib(GL_COLOR_BUFFER_BIT | GL_ENABLE_BIT | GL_CURRENT_BIT |
87 GL_POINT_BIT | GL_LINE_BIT | GL_POLYGON_BIT);
88 glDisable(GL_TEXTURE_2D);
89 glDisable(GL_ALPHA_TEST);
90 glDisable(GL_CULL_FACE);
91 glDisable(GL_LIGHTING);
93 glEnable(GL_POLYGON_OFFSET_FILL);
94 glEnable(GL_POLYGON_OFFSET_LINE);
95 glEnable(GL_POLYGON_OFFSET_POINT);
98 /* Draw background farthest back */
99 glPolygonOffset(3, 3);
100 glColor4dv(poly->color);
101 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
102 grits_poly_runlist(poly, 0, grits_poly_tess);
105 glEnable(GL_POLYGON_SMOOTH);
106 glEnable(GL_LINE_SMOOTH);
107 glEnable(GL_POINT_SMOOTH);
109 if (!poly->color[3] && poly->border[3] && poly->width > 1) {
110 /* Draw line border in the middle */
113 glPointSize(poly->width*2);
114 glLineWidth(poly->width*2);
116 glPolygonOffset(2, 2);
118 glPolygonMode(GL_FRONT_AND_BACK, GL_POINT);
119 grits_poly_runlist(poly, 1, grits_poly_outline);
120 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
121 grits_poly_runlist(poly, 1, grits_poly_outline);
124 if (poly->border[3]) {
125 /* Draw border front-most */
126 glColor4dv(poly->border);
128 glPointSize(poly->width);
129 glLineWidth(poly->width);
131 glPolygonOffset(1, 1);
132 if (poly->width > 1) {
133 glPolygonMode(GL_FRONT_AND_BACK, GL_POINT);
134 grits_poly_runlist(poly, 1, grits_poly_outline);
136 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
137 grits_poly_runlist(poly, 1, grits_poly_outline);
140 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
144 static void grits_poly_pick(GritsObject *_poly, GritsOpenGL *opengl)
146 //g_debug("GritsPoly: pick");
147 GritsPoly *poly = GRITS_POLY(_poly);
148 glPushAttrib(GL_ENABLE_BIT);
149 glDisable(GL_CULL_FACE);
150 grits_poly_runlist(poly, 0, grits_poly_tess);
154 static gboolean grits_poly_delete(gpointer list)
156 glDeleteLists((guint)list, 1);
165 * Create a new GritsPoly which TODO.
167 * Returns: the new #GritsPoly.
169 GritsPoly *grits_poly_new(gdouble (**points)[3])
171 //g_debug("GritsPoly: new - %p", points);
172 GritsPoly *poly = g_object_new(GRITS_TYPE_POLY, NULL);
173 poly->points = points;
177 static void _free_points(gdouble (**points)[3])
179 for (int i = 0; points[i]; i++)
184 GritsPoly *grits_poly_parse(const gchar *str,
185 const gchar *poly_sep, const gchar *point_sep, const gchar *coord_sep)
187 /* Split and count polygons */
188 gchar **spolys = g_strsplit(str, poly_sep, -1);
189 int npolys = g_strv_length(spolys);
191 GritsBounds bounds = {-90, 90, -180, 180};
192 gdouble (**polys)[3] = (gpointer)g_new0(double*, npolys+1);
193 for (int pi = 0; pi < npolys; pi++) {
194 /* Split and count coordinates */
195 gchar **scoords = g_strsplit(spolys[pi], point_sep, -1);
196 int ncoords = g_strv_length(scoords);
198 /* Create binary coords */
199 gdouble (*coords)[3] = (gpointer)g_new0(gdouble, 3*(ncoords+1));
200 for (int ci = 0; ci < ncoords; ci++) {
202 sscanf(scoords[ci], "%lf,%lf", &lat, &lon);
203 if (lat > bounds.n) bounds.n = lat;
204 if (lat < bounds.s) bounds.s = lat;
205 if (lon > bounds.e) bounds.e = lon;
206 if (lon < bounds.w) bounds.w = lon;
213 /* Insert coords into poly array */
219 /* Create GritsPoly */
220 GritsPoly *poly = grits_poly_new(polys);
221 GRITS_OBJECT(poly)->center.lat = (bounds.n + bounds.s)/2;
222 GRITS_OBJECT(poly)->center.lon = lon_avg(bounds.e, bounds.w);
223 GRITS_OBJECT(poly)->center.elev = 0;
224 GRITS_OBJECT(poly)->skip = GRITS_SKIP_CENTER;
225 g_object_weak_ref(G_OBJECT(poly), (GWeakNotify)_free_points, polys);
230 G_DEFINE_TYPE(GritsPoly, grits_poly, GRITS_TYPE_OBJECT);
231 static void grits_poly_init(GritsPoly *poly)
236 poly->border[3] = 0.2;
238 GRITS_OBJECT(poly)->skip = GRITS_SKIP_STATE;
241 static void grits_poly_finalize(GObject *_poly)
243 //g_debug("GritsPoly: finalize");
244 GritsPoly *poly = GRITS_POLY(_poly);
245 if (poly->list[0]) g_idle_add(grits_poly_delete, (gpointer)poly->list[0]);
246 if (poly->list[1]) g_idle_add(grits_poly_delete, (gpointer)poly->list[1]);
249 static void grits_poly_class_init(GritsPolyClass *klass)
251 g_debug("GritsPoly: class_init");
252 GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
253 gobject_class->finalize = grits_poly_finalize;
255 GritsObjectClass *object_class = GRITS_OBJECT_CLASS(klass);
256 object_class->draw = grits_poly_draw;
257 object_class->pick = grits_poly_pick;