/[zanavi_public1]/navit/navit/maptool/poly2tri-c/002/bin/main.c
ZANavi

Contents of /navit/navit/maptool/poly2tri-c/002/bin/main.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 31 - (show annotations) (download)
Mon Feb 4 17:41:59 2013 UTC (11 years, 2 months ago) by zoff99
File MIME type: text/plain
File size: 12591 byte(s)
new map version, lots of fixes and experimental new features
1 /*
2 * This file is a part of Poly2Tri-C
3 * (c) Barak Itkin <lightningismyname@gmail.com>
4 * http://code.google.com/p/poly2tri-c/
5 *
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without modification,
9 * are permitted provided that the following conditions are met:
10 *
11 * * Redistributions of source code must retain the above copyright notice,
12 * this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above copyright notice,
14 * this list of conditions and the following disclaimer in the documentation
15 * and/or other materials provided with the distribution.
16 * * Neither the name of Poly2Tri nor the names of its contributors may be
17 * used to endorse or promote products derived from this software without specific
18 * prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33 /* The file format:
34 * P <X> <Y> - Specify a Point (the default is that it belongs to the
35 * outline). The second line in the file must be of this type!
36 * H <X> <Y> - Specify that all points from here on (including this one)
37 * belong to a new Hole. This will stop only on the next 'H'
38 * directive (which will create a new hole)
39 * S <X> <Y> - Specify a Steiner point. Can appear anywhere.
40 */
41 #include <stdlib.h>
42 #include <stdio.h>
43 #include <glib.h>
44
45 #include <poly2tri-c/p2t/poly2tri.h>
46
47 #include <poly2tri-c/refine/refine.h>
48 #include <poly2tri-c/render/svg-plot.h>
49 #include <poly2tri-c/render/mesh-render.h>
50
51 #include <string.h>
52
53 static gint refine_max_steps = 1000;
54 static gboolean debug_print = TRUE;
55 static gboolean verbose = TRUE;
56 static gchar *input_file = NULL;
57 static gchar *output_file = NULL;
58 static gboolean render_mesh = FALSE;
59 static gboolean render_svg = FALSE;
60 static gint mesh_width = 100;
61 static gint mesh_height = 100;
62
63 static GOptionEntry entries[] =
64 {
65 { "refine-max-steps", 'r', 0, G_OPTION_ARG_INT, &refine_max_steps, "Set maximal refinement steps to N", "N" },
66 { "verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose, "Print output?", NULL },
67 { "debug", 'd', 0, G_OPTION_ARG_NONE, &debug_print, "Enable debug printing", NULL },
68 { "input", 'i', 0, G_OPTION_ARG_FILENAME, &input_file, "Use input file at FILE_IN", "FILE_IN" },
69 { "output", 'o', 0, G_OPTION_ARG_FILENAME, &output_file, "Use output file at FILE_OUT", "FILE_OUT" },
70 { "render-mesh", 'm', 0, G_OPTION_ARG_NONE, &render_mesh, "Render a color mesh of the result", NULL },
71 { "mesh-width", 'w', 0, G_OPTION_ARG_INT, &mesh_width, "The width of the color mesh image", NULL },
72 { "mesh-height", 'h', 0, G_OPTION_ARG_INT, &mesh_height, "The height of the color mesh iamge",NULL },
73 { "render-svg", 's', 0, G_OPTION_ARG_NONE, &render_svg, "Render an outline of the result", NULL },
74 { NULL }
75 };
76
77 typedef enum {
78 PTS_POINTS = 'P',
79 PTS_HOLE = 'H',
80 PTS_STEINER = 'S'
81 } PtsFilePartType;
82
83 typedef struct
84 {
85 PtsFilePartType type;
86 union {
87 GPtrArray *points;
88 P2tPoint *point;
89 } data;
90 } PtsFilePart;
91
92 /**
93 * read_points_file:
94 * @param path The path to the points & colors file
95 * @param points An pointer to an array of pointers to @ref P2RrPoint will be returned
96 * here. NULL can be passed.
97 * @param colors An pointer to an array of colors will be returned here. NULL can be
98 * passed.
99 */
100 GQueue*
101 read_points_file (const gchar *path)
102 {
103 int line;
104 FILE *f = fopen (path, "r");
105
106 PtsFilePart *current_part, *temp_part;
107 GPtrArray *current_points;
108 GQueue *file_parts = g_queue_new ();
109
110 if (f == NULL)
111 {
112 g_print ("Error! Could not read input file!");
113 exit (1);
114 }
115
116 if (verbose)
117 g_print ("Now parsing \"%s\"\n", path);
118
119 current_part = g_slice_new (PtsFilePart);
120 current_part->type = PTS_POINTS;
121 current_points = current_part->data.points = g_ptr_array_new ();
122 g_queue_push_tail (file_parts, current_part);
123
124 line = 0;
125
126 while (! feof (f))
127 {
128 char type;
129 float x, y;
130 int read_size;
131 gboolean error = FALSE;
132
133 ++line;
134
135 read_size = fscanf (f, " %[a-zA-Z]", &type);
136
137 if (read_size != 1)
138 {
139 g_error ("Expected a command type!");
140 exit (1);
141 }
142
143 switch (type)
144 {
145 case PTS_HOLE:
146 if (verbose) g_print ("Found a hole on directive %d\n", line);
147 current_part = g_slice_new (PtsFilePart);
148 current_part->type = PTS_HOLE;
149 current_points = current_part->data.points = g_ptr_array_new ();
150 g_queue_push_tail (file_parts, current_part);
151 /* Intentionally no break! */
152
153 case PTS_POINTS:
154 read_size = fscanf (f, "%f %f", &x, &y);
155 if ((error = (read_size != 2))) break;
156 g_ptr_array_add (current_points, p2t_point_new_dd (x, y));
157 break;
158
159 case PTS_STEINER:
160 if (verbose) g_print ("Found a steiner point on directive %d\n", line);
161 temp_part = g_slice_new (PtsFilePart);
162 temp_part->type = PTS_STEINER;
163 g_queue_push_tail (file_parts, temp_part);
164 read_size = fscanf (f, "%f %f", &x, &y);
165 if ((error = (read_size != 2))) break;
166 temp_part->data.point = p2t_point_new_dd (x, y);
167 break;
168
169 default:
170 error = TRUE;
171 break;
172 }
173
174 if (error)
175 {
176 g_error ("Bad directive number %d!", line);
177 exit (1);
178 }
179
180 /* Consume additional spaces, to detect EOF properly */
181 read_size = fscanf (f, " ");
182 }
183
184 fclose (f);
185
186 return file_parts;
187 }
188
189 void
190 free_read_results (GQueue *file_parts)
191 {
192 while (! g_queue_is_empty (file_parts))
193 {
194 PtsFilePart *temp = (PtsFilePart*) g_queue_pop_head (file_parts);
195 GPtrArray *pts;
196 gint i;
197 switch (temp->type)
198 {
199 case PTS_HOLE:
200 case PTS_POINTS:
201 pts = temp->data.points;
202 for (i = 0; i < pts->len; ++i)
203 p2t_point_free (point_index (pts, i));
204 g_ptr_array_free (pts, TRUE);
205 break;
206
207 case PTS_STEINER:
208 p2t_point_free (temp->data.point);
209 break;
210 }
211 g_slice_free (PtsFilePart, temp);
212 }
213 g_queue_free (file_parts);
214 }
215
216 /* Calculate a "deterministic random" color for each point
217 * based on its memory address. Since we know that least-significant bytes
218 * of the point address will change more than the mor-important ones, we
219 * make sure to take them into consideration in all the color channels.
220 */
221 static void
222 test_point_to_color (P2trPoint* point, guint8 *dest, gpointer user_data)
223 {
224 gulong value = (gulong) point;
225 guchar b1 = value & 0xff, b2 = (value & 0xff00) >> 2, b3 = (value & 0xff0000) >> 4;
226 dest[0] = b1;
227 dest[1] = (b1 ^ b2);
228 dest[2] = (b1 ^ b3);
229 }
230
231 void
232 p2tr_write_rgb_ppm (FILE *f,
233 guint8 *dest,
234 P2trImageConfig *config)
235 {
236 gint x, y;
237 guint8 *pixel;
238
239 fprintf (f, "P3\n");
240 fprintf (f, "%d %d\n", config->x_samples, config->y_samples);
241 fprintf (f, "255\n");
242
243 pixel = dest;
244
245 for (y = 0; y < config->y_samples; y++)
246 {
247 for (x = 0; x < config->x_samples; x++)
248 {
249 if (pixel[3] <= 0.5)
250 fprintf (f, " 0 0 0");
251 else
252 fprintf (f, "%3d %3d %3d", pixel[0], pixel[1], pixel[2]);
253
254 if (x != config->x_samples - 1)
255 fprintf (f, " ");
256
257 pixel += 4;
258 }
259 fprintf (f, "\n");
260 }
261 }
262
263 gint main (int argc, char *argv[])
264 {
265 FILE *svg_out = NULL, *mesh_out = NULL;
266 gchar *svg_out_path, *mesh_out_path;
267
268 GError *error = NULL;
269 GOptionContext *context;
270
271 GQueue *pts_parts;
272 GList *pts_iter;
273 PtsFilePart *cur_part;
274
275 P2tCDT *cdt;
276 P2trCDT *rcdt;
277 P2trRefiner *refiner;
278
279 context = g_option_context_new ("- Create a fine mesh from a given PSLG");
280 g_option_context_add_main_entries (context, entries, NULL);
281
282 if (!g_option_context_parse (context, &argc, &argv, &error))
283 {
284 g_print ("option parsing failed: %s\n", error->message);
285 exit (1);
286 }
287
288 g_option_context_free (context);
289
290 if (input_file == NULL)
291 {
292 g_print ("No input file given. Stop.");
293 exit (1);
294 }
295
296 if (! g_file_test (input_file, G_FILE_TEST_EXISTS))
297 {
298 g_print ("Input file does not exist. Stop.");
299 exit (1);
300 }
301
302 if (output_file == NULL && (render_svg || render_mesh))
303 {
304 g_print ("No output file given. Stop.");
305 exit (1);
306 }
307
308 if (render_svg)
309 {
310 svg_out_path = g_newa (gchar, strlen (output_file) + 4);
311 sprintf (svg_out_path, "%s.svg", output_file);
312
313 if ((svg_out = fopen (svg_out_path, "w")) == NULL)
314 {
315 g_print ("Can't open the svg output file. Stop.");
316 exit (1);
317 }
318 }
319
320 if (render_mesh)
321 {
322 mesh_out_path = g_newa (gchar, strlen (output_file) + 4);
323 sprintf (mesh_out_path, "%s.ppm", output_file);
324
325 if ((mesh_out = fopen (mesh_out_path, "w")) == NULL)
326 {
327 g_print ("Can't open the mesh output file. Stop.");
328 exit (1);
329 }
330 }
331
332 pts_parts = read_points_file (input_file);
333
334 for (pts_iter = pts_parts->head; pts_iter != NULL; pts_iter = pts_iter->next)
335 {
336 cur_part = (PtsFilePart*) pts_iter->data;
337 switch (cur_part->type)
338 {
339 case PTS_POINTS:
340 case PTS_HOLE:
341 if (cur_part->data.points->len < 3)
342 {
343 g_error ("Expected at least 3 points in eahc point sequence!");
344 exit (1);
345 }
346 break;
347
348 default:
349 break;
350 }
351 }
352
353 pts_iter = pts_parts->head;
354 cdt = p2t_cdt_new (((PtsFilePart*)pts_iter->data)->data.points);
355 for (pts_iter = pts_iter->next; pts_iter != NULL; pts_iter = pts_iter->next)
356 {
357 cur_part = (PtsFilePart*) pts_iter->data;
358 switch (cur_part->type)
359 {
360 case PTS_STEINER:
361 p2t_cdt_add_point (cdt, cur_part->data.point);
362 break;
363
364 case PTS_HOLE:
365 p2t_cdt_add_hole (cdt, cur_part->data.points);
366 break;
367
368 case PTS_POINTS:
369 g_assert_not_reached ();
370 break;
371
372 default:
373 break;
374 }
375 }
376
377 p2t_cdt_triangulate (cdt);
378
379 rcdt = p2tr_cdt_new (cdt);
380 p2t_cdt_free (cdt);
381
382 if (refine_max_steps > 0)
383 {
384 g_print ("Refining the mesh!\n");
385 refiner = p2tr_refiner_new (G_PI / 6, p2tr_refiner_false_too_big, rcdt);
386 p2tr_refiner_refine (refiner, refine_max_steps, NULL);
387 p2tr_refiner_free (refiner);
388 }
389
390 if (render_svg)
391 {
392 g_print ("Rendering SVG outline!");
393 p2tr_render_svg (rcdt->mesh, svg_out);
394 fclose (svg_out);
395 }
396
397 if (render_mesh)
398 {
399 P2trImageConfig imc;
400 guint8 *im;
401 gdouble min_x, min_y, max_x, max_y;
402
403 g_print ("Rendering color interpolation!");
404
405 p2tr_mesh_get_bounds (rcdt->mesh, &min_x, &min_y, &max_x, &max_y);
406
407 imc.cpp = 3;
408 imc.min_x = min_x;
409 imc.min_y = min_y;
410 imc.step_x = (max_x - min_x) / ((gfloat) mesh_width - 1);
411 imc.step_y = (max_y - min_y) / ((gfloat) mesh_height - 1);
412 imc.x_samples = mesh_width;
413 imc.y_samples = mesh_height;
414 imc.alpha_last = TRUE;
415
416 im = g_new (guint8, (1 + imc.cpp) * imc.x_samples * imc.y_samples);
417
418 p2tr_mesh_render_b (rcdt->mesh, im, &imc, test_point_to_color, NULL);
419
420 p2tr_write_rgb_ppm (mesh_out, im, &imc);
421 fclose (mesh_out);
422
423 g_free (im);
424 }
425
426 p2tr_cdt_free (rcdt);
427 free_read_results (pts_parts);
428
429 return 0;
430 }

   
Visit the ZANavi Wiki